1. 更新命令行
2. 更新页面管理
This commit is contained in:
parent
0da93d100c
commit
8631a84333
@ -10,6 +10,9 @@
|
||||
typedef uint8_t HShellLenType;
|
||||
#define HSHELL_ERROR_INDEX (0xff)
|
||||
|
||||
// 是否使用密码
|
||||
#define HSHELL_USE_PASSWORD
|
||||
|
||||
///< 可配置最多可注册回调多少个
|
||||
#ifndef HSHELL_CALL_MAX
|
||||
#define HSHELL_CALL_MAX 5
|
||||
@ -22,12 +25,24 @@ typedef uint8_t HShellLenType;
|
||||
|
||||
///< 解析token参数的最大个数
|
||||
#ifndef HSHELL_CMD_TOKEN_MAX
|
||||
#define HSHELL_CMD_TOKEN_MAX 5
|
||||
#define HSHELL_CMD_TOKEN_MAX 3
|
||||
#endif
|
||||
|
||||
///< 打印帮助命令行长度多少换行
|
||||
#ifndef HSHELL_CMD_LINE_NUM
|
||||
#define HSHELL_CMD_LINE_NUM 80
|
||||
#endif
|
||||
|
||||
///< 使用专门接口避免日志系统关闭日志打印导致命令不输出的问题
|
||||
#define HSHELL_PRINTF(format, ...) printf(format, ##__VA_ARGS__)
|
||||
#define HSHELL_PRINTFL(format, ...) printf(format "\r\n", ##__VA_ARGS__)
|
||||
#define HSHELL_PRINTF(format, ...) printf(format, ##__VA_ARGS__)
|
||||
|
||||
///< 回调参数固定格式
|
||||
#define HSHELL_FUNC_ARGS HShellLenType key, const HShellCmdToken *tokens, int tokensLen
|
||||
|
||||
///< 命令行参数, 需要使用上面的宏的同名参数
|
||||
#define HSHELL_ARGS_GET_UINT(index, result) \
|
||||
if (HSHellToUint32(tokens, tokensLen, index, &result) == 0) { HSHELL_PRINTFL("args error, index[%d], len[%d]", index, tokensLen); return ; }
|
||||
|
||||
///< 处理命令行token
|
||||
typedef struct __attribute__ ((__packed__)) HShellCmdToken
|
||||
@ -76,6 +91,27 @@ uint8_t HShellLex(const uint8_t *str, int strLen, HShellCmdToken *tokens, int to
|
||||
**/
|
||||
HShellLenType HShellMatchToken(const HShellCmdToken *token, const HShellMatch *matches, int matchLen, uint8_t ignoreCase);
|
||||
|
||||
/**
|
||||
* @brief 查找token匹配字符串, 判断是否忽略大小写
|
||||
* @param token 命令行解析的token
|
||||
* @param tokenLen 命令行解析的token个数
|
||||
* @param index 命令行解析的token索引
|
||||
* @param str 需要匹配的字符串
|
||||
* @param strLen 需要匹配的字符串长度
|
||||
* @param ignoreCase 是否忽略大小写
|
||||
* @return 返回是否匹配成功, 1成功, 0失败
|
||||
**/
|
||||
uint8_t HShellDiffString(const HShellCmdToken *token, uint8_t tokenLen, uint8_t index, const char *str, uint8_t strLen, uint8_t ignoreCase);
|
||||
|
||||
/**
|
||||
* @brief 将参数转换为uint32
|
||||
* @param token 命令行解析的token
|
||||
* @param index 命令行解析的token索引
|
||||
* @param value 转换后的uint32值
|
||||
* @return 返回是否转换成功, 1成功, 0失败
|
||||
**/
|
||||
uint8_t HSHellToUint32(const HShellCmdToken *token, uint8_t tokenLen, uint8_t index, uint32_t *value);
|
||||
|
||||
/**
|
||||
* @brief 注册命令行解析回调, 如果存在匹配映射表则覆盖原有映射
|
||||
* @param matches 匹配映射表
|
||||
@ -93,11 +129,17 @@ int16_t HSHellRegister(const HShellMatch *matches, int matchLen, shellCall call,
|
||||
void HSHellUnregister(int16_t index);
|
||||
|
||||
/**
|
||||
* @brief 添加命令行数据, 直到换行'\n'才处理
|
||||
* @brief 添加命令行数据, 直到直到换行将停止添加, 到HShellRun处理后恢复继续添加
|
||||
* @param str 命令行数据
|
||||
* @param strLen 命令行数据长度
|
||||
**/
|
||||
void HShellAddCmdData(uint8_t data);
|
||||
void HSHellAddCmdDatas(uint8_t *data, int len);
|
||||
void HSHellAddCmdDatas(const uint8_t *data, int len);
|
||||
|
||||
/**
|
||||
* @brief 处理命令行数据, 因添加数据在中断, 执行需在非中断执行
|
||||
**/
|
||||
void HShellRun();
|
||||
|
||||
|
||||
#endif // _H_SHELL_LEX_
|
||||
|
||||
@ -48,9 +48,10 @@
|
||||
#define UIPAGE_SHOW_HIDE_FUNC(show, hide) UIPAGE_SHOW_FUNC(show); UIPAGE_HIDE_FUNC(hide)
|
||||
|
||||
// 对应事件的data转换具体类型宏
|
||||
#define UI_CALL_INDEX_TYPE(value) ((enum eUIPage *)value)
|
||||
#define UI_CALL_INDEX_TYPE(value) ((HUiPageIndex_t *)value)
|
||||
/** ================================================================= */
|
||||
|
||||
typedef uint8_t HUiPageIndex_t;
|
||||
|
||||
// hide -> free -> update Page -> init -> show
|
||||
// 或者非返回时如下, 此时的hide和index事件都可存储该页面索引:
|
||||
@ -62,7 +63,7 @@ enum eCallCmd
|
||||
kCallShowPage, ///< 显示页面
|
||||
kCallHidePage, ///< 退出页面, 此事件如果是返回触发的可以存储索引数据
|
||||
kCallSwitchPage, ///< 切换页面, 对应页面返回false时则不切换, 所有切换都会触发这个事件
|
||||
kCallIndexSave, ///< 存储当前索引事件, 通知此事件说明当前不是返回事件(cmd, enum eUIPage *nextPage, 1);
|
||||
kCallIndexSave, ///< 存储当前索引事件, 通知此事件说明当前不是返回事件(cmd, HUiPageIndex_t *nextPage, 1);
|
||||
};
|
||||
|
||||
|
||||
@ -70,7 +71,7 @@ enum eCallCmd
|
||||
typedef enum eUIPage
|
||||
{
|
||||
|
||||
kUIPageMax, ///< ui最大个数, 不超过254个页面, 如超过则需要修改字节栈类型
|
||||
kUIPageMax = 4, ///< ui最大个数, 不超过254个页面, 如超过则需要修改字节栈类型
|
||||
} eUIPage;
|
||||
|
||||
///< cmd命令, data数据, len数据长度
|
||||
@ -81,11 +82,11 @@ typedef void (*initPageType_t)(pageCallType_t *call);
|
||||
void HUIPageInit(initPageType_t initPage);
|
||||
|
||||
// 设置主页, 切换到主页清空返回栈, 如果返回栈为空时, 当前页面不是主页, 则切换到主页
|
||||
void HUIPageSetHome(enum eUIPage page);
|
||||
void HUIPageSetHome(HUiPageIndex_t page);
|
||||
|
||||
// 切换页面, 当前页面入栈, 相同页面不操作, 需要检查栈, 栈存在就回栈清空之后的, 不存在就压栈
|
||||
// 因为有些页面可能不用HUIPageBack来返回, 所以需要兼容这种情况
|
||||
void HUIPageSwitch(enum eUIPage page);
|
||||
void HUIPageSwitch(HUiPageIndex_t page);
|
||||
|
||||
// 切换到主页
|
||||
void HUIPageSwitchHome();
|
||||
@ -119,13 +120,13 @@ void HUIPageResetCurrFree();
|
||||
uint8_t HUIPageGetCurrNotFree();
|
||||
|
||||
// 设置指定页面不释放内存
|
||||
void HUIPageSetNotFree(enum eUIPage page);
|
||||
void HUIPageSetNotFree(HUiPageIndex_t page);
|
||||
|
||||
// 恢复指定页面默认释放内存
|
||||
void HUIPageResetFree(enum eUIPage page);
|
||||
void HUIPageResetFree(HUiPageIndex_t page);
|
||||
|
||||
// 获取指定页面是否不释放, 是返回1, 否则返回0
|
||||
uint8_t HUIPageGetNotFree(enum eUIPage page);
|
||||
uint8_t HUIPageGetNotFree(HUiPageIndex_t page);
|
||||
|
||||
// 设置用户数据, 在 kCallShowPage 和 kCallHidePage 都可调用, 但每次切换这些事件后都会重置数据为0
|
||||
void HUIPageSetUserData(long userData);
|
||||
@ -140,10 +141,10 @@ uint8_t HUIPageSaveIndex(uint8_t value);
|
||||
uint8_t HUIPageGetIndex();
|
||||
|
||||
// 获取当前页面
|
||||
enum eUIPage HUIPageGetCurrPage();
|
||||
HUiPageIndex_t HUIPageGetCurrPage();
|
||||
|
||||
// 获取上一个页面
|
||||
enum eUIPage HUIPageGetPrevPage();
|
||||
HUiPageIndex_t HUIPageGetPrevPage();
|
||||
|
||||
// 获取返回栈使用长度
|
||||
uint8_t HUIPageGetStackLen();
|
||||
@ -155,7 +156,7 @@ uint8_t HUIPageGetIndexStackLen();
|
||||
uint8_t HUIPageIsBack();
|
||||
|
||||
// 检查该页面是否在返回栈, 是返回1, 否则返回0
|
||||
uint8_t HUIPageFindStack(enum eUIPage page);
|
||||
uint8_t HUIPageFindStack(HUiPageIndex_t page);
|
||||
|
||||
|
||||
#endif //__H_UI_PAGE_MANAGE_H__
|
||||
|
||||
474
src/HShellLex.c
474
src/HShellLex.c
@ -3,6 +3,7 @@
|
||||
#include <HShellLex.h>
|
||||
#include <HVector.h>
|
||||
#include <ctype.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
|
||||
@ -10,7 +11,7 @@
|
||||
#ifndef LogD
|
||||
#if 0
|
||||
#include <stdio.h>
|
||||
#define LogD(format, ...) printf("[%s:%s:%d]" format "\r\n", __FILE_NAME__, __FUNCTION__, __LINE__, ##__VA_ARGS__)
|
||||
#define LogD(format, ...) printf("[%s:%s:%d]" format "\r\n", __FILE__, __FUNCTION__, __LINE__, ##__VA_ARGS__)
|
||||
#else
|
||||
#define LogD(...)
|
||||
#endif
|
||||
@ -20,23 +21,267 @@
|
||||
#define CTRL_KEY(k) ((k) & 0x1f)
|
||||
|
||||
|
||||
struct __attribute__((packed)) HShellCmd {
|
||||
typedef struct __attribute__((packed)) ShellCmd {
|
||||
const HShellMatch *match; ///< 匹配表
|
||||
shellCall call; ///< 回调
|
||||
uint8_t matchLen; ///< 匹配表长度
|
||||
uint8_t ignoreCase : 1; ///< 忽略大小写
|
||||
uint8_t matchLen : 7; ///< 匹配表长度
|
||||
uint8_t ignoreCase : 1; ///< 忽略大小写
|
||||
} ShellCmd;
|
||||
|
||||
struct __attribute__((packed)) ShellInfo {
|
||||
ShellCmd shellCmd[HSHELL_CALL_MAX]; ///< 回调注册表
|
||||
HShellCmdToken cmdTokens[HSHELL_CMD_TOKEN_MAX]; ///< 解析参数
|
||||
uint8_t cursorPos; ///< 光标位置
|
||||
uint8_t escStatus : 3; ///< ESC转义状态, 最多7状态
|
||||
uint8_t run : 1; ///< 可执行, 当前不能继续加入缓存区
|
||||
uint8_t needPrint : 1; ///< 需要重绘当前行
|
||||
uint8_t password : 1; ///< 密码模式
|
||||
uint8_t userName : 1; ///< 用户名是否正确
|
||||
};
|
||||
|
||||
// 回调注册
|
||||
static struct HShellCmd shellCmd_[HSHELL_CALL_MAX];
|
||||
// 命令行数据
|
||||
// 命令行缓存数据
|
||||
static HVECTOR_DEFINE(cmdBuffer_, HSHELL_CMD_LINE_BUFFER);
|
||||
// 解析参数
|
||||
static HShellCmdToken cmdTokens_[HSHELL_CMD_TOKEN_MAX];
|
||||
// 光标位置
|
||||
static uint8_t cursorPos;
|
||||
static struct ShellInfo shellInfo_;
|
||||
|
||||
|
||||
static void PrintAllCmd() {
|
||||
uint16_t len = 0;
|
||||
for (int i = 0; i < HSHELL_CALL_MAX; ++i) {
|
||||
if (shellInfo_.shellCmd[i].match == NULL) {
|
||||
continue;
|
||||
}
|
||||
|
||||
for (int j = 0; j < shellInfo_.shellCmd[i].matchLen; ++j) {
|
||||
if (shellInfo_.shellCmd[i].matchLen <= 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
HSHELL_PRINTF("%s\t", (const char *)shellInfo_.shellCmd[i].match[j].match);
|
||||
len += shellInfo_.shellCmd[i].match[j].matchLen;
|
||||
if (len >= HSHELL_CMD_LINE_NUM) {
|
||||
HSHELL_PRINTF("\r\n");
|
||||
len = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (len > 0) {
|
||||
HSHELL_PRINTF("\r\n");
|
||||
}
|
||||
}
|
||||
|
||||
static void ShellParse()
|
||||
{
|
||||
if (HVectorEmpty(cmdBuffer_)) {
|
||||
return ;
|
||||
}
|
||||
|
||||
uint8_t len = HShellLex((const uint8_t *)HVectorGetByteDataPtr(cmdBuffer_, 0), HVectorGetUseByteLen(cmdBuffer_), shellInfo_.cmdTokens, HSHELL_CMD_TOKEN_MAX);
|
||||
if (len <= 0) {
|
||||
LogD("lex parse len[%d] empty", len);
|
||||
return ;
|
||||
}
|
||||
|
||||
#ifdef HSHELL_USE_PASSWORD
|
||||
if (shellInfo_.password == 0 || shellInfo_.userName == 0) {
|
||||
shellInfo_.needPrint = 1;
|
||||
|
||||
// 这个状态下说明用户名输入错误, 无论输入什么都是失败
|
||||
if (shellInfo_.password == 1 && shellInfo_.userName == 0) {
|
||||
shellInfo_.password = 0;
|
||||
return ;
|
||||
}
|
||||
|
||||
// 输入用户名
|
||||
if (shellInfo_.userName == 0) {
|
||||
if (HShellDiffString(shellInfo_.cmdTokens, len, 0, "hdroot", 6, 0) == 0) {
|
||||
// 用户名错误, 给输入假的密码机会
|
||||
shellInfo_.password = 1;
|
||||
return ;
|
||||
}
|
||||
|
||||
shellInfo_.userName = 1;
|
||||
return ;
|
||||
}
|
||||
|
||||
if (shellInfo_.password == 0) {
|
||||
if (HShellDiffString(shellInfo_.cmdTokens, len, 0, "hd123", 5, 0) == 0) {
|
||||
shellInfo_.userName = 0;
|
||||
return ;
|
||||
}
|
||||
|
||||
shellInfo_.password = 1;
|
||||
return ;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
if (shellInfo_.cmdTokens[0].len == 1 && shellInfo_.cmdTokens[0].str[0] == '?') {
|
||||
PrintAllCmd();
|
||||
return ;
|
||||
}
|
||||
|
||||
for (int i = 0; i < HSHELL_CALL_MAX; ++i) {
|
||||
if (shellInfo_.shellCmd[i].match == NULL) {
|
||||
continue;
|
||||
}
|
||||
|
||||
HShellLenType key = HShellMatchToken(shellInfo_.cmdTokens, shellInfo_.shellCmd[i].match, shellInfo_.shellCmd[i].matchLen, shellInfo_.shellCmd[i].ignoreCase);
|
||||
if (key != HSHELL_ERROR_INDEX) {
|
||||
shellInfo_.shellCmd[i].call(key, shellInfo_.cmdTokens, len);
|
||||
return ;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void PrintCmdLine() {
|
||||
HVectorLenType len = HVectorGetUseLen(cmdBuffer_);
|
||||
HVectorSetData(cmdBuffer_, len, '\0');
|
||||
HSHELL_PRINTF("\r\033[K\033[1;32m > ");
|
||||
#ifdef HSHELL_USE_PASSWORD
|
||||
if (shellInfo_.password == 0 || shellInfo_.userName == 0) {
|
||||
// 用户已经输入
|
||||
if (shellInfo_.password == 1 && shellInfo_.userName == 0) {
|
||||
HSHELL_PRINTF("password: \033[0m");
|
||||
fflush(stdout);
|
||||
return ;
|
||||
}
|
||||
|
||||
// 输入用户名
|
||||
if (shellInfo_.userName == 0) {
|
||||
HSHELL_PRINTF("username: %s\033[0m", (const char *)HVectorGetByteDataPtr(cmdBuffer_, 0));
|
||||
if (shellInfo_.cursorPos < len) {
|
||||
HSHELL_PRINTF("\033[%dD", len - shellInfo_.cursorPos);
|
||||
}
|
||||
} else if (shellInfo_.password == 0) {
|
||||
HSHELL_PRINTF("password: \033[0m");
|
||||
}
|
||||
|
||||
fflush(stdout);
|
||||
return ;
|
||||
}
|
||||
#endif
|
||||
|
||||
HSHELL_PRINTF("%s\033[0m", (const char *)HVectorGetByteDataPtr(cmdBuffer_, 0));
|
||||
if (shellInfo_.cursorPos < len) {
|
||||
HSHELL_PRINTF("\033[%dD", len - shellInfo_.cursorPos);
|
||||
}
|
||||
|
||||
fflush(stdout);
|
||||
}
|
||||
|
||||
static void DeleteBeginByte() {
|
||||
if (shellInfo_.cursorPos <= 0) {
|
||||
return ;
|
||||
}
|
||||
|
||||
HVectorRemoveData(cmdBuffer_, shellInfo_.cursorPos - 1, 1);
|
||||
--shellInfo_.cursorPos;
|
||||
shellInfo_.needPrint = 1;
|
||||
}
|
||||
|
||||
static void DeleteAfterByte() {
|
||||
if (shellInfo_.cursorPos <= 0) {
|
||||
return ;
|
||||
}
|
||||
|
||||
if (shellInfo_.cursorPos >= HVectorGetUseLen(cmdBuffer_)) {
|
||||
return ;
|
||||
}
|
||||
|
||||
HVectorRemoveData(cmdBuffer_, shellInfo_.cursorPos, 1);
|
||||
shellInfo_.needPrint = 1;
|
||||
}
|
||||
|
||||
|
||||
static void AddCmdData(uint8_t data) {
|
||||
enum eEscStaus {
|
||||
kEscNone,
|
||||
kEsc,
|
||||
kEscCsi,
|
||||
kEscCsiDel,
|
||||
};
|
||||
|
||||
if (shellInfo_.run) {
|
||||
return ;
|
||||
}
|
||||
|
||||
switch (shellInfo_.escStatus) {
|
||||
case kEsc: {
|
||||
if (data == '[') {
|
||||
shellInfo_.escStatus = kEscCsi;
|
||||
return ;
|
||||
}
|
||||
} break;
|
||||
case kEscCsi: {
|
||||
switch (data) {
|
||||
case 'D': {
|
||||
// 左键
|
||||
if (shellInfo_.cursorPos > 0) {
|
||||
--shellInfo_.cursorPos;
|
||||
}
|
||||
|
||||
shellInfo_.needPrint = 1;
|
||||
shellInfo_.escStatus = kEscNone;
|
||||
} return ;
|
||||
case 'C': {
|
||||
// 右键
|
||||
if (shellInfo_.cursorPos < HVectorGetUseLen(cmdBuffer_)) {
|
||||
++shellInfo_.cursorPos;
|
||||
}
|
||||
|
||||
shellInfo_.needPrint = 1;
|
||||
shellInfo_.escStatus = kEscNone;
|
||||
} return ;
|
||||
case 'A': // 上键
|
||||
case 'B': // 下键
|
||||
shellInfo_.escStatus = kEscNone;
|
||||
return ;
|
||||
case '3': {
|
||||
shellInfo_.escStatus = kEscCsiDel;
|
||||
} return ;
|
||||
default: break;
|
||||
}
|
||||
} break;
|
||||
case kEscCsiDel: {
|
||||
shellInfo_.escStatus = kEscNone;
|
||||
if (data == '~') {
|
||||
DeleteAfterByte();
|
||||
return ;
|
||||
}
|
||||
} break;
|
||||
default: break;
|
||||
}
|
||||
|
||||
shellInfo_.escStatus = kEscNone;
|
||||
switch (data) {
|
||||
case 0x1b: shellInfo_.escStatus = kEsc; return ;
|
||||
case '\t': return ;
|
||||
case '\r':
|
||||
case '\n': {
|
||||
shellInfo_.run = 1;
|
||||
} return ;
|
||||
case '\b':
|
||||
case 0x7f: {
|
||||
DeleteBeginByte();
|
||||
} return ;
|
||||
default: break;
|
||||
}
|
||||
|
||||
if (isprint(data) == 0) {
|
||||
LogD("not print char[%x]", data);
|
||||
return ;
|
||||
}
|
||||
|
||||
if (HVectorInsertData(cmdBuffer_, shellInfo_.cursorPos, data) == 0) {
|
||||
LogD("buffer is full");
|
||||
return ;
|
||||
}
|
||||
|
||||
shellInfo_.cursorPos++;
|
||||
shellInfo_.needPrint = 1;
|
||||
}
|
||||
|
||||
uint8_t HShellLex(const uint8_t *str, int strLen, HShellCmdToken *tokens, int tokensLen) {
|
||||
if (str == NULL || tokens == NULL || tokensLen <= 0) {
|
||||
LogD("str[%p] is nullptr or Tokens[%p] is nullptr or len[%d]", str, tokens, tokensLen);
|
||||
@ -91,6 +336,51 @@ HShellLenType HShellMatchToken(const HShellCmdToken *token, const HShellMatch *m
|
||||
return HSHELL_ERROR_INDEX;
|
||||
}
|
||||
|
||||
uint8_t HShellDiffString(const HShellCmdToken *token, uint8_t tokenLen, uint8_t index, const char *str, uint8_t strLen, uint8_t ignoreCase) {
|
||||
if (token == NULL || tokenLen <= 0 || index >= tokenLen || str == NULL || strLen <= 0) {
|
||||
LogD("token[%p] or tokenLen[%d] or index[%d] or str[%p] or strLen[%d] is nullptr", token, tokenLen, index, str, strLen);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (token[index].str == NULL || token[index].len == 0) {
|
||||
LogD("token[%d] is empty or str[%p] is nullptr", index, token[index].str);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (token[index].len != strLen) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int (*cmpFunc)(const char *, const char *, size_t) = ignoreCase ? strncasecmp : strncmp;
|
||||
return cmpFunc((const char *)token[index].str, str, strLen) == 0 ? 1 : 0;
|
||||
}
|
||||
|
||||
uint8_t HSHellToUint32(const HShellCmdToken *token, uint8_t tokenLen, uint8_t index, uint32_t *value) {
|
||||
if (token == NULL || tokenLen <= 0 || value == NULL) {
|
||||
LogD("token[%p] or tokenLen[%d] or value[%p] is nullptr", token, tokenLen, value);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (index >= tokenLen) {
|
||||
LogD("index[%d] is out of range", index);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (token[index].str == NULL || token[index].len == 0) {
|
||||
LogD("token[%d] is empty or str[%p] is nullptr", index, token[index].str);
|
||||
return 0;
|
||||
}
|
||||
|
||||
char *endPtr = NULL;
|
||||
*value = strtol((const char *)token[index].str, &endPtr, 0);
|
||||
if (endPtr == (const char *)token[index].str || *endPtr != '\0') {
|
||||
LogD("token[%d] is not uint32", index);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int16_t HSHellRegister(const HShellMatch *matches, int matchLen, shellCall call, uint8_t ignoreCase) {
|
||||
if (matches == NULL || matchLen <= 0 || call == NULL) {
|
||||
LogD("matches[%p] or matchLen[%d] or call[%p] is nullptr", matches, matchLen, call);
|
||||
@ -98,19 +388,19 @@ int16_t HSHellRegister(const HShellMatch *matches, int matchLen, shellCall call,
|
||||
}
|
||||
|
||||
for (int i = 0; i < HSHELL_CALL_MAX; ++i) {
|
||||
if (shellCmd_[i].match == matches) {
|
||||
if (shellInfo_.shellCmd[i].match == matches) {
|
||||
LogD("call[%p] is exist, override write index[%d]", call, i);
|
||||
shellCmd_[i].call = call;
|
||||
shellCmd_[i].matchLen = matchLen;
|
||||
shellCmd_[i].ignoreCase = ignoreCase ? 1 : 0;
|
||||
shellInfo_.shellCmd[i].call = call;
|
||||
shellInfo_.shellCmd[i].matchLen = matchLen;
|
||||
shellInfo_.shellCmd[i].ignoreCase = ignoreCase ? 1 : 0;
|
||||
return i;
|
||||
}
|
||||
|
||||
if (shellCmd_[i].match == NULL) {
|
||||
shellCmd_[i].match = matches;
|
||||
shellCmd_[i].call = call;
|
||||
shellCmd_[i].matchLen = matchLen;
|
||||
shellCmd_[i].ignoreCase = ignoreCase ? 1 : 0;
|
||||
if (shellInfo_.shellCmd[i].match == NULL) {
|
||||
shellInfo_.shellCmd[i].match = matches;
|
||||
shellInfo_.shellCmd[i].call = call;
|
||||
shellInfo_.shellCmd[i].matchLen = matchLen;
|
||||
shellInfo_.shellCmd[i].ignoreCase = ignoreCase ? 1 : 0;
|
||||
return i;
|
||||
}
|
||||
}
|
||||
@ -125,125 +415,41 @@ void HSHellUnregister(int16_t index) {
|
||||
return;
|
||||
}
|
||||
|
||||
shellCmd_[index].match = NULL;
|
||||
shellCmd_[index].call = NULL;
|
||||
shellCmd_[index].matchLen = 0;
|
||||
}
|
||||
|
||||
static void ShellParse()
|
||||
{
|
||||
if (HVectorEmpty(cmdBuffer_)) {
|
||||
return ;
|
||||
}
|
||||
|
||||
uint8_t len = HShellLex((const uint8_t *)HVectorGetByteDataPtr(cmdBuffer_, 0), HVectorGetUseByteLen(cmdBuffer_), cmdTokens_, HSHELL_CMD_TOKEN_MAX);
|
||||
LogD("lex parse len[%d], dataLen[%d]", len, HVectorGetUseByteLen(cmdBuffer_));
|
||||
if (len <= 0) {
|
||||
LogD("lex parse len[%d] empty", len);
|
||||
return ;
|
||||
}
|
||||
|
||||
for (int i = 0; i < HSHELL_CALL_MAX; ++i) {
|
||||
if (shellCmd_[i].match == NULL) {
|
||||
continue;
|
||||
}
|
||||
|
||||
HShellLenType key = HShellMatchToken(cmdTokens_, shellCmd_[i].match, shellCmd_[i].matchLen, shellCmd_[i].ignoreCase);
|
||||
if (key != HSHELL_ERROR_INDEX) {
|
||||
shellCmd_[i].call(key, cmdTokens_, len);
|
||||
return ;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void PrintCmdData() {
|
||||
if (HVectorEmpty(cmdBuffer_)) {
|
||||
return ;
|
||||
}
|
||||
|
||||
HVectorSetData(cmdBuffer_, HVectorGetUseLen(cmdBuffer_), '\0');
|
||||
HSHELL_PRINTF("\r\x1b[K%s", (const char *)HVectorGetByteDataPtr(cmdBuffer_, 0));
|
||||
}
|
||||
|
||||
///< 返回1需要打印数据
|
||||
static uint8_t AddCmdData(uint8_t data) {
|
||||
enum eEscStaus {
|
||||
kEscNone,
|
||||
kEsc,
|
||||
kEscCsi,
|
||||
};
|
||||
|
||||
static uint8_t escStatus = kEscNone;
|
||||
switch (escStatus) {
|
||||
case kEsc: {
|
||||
if (data == '[') {
|
||||
escStatus = kEscCsi;
|
||||
return 0;
|
||||
}
|
||||
} break;
|
||||
case kEscCsi: {
|
||||
if (data == 'D') {
|
||||
// 左键
|
||||
if (cursorPos > 0) {
|
||||
--cursorPos;
|
||||
}
|
||||
return 0;
|
||||
} else if (data == 'C') {
|
||||
// 右键
|
||||
if (cursorPos < HVectorGetUseLen(cmdBuffer_)) {
|
||||
++cursorPos;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
} break;
|
||||
}
|
||||
|
||||
escStatus = kEscNone;
|
||||
switch (data) {
|
||||
case 0x1b: escStatus = kEsc; return 0;
|
||||
case '\t':
|
||||
case '\r': return 0;
|
||||
case '\n': {
|
||||
cursorPos = 0;
|
||||
ShellParse();
|
||||
HVectorClear(cmdBuffer_);
|
||||
} return 0;
|
||||
case '\b': {
|
||||
if (cursorPos > 0) {
|
||||
HVectorRemoveData(cmdBuffer_, cursorPos - 1, 1);
|
||||
cursorPos--;
|
||||
}
|
||||
} return 1;
|
||||
default: break;
|
||||
}
|
||||
|
||||
if (isprint(data) == 0) {
|
||||
LogD("not print char[%x]", data);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (HVectorInsertData(cmdBuffer_, cursorPos, data) == 0) {
|
||||
LogD("buffer is full");
|
||||
return 0;
|
||||
}
|
||||
|
||||
cursorPos++;
|
||||
return 1;
|
||||
shellInfo_.shellCmd[index].match = NULL;
|
||||
shellInfo_.shellCmd[index].call = NULL;
|
||||
shellInfo_.shellCmd[index].matchLen = 0;
|
||||
}
|
||||
|
||||
void HShellAddCmdData(uint8_t data) {
|
||||
if (AddCmdData(data)) {
|
||||
PrintCmdData();
|
||||
}
|
||||
AddCmdData(data);
|
||||
}
|
||||
|
||||
void HSHellAddCmdDatas(uint8_t *data, int len) {
|
||||
uint8_t needPrint = 0;
|
||||
void HSHellAddCmdDatas(const uint8_t *data, int len) {
|
||||
if (shellInfo_.run) {
|
||||
return ;
|
||||
}
|
||||
|
||||
for (int i = 0; i < len; ++i) {
|
||||
needPrint |= AddCmdData(data[i]);
|
||||
}
|
||||
|
||||
if (HVectorGetUseLen(cmdBuffer_) > 0 && needPrint) {
|
||||
PrintCmdData();
|
||||
AddCmdData(data[i]);
|
||||
}
|
||||
}
|
||||
|
||||
void HShellRun() {
|
||||
if (shellInfo_.needPrint) {
|
||||
PrintCmdLine();
|
||||
shellInfo_.needPrint = 0;
|
||||
}
|
||||
|
||||
if (shellInfo_.run == 0) {
|
||||
return ;
|
||||
}
|
||||
|
||||
HSHELL_PRINTFL("");
|
||||
ShellParse();
|
||||
HVectorClear(cmdBuffer_);
|
||||
HVectorSetData(cmdBuffer_, 0, '\0');
|
||||
PrintCmdLine();
|
||||
|
||||
shellInfo_.cursorPos = 0;
|
||||
shellInfo_.run = 0;
|
||||
}
|
||||
|
||||
@ -60,7 +60,7 @@ static void InitPage() {
|
||||
/** =================================================== */
|
||||
|
||||
|
||||
static void UpdateIndexEvent(uint8_t currPage, uint8_t isHideEvent, enum eUIPage nextPage) {
|
||||
static void UpdateIndexEvent(uint8_t currPage, uint8_t isHideEvent, HUiPageIndex_t nextPage) {
|
||||
// 非回退情况下, 保存索引
|
||||
pageManage.saveIndex = pageManage.isBack == 0;
|
||||
if (isHideEvent) {
|
||||
@ -76,7 +76,7 @@ static void UpdateIndexEvent(uint8_t currPage, uint8_t isHideEvent, enum eUIPage
|
||||
pageManage.saveIndex = 0;
|
||||
}
|
||||
|
||||
static uint8_t CheckPageIsNull(enum eUIPage page) {
|
||||
static uint8_t CheckPageIsNull(HUiPageIndex_t page) {
|
||||
if (pageManage.pageCall[page] == NULL) {
|
||||
LogD("Page[%d] is nullptr", page);
|
||||
return 0;
|
||||
@ -99,7 +99,7 @@ static uint8_t CheckSwitchPage() {
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void HideFreePage(enum eUIPage currPage, enum eUIPage nextPage) {
|
||||
static void HideFreePage(HUiPageIndex_t currPage, HUiPageIndex_t nextPage) {
|
||||
if (pageManage.isInit == 1) {
|
||||
// hide -> free -> update Page -> init -> show
|
||||
UpdateIndexEvent(currPage, 1, nextPage);
|
||||
@ -127,7 +127,7 @@ static void RecoveryUserDataFlag() {
|
||||
pageManage.modifyUserData = 0;
|
||||
}
|
||||
|
||||
static void SwitchPage(enum eUIPage page) {
|
||||
static void SwitchPage(HUiPageIndex_t page) {
|
||||
if (CheckPageIsNull(page) == 0) {
|
||||
LogD("Switch Page[%d] is nullptr", page);
|
||||
return ;
|
||||
@ -171,13 +171,13 @@ void HUIPageInit(initPageType_t initPage) {
|
||||
//SwitchPage(pageManage.homePage);
|
||||
}
|
||||
|
||||
void HUIPageSetHome(enum eUIPage page) {
|
||||
void HUIPageSetHome(HUiPageIndex_t page) {
|
||||
pageManage.homePage = page;
|
||||
}
|
||||
|
||||
// 切换页面, 当前页面入栈, 相同页面不操作, 需要检查栈, 栈存在就回栈清空之后的, 不存在就压栈
|
||||
// 因为有些页面可能不用HUIPageBack来返回, 所以需要兼容这种情况
|
||||
void HUIPageSwitch(enum eUIPage page) {
|
||||
void HUIPageSwitch(HUiPageIndex_t page) {
|
||||
if (page < 0 || page >= kUIPageMax) {
|
||||
LogD("page[%d] out of range", page);
|
||||
return ;
|
||||
@ -304,7 +304,7 @@ void _HUIPageAddStack(int len, ...) {
|
||||
|
||||
va_list args;
|
||||
va_start(args, len);
|
||||
enum eUIPage curr = va_arg(args, enum eUIPage);
|
||||
HUiPageIndex_t curr = va_arg(args, int);
|
||||
HByteLenType findPos = HByteStackFind(pageStack, curr);
|
||||
if (findPos != HBYTE_STACK_ERROR) {
|
||||
HByteStackSetUseLen(pageStack, findPos);
|
||||
@ -320,7 +320,7 @@ void _HUIPageAddStack(int len, ...) {
|
||||
findPos = HByteStackGetUseLen(pageStack);
|
||||
HByteStackPush(pageStack, curr);
|
||||
for (int i = 1; i < len; ++i) {
|
||||
curr = va_arg(args, enum eUIPage);
|
||||
curr = va_arg(args, int);
|
||||
if (curr < 0 || curr >= kUIPageMax) {
|
||||
LogD("page[%d] out of range", curr);
|
||||
continue;
|
||||
@ -373,17 +373,17 @@ uint8_t HUIPageGetCurrNotFree() {
|
||||
}
|
||||
|
||||
// 设置指定页面不释放内存
|
||||
void HUIPageSetNotFree(enum eUIPage page) {
|
||||
void HUIPageSetNotFree(HUiPageIndex_t page) {
|
||||
HBitSet(notFreeBit, page, 1);
|
||||
}
|
||||
|
||||
// 恢复指定页面默认释放内存
|
||||
void HUIPageResetFree(enum eUIPage page) {
|
||||
void HUIPageResetFree(HUiPageIndex_t page) {
|
||||
HBitSet(notFreeBit, page, 0);
|
||||
}
|
||||
|
||||
// 获取指定页面是否不释放
|
||||
uint8_t HUIPageGetNotFree(enum eUIPage page) {
|
||||
uint8_t HUIPageGetNotFree(HUiPageIndex_t page) {
|
||||
return HBitGet(notFreeBit, page);
|
||||
}
|
||||
|
||||
@ -430,12 +430,12 @@ uint8_t HUIPageGetIndex() {
|
||||
}
|
||||
|
||||
// 获取当前页面
|
||||
enum eUIPage HUIPageGetCurrPage() {
|
||||
HUiPageIndex_t HUIPageGetCurrPage() {
|
||||
return pageManage.currPage;
|
||||
}
|
||||
|
||||
// 获取上一个页面
|
||||
enum eUIPage HUIPageGetPrevPage() {
|
||||
HUiPageIndex_t HUIPageGetPrevPage() {
|
||||
return pageManage.prevPage;
|
||||
}
|
||||
|
||||
@ -455,7 +455,7 @@ uint8_t HUIPageIsBack() {
|
||||
}
|
||||
|
||||
// 检查该页面是否在返回栈, 是返回1, 否则返回0
|
||||
uint8_t HUIPageFindStack(enum eUIPage page) {
|
||||
uint8_t HUIPageFindStack(HUiPageIndex_t page) {
|
||||
return HByteStackFind(pageStack, page) != HBYTE_STACK_ERROR;
|
||||
}
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user