mirror of
https://github.com/NevermindZZT/letter-shell.git
synced 2025-01-21 10:02:54 +08:00
commit
6d6803e954
@ -1,8 +1,8 @@
|
||||
# letter shell 3.x
|
||||
|
||||
![version](https://img.shields.io/badge/version-3.1.0-brightgreen.svg)
|
||||
![version](https://img.shields.io/badge/version-3.1.1-brightgreen.svg)
|
||||
![standard](https://img.shields.io/badge/standard-c99-brightgreen.svg)
|
||||
![build](https://img.shields.io/badge/build-2021.05.24-brightgreen.svg)
|
||||
![build](https://img.shields.io/badge/build-2021.06.27-brightgreen.svg)
|
||||
![license](https://img.shields.io/badge/license-MIT-brightgreen.svg)
|
||||
|
||||
一个功能强大的嵌入式shell
|
||||
@ -165,6 +165,7 @@
|
||||
| SHELL_PARAMETER_MAX_NUMBER | shell命令参数最大数量 |
|
||||
| SHELL_HISTORY_MAX_NUMBER | 历史命令记录数量 |
|
||||
| SHELL_DOUBLE_CLICK_TIME | 双击间隔(ms) |
|
||||
| SHELL_QUICK_HELP | 快速帮助 |
|
||||
| SHELL_MAX_NUMBER | 管理的最大shell数量 |
|
||||
| SHELL_GET_TICK() | 获取系统时间(ms) |
|
||||
| SHELL_USING_LOCK | 是否使用锁 |
|
||||
@ -283,7 +284,7 @@ letter shell采取一个静态数组对定义的多个shell进行管理,shell
|
||||
|
||||
### 执行未导出函数
|
||||
|
||||
letter shell支持通过函数地址直接执行函数,可以方便执行那些没有导出,但是有临时需要使用的函数,使用命令`exec [addr] [args]`执行,使用此功能需要开启`SHELL_EXEC_UNDEF_FUNC`宏,注意,由于直接操作函数地址执行,如果给进的地址有误,可能引起程序崩溃
|
||||
letter shell支持通过函数地址直接执行函数,可以方便执行那些没有导出,但是又临时需要使用的函数,使用命令`exec [addr] [args]`执行,使用此功能需要开启`SHELL_EXEC_UNDEF_FUNC`宏,注意,由于直接操作函数地址执行,如果给进的地址有误,可能引起程序崩溃
|
||||
|
||||
函数的地址可以通过编译生成的文件查找,比如说对于keil,可以在`.map`文件中查找到每个函数的地址,对于keil,`.map`文件中的地址需要偏移一个字节,才可以成功执行,比如说`shellClear`函数地址为`0x08028620`,则通过`exec`执行应为`exec 0x08028621`
|
||||
|
||||
@ -297,7 +298,7 @@ letter shell 3.x将可执行的函数命令定义,用户定义,按键定义
|
||||
|
||||
letter shell 支持使用命令导出方式和命令表方式进行命令的添加,定义,通过宏```SHELL_USING_CMD_EXPORT```控制
|
||||
|
||||
命令导出方式支持keil,IAR(未测试)以及GCC
|
||||
命令导出方式支持keil,IAR以及GCC
|
||||
|
||||
1. 命令导出方式
|
||||
|
||||
|
@ -13,6 +13,7 @@
|
||||
#define __SHELL_CFG_H__
|
||||
|
||||
#include "stdlib.h"
|
||||
unsigned int userGetTick();
|
||||
|
||||
/**
|
||||
* @brief 是否使用默认shell任务while循环,使能宏`SHELL_USING_TASK`后此宏有意义
|
||||
@ -101,6 +102,12 @@
|
||||
*/
|
||||
#define SHELL_DOUBLE_CLICK_TIME 200
|
||||
|
||||
/**
|
||||
* @brief 快速帮助
|
||||
* 作用于双击tab的场景,当使能此宏时,双击tab不会对命令进行help补全,而是直接显示对应命令的帮助信息
|
||||
*/
|
||||
#define SHELL_QUICK_HELP 1
|
||||
|
||||
/**
|
||||
* @brief 管理的最大shell数量
|
||||
*/
|
||||
@ -124,7 +131,7 @@
|
||||
* 定义此宏为获取系统Tick,如`HAL_GetTick()`
|
||||
* @note 此宏不定义时无法使用双击tab补全命令help,无法使用shell超时锁定
|
||||
*/
|
||||
#define SHELL_GET_TICK() 0
|
||||
#define SHELL_GET_TICK() userGetTick()
|
||||
|
||||
/**
|
||||
* @brief 使用锁
|
||||
|
@ -18,6 +18,7 @@
|
||||
#include <unistd.h>
|
||||
#include <stddef.h>
|
||||
#include <string.h>
|
||||
#include <sys/time.h>
|
||||
|
||||
Shell shell;
|
||||
char shellBuffer[512];
|
||||
@ -28,6 +29,18 @@ Log log = {
|
||||
.level = LOG_DEBUG
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief 获取系统tick
|
||||
*
|
||||
* @return unsigned int 系统tick
|
||||
*/
|
||||
unsigned int userGetTick()
|
||||
{
|
||||
struct timeval tv;
|
||||
gettimeofday(&tv, NULL);
|
||||
return (tv.tv_sec * 1000 + tv.tv_usec / 1000) & 0x7FFFFFFF;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 日志写函数实现
|
||||
*
|
||||
@ -73,8 +86,8 @@ unsigned short userShellRead(char *data, unsigned short len)
|
||||
{
|
||||
*data++ = getchar();
|
||||
}
|
||||
system("stty icanon");
|
||||
system("stty echo");
|
||||
// system("stty icanon");
|
||||
// system("stty echo");
|
||||
return len;
|
||||
}
|
||||
|
||||
@ -142,8 +155,8 @@ void userShellInit(void)
|
||||
log.write = terminalLogWrite;
|
||||
logRegister(&log, &shell);
|
||||
|
||||
logDebug("hello world");
|
||||
logHexDump(LOG_ALL_OBJ, LOG_DEBUG, (void *)&shell, sizeof(shell));
|
||||
// logDebug("hello world");
|
||||
// logHexDump(LOG_ALL_OBJ, LOG_DEBUG, (void *)&shell, sizeof(shell));
|
||||
}
|
||||
|
||||
|
||||
|
@ -40,20 +40,21 @@ unsigned int shellPassthrough(Shell *shell, const char *prompt, ShellPassthrough
|
||||
{
|
||||
if (data == '\r' || data == '\n')
|
||||
{
|
||||
if (shell->parser.length == 0)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
shellWriteString(shell, "\r\n");
|
||||
shell->parser.buffer[shell->parser.length] = 0;
|
||||
handler(shell->parser.buffer, shell->parser.length);
|
||||
shell->parser.length = 0;
|
||||
shell->parser.cursor = 0;
|
||||
if (shell->parser.length != 0)
|
||||
{
|
||||
shell->parser.buffer[shell->parser.length] = 0;
|
||||
handler(shell->parser.buffer, shell->parser.length);
|
||||
shell->parser.length = 0;
|
||||
shell->parser.cursor = 0;
|
||||
}
|
||||
shellWriteString(shell, prompt);
|
||||
}
|
||||
else if (data == SHELL_PASSTHROUGH_EXIT_KEY)
|
||||
{
|
||||
shellWriteString(shell, "\r\n");
|
||||
shell->parser.length = 0;
|
||||
shell->parser.cursor = 0;
|
||||
return -1;
|
||||
}
|
||||
else
|
||||
|
65
src/shell.c
65
src/shell.c
@ -158,6 +158,7 @@ ShellCommand* shellSeekCommand(Shell *shell,
|
||||
const char *cmd,
|
||||
ShellCommand *base,
|
||||
unsigned short compareLength);
|
||||
static void shellWriteCommandHelp(Shell *shell, char *cmd);
|
||||
|
||||
/**
|
||||
* @brief shell 初始化
|
||||
@ -168,18 +169,21 @@ void shellInit(Shell *shell, char *buffer, unsigned short size)
|
||||
{
|
||||
shell->parser.length = 0;
|
||||
shell->parser.cursor = 0;
|
||||
shell->history.offset = 0;
|
||||
shell->history.number = 0;
|
||||
shell->history.record = 0;
|
||||
shell->info.user = NULL;
|
||||
shell->status.isChecked = 1;
|
||||
|
||||
shell->parser.buffer = buffer;
|
||||
shell->parser.bufferSize = size / (SHELL_HISTORY_MAX_NUMBER + 1);
|
||||
|
||||
#if SHELL_HISTORY_MAX_NUMBER > 0
|
||||
shell->history.offset = 0;
|
||||
shell->history.number = 0;
|
||||
shell->history.record = 0;
|
||||
for (short i = 0; i < SHELL_HISTORY_MAX_NUMBER; i++)
|
||||
{
|
||||
shell->history.item[i] = buffer + shell->parser.bufferSize * (i + 1);
|
||||
}
|
||||
#endif /** SHELL_HISTORY_MAX_NUMBER > 0 */
|
||||
|
||||
#if SHELL_USING_CMD_EXPORT == 1
|
||||
#if defined(__CC_ARM) || (defined(__ARMCC_VERSION) && __ARMCC_VERSION >= 6000000)
|
||||
@ -1271,6 +1275,7 @@ static void shellWriteReturnValue(Shell *shell, int value)
|
||||
}
|
||||
|
||||
|
||||
#if SHELL_HISTORY_MAX_NUMBER > 0
|
||||
/**
|
||||
* @brief shell历史记录添加
|
||||
*
|
||||
@ -1350,6 +1355,7 @@ static void shellHistory(Shell *shell, signed char dir)
|
||||
}
|
||||
|
||||
}
|
||||
#endif /** SHELL_HISTORY_MAX_NUMBER > 0 */
|
||||
|
||||
|
||||
/**
|
||||
@ -1382,7 +1388,9 @@ void shellExec(Shell *shell)
|
||||
|
||||
if (shell->status.isChecked)
|
||||
{
|
||||
#if SHELL_HISTORY_MAX_NUMBER > 0
|
||||
shellHistoryAdd(shell);
|
||||
#endif /** SHELL_HISTORY_MAX_NUMBER > 0 */
|
||||
shellParserParam(shell);
|
||||
shell->parser.length = shell->parser.cursor = 0;
|
||||
if (shell->parser.paramCount == 0)
|
||||
@ -1411,6 +1419,7 @@ void shellExec(Shell *shell)
|
||||
}
|
||||
|
||||
|
||||
#if SHELL_HISTORY_MAX_NUMBER > 0
|
||||
/**
|
||||
* @brief shell上方向键输入
|
||||
*
|
||||
@ -1433,6 +1442,7 @@ void shellDown(Shell *shell)
|
||||
shellHistory(shell, -1);
|
||||
}
|
||||
SHELL_EXPORT_KEY(SHELL_CMD_PERMISSION(0), 0x1B5B4200, shellDown, down);
|
||||
#endif /** SHELL_HISTORY_MAX_NUMBER > 0 */
|
||||
|
||||
|
||||
/**
|
||||
@ -1543,6 +1553,12 @@ void shellTab(Shell *shell)
|
||||
&& shell->status.tabFlag
|
||||
&& SHELL_GET_TICK() - shell->info.activeTime < SHELL_DOUBLE_CLICK_TIME)
|
||||
{
|
||||
#if SHELL_QUICK_HELP == 1
|
||||
shellWriteString(shell, "\r\n");
|
||||
shellWriteCommandHelp(shell, shell->parser.buffer);
|
||||
shellWritePrompt(shell, 1);
|
||||
shellWriteString(shell, shell->parser.buffer);
|
||||
#else
|
||||
shellClearCommandLine(shell);
|
||||
for (short i = shell->parser.length; i >= 0; i--)
|
||||
{
|
||||
@ -1553,6 +1569,7 @@ void shellTab(Shell *shell)
|
||||
shell->parser.length += 5;
|
||||
shell->parser.cursor = shell->parser.length;
|
||||
shellWriteString(shell, shell->parser.buffer);
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -1614,6 +1631,31 @@ SHELL_EXPORT_KEY(SHELL_CMD_PERMISSION(0)|SHELL_CMD_ENABLE_UNCHECKED,
|
||||
0x0D0A0000, shellEnter, enter);
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief shell 写命令帮助信息
|
||||
*
|
||||
* @param shell shell对象
|
||||
* @param cmd 命令字符串
|
||||
*/
|
||||
static void shellWriteCommandHelp(Shell *shell, char *cmd)
|
||||
{
|
||||
ShellCommand *command = shellSeekCommand(shell,
|
||||
cmd,
|
||||
shell->commandList.base,
|
||||
0);
|
||||
if (command)
|
||||
{
|
||||
shellWriteString(shell, shellText[SHELL_TEXT_HELP_HEADER]);
|
||||
shellWriteString(shell, shellGetCommandName(command));
|
||||
shellWriteString(shell, "\r\n");
|
||||
shellWriteString(shell, shellGetCommandDesc(command));
|
||||
shellWriteString(shell, "\r\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
shellWriteString(shell, shellText[SHELL_TEXT_CMD_NOT_FOUND]);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief shell help
|
||||
@ -1631,22 +1673,7 @@ void shellHelp(int argc, char *argv[])
|
||||
}
|
||||
else if (argc > 1)
|
||||
{
|
||||
ShellCommand *command = shellSeekCommand(shell,
|
||||
argv[1],
|
||||
shell->commandList.base,
|
||||
0);
|
||||
if (command)
|
||||
{
|
||||
shellWriteString(shell, shellText[SHELL_TEXT_HELP_HEADER]);
|
||||
shellWriteString(shell, shellGetCommandName(command));
|
||||
shellWriteString(shell, "\r\n");
|
||||
shellWriteString(shell, shellGetCommandDesc(command));
|
||||
shellWriteString(shell, "\r\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
shellWriteString(shell, shellText[SHELL_TEXT_CMD_NOT_FOUND]);
|
||||
}
|
||||
shellWriteCommandHelp(shell, argv[1]);
|
||||
}
|
||||
}
|
||||
SHELL_EXPORT_CMD(
|
||||
|
@ -14,7 +14,7 @@
|
||||
|
||||
#include "shell_cfg.h"
|
||||
|
||||
#define SHELL_VERSION "3.1.0" /**< 版本号 */
|
||||
#define SHELL_VERSION "3.1.1" /**< 版本号 */
|
||||
|
||||
|
||||
/**
|
||||
@ -341,6 +341,7 @@ typedef struct shell_def
|
||||
unsigned short paramCount; /**< 参数数量 */
|
||||
int keyValue; /**< 输入按键键值 */
|
||||
} parser;
|
||||
#if SHELL_HISTORY_MAX_NUMBER > 0
|
||||
struct
|
||||
{
|
||||
char *item[SHELL_HISTORY_MAX_NUMBER]; /**< 历史记录 */
|
||||
@ -348,6 +349,7 @@ typedef struct shell_def
|
||||
unsigned short record; /**< 当前记录位置 */
|
||||
signed short offset; /**< 当前历史记录偏移 */
|
||||
} history;
|
||||
#endif /** SHELL_HISTORY_MAX_NUMBER > 0 */
|
||||
struct
|
||||
{
|
||||
void *base; /**< 命令表基址 */
|
||||
|
@ -100,6 +100,13 @@
|
||||
*/
|
||||
#define SHELL_DOUBLE_CLICK_TIME 200
|
||||
|
||||
/**
|
||||
* @brief 快速帮助
|
||||
* 作用于双击tab的场景,当使能此宏时,双击tab不会对命令进行help补全,而是直接显示对应命令的帮助信息
|
||||
*/
|
||||
#define SHELL_QUICK_HELP 1
|
||||
|
||||
|
||||
/**
|
||||
* @brief 管理的最大shell数量
|
||||
*/
|
||||
|
Loading…
x
Reference in New Issue
Block a user