1
0
mirror of https://github.com/NevermindZZT/letter-shell.git synced 2025-01-21 10:02:54 +08:00
letter-shell/shell.c
Letter 2f30bd6674 优化在使用密码的情况下shell显示信息,提示符的逻辑
优化在使用密码的情况下shell显示信息,提示符的逻辑
删减部分代码
独立定义shell的提示性文本
2019-11-16 20:01:25 +08:00

1274 lines
32 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/**
* @file shell.c
* @author Letter (NevermindZZT@gmail.cn)
* @brief letter shell
* @version 2.0.0
* @date 2018-12-29
*
* @Copyright (c) 2018 Letter
*
*/
#include "shell.h"
#include "string.h"
#include "stdio.h"
#include "stdarg.h"
#if SHELL_AUTO_PRASE == 1
#include "shell_ext.h"
#endif
/**
* @brief shell提示信息文本索引
*/
enum
{
TEXT_INFO,
TEXT_PWD_HINT,
TEXT_PWD_RIGHT,
TEXT_PWD_ERROR,
TEXT_FUN_LIST,
TEXT_VAR_LIST,
TEXT_CMD_NONE,
TEXT_CMD_TOO_LONG,
TEXT_READ_NOT_DEF,
};
/**
* @brief shell提示信息文本
*/
static const char *shellText[] =
{
[TEXT_INFO] = "\r\n\r\n"
"+=========================================================+\r\n"
"| (C) COPYRIGHT 2019 Letter |\r\n"
"| Letter shell v"SHELL_VERSION" |\r\n"
"| Build: "__DATE__" "__TIME__" |\r\n"
"+=========================================================+\r\n",
[TEXT_PWD_HINT] = "\r\nPlease input password:",
[TEXT_PWD_RIGHT] = "\r\npassword confirm success.\r\n",
[TEXT_PWD_ERROR] = "\r\npassword confirm failed.\r\n",
[TEXT_FUN_LIST] = "\r\nCOMMAND LIST:\r\n\r\n",
[TEXT_VAR_LIST] = "\r\nVARIABLE LIST:\r\n\r\n",
[TEXT_CMD_NONE] = "Command not found\r\n",
[TEXT_CMD_TOO_LONG] = "\r\nWarnig: Command is too long\r\n",
[TEXT_READ_NOT_DEF] = "error: shell.read must be defined\r\n",
};
static SHELL_TypeDef *shellList[SHELL_MAX_NUMBER] = {NULL}; /**< shell列表 */
static void shellAdd(SHELL_TypeDef *shell);
static void shellDisplayItem(SHELL_TypeDef *shell, unsigned short index);
static void shellEnter(SHELL_TypeDef *shell);
static void shellTab(SHELL_TypeDef *shell);
static void shellBackspace(SHELL_TypeDef *shell);
static void shellAnsiStart(SHELL_TypeDef *shell);
#if SHELL_USING_VAR == 1
static void shellDisplayVariable(SHELL_TypeDef *shell, char *var);
void shellListVariables(void);
#endif /** SHELL_USING_VAR == 1 */
#if SHELL_USING_CMD_EXPORT != 1
/**
* @brief shell默认命令表
*
* @note 当使用命令表方式定义命令的时候,此表才会生效
* @note 添加命令时可使用SHELL_CMD_ITEM宏如SHELL_CMD_ITEM(help, shellHelp, command help)
* @note 可不使用默认命令表初始化完成之后可调用shellSetCommandList接口设置命令表
*/
const SHELL_CommandTypeDef shellDefaultCommandList[] =
{
SHELL_CMD_ITEM_EX(help, shellHelp, command help, help [command] --show help info of command),
#if SHELL_USING_VAR == 1
SHELL_CMD_ITEM(vars, shellListVariables, show vars),
SHELL_CMD_ITEM_EX(setVar, shellSetVariable, set var, setVar $[var] [value]),
#endif /** SHELL_USING_VAR == 1 */
SHELL_CMD_ITEM(cls, shellClear, clear command line),
};
#if SHELL_USING_VAR == 1
/**
* @brief shell默认变量表
*
*/
const SHELL_VaribaleTypeDef shellDefaultVariableList[] =
{
};
#endif /** SHELL_USING_VAR == 1 */
#endif /** SHELL_USING_CMD_EXPORT != 1 */
/**
* @brief 默认按键响应映射函数表
*
*/
const SHELL_KeyFunctionDef shellDefaultKeyFunctionList[] =
{
{SHELL_KEY_LF, shellEnter},
{SHELL_KEY_CR, shellEnter},
{SHELL_KEY_TAB, shellTab},
{SHELL_KEY_BACKSPACE, shellBackspace},
{SHELL_KEY_DELETE, shellBackspace},
{SHELL_KEY_ESC, shellAnsiStart},
};
/**
* @brief shell初始化
*
* @param shell shell对象
*/
void shellInit(SHELL_TypeDef *shell)
{
shell->length = 0;
shell->cursor = 0;
shell->historyCount = 0;
shell->historyFlag = 0;
shell->historyOffset = 0;
shell->status = SHELL_IN_NORMAL;
shell->command = SHELL_DEFAULT_COMMAND;
shell->isActive = 0;
shellAdd(shell);
#if SHELL_USING_AUTH == 1
shell->isPasswordConfirm = 0;
shellDisplay(shell, shellText[TEXT_PWD_HINT]);
#else
shellDisplay(shell, shellText[TEXT_INFO]);
shellDisplay(shell, shell->command);
#endif
#if SHELL_USING_CMD_EXPORT == 1
#if defined(__CC_ARM) || (defined(__ARMCC_VERSION) && __ARMCC_VERSION >= 6000000)
extern const unsigned int shellCommand$$Base;
extern const unsigned int shellCommand$$Limit;
extern const unsigned int shellVariable$$Base;
extern const unsigned int shellVariable$$Limit;
shell->commandBase = (SHELL_CommandTypeDef *)(&shellCommand$$Base);
shell->commandNumber = ((unsigned int)(&shellCommand$$Limit)
- (unsigned int)(&shellCommand$$Base))
/ sizeof(SHELL_CommandTypeDef);
#if SHELL_USING_VAR == 1
shell->variableBase = (SHELL_VaribaleTypeDef *)(&shellVariable$$Base);
shell->variableNumber = ((unsigned int)(&shellVariable$$Limit)
- (unsigned int)(&shellVariable$$Base))
/ sizeof(SHELL_VaribaleTypeDef);
#endif /** SHELL_USING_VAR == 1 */
#elif defined(__ICCARM__)
shell->commandBase = (SHELL_CommandTypeDef *)(__section_begin("shellCommand"));
shell->commandNumber = ((unsigned int)(__section_end("shellCommand"))
- (unsigned int)(__section_begin("shellCommand")))
/ sizeof(SHELL_CommandTypeDef);
#if SHELL_USING_VAR == 1
shell->variableBase = (SHELL_VaribaleTypeDef *)(__section_begin("shellVariable"));
shell->variableNumber = ((unsigned int)(__section_end("shellVariable"))
- (unsigned int)(__section_begin("shellVariable")))
/ sizeof(SHELL_VaribaleTypeDef);
#endif /** SHELL_USING_VAR == 1 */
#elif defined(__GNUC__)
extern const unsigned int _shell_command_start;
extern const unsigned int _shell_command_end;
shell->commandBase = (SHELL_CommandTypeDef *)(&_shell_command_start);
shell->commandNumber = ((unsigned int)(&_shell_command_end)
- (unsigned int)(&_shell_command_start))
/ sizeof(SHELL_CommandTypeDef);
#if SHELL_USING_VAR == 1
extern const unsigned int _shell_variable_start;
extern const unsigned int _shell_variable_end;
shell->variableBase = (SHELL_VaribaleTypeDef *)(&_shell_variable_start);
shell->variableNumber = ((unsigned int)(&_shell_variable_end)
- (unsigned int)(&_shell_variable_start))
/ sizeof(SHELL_VaribaleTypeDef);
#endif /** SHELL_USING_VAR == 1 */
#else
#error not supported compiler, please use command table mode
#endif
#else
shell->commandBase = (SHELL_CommandTypeDef *)shellDefaultCommandList;
shell->commandNumber = sizeof(shellDefaultCommandList) / sizeof(SHELL_CommandTypeDef);
#if SHELL_USING_VAR == 1
shell->variableBase = (SHELL_VaribaleTypeDef *)shellDefaultVariableList;
shell->variableNumber = sizeof(shellDefaultVariableList) / sizeof(SHELL_VaribaleTypeDef);
#endif /** SHELL_USING_VAR == 1 */
#endif
}
#if SHELL_USING_CMD_EXPORT != 1
/**
* @brief shell设置命令表
*
* @param shell shell对象
* @param base 命令表基址
* @param size 命令数量
*
* @note 此接口不可在shellInit之前调用
* @note 不调用此接口,则使用默认命令表或命令导出形成的命令表(取决于命令定义方式)
*/
void shellSetCommandList(SHELL_TypeDef *shell, SHELL_CommandTypeDef *base, unsigned short size)
{
shell->commandBase = base;
shell->commandNumber = size;
}
#if SHELL_USING_VAR == 1
/**
* @brief shell设置变量表
*
* @param shell shell对象
* @param base 变量表基址
* @param size 变量数量
*
* @note 此接口不可在shellInit之前调用
* @note 不调用此接口,则使用默认命令表或命令导出形成的命令表(取决于命令定义方式)
*/
void shellSetVariableList(SHELL_TypeDef *shell, SHELL_VaribaleTypeDef *base, unsigned short size)
{
shell->variableBase = base;
shell->variableNumber = size;
}
#endif /** SHELL_USING_VAR == 1 */
#endif /** SHELL_USING_CMD_EXPORT != 1 */
/**
* @brief shell设置按键响应
*
* @param shell shell对象
* @param base 按键响应表基址
* @param size 按键响应数量
*/
void shellSetKeyFuncList(SHELL_TypeDef *shell, SHELL_KeyFunctionDef *base, unsigned short size)
{
shell->keyFuncBase = (int)base;
shell->keyFuncNumber = size;
}
/**
* @brief 添加shell到shell列表
*
* @param shell shell对象
*/
static void shellAdd(SHELL_TypeDef *shell)
{
for (short i = 0; i < SHELL_MAX_NUMBER; i++)
{
if (shellList[i] == NULL)
{
shellList[i] = shell;
return;
}
}
}
/**
* @brief 获取当前活动shell
*
* @return SHELL_TypeDef* 当前活动shell对象
*/
SHELL_TypeDef *shellGetCurrent(void)
{
for (short i = 0; i < SHELL_MAX_NUMBER; i++)
{
if (shellList[i] != NULL && shellList[i]->isActive == 1)
{
return shellList[i];
}
}
return NULL;
}
#if SHELL_PRINT_BUFFER > 0
/**
* @brief shell格式化输出
*
* @param shell shell对象
* @param fmt 格式化字符串
* @param ... 参数
*/
void shellPrint(SHELL_TypeDef *shell, char *fmt, ...)
{
char buffer[SHELL_PRINT_BUFFER];
va_list vargs;
if (!shell)
{
return;
}
va_start(vargs, fmt);
vsnprintf(buffer, SHELL_PRINT_BUFFER - 1, fmt, vargs);
va_end(vargs);
shellDisplay(shell, buffer);
}
#endif
/**
* @brief shell显示字符串
*
* @param shell shell对象
* @param string 字符串
* @return unsigned short 字符串长度
*/
unsigned short shellDisplay(SHELL_TypeDef *shell, const char *string)
{
unsigned short count = 0;
if (shell->write == NULL)
{
return 0;
}
while(*string)
{
shell->write(*string++);
count ++;
}
return count;
}
/**
* @brief shell显示字符
*
* @param shell shel对象
* @param data 字符
*/
static void shellDisplayByte(SHELL_TypeDef *shell, char data)
{
if (shell->write == NULL)
{
return;
}
shell->write(data);
}
#if SHELL_USING_VAR == 1 || SHELL_DISPLAY_RETURN == 1
/**
* @brief shell显示值
*
* @param shell shell对象
* @param value 值
*/
static void shellDisplayValue(SHELL_TypeDef *shell, int value)
{
char str[11] = "0000000000";
unsigned int v = value;
char i = 10;
char tmp;
if (value < 0)
{
shellDisplay(shell, "-");
v = -v;
}
while (v)
{
str[--i] = v % 10 + 48;
v /= 10;
}
shellDisplay(shell, str + i - (value == 0));
v = value;
if (value < 0)
{
v = (unsigned int)value;
}
i = 8;
str[8] = 0;
while (v)
{
tmp = v & 0x0000000F;
str[--i] = (tmp > 9) ? (tmp + 87) : (tmp + 48);
v >>= 4;
}
shellDisplay(shell, ", 0x");
shellDisplay(shell, str);
shellDisplay(shell, "\r\n");
}
#endif
#if SHELL_DISPLAY_RETURN == 1
/**
* @brief shell显示函数调用返回值
*
* @param shell shel对象
* @param value 值
*/
static void shellDisplayReturn(SHELL_TypeDef *shell, int value)
{
shellDisplay(shell, "Return: ");
shellDisplayValue(shell, value);
}
#endif /** SHELL_DISPLAY_RETURN == 1 */
/**
* @brief shell字符串复制
*
* @param dest 目标字符串
* @param src 源字符串
* @return unsigned short 字符串长度
*/
static unsigned short shellStringCopy(char *dest, char* src)
{
unsigned short count = 0;
while (*(src + count))
{
*(dest + count) = *(src + count);
count++;
}
*(dest + count) = 0;
return count;
}
/**
* @brief shell字符串比较
*
* @param dest 目标字符串
* @param src 源字符串
* @return unsigned short 匹配长度
*/
static unsigned short shellStringCompare(char* dest, char *src)
{
unsigned short match = 0;
unsigned short i = 0;
while (*(dest +i) && *(src + i))
{
if (*(dest + i) != *(src +i))
{
break;
}
match ++;
i++;
}
return match;
}
/**
* @brief shell删除
*
* @param shell shell对象
* @param length 删除的长度
*/
static void shellDelete(SHELL_TypeDef *shell, unsigned short length)
{
while (length--)
{
shellDisplay(shell, "\b \b");
}
}
/**
* @brief shell清除输入
*
* @param shell shell对象
*/
static void shellClearLine(SHELL_TypeDef *shell)
{
for (short i = shell->length - shell->cursor; i > 0; i--)
{
shellDisplayByte(shell, ' ');
}
shellDelete(shell, shell->length);
}
/**
* @brief shell历史记录添加
*
* @param shell shell对象
*/
static void shellHistoryAdd(SHELL_TypeDef *shell)
{
shell->historyOffset = 0;
if (strcmp(shell->history[shell->historyFlag - 1], shell->buffer) == 0)
{
return;
}
if (shellStringCopy(shell->history[shell->historyFlag], shell->buffer) != 0)
{
shell->historyFlag++;
}
if (++shell->historyCount > SHELL_HISTORY_MAX_NUMBER)
{
shell->historyCount = SHELL_HISTORY_MAX_NUMBER;
}
if (shell->historyFlag >= SHELL_HISTORY_MAX_NUMBER)
{
shell->historyFlag = 0;
}
}
/**
* @brief shell历史记录查找
*
* @param shell shell对象
* @param dir 查找方向
*/
static void shellHistory(SHELL_TypeDef *shell, unsigned char dir)
{
if (dir == 0)
{
if (shell->historyOffset--
<= -((shell->historyCount > shell->historyFlag)
? shell->historyCount : shell->historyFlag))
{
shell->historyOffset = -((shell->historyCount > shell->historyFlag)
? shell->historyCount : shell->historyFlag);
}
}
else if (dir == 1)
{
if (++shell->historyOffset > 0)
{
shell->historyOffset = 0;
return;
}
}
else
{
return;
}
shellClearLine(shell);
if (shell->historyOffset == 0)
{
shell->cursor = shell->length = 0;
}
else
{
if ((shell->length = shellStringCopy(shell->buffer,
shell->history[(shell->historyFlag + SHELL_HISTORY_MAX_NUMBER
+ shell->historyOffset) % SHELL_HISTORY_MAX_NUMBER])) == 0)
{
return;
}
shell->cursor = shell->length;
shellDisplay(shell, shell->buffer);
}
}
/**
* @brief shell回车输入处理
*
* @param shell shell对象
*/
static void shellEnter(SHELL_TypeDef *shell)
{
unsigned char paramCount = 0;
unsigned char quotes = 0;
unsigned char record = 1;
SHELL_CommandTypeDef *base;
unsigned char runFlag = 0;
int returnValue;
(void) returnValue;
#if SHELL_USING_AUTH == 1
if(0 == shell->isPasswordConfirm)
{
if((shell->length != strlen(SHELL_USER_PASSWORD))
||(strncmp(shell->buffer, SHELL_USER_PASSWORD, strlen(SHELL_USER_PASSWORD)) != 0))
{
shellDisplay(shell, shellText[TEXT_PWD_ERROR]);
shellDisplay(shell, shellText[TEXT_PWD_HINT]);
}
else
{
shell->isPasswordConfirm = 1;
shellDisplay(shell, shellText[TEXT_PWD_RIGHT]);
shellDisplay(shell, shellText[TEXT_INFO]);
shellDisplay(shell, shell->command);
}
shell->length = 0;
shell->cursor = 0;
return;
}
#endif
if (shell->length == 0)
{
shellDisplay(shell, shell->command);
return;
}
*(shell->buffer + shell->length++) = 0;
shellHistoryAdd(shell);
for (unsigned short i = 0; i < shell->length; i++)
{
if ((quotes != 0 ||
(*(shell->buffer + i) != ' ' &&
*(shell->buffer + i) != '\t' &&
*(shell->buffer + i) != ',')) &&
*(shell->buffer + i) != 0)
{
if (*(shell->buffer + i) == '\"')
{
quotes = quotes ? 0 : 1;
#if SHELL_AUTO_PRASE == 0
*(shell->buffer + i) = 0;
continue;
#endif
}
if (record == 1)
{
shell->param[paramCount++] = shell->buffer + i;
record = 0;
}
if (*(shell->buffer + i) == '\\' &&
*(shell->buffer + i) != 0)
{
i++;
}
}
else
{
*(shell->buffer + i) = 0;
record = 1;
}
}
shell->length = 0;
shell->cursor = 0;
if (paramCount == 0)
{
shellDisplay(shell, shell->command);
return;
}
shellDisplay(shell, "\r\n");
base = shell->commandBase;
if (strcmp((const char *)shell->param[0], "help") == 0)
{
shell->isActive = 1;
shellHelp(paramCount, shell->param);
shell->isActive = 0;
shellDisplay(shell, shell->command);
return;
}
#if SHELL_USING_VAR == 1
if (shell->param[0][0] == '$')
{
shellDisplayVariable(shell, shell->param[0]);
shellDisplay(shell, shell->command);
return;
}
#endif /** SHELL_USING_VAR == 1 */
for (unsigned char i = 0; i < shell->commandNumber; i++)
{
if (strcmp((const char *)shell->param[0], (base + i)->name) == 0)
{
runFlag = 1;
shell->isActive = 1;
#if SHELL_AUTO_PRASE == 0
returnValue = (base + i)->function(paramCount, shell->param);
#else
returnValue = shellExtRun((base + i)->function, paramCount, shell->param);
#endif /** SHELL_AUTO_PRASE == 0 */
shell->isActive = 0;
#if SHELL_DISPLAY_RETURN == 1
shellDisplayReturn(shell, returnValue);
#endif /** SHELL_DISPLAY_RETURN == 1 */
break;
}
}
if (runFlag == 0)
{
shellDisplay(shell, shellText[TEXT_CMD_NONE]);
}
shellDisplay(shell, shell->command);
}
/**
* @brief shell退格输入处理
*
* @param shell shell对象
*/
static void shellBackspace(SHELL_TypeDef *shell)
{
if (shell->length == 0)
{
return;
}
if (shell->cursor == shell->length)
{
shell->length--;
shell->cursor--;
shell->buffer[shell->length] = 0;
shellDelete(shell, 1);
}
else if (shell->cursor > 0)
{
for (short i = 0; i < shell->length - shell->cursor; i++)
{
shell->buffer[shell->cursor + i - 1] = shell->buffer[shell->cursor + i];
}
shell->length--;
shell->cursor--;
shell->buffer[shell->length] = 0;
shellDisplayByte(shell, '\b');
for (short i = shell->cursor; i < shell->length; i++)
{
shellDisplayByte(shell, shell->buffer[i]);
}
shellDisplayByte(shell, ' ');
for (short i = shell->length - shell->cursor + 1; i > 0; i--)
{
shellDisplayByte(shell, '\b');
}
}
}
/**
* @brief shell Tab键输入处理
*
* @param shell shell对象
*/
static void shellTab(SHELL_TypeDef *shell)
{
unsigned short maxMatch = SHELL_COMMAND_MAX_LENGTH;
unsigned short lastMatchIndex = 0;
unsigned short matchNum = 0;
unsigned short length;
SHELL_CommandTypeDef *base = shell->commandBase;
if (shell->length != 0)
{
shell->buffer[shell->length] = 0;
for (short i = 0; i < shell->commandNumber; i++)
{
if (shellStringCompare(shell->buffer,
(char *)(base + i)->name)
== shell->length)
{
if (matchNum != 0)
{
if (matchNum == 1)
{
shellDisplay(shell, "\r\n");
}
shellDisplayItem(shell, lastMatchIndex);
length = shellStringCompare((char *)(base + lastMatchIndex)->name,
(char *)(base +i)->name);
maxMatch = (maxMatch > length) ? length : maxMatch;
}
lastMatchIndex = i;
matchNum ++;
}
}
if (matchNum == 0)
{
return;
}
if (matchNum == 1)
{
shellClearLine(shell);
}
if (matchNum != 0)
{
shell->length = shellStringCopy(shell->buffer,
(char *)(base + lastMatchIndex)->name);
}
if (matchNum > 1)
{
shellDisplayItem(shell, lastMatchIndex);
shellDisplay(shell, shell->command);
shell->length = maxMatch;
}
shell->buffer[shell->length] = 0;
shell->cursor = shell->length;
shellDisplay(shell, shell->buffer);
}
else
{
shell->isActive = 1;
shellHelp(1, (void *)0);
shell->isActive = 0;
shellDisplay(shell, shell->command);
}
#if SHELL_LONG_HELP == 1
static int time = 0;
if (SHELL_GET_TICK())
{
if (matchNum == 1 && SHELL_GET_TICK() - time < SHELL_DOUBLE_CLICK_TIME)
{
shellClearLine(shell);
for (short i = shell->length; i >= 0; i--)
{
shell->buffer[i + 5] = shell->buffer[i];
}
shellStringCopy(shell->buffer, "help");
shell->buffer[4] = ' ';
shell->length += 5;
shell->cursor = shell->length;
shellDisplay(shell, shell->buffer);
}
time = SHELL_GET_TICK();
}
#endif /** SHELL_LONG_HELP == 1 */
}
/**
* @brief shell正常按键处理
*
* @param shell shell对象
* @param data 输入的数据
*/
static void shellNormal(SHELL_TypeDef *shell, char data)
{
if (data == 0)
{
return;
}
if (shell->length < SHELL_COMMAND_MAX_LENGTH - 1)
{
if (shell->length == shell->cursor)
{
shell->buffer[shell->length++] = data;
shell->cursor++;
shellDisplayByte(shell, data);
}
else
{
for (short i = shell->length - shell->cursor; i > 0; i--)
{
shell->buffer[shell->cursor + i] = shell->buffer[shell->cursor + i - 1];
}
shell->buffer[shell->cursor++] = data;
shell->buffer[++shell->length] = 0;
for (short i = shell->cursor - 1; i < shell->length; i++)
{
shellDisplayByte(shell, shell->buffer[i]);
}
for (short i = shell->length - shell->cursor; i > 0; i--)
{
shellDisplayByte(shell, '\b');
}
}
}
else
{
shellDisplay(shell, shellText[TEXT_CMD_TOO_LONG]);
shellDisplay(shell, shell->command);
shellDisplay(shell, shell->buffer);
shell->cursor = shell->length;
}
}
/**
* @brief shell开始ansi控制序列
*
* @param shell shell对象
*/
static void shellAnsiStart(SHELL_TypeDef *shell)
{
shell->status = SHELL_ANSI_ESC;
}
/**
* @brief shell ansi控制序列处理
*
* @param shell shell对象
* @param data 输入的数据
*/
void shellAnsi(SHELL_TypeDef *shell, char data)
{
switch ((unsigned char)(shell->status))
{
case SHELL_ANSI_CSI:
switch (data)
{
case 0x41: /** 方向上键 */
shellHistory(shell, 0);
break;
case 0x42: /** 方向下键 */
shellHistory(shell, 1);
break;
case 0x43: /** 方向右键 */
if (shell->cursor < shell->length)
{
shellDisplayByte(shell, shell->buffer[shell->cursor]);
shell->cursor++;
}
break;
case 0x44: /** 方向左键 */
if (shell->cursor > 0)
{
shellDisplayByte(shell, '\b');
shell->cursor--;
}
break;
default:
break;
}
shell->status = SHELL_IN_NORMAL;
break;
case SHELL_ANSI_ESC:
if (data == 0x5B)
{
shell->status = SHELL_ANSI_CSI;
}
else
{
shell->status = SHELL_IN_NORMAL;
}
break;
default:
break;
}
}
/**
* @brief shell处理
*
* @param shell shell对象
* @param data 输入数据
*/
void shellHandler(SHELL_TypeDef *shell, char data)
{
if (shell->status == SHELL_IN_NORMAL)
{
char keyDefFind = 0;
SHELL_KeyFunctionDef *base = (SHELL_KeyFunctionDef *)shell->keyFuncBase;
#if SHELL_USING_AUTH == 1
if (shell->isPasswordConfirm == 1)
{
#endif
for (short i = 0; i < shell->keyFuncNumber; i++)
{
if (base[i].keyCode == data) {
if (base[i].keyFunction) {
base[i].keyFunction(shell);
}
keyDefFind = 1;
}
}
#if SHELL_USING_AUTH == 1
}
#endif
if (keyDefFind == 0)
{
for (short i = 0;
i < sizeof(shellDefaultKeyFunctionList) / sizeof(SHELL_KeyFunctionDef);
i++)
{
if (shellDefaultKeyFunctionList[i].keyCode == data) {
if (shellDefaultKeyFunctionList[i].keyFunction) {
shellDefaultKeyFunctionList[i].keyFunction(shell);
}
keyDefFind = 1;
}
}
}
if (keyDefFind == 0)
{
shellNormal(shell, data);
}
}
else
{
shellAnsi(shell, data);
}
}
#if SHELL_USING_TASK == 1
/**
* @brief shell 任务
*
* @param param shell对象
*
* @note 使用操作系统时定义的shell read函数必须是阻塞式的
* @note 不使用操作系统时可以通过不断查询的方式使用shell修改宏SHELL_TASK_WHILE
* 为0然后在主循环中不断调用此函数
*/
void shellTask(void *param)
{
SHELL_TypeDef *shell = (SHELL_TypeDef *)param;
char data;
if (shell->read == NULL)
{
shellDisplay(shell, shellText[TEXT_READ_NOT_DEF]);
while (1) ;
}
#if SHELL_TASK_WHILE == 1
while (1)
{
#endif
if (shell->read(&data) == 0)
{
shellInput(shell, data);
}
#if SHELL_TASK_WHILE == 1
}
#endif
}
#endif
#if SHELL_USING_VAR == 1
/**
* @brief shell获取变量
*
* @param shell shell对象
* @param var 参数
* @return int 变量值
*/
int shellGetVariable(SHELL_TypeDef *shell, char *var)
{
SHELL_VaribaleTypeDef *base = shell->variableBase;
int value = 0;
if (var[0] == '$')
{
var++;
}
for (short i = 0; i < shell->variableNumber; i++)
{
if (strcmp((const char *)var, (const char *)(base + i)->name) == 0)
{
switch ((base + i)->type)
{
case SHELL_VAR_INT:
value = *((int *)((base + i)->value));
break;
case SHELL_VAR_SHORT:
value = *((short *)((base + i)->value));
break;
case SHELL_VAR_CHAR:
value = *((char *)((base + i)->value));
break;
case SHELL_VAR_POINTER:
case SHELL_VAL:
value = (int)((base + i)->value);
default:
break;
}
}
}
return value;
}
/**
* @brief shell设置变量值
*
* @param var 变量
* @param value 值
*/
void shellSetVariable(char *var, int value)
{
SHELL_TypeDef *shell = shellGetCurrent();
char isVarFind = 0;
if (!shell)
{
return;
}
SHELL_VaribaleTypeDef *base = shell->variableBase;
for (short i = 0; i < shell->variableNumber; i++)
{
if (strcmp((const char *)var, (const char *)(base + i)->name) == 0)
{
switch ((base + i)->type)
{
case SHELL_VAR_INT:
*((int *)((base + i)->value)) = value;
break;
case SHELL_VAR_SHORT:
*((short *)((base + i)->value)) = value;
break;
case SHELL_VAR_CHAR:
*((char *)((base + i)->value)) = value;
break;
case SHELL_VAL:
shellDisplay(shell, "can't set val\r\n");
break;
default:
break;
}
isVarFind = 1;
}
}
if (!isVarFind)
{
shellDisplay(shell, "var not found\r\n");
}
else
{
shellDisplayVariable(shell, var);
}
}
SHELL_EXPORT_CMD_EX(setVar, shellSetVariable, set var, setVar $[var] [value]);
/**
* @brief shell显示变量
*
* @param shell shell对象
* @param var 变量
*/
static void shellDisplayVariable(SHELL_TypeDef *shell, char *var)
{
shellDisplay(shell, var[0] == '$' ? var + 1 : var);
shellDisplay(shell, " = ");
shellDisplayValue(shell, shellGetVariable(shell, var));
}
/**
* @brief shell显示所有变量
*
*/
void shellListVariables(void)
{
SHELL_TypeDef *shell = shellGetCurrent();
if (!shell)
{
return;
}
SHELL_VaribaleTypeDef *base = shell->variableBase;
unsigned short spaceLength;
shellDisplay(shell, shellText[TEXT_VAR_LIST]);
for (short i = 0; i < shell->variableNumber; i++)
{
spaceLength = 22 - shellDisplay(shell, (base + i)->name);
spaceLength = (spaceLength > 0) ? spaceLength : 4;
do {
shellDisplay(shell, " ");
} while (--spaceLength);
shellDisplay(shell, "--");
shellDisplay(shell, (base + i)->desc);
shellDisplay(shell, "\r\n");
}
}
SHELL_EXPORT_CMD(vars, shellListVariables, show vars);
#endif /** SHELL_USING_VAR == 1 */
/**
* @brief shell显示一条命令信息
*
* @param shell shell对象
* @param index 要显示的命令索引
*/
static void shellDisplayItem(SHELL_TypeDef *shell, unsigned short index)
{
unsigned short spaceLength;
SHELL_CommandTypeDef *base = shell->commandBase;
spaceLength = 22 - shellDisplay(shell, (base + index)->name);
spaceLength = (spaceLength > 0) ? spaceLength : 4;
do {
shellDisplay(shell, " ");
} while (--spaceLength);
shellDisplay(shell, "--");
shellDisplay(shell, (base + index)->desc);
shellDisplay(shell, "\r\n");
}
/**
* @brief shell帮助
*
* @param argc 参数个数
* @param argv 参数
*/
void shellHelp(int argc, char *argv[])
{
SHELL_TypeDef *shell = shellGetCurrent();
if (!shell)
{
return;
}
#if SHELL_LONG_HELP == 1
if (argc == 1)
{
#endif /** SHELL_LONG_HELP == 1 */
shellDisplay(shell, shellText[TEXT_FUN_LIST]);
for(unsigned short i = 0; i < shell->commandNumber; i++)
{
shellDisplayItem(shell, i);
}
#if SHELL_LONG_HELP == 1
}
else if (argc == 2) {
SHELL_CommandTypeDef *base = shell->commandBase;
for (unsigned char i = 0; i < shell->commandNumber; i++)
{
if (strcmp((const char *)argv[1], (base + i)->name) == 0)
{
shellDisplay(shell, "command help --");
shellDisplay(shell, (base + i)->name);
shellDisplay(shell, ":\r\n");
shellDisplay(shell, (base + i)->desc);
shellDisplay(shell, "\r\n");
if ((base + i)->help)
{
shellDisplay(shell, (base + i)->help);
shellDisplay(shell, "\r\n");
}
return;
}
}
shellDisplay(shell, shellText[TEXT_CMD_NONE]);
}
#endif /** SHELL_LONG_HELP == 1 */
}
SHELL_EXPORT_CMD_EX(help, shellHelp, command help, help [command] --show help info of command);
/**
* @brief 清空命令行
*
*/
void shellClear(void)
{
SHELL_TypeDef *shell = shellGetCurrent();
if (!shell)
{
return;
}
shellDisplay(shell, "\033[2J\033[1H");
}
SHELL_EXPORT_CMD(cls, shellClear, clear command line);