Skip to content

Commit 6d6803e

Browse files
authored
Merge pull request #92 from NevermindZZT/shell3.1
Shell3.1.1
2 parents abba67c + a34f08a commit 6d6803e

File tree

7 files changed

+94
-36
lines changed

7 files changed

+94
-36
lines changed

README.md

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
# letter shell 3.x
22

3-
![version](https://img.shields.io/badge/version-3.1.0-brightgreen.svg)
3+
![version](https://img.shields.io/badge/version-3.1.1-brightgreen.svg)
44
![standard](https://img.shields.io/badge/standard-c99-brightgreen.svg)
5-
![build](https://img.shields.io/badge/build-2021.05.24-brightgreen.svg)
5+
![build](https://img.shields.io/badge/build-2021.06.27-brightgreen.svg)
66
![license](https://img.shields.io/badge/license-MIT-brightgreen.svg)
77

88
一个功能强大的嵌入式shell
@@ -165,6 +165,7 @@
165165
| SHELL_PARAMETER_MAX_NUMBER | shell命令参数最大数量 |
166166
| SHELL_HISTORY_MAX_NUMBER | 历史命令记录数量 |
167167
| SHELL_DOUBLE_CLICK_TIME | 双击间隔(ms) |
168+
| SHELL_QUICK_HELP | 快速帮助 |
168169
| SHELL_MAX_NUMBER | 管理的最大shell数量 |
169170
| SHELL_GET_TICK() | 获取系统时间(ms) |
170171
| SHELL_USING_LOCK | 是否使用锁 |
@@ -283,7 +284,7 @@ letter shell采取一个静态数组对定义的多个shell进行管理,shell
283284
284285
### 执行未导出函数
285286
286-
letter shell支持通过函数地址直接执行函数,可以方便执行那些没有导出,但是有临时需要使用的函数,使用命令`exec [addr] [args]`执行,使用此功能需要开启`SHELL_EXEC_UNDEF_FUNC`宏,注意,由于直接操作函数地址执行,如果给进的地址有误,可能引起程序崩溃
287+
letter shell支持通过函数地址直接执行函数,可以方便执行那些没有导出,但是又临时需要使用的函数,使用命令`exec [addr] [args]`执行,使用此功能需要开启`SHELL_EXEC_UNDEF_FUNC`宏,注意,由于直接操作函数地址执行,如果给进的地址有误,可能引起程序崩溃
287288
288289
函数的地址可以通过编译生成的文件查找,比如说对于keil,可以在`.map`文件中查找到每个函数的地址,对于keil,`.map`文件中的地址需要偏移一个字节,才可以成功执行,比如说`shellClear`函数地址为`0x08028620`,则通过`exec`执行应为`exec 0x08028621`
289290
@@ -297,7 +298,7 @@ letter shell 3.x将可执行的函数命令定义,用户定义,按键定义
297298
298299
letter shell 支持使用命令导出方式和命令表方式进行命令的添加,定义,通过宏```SHELL_USING_CMD_EXPORT```控制
299300
300-
命令导出方式支持keil,IAR(未测试)以及GCC
301+
命令导出方式支持keil,IAR以及GCC
301302
302303
1. 命令导出方式
303304

demo/x86-gcc/shell_cfg.h

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
#define __SHELL_CFG_H__
1414

1515
#include "stdlib.h"
16+
unsigned int userGetTick();
1617

1718
/**
1819
* @brief 是否使用默认shell任务while循环,使能宏`SHELL_USING_TASK`后此宏有意义
@@ -101,6 +102,12 @@
101102
*/
102103
#define SHELL_DOUBLE_CLICK_TIME 200
103104

105+
/**
106+
* @brief 快速帮助
107+
* 作用于双击tab的场景,当使能此宏时,双击tab不会对命令进行help补全,而是直接显示对应命令的帮助信息
108+
*/
109+
#define SHELL_QUICK_HELP 1
110+
104111
/**
105112
* @brief 管理的最大shell数量
106113
*/
@@ -124,7 +131,7 @@
124131
* 定义此宏为获取系统Tick,如`HAL_GetTick()`
125132
* @note 此宏不定义时无法使用双击tab补全命令help,无法使用shell超时锁定
126133
*/
127-
#define SHELL_GET_TICK() 0
134+
#define SHELL_GET_TICK() userGetTick()
128135

129136
/**
130137
* @brief 使用锁

demo/x86-gcc/shell_port.c

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
#include <unistd.h>
1919
#include <stddef.h>
2020
#include <string.h>
21+
#include <sys/time.h>
2122

2223
Shell shell;
2324
char shellBuffer[512];
@@ -28,6 +29,18 @@ Log log = {
2829
.level = LOG_DEBUG
2930
};
3031

32+
/**
33+
* @brief 获取系统tick
34+
*
35+
* @return unsigned int 系统tick
36+
*/
37+
unsigned int userGetTick()
38+
{
39+
struct timeval tv;
40+
gettimeofday(&tv, NULL);
41+
return (tv.tv_sec * 1000 + tv.tv_usec / 1000) & 0x7FFFFFFF;
42+
}
43+
3144
/**
3245
* @brief 日志写函数实现
3346
*
@@ -73,8 +86,8 @@ unsigned short userShellRead(char *data, unsigned short len)
7386
{
7487
*data++ = getchar();
7588
}
76-
system("stty icanon");
77-
system("stty echo");
89+
// system("stty icanon");
90+
// system("stty echo");
7891
return len;
7992
}
8093

@@ -142,8 +155,8 @@ void userShellInit(void)
142155
log.write = terminalLogWrite;
143156
logRegister(&log, &shell);
144157

145-
logDebug("hello world");
146-
logHexDump(LOG_ALL_OBJ, LOG_DEBUG, (void *)&shell, sizeof(shell));
158+
// logDebug("hello world");
159+
// logHexDump(LOG_ALL_OBJ, LOG_DEBUG, (void *)&shell, sizeof(shell));
147160
}
148161

149162

extensions/shell_enhance/shell_passthrough.c

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -40,20 +40,21 @@ unsigned int shellPassthrough(Shell *shell, const char *prompt, ShellPassthrough
4040
{
4141
if (data == '\r' || data == '\n')
4242
{
43-
if (shell->parser.length == 0)
43+
shellWriteString(shell, "\r\n");
44+
if (shell->parser.length != 0)
4445
{
45-
continue;
46+
shell->parser.buffer[shell->parser.length] = 0;
47+
handler(shell->parser.buffer, shell->parser.length);
48+
shell->parser.length = 0;
49+
shell->parser.cursor = 0;
4650
}
47-
shellWriteString(shell, "\r\n");
48-
shell->parser.buffer[shell->parser.length] = 0;
49-
handler(shell->parser.buffer, shell->parser.length);
50-
shell->parser.length = 0;
51-
shell->parser.cursor = 0;
5251
shellWriteString(shell, prompt);
5352
}
5453
else if (data == SHELL_PASSTHROUGH_EXIT_KEY)
5554
{
5655
shellWriteString(shell, "\r\n");
56+
shell->parser.length = 0;
57+
shell->parser.cursor = 0;
5758
return -1;
5859
}
5960
else

src/shell.c

Lines changed: 46 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -158,6 +158,7 @@ ShellCommand* shellSeekCommand(Shell *shell,
158158
const char *cmd,
159159
ShellCommand *base,
160160
unsigned short compareLength);
161+
static void shellWriteCommandHelp(Shell *shell, char *cmd);
161162

162163
/**
163164
* @brief shell 初始化
@@ -168,18 +169,21 @@ void shellInit(Shell *shell, char *buffer, unsigned short size)
168169
{
169170
shell->parser.length = 0;
170171
shell->parser.cursor = 0;
171-
shell->history.offset = 0;
172-
shell->history.number = 0;
173-
shell->history.record = 0;
174172
shell->info.user = NULL;
175173
shell->status.isChecked = 1;
176174

177175
shell->parser.buffer = buffer;
178176
shell->parser.bufferSize = size / (SHELL_HISTORY_MAX_NUMBER + 1);
177+
178+
#if SHELL_HISTORY_MAX_NUMBER > 0
179+
shell->history.offset = 0;
180+
shell->history.number = 0;
181+
shell->history.record = 0;
179182
for (short i = 0; i < SHELL_HISTORY_MAX_NUMBER; i++)
180183
{
181184
shell->history.item[i] = buffer + shell->parser.bufferSize * (i + 1);
182185
}
186+
#endif /** SHELL_HISTORY_MAX_NUMBER > 0 */
183187

184188
#if SHELL_USING_CMD_EXPORT == 1
185189
#if defined(__CC_ARM) || (defined(__ARMCC_VERSION) && __ARMCC_VERSION >= 6000000)
@@ -1271,6 +1275,7 @@ static void shellWriteReturnValue(Shell *shell, int value)
12711275
}
12721276

12731277

1278+
#if SHELL_HISTORY_MAX_NUMBER > 0
12741279
/**
12751280
* @brief shell历史记录添加
12761281
*
@@ -1350,6 +1355,7 @@ static void shellHistory(Shell *shell, signed char dir)
13501355
}
13511356

13521357
}
1358+
#endif /** SHELL_HISTORY_MAX_NUMBER > 0 */
13531359

13541360

13551361
/**
@@ -1382,7 +1388,9 @@ void shellExec(Shell *shell)
13821388

13831389
if (shell->status.isChecked)
13841390
{
1391+
#if SHELL_HISTORY_MAX_NUMBER > 0
13851392
shellHistoryAdd(shell);
1393+
#endif /** SHELL_HISTORY_MAX_NUMBER > 0 */
13861394
shellParserParam(shell);
13871395
shell->parser.length = shell->parser.cursor = 0;
13881396
if (shell->parser.paramCount == 0)
@@ -1411,6 +1419,7 @@ void shellExec(Shell *shell)
14111419
}
14121420

14131421

1422+
#if SHELL_HISTORY_MAX_NUMBER > 0
14141423
/**
14151424
* @brief shell上方向键输入
14161425
*
@@ -1433,6 +1442,7 @@ void shellDown(Shell *shell)
14331442
shellHistory(shell, -1);
14341443
}
14351444
SHELL_EXPORT_KEY(SHELL_CMD_PERMISSION(0), 0x1B5B4200, shellDown, down);
1445+
#endif /** SHELL_HISTORY_MAX_NUMBER > 0 */
14361446

14371447

14381448
/**
@@ -1543,6 +1553,12 @@ void shellTab(Shell *shell)
15431553
&& shell->status.tabFlag
15441554
&& SHELL_GET_TICK() - shell->info.activeTime < SHELL_DOUBLE_CLICK_TIME)
15451555
{
1556+
#if SHELL_QUICK_HELP == 1
1557+
shellWriteString(shell, "\r\n");
1558+
shellWriteCommandHelp(shell, shell->parser.buffer);
1559+
shellWritePrompt(shell, 1);
1560+
shellWriteString(shell, shell->parser.buffer);
1561+
#else
15461562
shellClearCommandLine(shell);
15471563
for (short i = shell->parser.length; i >= 0; i--)
15481564
{
@@ -1553,6 +1569,7 @@ void shellTab(Shell *shell)
15531569
shell->parser.length += 5;
15541570
shell->parser.cursor = shell->parser.length;
15551571
shellWriteString(shell, shell->parser.buffer);
1572+
#endif
15561573
}
15571574
else
15581575
{
@@ -1614,6 +1631,31 @@ SHELL_EXPORT_KEY(SHELL_CMD_PERMISSION(0)|SHELL_CMD_ENABLE_UNCHECKED,
16141631
0x0D0A0000, shellEnter, enter);
16151632
#endif
16161633

1634+
/**
1635+
* @brief shell 写命令帮助信息
1636+
*
1637+
* @param shell shell对象
1638+
* @param cmd 命令字符串
1639+
*/
1640+
static void shellWriteCommandHelp(Shell *shell, char *cmd)
1641+
{
1642+
ShellCommand *command = shellSeekCommand(shell,
1643+
cmd,
1644+
shell->commandList.base,
1645+
0);
1646+
if (command)
1647+
{
1648+
shellWriteString(shell, shellText[SHELL_TEXT_HELP_HEADER]);
1649+
shellWriteString(shell, shellGetCommandName(command));
1650+
shellWriteString(shell, "\r\n");
1651+
shellWriteString(shell, shellGetCommandDesc(command));
1652+
shellWriteString(shell, "\r\n");
1653+
}
1654+
else
1655+
{
1656+
shellWriteString(shell, shellText[SHELL_TEXT_CMD_NOT_FOUND]);
1657+
}
1658+
}
16171659

16181660
/**
16191661
* @brief shell help
@@ -1631,22 +1673,7 @@ void shellHelp(int argc, char *argv[])
16311673
}
16321674
else if (argc > 1)
16331675
{
1634-
ShellCommand *command = shellSeekCommand(shell,
1635-
argv[1],
1636-
shell->commandList.base,
1637-
0);
1638-
if (command)
1639-
{
1640-
shellWriteString(shell, shellText[SHELL_TEXT_HELP_HEADER]);
1641-
shellWriteString(shell, shellGetCommandName(command));
1642-
shellWriteString(shell, "\r\n");
1643-
shellWriteString(shell, shellGetCommandDesc(command));
1644-
shellWriteString(shell, "\r\n");
1645-
}
1646-
else
1647-
{
1648-
shellWriteString(shell, shellText[SHELL_TEXT_CMD_NOT_FOUND]);
1649-
}
1676+
shellWriteCommandHelp(shell, argv[1]);
16501677
}
16511678
}
16521679
SHELL_EXPORT_CMD(

src/shell.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414

1515
#include "shell_cfg.h"
1616

17-
#define SHELL_VERSION "3.1.0" /**< 版本号 */
17+
#define SHELL_VERSION "3.1.1" /**< 版本号 */
1818

1919

2020
/**
@@ -341,13 +341,15 @@ typedef struct shell_def
341341
unsigned short paramCount; /**< 参数数量 */
342342
int keyValue; /**< 输入按键键值 */
343343
} parser;
344+
#if SHELL_HISTORY_MAX_NUMBER > 0
344345
struct
345346
{
346347
char *item[SHELL_HISTORY_MAX_NUMBER]; /**< 历史记录 */
347348
unsigned short number; /**< 历史记录数 */
348349
unsigned short record; /**< 当前记录位置 */
349350
signed short offset; /**< 当前历史记录偏移 */
350351
} history;
352+
#endif /** SHELL_HISTORY_MAX_NUMBER > 0 */
351353
struct
352354
{
353355
void *base; /**< 命令表基址 */

src/shell_cfg.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,13 @@
100100
*/
101101
#define SHELL_DOUBLE_CLICK_TIME 200
102102

103+
/**
104+
* @brief 快速帮助
105+
* 作用于双击tab的场景,当使能此宏时,双击tab不会对命令进行help补全,而是直接显示对应命令的帮助信息
106+
*/
107+
#define SHELL_QUICK_HELP 1
108+
109+
103110
/**
104111
* @brief 管理的最大shell数量
105112
*/

0 commit comments

Comments
 (0)