修改配置文件,支持历史记录和变量为0
This commit is contained in:
parent
42af1b6e78
commit
a586080941
|
@ -4,6 +4,7 @@
|
|||
*DebugConfig/
|
||||
*Listings/
|
||||
*OBJ/
|
||||
*example/arduino/src
|
||||
|
||||
example/stm32/qemu/qemu_stm32
|
||||
|
||||
|
|
|
@ -38,7 +38,8 @@
|
|||
"stdio.h": "c",
|
||||
"xnr_line.h": "c",
|
||||
"errno.h": "c",
|
||||
"stdint.h": "c"
|
||||
"stdint.h": "c",
|
||||
"*.xcmd_confg": "c"
|
||||
},
|
||||
"cmake.sourceDirectory": "/home/hqm/project/xcmd/example/esp_idf",
|
||||
"MicroPython.executeButton": [
|
||||
|
|
90
README.md
90
README.md
|
@ -1,5 +1,5 @@
|
|||
# xcmd
|
||||
|
||||
[English Version](./README.en.md)s
|
||||
#### 效果展示
|
||||
|
||||
![输入图片说明](https://images.gitee.com/uploads/images/2021/0922/220957_66faa768_1680380.gif "演示1.gif")
|
||||
|
@ -16,13 +16,11 @@ xcmd是一款单片机命令行工具,移植十分方便,并且对flash与ra
|
|||
6. **支持 `xcmd_cmd_register()/xcmd_key_register`方法注册命令或按键**
|
||||
7. **支持 `XCMD_EXPORT_CMD()/XCMD_EXPORT_KEY()`方法直接导出命令或按键,不需要额外运行注册函数**
|
||||
|
||||
#### 支持的平台
|
||||
#### 支持的平台示例
|
||||
|
||||
1. linux
|
||||
2. arduino
|
||||
3. stm32
|
||||
4. esp32
|
||||
5. qemu-stm32
|
||||
3. esp32
|
||||
|
||||
#### 测试过的串口软件
|
||||
|
||||
|
@ -50,34 +48,38 @@ xcmd是一款单片机命令行工具,移植十分方便,并且对flash与ra
|
|||
|
||||
```C
|
||||
/* 例如移植到Arduino平台 */
|
||||
int cmd_get_char(uint8_t *ch)
|
||||
#include "src/xcmd.h"
|
||||
#include "arduino_xcmd.h"
|
||||
#include <Arduino.h>
|
||||
|
||||
xcmder_t xcmder;
|
||||
|
||||
static int io_write(int fd, const char *buf, size_t len)
|
||||
{
|
||||
if(Serial.available())
|
||||
{
|
||||
*ch = Serial.read();
|
||||
return 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
Serial.write(buf, len);
|
||||
return len;
|
||||
}
|
||||
|
||||
int cmd_put_char(uint8_t ch)
|
||||
static int io_read(int fd, char *buf, size_t len)
|
||||
{
|
||||
Serial.write(ch);
|
||||
return 1;
|
||||
int i=0;
|
||||
while (Serial.available() > 0)
|
||||
{
|
||||
buf[i++] = (char)Serial.read();
|
||||
}
|
||||
return i;
|
||||
}
|
||||
|
||||
void setup() {
|
||||
Serial.begin(115200);
|
||||
xcmd_init(cmd_get_char, cmd_put_char);
|
||||
xcmd_init(&xcmder, io_write, io_read);
|
||||
}
|
||||
|
||||
void loop() {
|
||||
|
||||
xcmd_task();
|
||||
xcmd_task(&xcmder);
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
#### 配置
|
||||
|
@ -87,12 +89,50 @@ void loop() {
|
|||
**注意**: 如果不知道如何修改连接脚本,建议不要使能ENABLE_XCMD_EXPORT。不使能ENABLE_XCMD_EXPORT的情况下有更好的兼容性移植更加简单
|
||||
|
||||
```C
|
||||
#define XCMD_LINE_MAX_LENGTH (128) /* 命令行支持的最大字符数 */
|
||||
#define XCMD_HISTORY_MAX_NUM (16) /* 支持的历史记录个数, 这个参数对内存的影响很大,建议arduino设置为0,0为不支持 */
|
||||
#ifndef XCMD_LINE_MAX_LENGTH
|
||||
#define XCMD_LINE_MAX_LENGTH (32) /* 命令行支持的最大字符数 */
|
||||
#endif
|
||||
|
||||
#ifndef XCMD_PRINT_BUF_MAX_LENGTH
|
||||
#define XCMD_PRINT_BUF_MAX_LENGTH (64) /* xcmd_print缓存 */
|
||||
#endif
|
||||
|
||||
#ifndef XCMD_HISTORY_BUF_SZIE
|
||||
#define XCMD_HISTORY_BUF_SZIE (64) /* 支持的历史记录个数, 这个参数对内存的影响很大,建议arduino设置为0,0为不支持 */
|
||||
#endif
|
||||
|
||||
#ifndef XCMD_PARAM_MAX_NUM
|
||||
#define XCMD_PARAM_MAX_NUM (8) /* 支持输入的参数个数 */
|
||||
// #define XCMD_DEFAULT_PROMPT "->" /* 提示符 */
|
||||
// #define XCMD_DEFAULT_PROMPT_CLOLR TX_GREEN /* 提示符颜色 */
|
||||
// #define ENABLE_XCMD_EXPORT /* 需要修改lds,启用后支持XCMD_EXPORT_CMD和XCMD_EXPORT_KEY方法导出命令 */
|
||||
#endif
|
||||
|
||||
#if XCMD_PRINT_BUF_MAX_LENGTH < (XCMD_LINE_MAX_LENGTH+32)
|
||||
#undef XCMD_PRINT_BUF_MAX_LENGTH
|
||||
#define XCMD_PRINT_BUF_MAX_LENGTH (XCMD_LINE_MAX_LENGTH+32) /* xcmd_print缓存 */
|
||||
#endif
|
||||
|
||||
#ifndef XCMD_DEFAULT_PROMPT
|
||||
#define XCMD_DEFAULT_PROMPT "$ " /*提示符*/
|
||||
#endif
|
||||
|
||||
#ifndef XCMD_DEFAULT_PROMPT_CLOLR
|
||||
#define XCMD_DEFAULT_PROMPT_CLOLR ANSI_BLUE /*提示符颜色*/
|
||||
#endif
|
||||
|
||||
#ifndef XCMD_VAR_NUM
|
||||
#define XCMD_VAR_NUM (4)
|
||||
#endif
|
||||
|
||||
#ifndef XCMD_VAR_NAME_BUF_SZIE
|
||||
#define XCMD_VAR_NAME_BUF_SZIE (32)
|
||||
#endif
|
||||
|
||||
#ifndef XCMD_VAR_VAR_SZIE
|
||||
#define XCMD_VAR_VAR_SZIE (32)
|
||||
#endif
|
||||
|
||||
#ifndef ENABLE_XCMD_EXPORT
|
||||
//#define ENABLE_XCMD_EXPORT /*使能XCMD_EXPORT_CMD和XCMD_EXPORT_KEY*/
|
||||
#endif
|
||||
```
|
||||
|
||||
#### 使用说明
|
||||
|
|
|
@ -5,50 +5,28 @@
|
|||
extern "C" {
|
||||
#endif
|
||||
|
||||
#ifndef XCMD_LINE_MAX_LENGTH
|
||||
#define XCMD_LINE_MAX_LENGTH (32) /* 命令行支持的最大字符数 */
|
||||
#endif
|
||||
|
||||
#ifndef XCMD_PRINT_BUF_MAX_LENGTH
|
||||
#define XCMD_PRINT_BUF_MAX_LENGTH (64) /* xcmd_print缓存 */
|
||||
#endif
|
||||
|
||||
#ifndef XCMD_HISTORY_BUF_SZIE
|
||||
#define XCMD_HISTORY_BUF_SZIE (64) /* 支持的历史记录个数, 这个参数对内存的影响很大,建议arduino设置为0,0为不支持 */
|
||||
#endif
|
||||
#define XCMD_HISTORY_BUF_SZIE (128) /* 支持的历史记录缓存大小,实际历史记录个数取决于记录的命令长度,建议内存较小的单片机设置为0 */
|
||||
|
||||
#ifndef XCMD_PARAM_MAX_NUM
|
||||
#define XCMD_PARAM_MAX_NUM (8) /* 支持输入的参数个数 */
|
||||
#endif
|
||||
|
||||
#if XCMD_PRINT_BUF_MAX_LENGTH < (XCMD_LINE_MAX_LENGTH+32)
|
||||
#undef XCMD_PRINT_BUF_MAX_LENGTH
|
||||
#define XCMD_PRINT_BUF_MAX_LENGTH (XCMD_LINE_MAX_LENGTH+32) /* xcmd_print缓存 */
|
||||
#endif
|
||||
|
||||
#ifndef XCMD_DEFAULT_PROMPT
|
||||
#define XCMD_DEFAULT_PROMPT "$ " /*提示符*/
|
||||
#endif
|
||||
|
||||
#ifndef XCMD_DEFAULT_PROMPT_CLOLR
|
||||
#define XCMD_DEFAULT_PROMPT_CLOLR ANSI_BLUE /*提示符颜色*/
|
||||
#endif
|
||||
|
||||
#ifndef XCMD_VAR_NUM
|
||||
#define XCMD_VAR_NUM (4)
|
||||
#endif
|
||||
|
||||
#ifndef XCMD_VAR_NAME_BUF_SZIE
|
||||
#define XCMD_VAR_NAME_BUF_SZIE (32)
|
||||
#endif
|
||||
#define XCMD_VAR_NUM (0) /* 支持的变量的个数,可以为0 */
|
||||
#define XCMD_VAR_NAME_BUF_SZIE (0) /* 变量名最大长度,可以为0 */
|
||||
#define XCMD_VAR_VAR_SZIE (0) /* 变量最大长度,可以为0 */
|
||||
|
||||
#ifndef XCMD_VAR_VAR_SZIE
|
||||
#define XCMD_VAR_VAR_SZIE (32)
|
||||
#endif
|
||||
|
||||
#ifndef ENABLE_XCMD_EXPORT
|
||||
//#define ENABLE_XCMD_EXPORT /*使能XCMD_EXPORT_CMD和XCMD_EXPORT_KEY*/
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
|
|
@ -1,372 +0,0 @@
|
|||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdarg.h>
|
||||
#include <ctype.h>
|
||||
#include "xcmd.h"
|
||||
#include "xcmd_cmds.h"
|
||||
#include "xcmd_keys.h"
|
||||
|
||||
static struct
|
||||
{
|
||||
xcmd_t head;
|
||||
} g_cmd_list;
|
||||
|
||||
static struct
|
||||
{
|
||||
xcmd_key_t head;
|
||||
} g_key_list;
|
||||
|
||||
int xcmd_key_register(xcmd_key_t *keys, uint16_t number)
|
||||
{
|
||||
#ifndef ENABLE_XCMD_EXPORT
|
||||
uint16_t i = 0;
|
||||
xcmd_key_t *temp;
|
||||
|
||||
while (i < number)
|
||||
{
|
||||
temp = g_key_list.head.next;
|
||||
g_key_list.head.next = &keys[i];
|
||||
keys[i].next = temp;
|
||||
++i;
|
||||
}
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
int xcmd_cmd_register(xcmd_t *cmds, uint16_t number)
|
||||
{
|
||||
#ifndef ENABLE_XCMD_EXPORT
|
||||
xcmd_t *temp;
|
||||
uint16_t i = 0;
|
||||
while (i < number)
|
||||
{
|
||||
temp = g_cmd_list.head.next;
|
||||
g_cmd_list.head.next = &cmds[i];
|
||||
cmds[i].next = temp;
|
||||
++i;
|
||||
}
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
int xcmd_unregister_key(char *key)
|
||||
{
|
||||
#ifndef ENABLE_XCMD_EXPORT
|
||||
xcmd_key_t *bk = &g_key_list.head;
|
||||
xcmd_key_t *p = NULL;
|
||||
XCMD_KEY_FOR_EACH(p)
|
||||
{
|
||||
if (strcmp(key, p->name) == 0)
|
||||
{
|
||||
bk->next = p->next;
|
||||
return 0;
|
||||
}
|
||||
bk = p;
|
||||
}
|
||||
#endif
|
||||
return -1;
|
||||
}
|
||||
|
||||
int xcmd_unregister_cmd(char *cmd)
|
||||
{
|
||||
#ifndef ENABLE_XCMD_EXPORT
|
||||
xcmd_t *bk = &g_cmd_list.head;
|
||||
xcmd_t *p = NULL;
|
||||
XCMD_CMD_FOR_EACH(p)
|
||||
{
|
||||
if (strcmp(cmd, p->name) == 0)
|
||||
{
|
||||
bk->next = p->next;
|
||||
return 0;
|
||||
}
|
||||
bk = p;
|
||||
}
|
||||
#endif
|
||||
return -1;
|
||||
}
|
||||
|
||||
xcmd_key_t *xcmd_keylist_get(void)
|
||||
{
|
||||
#ifndef ENABLE_XCMD_EXPORT
|
||||
return g_key_list.head.next;
|
||||
#else
|
||||
return &_xcmd_key_list_start;
|
||||
#endif
|
||||
}
|
||||
|
||||
xcmd_t *xcmd_cmdlist_get(void)
|
||||
{
|
||||
#ifndef ENABLE_XCMD_EXPORT
|
||||
return g_cmd_list.head.next;
|
||||
#else
|
||||
return &_xcmd_cmd_list_start;
|
||||
#endif
|
||||
}
|
||||
|
||||
static void xcmd_key_match(xcmder_t *xcmder, char *key)
|
||||
{
|
||||
xcmd_key_t *p = NULL;
|
||||
XCMD_KEY_FOR_EACH(p)
|
||||
{
|
||||
if (strcmp(key, p->name) == 0)
|
||||
{
|
||||
if (p->func(0, (char **)&xcmder) == 0)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static int xcmd_cmd_match(xcmder_t *xcmder, int argc, char *argv[])
|
||||
{
|
||||
uint8_t flag = 0;
|
||||
int ret = -1;
|
||||
xcmd_t *p = NULL;
|
||||
XCMD_CMD_FOR_EACH(p)
|
||||
{
|
||||
if (strcmp(p->name, argv[0]) == 0)
|
||||
{
|
||||
flag = 1;
|
||||
if (argc > 1)
|
||||
{
|
||||
if (p->help && ((strcmp(argv[1], "?") == 0) || (strcmp(argv[1], "-h") == 0)))
|
||||
{
|
||||
xcmd_print(xcmder, "%s\r\n", p->help);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (xcmder->pre_cmd_cbk)
|
||||
{
|
||||
argc = xcmder->pre_cmd_cbk(argc, argv);
|
||||
argv[argc] = (char *)xcmder;
|
||||
}
|
||||
ret = p->func(argc, argv);
|
||||
if (xcmder->after_cmd_cbk)
|
||||
argc = xcmder->after_cmd_cbk(argc, argv);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (0 == flag)
|
||||
{
|
||||
if (NULL == xcmder->unknow_cmd_cbk)
|
||||
xcmd_print(xcmder, "cmd \"%s\" does not exist\r\n", argv[0]);
|
||||
else
|
||||
xcmder->unknow_cmd_cbk(argc, argv);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
int xcmd_exec(xcmder_t *xcmder, char *str)
|
||||
{
|
||||
int param_num = 0;
|
||||
int ret = -1;
|
||||
char *cmd_param_buff[XCMD_PARAM_MAX_NUM + 1];
|
||||
char temp[XNR_LINE_MAX_LENGTH];
|
||||
strncpy(temp, str, XNR_LINE_MAX_LENGTH);
|
||||
param_num = xnr_line_tok(temp, " ", cmd_param_buff, XCMD_PARAM_MAX_NUM);
|
||||
if (param_num > 0)
|
||||
{
|
||||
cmd_param_buff[param_num] = (char *)xcmder;
|
||||
ret = xcmd_cmd_match(xcmder, param_num, cmd_param_buff);
|
||||
}
|
||||
xnr_line_clear(&xcmder->line);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void xcmd_key_exec(xcmder_t *xcmder, char *key)
|
||||
{
|
||||
xcmd_key_match(xcmder, key);
|
||||
}
|
||||
|
||||
void xcmd_task(xcmder_t *xcmder)
|
||||
{
|
||||
int c;
|
||||
if (xcmder->_initOK)
|
||||
{
|
||||
c = xnr_io_getc(&xcmder->io);
|
||||
if (xnr_key_encode(&xcmder->key, c))
|
||||
{
|
||||
char *key_val = xnr_key_val(&xcmder->key);
|
||||
if (isprint((int)key_val[0u])) // 可显示字符
|
||||
{
|
||||
xnr_line_insert(&xcmder->line, c); // 向行中插入可显示字符
|
||||
}
|
||||
else // 不可显示字符,即快捷键
|
||||
{
|
||||
xcmd_key_exec(xcmder, key_val);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void xcmd_reg_unknow_cmd_cbk(xcmder_t *xcmder, cmd_func_t cbk)
|
||||
{
|
||||
xcmder->unknow_cmd_cbk = cbk;
|
||||
}
|
||||
|
||||
void xcmd_reg_pre_cmd_cbk(xcmder_t *xcmder, cmd_func_t cbk)
|
||||
{
|
||||
xcmder->pre_cmd_cbk = cbk;
|
||||
}
|
||||
|
||||
void xcmd_reg_after_cmd_cbk(xcmder_t *xcmder, cmd_func_t cbk)
|
||||
{
|
||||
xcmder->after_cmd_cbk = cbk;
|
||||
}
|
||||
|
||||
int xcmd_getopt(xcmder_t *xcmder, int argc, char *const argv[], const char *optstring)
|
||||
{
|
||||
static char *nextc = NULL; // 字符串中下一个选项字符位置
|
||||
char *c = NULL; // 选项字符
|
||||
int has_arg = 0; // 选项是否有参数
|
||||
int is_long_opt = 0; // 是否是长选项
|
||||
int opt_long_index = -1; // 如果是长选项,存储它的下标
|
||||
|
||||
xcmder->optarg = 0;
|
||||
|
||||
if (nextc == NULL || *nextc == '\0')
|
||||
{
|
||||
if (xcmder->optind >= argc || argv[xcmder->optind][0] != '-' || argv[xcmder->optind][1] == '\0')
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
nextc = argv[xcmder->optind] + 1;
|
||||
|
||||
if (*nextc == '-')
|
||||
{
|
||||
is_long_opt = 1;
|
||||
nextc++;
|
||||
}
|
||||
|
||||
xcmder->optind++;
|
||||
}
|
||||
|
||||
if (is_long_opt)
|
||||
{
|
||||
// 如果是长选项,查找选项字符串和操作数
|
||||
char buf[XCMD_PARAM_MAX_NUM + 1];
|
||||
char *p = strchr(nextc, '=');
|
||||
|
||||
if (p != NULL)
|
||||
{
|
||||
// 选项字符串和操作数之间有等号
|
||||
int len = p - nextc;
|
||||
|
||||
if (len > XCMD_PARAM_MAX_NUM)
|
||||
{
|
||||
return '?';
|
||||
}
|
||||
|
||||
strncpy(buf, nextc, len);
|
||||
buf[len] = '\0';
|
||||
nextc = p + 1;
|
||||
xcmder->optarg = nextc;
|
||||
nextc = NULL; // xcmder->optarg 后面不会再有操作数
|
||||
}
|
||||
else
|
||||
{
|
||||
// 选项字符串后没有等号
|
||||
int len = strlen(nextc);
|
||||
|
||||
if (len > XCMD_PARAM_MAX_NUM)
|
||||
{
|
||||
return '?';
|
||||
}
|
||||
|
||||
strncpy(buf, nextc, XCMD_PARAM_MAX_NUM);
|
||||
nextc = NULL;
|
||||
}
|
||||
|
||||
// 在 optstring 中查找长选项
|
||||
int i;
|
||||
for (i = 0; optstring[i] != '\0'; i += 2)
|
||||
{
|
||||
if (optstring[i] == ':' || optstring[i + 1] == ':')
|
||||
{
|
||||
// 忽略有错误格式的选项(参见实例代码,有两个冒号的应该可以解析出错)
|
||||
continue;
|
||||
}
|
||||
|
||||
if (strcmp(buf, optstring + i) == 0)
|
||||
{
|
||||
opt_long_index = i / 2;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
c = nextc++;
|
||||
has_arg = 0;
|
||||
|
||||
if (*nextc == ':')
|
||||
{
|
||||
has_arg = 1;
|
||||
nextc++;
|
||||
}
|
||||
|
||||
if (*c == ':' || strchr(optstring, *c) == NULL)
|
||||
{
|
||||
return '?';
|
||||
}
|
||||
}
|
||||
|
||||
if (opt_long_index >= 0 || has_arg)
|
||||
{
|
||||
if (nextc != NULL)
|
||||
{
|
||||
xcmder->optarg = nextc;
|
||||
nextc = NULL;
|
||||
}
|
||||
else if (xcmder->optind < argc)
|
||||
{
|
||||
xcmder->optarg = argv[xcmder->optind];
|
||||
xcmder->optind++;
|
||||
}
|
||||
else
|
||||
{
|
||||
return ':';
|
||||
}
|
||||
}
|
||||
|
||||
if (opt_long_index >= 0)
|
||||
{
|
||||
return optstring[opt_long_index * 2];
|
||||
}
|
||||
else
|
||||
{
|
||||
return *c;
|
||||
}
|
||||
}
|
||||
|
||||
void xcmd_init(xcmder_t *xcmder, io_write_t write, io_read_t read)
|
||||
{
|
||||
if (write && read && xcmder && 0 == xcmder->_initOK)
|
||||
{
|
||||
xcmder->unknow_cmd_cbk = NULL;
|
||||
xcmder->pre_cmd_cbk = NULL;
|
||||
xcmder->after_cmd_cbk = NULL;
|
||||
xcmder->user_data = NULL;
|
||||
xcmder->optarg = NULL;
|
||||
xcmder->optind = 1;
|
||||
#ifndef ENABLE_XCMD_EXPORT
|
||||
g_cmd_list.head.next = NULL;
|
||||
#endif
|
||||
xnr_var_init(&xcmder->var_tab, xcmder->var_buf, XCMD_VAR_NUM);
|
||||
xnr_io_init(&xcmder->io, write, read);
|
||||
xnr_key_init(&xcmder->key);
|
||||
xnr_line_init(&xcmder->line, &xcmder->io);
|
||||
xnr_history_init(&xcmder->history, &xcmder->io);
|
||||
default_cmds_init();
|
||||
default_keys_init();
|
||||
xcmd_exec(xcmder, "logo");
|
||||
xcmd_unregister_cmd("logo");
|
||||
xnr_var_set(&xcmder->var_tab, "prompt", ANSI_COLOR_TXT(XCMD_DEFAULT_PROMPT_CLOLR, XCMD_DEFAULT_PROMPT));
|
||||
char *var_val = xnr_var_value(&xcmder->var_tab, "prompt");
|
||||
xnr_line_bind_prompt(&xcmder->line, var_val);
|
||||
xnr_line_clear(&xcmder->line);
|
||||
xcmder->_initOK = 1;
|
||||
}
|
||||
}
|
|
@ -1,139 +0,0 @@
|
|||
#ifndef XCMD_H
|
||||
#define XCMD_H
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include "xnr_line.h"
|
||||
#include "xnr_history.h"
|
||||
#include "xnr_io.h"
|
||||
#include "xnr_key.h"
|
||||
#include "xnr_var.h"
|
||||
#include "xcmd_confg.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
typedef int (*cmd_func_t)(int, char **);
|
||||
typedef struct cmd
|
||||
{
|
||||
const char *name;
|
||||
cmd_func_t func;
|
||||
const char *help;
|
||||
#ifndef ENABLE_XCMD_EXPORT
|
||||
struct cmd *next;
|
||||
#endif
|
||||
} xcmd_t;
|
||||
typedef xcmd_t xcmd_key_t;
|
||||
|
||||
#ifndef XCMD_PARAM_MAX_NUM
|
||||
#define XCMD_PARAM_MAX_NUM (8) /* 支持输入的参数个数 */
|
||||
#endif
|
||||
|
||||
#define XCMD_CURRENT() ((xcmder_t *)(argv[argc]))
|
||||
|
||||
#ifndef XCMD_SECTION
|
||||
#if defined(__CC_ARM) || defined(__CLANG_ARM)
|
||||
#define XCMD_SECTION(x) __attribute__((section(x)))
|
||||
#elif defined(__IAR_SYSTEMS_ICC__)
|
||||
#define XCMD_SECTION(x) @x
|
||||
#elif defined(__GNUC__)
|
||||
#define XCMD_SECTION(x) __attribute__((section(x)))
|
||||
#else
|
||||
#define XCMD_SECTION(x)
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef XCMD_USED
|
||||
#if defined(__CC_ARM) || defined(__CLANG_ARM)
|
||||
#define XCMD_USED __attribute__((used))
|
||||
#elif defined(__IAR_SYSTEMS_ICC__)
|
||||
#define XCMD_USED __root
|
||||
#elif defined(__GNUC__)
|
||||
#define XCMD_USED __attribute__((used))
|
||||
#else
|
||||
#define XCMD_USED
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef ENABLE_XCMD_EXPORT
|
||||
#define XCMD_EXPORT_CMD(_name, _func, _help) XCMD_USED const xcmd_t XCMD_SECTION("_xcmd_cmd_list") \
|
||||
xcmd_cmd_##_name = { \
|
||||
.name = #_name, \
|
||||
.func = _func, \
|
||||
.help = _help};
|
||||
#define XCMD_EXPORT_KEY(_key, _func, _help) XCMD_USED const xcmd_key_t XCMD_SECTION("_xcmd_key_list") \
|
||||
xcmd_key_##_key = { \
|
||||
.key = _key, \
|
||||
.func = _func, \
|
||||
.help = _help};
|
||||
extern xcmd_t _xcmd_cmd_list_start;
|
||||
extern xcmd_t _xcmd_cmd_list_end;
|
||||
extern xcmd_key_t _xcmd_key_list_start;
|
||||
extern xcmd_key_t _xcmd_key_list_end;
|
||||
#define XCMD_CMD_FOR_EACH(pos) for ((pos) = &_xcmd_cmd_list_start; (pos) < &_xcmd_cmd_list_end; ++(pos))
|
||||
#define XCMD_KEY_FOR_EACH(pos) for ((pos) = &_xcmd_key_list_start; (pos) < &_xcmd_key_list_end; ++(pos))
|
||||
#else
|
||||
/**
|
||||
* @description: 获取命令列表,可以通过next指针可以遍历所有指令
|
||||
* @param {*}
|
||||
* @param {}
|
||||
* @return {xcmd_t *}:指令链表表头
|
||||
*/
|
||||
xcmd_t *xcmd_cmdlist_get(void);
|
||||
/**
|
||||
* @description: 获取按键列表,可以通过next指针可以遍历所有按键
|
||||
* @param {*}
|
||||
* @param {}
|
||||
* @return {xcmd_key_t *}:快捷键链表表头
|
||||
*/
|
||||
xcmd_key_t *xcmd_keylist_get(void);
|
||||
#define XCMD_EXPORT_CMD(name, func, help)
|
||||
#define XCMD_EXPORT_KEY(key, func, help)
|
||||
#define XCMD_CMD_FOR_EACH(pos) for ((pos) = xcmd_cmdlist_get(); (pos); (pos) = (pos)->next)
|
||||
#define XCMD_KEY_FOR_EACH(pos) for ((pos) = xcmd_keylist_get(); (pos); (pos) = (pos)->next)
|
||||
#endif
|
||||
|
||||
#define xcmd_print(xcmder, fmt, args...) xnr_io_printf(&(xcmder)->io, fmt, ##args)
|
||||
#define xcmd_puts(xcmder, str) xnr_io_puts(&(xcmder)->io, str)
|
||||
#define xcmd_putc(xcmder, c) xnr_io_putc(&(xcmder)->io, c)
|
||||
#define xcmd_getc(xcmder) xnr_io_getc(&(xcmder)->io)
|
||||
|
||||
typedef struct xcmd
|
||||
{
|
||||
xnr_io_t io;
|
||||
xnr_key_t key;
|
||||
xnr_var_tab_t var_tab;
|
||||
xnr_var_t var_buf[XCMD_VAR_NUM];
|
||||
xnr_history_t history;
|
||||
xnr_line_t line;
|
||||
cmd_func_t unknow_cmd_cbk; // 输入为命令序列,输出未处理
|
||||
cmd_func_t pre_cmd_cbk; // 输入为命令序列,输出重新赋值给argc
|
||||
cmd_func_t after_cmd_cbk; // 输入为命令序列,输出未处理
|
||||
void *user_data; // 用户数据
|
||||
int optind; // 选项在参数列表中的位置
|
||||
char *optarg; // 选项参数的值
|
||||
bool _initOK;
|
||||
} xcmder_t;
|
||||
|
||||
void xcmd_init(xcmder_t *xcmder, io_write_t write, io_read_t read);
|
||||
void xcmd_task(xcmder_t *xcmder);
|
||||
void xcmd_reg_unknow_cmd_cbk(xcmder_t *xcmder, cmd_func_t cbk);
|
||||
void xcmd_reg_pre_cmd_cbk(xcmder_t *xcmder, cmd_func_t cbk);
|
||||
void xcmd_reg_after_cmd_cbk(xcmder_t *xcmder, cmd_func_t cbk);
|
||||
|
||||
int xcmd_exec(xcmder_t *xcmder, char *str);
|
||||
int xcmd_getopt(xcmder_t *xcmder, int argc, char * const argv[], const char *optstring);
|
||||
|
||||
int xcmd_key_register(xcmd_key_t *keys, uint16_t number);
|
||||
int xcmd_unregister_key(char *key);
|
||||
int xcmd_cmd_register(xcmd_t *cmds, uint16_t number);
|
||||
int xcmd_unregister_cmd(char *cmd);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
|
@ -1,100 +0,0 @@
|
|||
#include "xcmd_confg.h"
|
||||
#include "xcmd_cmds.h"
|
||||
#include "xcmd.h"
|
||||
#include <stdlib.h>
|
||||
|
||||
#define VERSION "2.0 .0"
|
||||
|
||||
static int cmd_clear(int argc, char* argv[])
|
||||
{
|
||||
xcmder_t *xcmder = XCMD_CURRENT();
|
||||
xcmd_print(xcmder, "\033c");
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int cmd_help(int argc, char* argv[])
|
||||
{
|
||||
xcmder_t *xcmder = XCMD_CURRENT();
|
||||
xcmd_t *p = NULL;
|
||||
XCMD_CMD_FOR_EACH(p)
|
||||
{
|
||||
xcmd_print(xcmder, "%-20s %s\r\n",p->name, p->help);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int cmd_keys(int argc, char* argv[])
|
||||
{
|
||||
xcmder_t *xcmder = XCMD_CURRENT();
|
||||
xcmd_key_t *p = NULL;
|
||||
XCMD_KEY_FOR_EACH(p)
|
||||
{
|
||||
xcmd_print(xcmder, "0x%08X\t", p->name);
|
||||
xcmd_print(xcmder, "%s\r\n",p->help);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int cmd_logo(int argc, char* argv[])
|
||||
{
|
||||
xcmder_t *xcmder = XCMD_CURRENT();
|
||||
char *log = "\
|
||||
_ _ ___ __ __ ____ \r\n\
|
||||
( \\/ )/ __)( \\/ )( _ \\ \r\n\
|
||||
) (( (__ ) ( )(_) )\r\n\
|
||||
(_/\\_)\\___)(_/\\/\\_)(____/\r\n ";
|
||||
xcmd_puts(xcmder, log);
|
||||
xcmd_print(xcmder, "\r\n%-10s %s %s\r\n","Build" ,__DATE__, __TIME__);
|
||||
xcmd_print(xcmder, "%-10s %s\r\n","Version", VERSION);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int cmd_set(int argc, char* argv[])
|
||||
{
|
||||
xcmder_t *xcmder = XCMD_CURRENT();
|
||||
if(argc >= 3)
|
||||
{
|
||||
xnr_var_set(&xcmder->var_tab, argv[1], argv[2]);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int cmd_var(int argc, char* argv[])
|
||||
{
|
||||
xcmder_t *xcmder = XCMD_CURRENT();
|
||||
int id = 0;
|
||||
xnr_var_t *var;
|
||||
while(1)
|
||||
{
|
||||
var = xnr_var(&xcmder->var_tab, id++);
|
||||
if(NULL == var)
|
||||
break;
|
||||
if(var->name[0] != '\0')
|
||||
xcmd_print(xcmder, "%-15s:%s\n", var->name, var->value);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
XCMD_EXPORT_CMD(clear, cmd_clear, "clear screen")
|
||||
XCMD_EXPORT_CMD(help, cmd_help, "show this list")
|
||||
XCMD_EXPORT_CMD(keys, cmd_keys, "show keys")
|
||||
XCMD_EXPORT_CMD(logo, cmd_logo, "show logo")
|
||||
XCMD_EXPORT_CMD(setvar, cmd_set, "set var")
|
||||
XCMD_EXPORT_CMD(var, cmd_var, "get all var")
|
||||
|
||||
static xcmd_t cmds[] =
|
||||
{
|
||||
#ifndef ENABLE_XCMD_EXPORT
|
||||
{"clear", cmd_clear, "clear screen", NULL},
|
||||
{"help", cmd_help, "show this list", NULL},
|
||||
{"keys", cmd_keys, "show keys", NULL},
|
||||
{"logo", cmd_logo, "show logo", NULL},
|
||||
{"setvar", cmd_set, "set var", NULL},
|
||||
{"var", cmd_var, "get all var", NULL},
|
||||
#endif
|
||||
};
|
||||
|
||||
void default_cmds_init(void)
|
||||
{
|
||||
xcmd_cmd_register(cmds, sizeof(cmds)/sizeof(xcmd_t));
|
||||
}
|
|
@ -1,15 +0,0 @@
|
|||
#ifndef XCMMD_DEFAULT_CMDS_H
|
||||
#define XCMMD_DEFAULT_CMDS_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
|
||||
void default_cmds_init(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /*XCMMD_DEFAULT_CMDS_H*/
|
|
@ -1,57 +0,0 @@
|
|||
#ifndef xcmd_confg_H
|
||||
#define xcmd_confg_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#ifndef XCMD_LINE_MAX_LENGTH
|
||||
#define XCMD_LINE_MAX_LENGTH (32) /* 命令行支持的最大字符数 */
|
||||
#endif
|
||||
|
||||
#ifndef XCMD_PRINT_BUF_MAX_LENGTH
|
||||
#define XCMD_PRINT_BUF_MAX_LENGTH (64) /* xcmd_print缓存 */
|
||||
#endif
|
||||
|
||||
#ifndef XCMD_HISTORY_BUF_SZIE
|
||||
#define XCMD_HISTORY_BUF_SZIE (64) /* 支持的历史记录个数, 这个参数对内存的影响很大,建议arduino设置为0,0为不支持 */
|
||||
#endif
|
||||
|
||||
#ifndef XCMD_PARAM_MAX_NUM
|
||||
#define XCMD_PARAM_MAX_NUM (8) /* 支持输入的参数个数 */
|
||||
#endif
|
||||
|
||||
#if XCMD_PRINT_BUF_MAX_LENGTH < (XCMD_LINE_MAX_LENGTH+32)
|
||||
#undef XCMD_PRINT_BUF_MAX_LENGTH
|
||||
#define XCMD_PRINT_BUF_MAX_LENGTH (XCMD_LINE_MAX_LENGTH+32) /* xcmd_print缓存 */
|
||||
#endif
|
||||
|
||||
#ifndef XCMD_DEFAULT_PROMPT
|
||||
#define XCMD_DEFAULT_PROMPT "$ " /*提示符*/
|
||||
#endif
|
||||
|
||||
#ifndef XCMD_DEFAULT_PROMPT_CLOLR
|
||||
#define XCMD_DEFAULT_PROMPT_CLOLR ANSI_BLUE /*提示符颜色*/
|
||||
#endif
|
||||
|
||||
#ifndef XCMD_VAR_NUM
|
||||
#define XCMD_VAR_NUM (4)
|
||||
#endif
|
||||
|
||||
#ifndef XCMD_VAR_NAME_BUF_SZIE
|
||||
#define XCMD_VAR_NAME_BUF_SZIE (32)
|
||||
#endif
|
||||
|
||||
#ifndef XCMD_VAR_VAR_SZIE
|
||||
#define XCMD_VAR_VAR_SZIE (32)
|
||||
#endif
|
||||
|
||||
#ifndef ENABLE_XCMD_EXPORT
|
||||
//#define ENABLE_XCMD_EXPORT /*使能XCMD_EXPORT_CMD和XCMD_EXPORT_KEY*/
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* xcmd_confg_H */
|
|
@ -1,166 +0,0 @@
|
|||
#include "xcmd_confg.h"
|
||||
#include "xcmd.h"
|
||||
#include "xcmd_keys.h"
|
||||
|
||||
static int xcmd_str_match(const char *str1, const char *str2)
|
||||
{
|
||||
int i = 0;
|
||||
for (i = 0; str1[i] && str2[i]; i++)
|
||||
{
|
||||
if (str1[i] != str2[i])
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
return i;
|
||||
}
|
||||
|
||||
static int xcmd_del_char(int argc, char *argv[])
|
||||
{
|
||||
xcmder_t *xcmder = XCMD_CURRENT();
|
||||
xnr_line_delete(&xcmder->line);
|
||||
return 0;
|
||||
}
|
||||
XCMD_EXPORT_KEY(KEY_CTR_H, xcmd_del_char, "backspace")
|
||||
XCMD_EXPORT_KEY(KEY_BACKSPACE, xcmd_del_char, "delete")
|
||||
|
||||
static int xcmd_enter(int argc, char *argv[])
|
||||
{
|
||||
xcmder_t *xcmder = XCMD_CURRENT();
|
||||
char out_line[XNR_LINE_MAX_LENGTH] = {0};
|
||||
xcmd_print(xcmder, "\n\r");
|
||||
char *line = xnr_line_line(&xcmder->line);
|
||||
xnr_history_append(&xcmder->history, line);
|
||||
xnr_var_repalce(&xcmder->var_tab, line, out_line, XNR_LINE_MAX_LENGTH);
|
||||
if (out_line[0])
|
||||
{
|
||||
xcmd_exec(xcmder, out_line);
|
||||
}
|
||||
else
|
||||
{
|
||||
xnr_line_clear(&xcmder->line);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
XCMD_EXPORT_KEY(KEY_CTR_M, xcmd_enter, "enter")
|
||||
XCMD_EXPORT_KEY(KEY_CTR_J, xcmd_enter, "enter")
|
||||
|
||||
static int xcmd_cursor_left(int argc, char *argv[])
|
||||
{
|
||||
xcmder_t *xcmder = XCMD_CURRENT();
|
||||
xnr_line_cursor_left(&xcmder->line);
|
||||
return 0;
|
||||
}
|
||||
XCMD_EXPORT_KEY(KEY_LEFT, xcmd_cursor_left, "left")
|
||||
|
||||
static int xcmd_cursor_right(int argc, char *argv[])
|
||||
{
|
||||
xcmder_t *xcmder = XCMD_CURRENT();
|
||||
xnr_line_cursor_right(&xcmder->line);
|
||||
return 0;
|
||||
}
|
||||
XCMD_EXPORT_KEY(KEY_RIGHT, xcmd_cursor_right, "right")
|
||||
|
||||
static int xcmd_history_dw(int argc, char *argv[])
|
||||
{
|
||||
xcmder_t *xcmder = XCMD_CURRENT();
|
||||
char out_line[XNR_LINE_MAX_LENGTH] = {0};
|
||||
if (xnr_history_dw(&xcmder->history, out_line, XNR_LINE_MAX_LENGTH) > 0)
|
||||
{
|
||||
xnr_line_clear(&xcmder->line);
|
||||
xnr_line_puts(&xcmder->line, out_line);
|
||||
}
|
||||
else
|
||||
{
|
||||
xnr_line_clear(&xcmder->line);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
XCMD_EXPORT_KEY(KEY_DW, xcmd_history_dw, "down")
|
||||
|
||||
static int xcmd_history_up(int argc, char *argv[])
|
||||
{
|
||||
xcmder_t *xcmder = XCMD_CURRENT();
|
||||
char out_line[XNR_LINE_MAX_LENGTH] = {0};
|
||||
if (xnr_history_up(&xcmder->history, out_line, XNR_LINE_MAX_LENGTH) > 0)
|
||||
{
|
||||
xnr_line_clear(&xcmder->line);
|
||||
xnr_line_puts(&xcmder->line, out_line);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
XCMD_EXPORT_KEY(KEY_UP, xcmd_history_up, "up")
|
||||
|
||||
static int xcmd_auto_completion(int argc, char *argv[])
|
||||
{
|
||||
xcmder_t *xcmder = XCMD_CURRENT();
|
||||
xcmd_t *match_cmd_first = NULL;
|
||||
uint16_t match_num = 0;
|
||||
uint16_t match_subscript_min = 0;
|
||||
char *display_line = xnr_line_line(&xcmder->line);
|
||||
uint16_t cursor_pos = xnr_line_cursor(&xcmder->line);
|
||||
xcmd_t *p = NULL;
|
||||
XCMD_CMD_FOR_EACH(p)
|
||||
{
|
||||
if (strncmp(display_line, p->name, cursor_pos) == 0)
|
||||
{
|
||||
if (match_num == 0)
|
||||
{
|
||||
match_cmd_first = p;
|
||||
match_subscript_min = strlen(p->name);
|
||||
}
|
||||
else if (match_num == 1)
|
||||
{
|
||||
xcmd_print(xcmder, "\r\n%-15s%-15s", match_cmd_first->name, p->name);
|
||||
}
|
||||
else
|
||||
{
|
||||
xcmd_print(xcmder, "%-15s", p->name);
|
||||
if ((match_num % 4) == 0)
|
||||
{
|
||||
xcmd_print(xcmder, "\r\n");
|
||||
}
|
||||
}
|
||||
uint16_t subscript = xcmd_str_match(match_cmd_first->name, p->name);
|
||||
if (subscript < match_subscript_min)
|
||||
{
|
||||
match_subscript_min = subscript;
|
||||
}
|
||||
match_num++;
|
||||
}
|
||||
}
|
||||
|
||||
if (match_num == 1)
|
||||
{
|
||||
xnr_line_clear(&xcmder->line);
|
||||
xnr_line_puts(&xcmder->line, match_cmd_first->name);
|
||||
}
|
||||
else if (match_num > 1)
|
||||
{
|
||||
xcmd_print(xcmder, "\r\n");
|
||||
xnr_line_clear(&xcmder->line);
|
||||
xnr_line_write(&xcmder->line, match_cmd_first->name, match_subscript_min);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
XCMD_EXPORT_KEY(KEY_TAB, xcmd_auto_completion, "tab")
|
||||
|
||||
static xcmd_key_t default_keys[] =
|
||||
{
|
||||
#ifndef ENABLE_XCMD_EXPORT
|
||||
{KEY_CTR_M, xcmd_enter, "enter", NULL},
|
||||
{KEY_CTR_J, xcmd_enter, "enter", NULL},
|
||||
{KEY_CTR_H, xcmd_del_char, "backspace", NULL},
|
||||
{KEY_BACKSPACE, xcmd_del_char, "delete", NULL},
|
||||
{KEY_LEFT, xcmd_cursor_left, "left", NULL},
|
||||
{KEY_RIGHT, xcmd_cursor_right, "right", NULL},
|
||||
{KEY_TAB, xcmd_auto_completion, "tab", NULL},
|
||||
{KEY_DW, xcmd_history_dw, "down", NULL},
|
||||
{KEY_UP, xcmd_history_up, "up", NULL},
|
||||
#endif
|
||||
};
|
||||
|
||||
void default_keys_init(void)
|
||||
{
|
||||
xcmd_key_register(default_keys, sizeof(default_keys) / sizeof(xcmd_key_t));
|
||||
}
|
|
@ -1,14 +0,0 @@
|
|||
#ifndef xcmd_keys_H
|
||||
#define xcmd_keys_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
void default_keys_init(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* xcmd_keys_H */
|
|
@ -1,31 +0,0 @@
|
|||
#ifndef XNR_CONF_H
|
||||
#define XNR_CONF_H
|
||||
|
||||
#include "xcmd_confg.h"
|
||||
|
||||
//行缓存长度
|
||||
#ifndef XNR_LINE_MAX_LENGTH
|
||||
#define XNR_LINE_MAX_LENGTH (XCMD_LINE_MAX_LENGTH)
|
||||
#endif
|
||||
|
||||
//历史记录缓存长度
|
||||
#ifndef XNR_HISTORY_BUF_SZIE
|
||||
#define XNR_HISTORY_BUF_SZIE (XCMD_HISTORY_BUF_SZIE)
|
||||
#endif
|
||||
|
||||
//变量名长度
|
||||
#ifndef XNR_VAR_NAME_LEN
|
||||
#define XNR_VAR_NAME_LEN (XCMD_VAR_NAME_BUF_SZIE)
|
||||
#endif
|
||||
|
||||
//变量值长度
|
||||
#ifndef XNR_VAR_VAR_LEN
|
||||
#define XNR_VAR_VAR_LEN (XCMD_VAR_VAR_SZIE)
|
||||
#endif
|
||||
|
||||
//IO print缓存大小
|
||||
#ifndef XNR_PRINT_BUF_MAX_LENGTH
|
||||
#define XNR_PRINT_BUF_MAX_LENGTH (XCMD_PRINT_BUF_MAX_LENGTH)
|
||||
#endif
|
||||
|
||||
#endif
|
|
@ -1,191 +0,0 @@
|
|||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include "xnr_history.h"
|
||||
|
||||
int xnr_history_init(xnr_history_t *history, xnr_io_t *io)
|
||||
{
|
||||
if (NULL == history || NULL == io)
|
||||
return -1;
|
||||
history->head = 0;
|
||||
history->tail = 0;
|
||||
history->length = 0;
|
||||
history->id = 0;
|
||||
history->io = io;
|
||||
memset(history->buffer, 0, XNR_HISTORY_BUF_SZIE);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int xnr_history_clear(xnr_history_t *history)
|
||||
{
|
||||
return xnr_history_init(history, history->io);
|
||||
}
|
||||
|
||||
int xnr_history_length(xnr_history_t *history)
|
||||
{
|
||||
return history->length;
|
||||
}
|
||||
|
||||
int xnr_history_append(xnr_history_t *history, char *cmd)
|
||||
{
|
||||
if ((history == NULL) || (cmd == NULL))
|
||||
return -1;
|
||||
int len = strlen(cmd) + 1; // 包括'\0'
|
||||
if (len == 1 || len > (XNR_HISTORY_BUF_SZIE - 1))
|
||||
return -1;
|
||||
|
||||
if (xnr_history_cmp(history, -1, cmd) != 0) // 最近的一次历史记录不同
|
||||
{
|
||||
for (int i = 0; i < len; i++)
|
||||
{
|
||||
history->buffer[history->head++] = cmd[i];
|
||||
history->head %= XNR_HISTORY_BUF_SZIE;
|
||||
if (history->head == history->tail) // 缓存空间不足
|
||||
{
|
||||
while (1)
|
||||
{
|
||||
history->buffer[history->tail++] = '\0';
|
||||
history->tail %= XNR_HISTORY_BUF_SZIE;
|
||||
if (history->buffer[history->tail] == '\0')
|
||||
{
|
||||
++history->tail;
|
||||
history->tail %= XNR_HISTORY_BUF_SZIE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
--history->length;
|
||||
}
|
||||
}
|
||||
++history->length;
|
||||
}
|
||||
history->id = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int xnr_history_pos(xnr_history_t *history, int id)
|
||||
{
|
||||
if ((history == NULL))
|
||||
return -1;
|
||||
if (history->head == history->tail)
|
||||
return -1; // buffer中没有缓存历史命令
|
||||
|
||||
int pos = history->tail;
|
||||
if (id < 0)
|
||||
{
|
||||
id = -id;
|
||||
if (id > (history->length)) // 负id从1开始
|
||||
{
|
||||
return -1; // id超限
|
||||
}
|
||||
pos = history->head - 1;
|
||||
pos = pos < 0 ? (XNR_HISTORY_BUF_SZIE - 1) : pos;
|
||||
for (int i = 0; i < id; i++)
|
||||
{
|
||||
while (1)
|
||||
{
|
||||
--pos;
|
||||
pos = pos < 0 ? (XNR_HISTORY_BUF_SZIE - 1) : pos;
|
||||
if (history->buffer[pos] == '\0')
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
++pos;
|
||||
pos %= XNR_HISTORY_BUF_SZIE;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (id > (history->length - 1)) // 正id从0开始
|
||||
{
|
||||
return -1; // id超限
|
||||
}
|
||||
for (int i = 0; i < id; i++)
|
||||
{
|
||||
while (1)
|
||||
{
|
||||
++pos;
|
||||
pos %= XNR_HISTORY_BUF_SZIE;
|
||||
if (history->buffer[pos] == '\0')
|
||||
{
|
||||
++pos;
|
||||
pos %= XNR_HISTORY_BUF_SZIE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return pos;
|
||||
}
|
||||
|
||||
int xnr_history_get(xnr_history_t *history, int id, char *buf, int buf_len)
|
||||
{
|
||||
if ((history == NULL) || (buf == NULL) || (buf_len == 0))
|
||||
return 0;
|
||||
int pos = xnr_history_pos(history, id);
|
||||
if (pos < 0)
|
||||
return 0; // id超限
|
||||
for (int i = 0; i < buf_len; i++)
|
||||
{
|
||||
buf[i] = history->buffer[pos++];
|
||||
pos %= XNR_HISTORY_BUF_SZIE;
|
||||
if (buf[i] == '\0')
|
||||
{
|
||||
return i; // 返回字符串的长度
|
||||
}
|
||||
}
|
||||
buf[buf_len - 1] = '\0';
|
||||
return -(buf_len - 1); // 由于buf的size小于历史命令,返回字符串的长度
|
||||
}
|
||||
|
||||
int xnr_history_cmp(xnr_history_t *history, int id, char *cmd)
|
||||
{
|
||||
if ((history == NULL) || (cmd == NULL))
|
||||
return -1;
|
||||
int pos = xnr_history_pos(history, id);
|
||||
if (pos < 0)
|
||||
return -1; // id超限
|
||||
char c;
|
||||
while (1)
|
||||
{
|
||||
c = history->buffer[pos++];
|
||||
pos %= XNR_HISTORY_BUF_SZIE;
|
||||
if (c && *cmd && (c == *cmd))
|
||||
{
|
||||
++cmd;
|
||||
}
|
||||
else
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
return *cmd - c;
|
||||
}
|
||||
|
||||
int xnr_history_up(xnr_history_t *history, char *buf, int buf_len)
|
||||
{
|
||||
int id = history->id;
|
||||
int ret = 0;
|
||||
ret = xnr_history_get(history, --id, buf, buf_len);
|
||||
if (ret > 0)
|
||||
{
|
||||
history->id = id;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
int xnr_history_dw(xnr_history_t *history, char *buf, int buf_len)
|
||||
{
|
||||
int id = history->id;
|
||||
int ret = 0;
|
||||
if (id >= -1)
|
||||
{
|
||||
history->id = 0;
|
||||
return ret;
|
||||
}
|
||||
ret = xnr_history_get(history, ++id, buf, buf_len);
|
||||
if (ret > 0)
|
||||
{
|
||||
history->id = id;
|
||||
}
|
||||
return ret;
|
||||
}
|
|
@ -1,92 +0,0 @@
|
|||
#ifndef XNR_HISTORY_H
|
||||
#define XNR_HISTORY_H
|
||||
|
||||
#include "xnr_conf.h"
|
||||
#include "xnr_io.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#ifndef XNR_HISTORY_BUF_SZIE
|
||||
#define XNR_HISTORY_BUF_SZIE (256)
|
||||
#endif
|
||||
|
||||
typedef struct xnr_history //doc/history.drawio
|
||||
{
|
||||
char buffer[XNR_HISTORY_BUF_SZIE];
|
||||
int length;
|
||||
int head;
|
||||
int tail;
|
||||
int id;
|
||||
xnr_io_t *io;
|
||||
}xnr_history_t;
|
||||
|
||||
/**
|
||||
* @description: 初始化
|
||||
* @param history:xnr_history实例,io:xnr_io实例
|
||||
* @return -1:失败,0:成功
|
||||
*/
|
||||
int xnr_history_init(xnr_history_t *history, xnr_io_t *io);
|
||||
|
||||
/**
|
||||
* @description: 清除历史记录
|
||||
* @param history:xnr_history实例
|
||||
* @return -1:失败,0:成功
|
||||
*/
|
||||
int xnr_history_clear(xnr_history_t *history);
|
||||
|
||||
/**
|
||||
* @description: 获取历史记录个数
|
||||
* @param history:xnr_history实例
|
||||
* @return 历史记录个数
|
||||
*/
|
||||
int xnr_history_length(xnr_history_t *history);
|
||||
|
||||
/**
|
||||
* @description: 记录命令
|
||||
* @param history:xnr_history实例,cmd:命令
|
||||
* @return -1:失败,0:成功
|
||||
*/
|
||||
int xnr_history_append(xnr_history_t *history, char* cmd);
|
||||
|
||||
/**
|
||||
* @description: 获取历史记录编号在历史ringbuffer对应的起始位置
|
||||
* @param history:xnr_history实例
|
||||
* @return -1:失败,其他:历史记录在ringbuffer对应的起始位置
|
||||
*/
|
||||
int xnr_history_pos(xnr_history_t *history, int id);
|
||||
|
||||
/**
|
||||
* @description: 历史记录与命令比对
|
||||
* @param history:xnr_history实例,id:历史记录编号,cmd:命令
|
||||
* @return 其他:失败,0:成功
|
||||
*/
|
||||
int xnr_history_cmp(xnr_history_t *history, int id, char *cmd);
|
||||
|
||||
/**
|
||||
* @description: 从历史记录中获取命令
|
||||
* @param history:xnr_history实例,id:历史记录编号,buf:命令缓存buf,buf_len:缓存长度
|
||||
* @return -1:失败,其他:历史命令长度
|
||||
*/
|
||||
int xnr_history_get(xnr_history_t *history, int id, char *buf, int buf_len);
|
||||
|
||||
/**
|
||||
* @description: 获取上一条历史记录
|
||||
* @param history:xnr_history实例,buf:命令缓存buf,buf_len:缓存长度
|
||||
* @return -1:失败,其他:历史命令长度
|
||||
*/
|
||||
int xnr_history_up(xnr_history_t *history, char *buf, int buf_len);
|
||||
|
||||
/**
|
||||
* @description: 获取下一条历史记录
|
||||
* @param history:xnr_history实例,buf:命令缓存buf,buf_len:缓存长度
|
||||
* @return -1:失败,其他:历史命令长度
|
||||
*/
|
||||
int xnr_history_dw(xnr_history_t *history, char *buf, int buf_len);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
|
@ -1,82 +0,0 @@
|
|||
#include <stdarg.h>
|
||||
#include <string.h>
|
||||
#include "xnr_io.h"
|
||||
|
||||
int xnr_io_init(xnr_io_t *io,
|
||||
io_write_t write,
|
||||
io_read_t read)
|
||||
{
|
||||
if(NULL == io)
|
||||
return -1;
|
||||
io->in_fd = STDIN_FILENO;
|
||||
io->out_fd = STDOUT_FILENO;
|
||||
io->read = read;
|
||||
io->write = write;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int xnr_io_puts(xnr_io_t *io, const char *str)
|
||||
{
|
||||
if(NULL == io || NULL == str)
|
||||
return -1;
|
||||
return io->write(io->out_fd, str, strlen(str));
|
||||
}
|
||||
|
||||
int xnr_io_putc(xnr_io_t *io, char c)
|
||||
{
|
||||
if(NULL == io)
|
||||
return -1;
|
||||
return io->write(io->out_fd, &c, 1);
|
||||
}
|
||||
|
||||
int xnr_io_printf(xnr_io_t *io, const char *fmt, ...)
|
||||
{
|
||||
if(NULL == io || NULL == fmt)
|
||||
return -1;
|
||||
char ucstring[XNR_PRINT_BUF_MAX_LENGTH] = {0};
|
||||
va_list arg;
|
||||
va_start(arg, fmt);
|
||||
int len = vsnprintf(ucstring, XNR_PRINT_BUF_MAX_LENGTH, fmt, arg);
|
||||
va_end(arg);
|
||||
return io->write(io->out_fd, ucstring, len);
|
||||
}
|
||||
|
||||
void xnr_io_set_in_fd(xnr_io_t *io, int in_fd)
|
||||
{
|
||||
if(NULL == io)
|
||||
return;
|
||||
io->in_fd = in_fd;
|
||||
}
|
||||
|
||||
void xnr_io_set_out_fd(xnr_io_t *io, int out_fd)
|
||||
{
|
||||
if(NULL == io)
|
||||
return;
|
||||
io->out_fd = out_fd;
|
||||
}
|
||||
|
||||
int xnr_io_in_fd(xnr_io_t *io)
|
||||
{
|
||||
if(NULL == io)
|
||||
return -1;
|
||||
return io->in_fd;
|
||||
}
|
||||
|
||||
int xnr_io_out_fd(xnr_io_t *io)
|
||||
{
|
||||
if(NULL == io)
|
||||
return -1;
|
||||
return io->out_fd;
|
||||
}
|
||||
|
||||
int xnr_io_getc(xnr_io_t *io)
|
||||
{
|
||||
if(NULL == io)
|
||||
return -1;
|
||||
char c;
|
||||
if (io->read(io->in_fd, &c, 1))
|
||||
{
|
||||
return c;
|
||||
}
|
||||
return -1;
|
||||
}
|
|
@ -1,90 +0,0 @@
|
|||
#ifndef XNR_IO_H
|
||||
#define XNR_IO_H
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stddef.h>
|
||||
#include "xnr_conf.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#ifndef XNR_PRINT_BUF_MAX_LENGTH
|
||||
#define XNR_PRINT_BUF_MAX_LENGTH (128)
|
||||
#endif
|
||||
|
||||
/* 标准文件描述符. */
|
||||
#ifndef STDIN_FILENO
|
||||
#define STDIN_FILENO 0 /* 标准输入. */
|
||||
#endif
|
||||
#ifndef STDOUT_FILENO
|
||||
#define STDOUT_FILENO 1 /* 标准输出. */
|
||||
#endif
|
||||
#ifndef STDERR_FILENO
|
||||
#define STDERR_FILENO 2 /* 标准错误. */
|
||||
#endif
|
||||
|
||||
typedef int (*io_write_t)(int fd, const char *buf, size_t len);
|
||||
typedef int (*io_read_t)(int fd, char *buf, size_t len);
|
||||
|
||||
typedef struct xnr_io
|
||||
{
|
||||
int in_fd;
|
||||
int out_fd;
|
||||
io_write_t write;
|
||||
io_read_t read;
|
||||
} xnr_io_t;
|
||||
|
||||
/**
|
||||
* @description: 初始化
|
||||
* @param io:xnr_io实例,write:写函数,read:读函数,in_fd:读fd, out_fd:写fd
|
||||
*
|
||||
* @return -1:失败,0:成功
|
||||
*/
|
||||
int xnr_io_init(xnr_io_t *io,
|
||||
io_write_t write,
|
||||
io_read_t read);
|
||||
|
||||
/**
|
||||
* @description: 设置读写fd
|
||||
* @param io:xnr_io实例,in_fd:读编号, out_fd:写编号
|
||||
* @return 无
|
||||
*/
|
||||
void xnr_io_set_in_fd(xnr_io_t *io, int in_fd);
|
||||
void xnr_io_set_out_fd(xnr_io_t *io, int out_fd);
|
||||
int xnr_io_in_fd(xnr_io_t *io);
|
||||
int xnr_io_out_fd(xnr_io_t *io);
|
||||
|
||||
/**
|
||||
* @description: 打印字符串
|
||||
* @param io:xnr_io实例,fmt:格式化字符串,...:参数
|
||||
* @return -1:失败,其他:字符串长度
|
||||
*/
|
||||
int xnr_io_printf(xnr_io_t *io, const char *fmt, ...);
|
||||
|
||||
/**
|
||||
* @description: 打印字符串
|
||||
* @param io:xnr_io实例,str:字符串
|
||||
* @return -1:失败,其他:字符串长度
|
||||
*/
|
||||
int xnr_io_puts(xnr_io_t *io, const char *str);
|
||||
|
||||
/**
|
||||
* @description: 打印字符
|
||||
* @param io:xnr_io实例,c:字符
|
||||
* @return -1:失败,其他:成功
|
||||
*/
|
||||
int xnr_io_putc(xnr_io_t *io, char c);
|
||||
|
||||
/**
|
||||
* @description: 读取字符
|
||||
* @param io:xnr_io实例
|
||||
* @return -1:失败,其他:获取到的字符
|
||||
*/
|
||||
int xnr_io_getc(xnr_io_t *io);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
|
@ -1,70 +0,0 @@
|
|||
#include "xnr_key.h"
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdint.h>
|
||||
|
||||
|
||||
#define _IS_END_KEY(c) ((((c) >= 'A') && ((c) <= 'D')) || (((c) >= 'P') && ((c) <= 'S')) || \
|
||||
((c) == '~') || ((c) == 'H') || ((c) == 'F'))
|
||||
|
||||
char *xnr_key_val(xnr_key_t *key)
|
||||
{
|
||||
if(NULL == key)
|
||||
return NULL;
|
||||
return key->encode_buf;
|
||||
}
|
||||
|
||||
int xnr_key_encode(xnr_key_t *key, int ch)
|
||||
{
|
||||
if((NULL == key) || (-1 == ch))
|
||||
return 0;
|
||||
int ret = 0;
|
||||
switch (key->case_stu)
|
||||
{
|
||||
case 0: //开始状态
|
||||
key->encode_cnt = 0;
|
||||
if (ch == 0x1B) //输入的字符是 ESC
|
||||
{
|
||||
key->encode_buf[key->encode_cnt++] = ch;
|
||||
key->case_stu = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
key->encode_buf[key->encode_cnt++] = ch;
|
||||
key->encode_buf[key->encode_cnt] = '\0';
|
||||
key->encode_cnt = 0;
|
||||
ret = 1;
|
||||
}
|
||||
break;
|
||||
case 1:
|
||||
if (_IS_END_KEY(ch))
|
||||
{
|
||||
key->encode_buf[key->encode_cnt++] = ch;
|
||||
key->encode_buf[key->encode_cnt] = '\0';
|
||||
ret = key->encode_cnt;
|
||||
key->case_stu = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
key->encode_buf[key->encode_cnt++] = ch;
|
||||
if (key->encode_cnt >= 6)
|
||||
{
|
||||
key->case_stu = 0;
|
||||
ret = 0;
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
int xnr_key_init(xnr_key_t *key)
|
||||
{
|
||||
if (NULL == key)
|
||||
return -1;
|
||||
key->case_stu = 0;
|
||||
key->encode_cnt = 0;
|
||||
return 0;
|
||||
}
|
|
@ -1,98 +0,0 @@
|
|||
#ifndef XNR_KEY_H
|
||||
#define XNR_KEY_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define KEY_CTR_A "\x01"
|
||||
#define KEY_CTR_B "\x02"
|
||||
#define KEY_CTR_C "\x03"
|
||||
#define KEY_CTR_D "\x04"
|
||||
#define KEY_CTR_E "\x05"
|
||||
#define KEY_CTR_F "\x06"
|
||||
#define KEY_CTR_G "\x07"
|
||||
#define KEY_CTR_H "\x08"
|
||||
#define KEY_CTR_I "\x09"
|
||||
#define KEY_TAB "\x09"
|
||||
#define KEY_CTR_J "\x0A"
|
||||
#define KEY_CTR_K "\x0B"
|
||||
#define KEY_CTR_L "\x0C"
|
||||
#define KEY_CTR_M "\x0D"
|
||||
#define KEY_ENTER "\n"
|
||||
#define KEY_CTR_N "\x0E"
|
||||
#define KEY_CTR_O "\x0F"
|
||||
#define KEY_CTR_P "\x10"
|
||||
#define KEY_CTR_Q "\x11"
|
||||
#define KEY_CTR_R "\x12"
|
||||
#define KEY_CTR_S "\x13"
|
||||
#define KEY_CTR_T "\x14"
|
||||
#define KEY_CTR_U "\x15"
|
||||
#define KEY_CTR_V "\x16"
|
||||
#define KEY_CTR_W "\x17"
|
||||
#define KEY_CTR_X "\x18"
|
||||
#define KEY_CTR_Y "\x19"
|
||||
#define KEY_CTR_Z "\x1A"
|
||||
#define KEY_PAUSE "\x1A"
|
||||
#define KEY_ESC "\x1B"
|
||||
#define KEY_BACKSPACE "\x7F"
|
||||
#define KEY_UP "\x1B[A"
|
||||
#define KEY_DW "\x1B[B"
|
||||
#define KEY_RIGHT "\x1B[C"
|
||||
#define KEY_LEFT "\x1B[D"
|
||||
#define KEY_HOME "\x1B[H"
|
||||
#define KEY_EMD "\x1B[F"
|
||||
#define KEY_CTR_UP "\x1B[1;5A"
|
||||
#define KEY_CTR_DW "\x1B[1;5B"
|
||||
#define KEY_CTR_RIGHT "\x1B[1;5C"
|
||||
#define KEY_CTR_LEFT "\x1B[1;5D"
|
||||
#define KEY_INSERT "\x1B[2~"
|
||||
#define KEY_DELETE "\x1B[3~"
|
||||
#define KEY_PAGE_UP "\x1B[5~"
|
||||
#define KEY_PAGE_DOWN "\x1B[6~"
|
||||
#define KEY_F1 "\x1BOP"
|
||||
#define KEY_F2 "\x1BOQ"
|
||||
#define KEY_F3 "\x1BOR"
|
||||
#define KEY_F4 "\x1BOS"
|
||||
#define KEY_F5 "\x1B[15~"
|
||||
#define KEY_F6 "\x1B[17~"
|
||||
#define KEY_F7 "\x1B[18~"
|
||||
#define KEY_F8 "\x1B[19~"
|
||||
#define KEY_F9 "\x1B[20~"
|
||||
#define KEY_F10 "\x1B[21~"
|
||||
#define KEY_F11 "\x1B[23~"
|
||||
#define KEY_F12 "\x1B[24~"
|
||||
|
||||
typedef struct xnr_key
|
||||
{
|
||||
char encode_buf[8];
|
||||
int encode_cnt;
|
||||
int case_stu;
|
||||
} xnr_key_t;
|
||||
|
||||
/**
|
||||
* @description: 按键初始化
|
||||
* @param key:按键实例
|
||||
* @return -1:失败,0:成功
|
||||
*/
|
||||
int xnr_key_init(xnr_key_t *key);
|
||||
|
||||
/**
|
||||
* @description: 把输入字符编码成按键字符串
|
||||
* @param key:按键实例,ch:输入字符
|
||||
* @return 0:失败,1:成功
|
||||
*/
|
||||
int xnr_key_encode(xnr_key_t *key, int ch);
|
||||
|
||||
/**
|
||||
* @description: 获取按键字符串
|
||||
* @param key:按键实例
|
||||
* @return NULL:失败,其他:按键字符串
|
||||
*/
|
||||
char *xnr_key_val(xnr_key_t *key);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
|
@ -1,304 +0,0 @@
|
|||
#include "xnr_line.h"
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdarg.h>
|
||||
|
||||
/**
|
||||
* 在字符串s中查找任意一个属于字符串delim中的字符,
|
||||
* 如果找到了,返回该字符在s中的位置,同时忽略双引号
|
||||
* 中的内容
|
||||
*/
|
||||
static char *_strpbrk(char *s, const char *delim) // 返回s1中第一个满足条件的字符的指针, 并且保留""号内的源格式
|
||||
{
|
||||
char flag = 0; // 用来标记是否在双引号内部,0表示否,1表示是
|
||||
for (int i = 0; s[i]; i++)
|
||||
{
|
||||
if (s[i] == '\"')
|
||||
{ // 如果当前位置为双引号
|
||||
// 从字符串中去掉双引号
|
||||
for (int k = i; s[k]; k++)
|
||||
{
|
||||
s[k] = s[k + 1];
|
||||
}
|
||||
// 改变flag的值
|
||||
flag = !flag;
|
||||
}
|
||||
else if (flag == 0)
|
||||
{
|
||||
// 只有不在双引号内部才查找delim中的字符
|
||||
for (int j = 0; delim[j]; j++)
|
||||
{
|
||||
if (s[i] == delim[j])
|
||||
{
|
||||
return &s[i]; // 找到了,返回字符位置
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return NULL; // 没找到,返回NULL
|
||||
}
|
||||
|
||||
/**
|
||||
* 在字符串s中查找由字符串delim中的字符分隔出来的下一个子串,
|
||||
* 如果找到了,返回该子串的头指针,同时更新save_ptr的值,用于
|
||||
* 下一次调用时继续切割
|
||||
*/
|
||||
char *_strtok(char *s, const char *delim, char **save_ptr)
|
||||
{
|
||||
// 如果s为NULL,则从上一次保存的位置开始切割
|
||||
if (s == NULL)
|
||||
{
|
||||
s = *save_ptr;
|
||||
}
|
||||
|
||||
// 跳过连续的分隔符
|
||||
s += strspn(s, delim);
|
||||
if (*s == '\0')
|
||||
{
|
||||
// 字符串已经结束
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// 找到本次切割的子串
|
||||
char *token = s;
|
||||
s = _strpbrk(token, delim);
|
||||
if (s == NULL)
|
||||
{
|
||||
// 没有找到分隔符,返回剩余的字符串
|
||||
*save_ptr = strchr(token, '\0');
|
||||
}
|
||||
else
|
||||
{
|
||||
// 找到分隔符,替换为'\0',并更新save_ptr的值
|
||||
*s = '\0';
|
||||
*save_ptr = s + 1;
|
||||
}
|
||||
return token;
|
||||
}
|
||||
|
||||
static int strlen_without_ansi(const char *str)
|
||||
{
|
||||
int len = 0;
|
||||
int i = 0;
|
||||
while (str[i] != '\0')
|
||||
{
|
||||
if (str[i] == '\x1b')
|
||||
{
|
||||
// skip ANSI escape sequence
|
||||
while (str[i] != 'm' && str[i] != '\0')
|
||||
{
|
||||
++i;
|
||||
}
|
||||
if (str[i] == '\0')
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
++len;
|
||||
}
|
||||
++i;
|
||||
}
|
||||
return len;
|
||||
}
|
||||
|
||||
int xnr_line_init(xnr_line_t *le, xnr_io_t *io)
|
||||
{
|
||||
if (NULL == le || NULL == io)
|
||||
return -1;
|
||||
le->length = 0;
|
||||
le->cursor = 0;
|
||||
le->prompt = ANSI_COLOR_TXT(ANSI_BLUE, "->");
|
||||
le->line[0] = '\0';
|
||||
le->io = io;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int xnr_line_bind_prompt(xnr_line_t *le, const char *prompt)
|
||||
{
|
||||
if (NULL == le || NULL == prompt)
|
||||
return -1;
|
||||
le->prompt = prompt;
|
||||
return 0;
|
||||
}
|
||||
|
||||
const char *xnr_line_prompt(xnr_line_t *le)
|
||||
{
|
||||
if (NULL == le)
|
||||
return NULL;
|
||||
return le->prompt;
|
||||
}
|
||||
|
||||
int xnr_line_insert(xnr_line_t *le, char c)
|
||||
{
|
||||
if (NULL == le)
|
||||
return -1;
|
||||
|
||||
if (le->length < XNR_LINE_MAX_LENGTH - 1) // 需要保留一个位置存放'\0'
|
||||
{
|
||||
for (int i = le->length; i > le->cursor; i--)
|
||||
{
|
||||
le->line[i] = le->line[i - 1];
|
||||
}
|
||||
++le->length;
|
||||
le->line[le->length] = '\0';
|
||||
le->line[le->cursor++] = c;
|
||||
xnr_io_printf(le->io, ICH(1)); // 在当前光标位置插入空格
|
||||
xnr_io_printf(le->io, "%c", c); // 将空格替换成字符
|
||||
return 0;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
int xnr_line_delete(xnr_line_t *le)
|
||||
{
|
||||
if (NULL == le)
|
||||
return -1;
|
||||
if (le->cursor > 0)
|
||||
{
|
||||
for (int i = le->cursor - 1; i < le->length - 1; i++)
|
||||
{
|
||||
le->line[i] = le->line[i + 1];
|
||||
}
|
||||
--le->length;
|
||||
--le->cursor;
|
||||
le->line[le->length] = '\0';
|
||||
xnr_io_printf(le->io, CUB(1));
|
||||
xnr_io_printf(le->io, DCH(1));
|
||||
return 0;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
char *xnr_line_line(xnr_line_t *le)
|
||||
{
|
||||
if (NULL == le)
|
||||
return NULL;
|
||||
return le->line;
|
||||
}
|
||||
|
||||
int xnr_line_cursor(xnr_line_t *le)
|
||||
{
|
||||
if (NULL == le)
|
||||
return 0;
|
||||
return le->cursor;
|
||||
}
|
||||
|
||||
int xnr_line_length(xnr_line_t *le) // 不包含'\0'
|
||||
{
|
||||
if (NULL == le)
|
||||
return 0;
|
||||
return le->length;
|
||||
}
|
||||
|
||||
int xnr_line_cursor_left(xnr_line_t *le)
|
||||
{
|
||||
if (NULL == le)
|
||||
return 0;
|
||||
int pos = xnr_line_cursor(le);
|
||||
if (pos > 0)
|
||||
xnr_line_cursor_set(le, --pos);
|
||||
return pos;
|
||||
}
|
||||
|
||||
int xnr_line_cursor_right(xnr_line_t *le)
|
||||
{
|
||||
if (NULL == le)
|
||||
return 0;
|
||||
int pos = xnr_line_cursor(le);
|
||||
if (pos < xnr_line_length(le))
|
||||
xnr_line_cursor_set(le, ++pos);
|
||||
return pos;
|
||||
}
|
||||
|
||||
int xnr_line_cursor_set(xnr_line_t *le, int pos)
|
||||
{
|
||||
if (NULL == le)
|
||||
return 0;
|
||||
if (pos > le->length)
|
||||
{
|
||||
pos = le->length;
|
||||
}
|
||||
le->cursor = pos;
|
||||
pos = le->cursor + strlen_without_ansi(le->prompt) + 1;
|
||||
xnr_io_printf(le->io, CHA(pos));
|
||||
return pos;
|
||||
}
|
||||
|
||||
void xnr_line_cls(xnr_line_t *le) // 仅清除屏幕显示,clear时也会显示prompt
|
||||
{
|
||||
if (NULL == le)
|
||||
return;
|
||||
xnr_io_printf(le->io, DL(0));
|
||||
xnr_io_printf(le->io, "%s", le->prompt);
|
||||
le->length = 0;
|
||||
le->cursor = 0;
|
||||
}
|
||||
|
||||
void xnr_line_clear(xnr_line_t *le) // 仅清除屏幕显示和le buffer, clear时也会显示prompt,所以建议新行后都调用此函数
|
||||
{
|
||||
if (NULL == le)
|
||||
return;
|
||||
xnr_line_cls(le);
|
||||
le->line[0] = '\0';
|
||||
}
|
||||
|
||||
char xnr_line_current_char(xnr_line_t *le)
|
||||
{
|
||||
if (NULL == le)
|
||||
return '\0';
|
||||
if (le->cursor < le->length)
|
||||
{
|
||||
return le->line[le->cursor];
|
||||
}
|
||||
return '\0';
|
||||
}
|
||||
|
||||
void xnr_line_write(xnr_line_t *le, const char *buf, int len)
|
||||
{
|
||||
if (NULL == le)
|
||||
return;
|
||||
if (len > XNR_LINE_MAX_LENGTH - 1)
|
||||
{
|
||||
len = XNR_LINE_MAX_LENGTH - 1;
|
||||
}
|
||||
for (int i = 0; i < len; i++)
|
||||
{
|
||||
xnr_line_insert(le, buf[i]);
|
||||
}
|
||||
}
|
||||
|
||||
void xnr_line_puts(xnr_line_t *le, const char *str)
|
||||
{
|
||||
if (NULL == le)
|
||||
return;
|
||||
xnr_line_write(le, str, strlen(str));
|
||||
}
|
||||
|
||||
void xnr_line_print(xnr_line_t *le, const char *fmt, ...)
|
||||
{
|
||||
if (NULL == le)
|
||||
return;
|
||||
char ucstring[XNR_LINE_MAX_LENGTH] = {0};
|
||||
va_list arg;
|
||||
va_start(arg, fmt);
|
||||
vsnprintf(ucstring, XNR_LINE_MAX_LENGTH, fmt, arg);
|
||||
va_end(arg);
|
||||
xnr_line_write(le, ucstring, strlen(ucstring));
|
||||
}
|
||||
|
||||
int xnr_line_tok(char *msg, char *delim, char *get[], int max_num)
|
||||
{
|
||||
int i, ret;
|
||||
char *ptr = NULL;
|
||||
char *sp = NULL;
|
||||
ptr = _strtok(msg, delim, &sp);
|
||||
for (i = 0; ptr != NULL && i < max_num; i++)
|
||||
{
|
||||
get[i] = ptr;
|
||||
ptr = _strtok(NULL, delim, &sp);
|
||||
}
|
||||
ret = i;
|
||||
return ret;
|
||||
}
|
|
@ -1,219 +0,0 @@
|
|||
#ifndef XNR_LINE_H
|
||||
#define XNR_LINE_H
|
||||
|
||||
#include "xnr_conf.h"
|
||||
#include "xnr_io.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
/*光标操作符,其中0x1B是ESC,只适用于xnr_print函数*/
|
||||
#define CUU(n) "\x1B[%dA", n /* 光标向上 光标向上 <n> 行 */
|
||||
#define CUD(n) "\x1B[%dB", n /* 光标向下 光标向下 <n> 行 */
|
||||
#define CUF(n) "\x1B[%dC", n /* 光标向前 光标向前(右)<n> 行 */
|
||||
#define CUB(n) "\x1B[%dD", n /* 光标向后 光标向后(左)<n> 行 */
|
||||
#define CNL(n) "\x1B[%dE", n /* 光标下一行 光标从当前位置向下 <n> 行 */
|
||||
#define CPL(n) "\x1B[%dF", n /* 光标当前行 光标从当前位置向上 <n> 行 */
|
||||
#define CHA(n) "\x1B[%dG", n /* 绝对光标水平 光标在当前行中水平移动到第 <n> 个位置 */
|
||||
#define VPA(n) "\x1B[%dd", n /* 绝对垂直行位置 光标在当前列中垂直移动到第 <n> 个位置 */
|
||||
#define CUP(y, x) "\x1B[%d;%dH", y, x /* 光标位置 *光标移动到视区中的 <x>; <y> 坐标,其中 <x> 是 <y> 行的列 */
|
||||
#define HVP(y, x) "\x1B[%d;%df", y, x /* 水平垂直位置 *光标移动到视区中的 <x>; <y> 坐标,其中 <x> 是 <y> 行的列 */
|
||||
|
||||
/*光标可见性*/
|
||||
#define CU_START_BL "\x1B[?12h" /* ATT160 文本光标启用闪烁 开始光标闪烁 */
|
||||
#define CU_STOP_BL "\x1B[?12l" /* ATT160 文本光标禁用闪烁 停止闪烁光标 */
|
||||
#define CU_SHOW "\x1B[?25h" /* DECTCEM 文本光标启用模式显示 显示光标 */
|
||||
#define CU_HIDE "\x1B[?25l" /* DECTCEM 文本光标启用模式隐藏 隐藏光标 */
|
||||
|
||||
/* 字符操作 */
|
||||
#define ICH(n) "\x1B[%d@", n /* 插入字符 在当前光标位置插入 <n> 个空格,这会将所有现有文本移到右侧。 向右溢出屏幕的文本会被删除。*/
|
||||
#define DCH(n) "\x1B[%dP", n /* 删除字符 删除当前光标位置的 <n> 个字符,这会从屏幕右边缘以空格字符移动。*/
|
||||
#define ECH(n) "\x1B[%dX", n /* 擦除字符 擦除当前光标位置的 <n> 个字符,方法是使用空格字符覆盖它们。*/
|
||||
#define IL(n) "\x1B[%dL", n /* 插入行 将 <n> 行插入光标位置的缓冲区。 光标所在的行及其下方的行将向下移动。*/
|
||||
#define DL(n) "\x1B[%dM\r", n /* 删除行 从缓冲区中删除 <n> 行,从光标所在的行开始。*/
|
||||
|
||||
/* 打印字体样式 */
|
||||
#define ANSI_COLOR(fg, bg, style) "\x1b[" style ";" fg ";" bg "m"
|
||||
#define ANSI_TXT(fg, bg, style, txt) ANSI_COLOR(fg, bg, style) txt ANSI_COLOR(ANSI_DEFAULT, ANSI_BG_DEFAULT, ANSI_RESET)
|
||||
#define ANSI_COLOR_TXT(fg, txt) "\x1b[" fg "m" txt "\x1b[39m"
|
||||
#define ANSI_BG_TXT(bg, txt) "\x1b[" bg "m" txt "\x1b[49m"
|
||||
#define ANSI_STYLE_TXT(style, txt) "\x1b[" style "m" txt "\x1b[0m"
|
||||
|
||||
// 前景色
|
||||
#define ANSI_BLACK "30"
|
||||
#define ANSI_RED "31"
|
||||
#define ANSI_GREEN "32"
|
||||
#define ANSI_YELLOW "33"
|
||||
#define ANSI_BLUE "34"
|
||||
#define ANSI_MAGENTA "35"
|
||||
#define ANSI_CYAN "36"
|
||||
#define ANSI_WHITE "37"
|
||||
#define ANSI_DEFAULT "39"
|
||||
|
||||
// 背景色
|
||||
#define ANSI_BG_BLACK "40"
|
||||
#define ANSI_BG_RED "41"
|
||||
#define ANSI_BG_GREEN "42"
|
||||
#define ANSI_BG_YELLOW "43"
|
||||
#define ANSI_BG_BLUE "44"
|
||||
#define ANSI_BG_MAGENTA "45"
|
||||
#define ANSI_BG_CYAN "46"
|
||||
#define ANSI_BG_WHITE "47"
|
||||
#define ANSI_BG_DEFAULT "49"
|
||||
|
||||
// 样式
|
||||
#define ANSI_RESET "0"
|
||||
#define ANSI_BOLD "1"
|
||||
#define ANSI_DIM "2"
|
||||
#define ANSI_ITALIC "3"
|
||||
#define ANSI_UNDERLINED "4"
|
||||
#define ANSI_BLINK "5"
|
||||
#define ANSI_REVERSE "7"
|
||||
#define ANSI_HIDDEN "8"
|
||||
|
||||
#ifndef XNR_LINE_MAX_LENGTH
|
||||
#define XNR_LINE_MAX_LENGTH (64)
|
||||
#endif
|
||||
|
||||
typedef struct xnr_line
|
||||
{
|
||||
char line[XNR_LINE_MAX_LENGTH];
|
||||
const char *prompt;
|
||||
int length;
|
||||
int cursor;
|
||||
xnr_io_t *io;
|
||||
} xnr_line_t;
|
||||
|
||||
/**
|
||||
* @description: 初始化
|
||||
* @param le:xnr_line实例,io:xnr_io实例
|
||||
* @return -1:失败,0:成功
|
||||
*/
|
||||
int xnr_line_init(xnr_line_t *le, xnr_io_t *io);
|
||||
|
||||
/**
|
||||
* @description: 在行中光标位置插入一个字符
|
||||
* @param le:xnr_line实例,c:要插入的字符
|
||||
* @return -1:失败,0:成功
|
||||
*/
|
||||
int xnr_line_insert(xnr_line_t *le, char c);
|
||||
|
||||
/**
|
||||
* @description: 删除行中光标位置的一个字符
|
||||
* @param le:xnr_line实例
|
||||
* @return -1:失败,0:成功
|
||||
*/
|
||||
int xnr_line_delete(xnr_line_t *le);
|
||||
|
||||
/**
|
||||
* @description: 获取行缓存指针
|
||||
* @param le:xnr_line实例
|
||||
* @return NULL:失败,其他:成功
|
||||
*/
|
||||
char *xnr_line_line(xnr_line_t *le);
|
||||
|
||||
/**
|
||||
* @description: 获取行缓存指针
|
||||
* @param le:xnr_line实例
|
||||
* @return 行中的字符串长度,不包含'\0'
|
||||
*/
|
||||
int xnr_line_length(xnr_line_t *le);
|
||||
|
||||
/**
|
||||
* @description: 获取行光标位置
|
||||
* @param le:xnr_line实例
|
||||
* @return 返回行光标位置
|
||||
*/
|
||||
int xnr_line_cursor(xnr_line_t *le);
|
||||
|
||||
/**
|
||||
* @description: 设置行光标位置
|
||||
* @param le:xnr_line实例,pos:光标位置
|
||||
* @return 返回行实际光标位置
|
||||
*/
|
||||
int xnr_line_cursor_set(xnr_line_t *le, int pos);
|
||||
|
||||
/**
|
||||
* @description: 光标左移
|
||||
* @param le:xnr_line实例
|
||||
* @return 返回行实际光标位置
|
||||
*/
|
||||
int xnr_line_cursor_left(xnr_line_t *le);
|
||||
|
||||
/**
|
||||
* @description: 光标右移
|
||||
* @param le:xnr_line实例
|
||||
* @return 返回行实际光标位置
|
||||
*/
|
||||
int xnr_line_cursor_right(xnr_line_t *le);
|
||||
|
||||
/**
|
||||
* @description: 仅清除屏幕显示,cls时也会显示prompt
|
||||
* @param le:xnr_line实例
|
||||
* @return 无
|
||||
*/
|
||||
void xnr_line_cls(xnr_line_t *le);
|
||||
|
||||
/**
|
||||
* @description: 仅清除屏幕显示和line buffer, clear时也会显示prompt,所以建议新行后都调用此函数
|
||||
* @param le:xnr_line实例
|
||||
* @return 无
|
||||
*/
|
||||
void xnr_line_clear(xnr_line_t *le);
|
||||
|
||||
/**
|
||||
* @description: 获取光标所在位置的字符
|
||||
* @param le:xnr_line实例
|
||||
* @return 返回光标所在位置的字符
|
||||
*/
|
||||
char xnr_line_current_char(xnr_line_t *le);
|
||||
|
||||
/**
|
||||
* @description: 向行中写字符数组
|
||||
* @param le:xnr_line实例,buf:字符数组,len:字符数组长度
|
||||
* @return 无
|
||||
*/
|
||||
void xnr_line_write(xnr_line_t *le, const char *buf, int len);
|
||||
|
||||
/**
|
||||
* @description: 向行中打印字符串
|
||||
* @param le:xnr_line实例,fmt:格式化字符串,...:参数
|
||||
* @return 无
|
||||
*/
|
||||
void xnr_line_print(xnr_line_t *le, const char *fmt, ...);
|
||||
|
||||
/**
|
||||
* @description: 向行中写字符串
|
||||
* @param le:xnr_line实例,str:字符串
|
||||
* @return 无
|
||||
*/
|
||||
void xnr_line_puts(xnr_line_t *le, const char *str);
|
||||
|
||||
/**
|
||||
* @description: 切分字符串,类似strtok
|
||||
* @param msg:输入字符串,delim:切分标记,get:切分后的结果, max_num:结果buf大小
|
||||
* @return 返回切分后的子字符串个数
|
||||
*/
|
||||
int xnr_line_tok(char *msg, char *delim, char *get[], int max_num);
|
||||
|
||||
/**
|
||||
* @description: 设置提示词,支持ANSI颜色控制
|
||||
* @param le:xnr_line实例,prompt:字符串,切记内部仅存储此字符串指针
|
||||
* @return -1:失败,0:成功
|
||||
*/
|
||||
int xnr_line_bind_prompt(xnr_line_t *le, const char *prompt);
|
||||
|
||||
/**
|
||||
* @description: 获取提示词,可能带有ANSI颜色控制
|
||||
* @param le:xnr_line实例
|
||||
* @return NULL:失败,其他:返回提示词
|
||||
*/
|
||||
const char *xnr_line_prompt(xnr_line_t *le);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
|
@ -1,142 +0,0 @@
|
|||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <ctype.h>
|
||||
#include "xnr_var.h"
|
||||
|
||||
int xnr_var_init(xnr_var_tab_t *tab, xnr_var_t *var_buf, int num)
|
||||
{
|
||||
if (NULL == tab || NULL == var_buf || 0 == num)
|
||||
return -1;
|
||||
tab->capacity = num;
|
||||
tab->var_buf = var_buf;
|
||||
memset(var_buf, 0, sizeof(xnr_var_t) * num);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int xnr_var_set(xnr_var_tab_t *tab, char *name, char *value)
|
||||
{
|
||||
if (NULL == tab ||
|
||||
NULL == name ||
|
||||
NULL == value ||
|
||||
strlen(name) == 0 || strlen(name) >= XNR_VAR_NAME_LEN ||
|
||||
strlen(value) == 0 || strlen(value) >= XNR_VAR_VAR_LEN)
|
||||
return -1;
|
||||
int var_id = -1; // 保存需要设置的槽位
|
||||
int var_empty_id = -1; // 保存空闲槽位
|
||||
for (int i = 0; i < tab->capacity; i++) // 查找name是否存在
|
||||
{
|
||||
if ((-1 == var_empty_id) && (tab->var_buf[i].name[0] == '\0'))
|
||||
{
|
||||
var_empty_id = i;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (strcmp(tab->var_buf[i].name, name) == 0)
|
||||
{
|
||||
var_id = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (-1 == var_id) // 获取一个空闲的var槽位
|
||||
var_id = var_empty_id;
|
||||
|
||||
if (-1 == var_id) // 没有空余槽位
|
||||
return -1;
|
||||
|
||||
if (strcmp(value, "nil") == 0) // 删除变量
|
||||
{
|
||||
tab->var_buf[var_id].name[0] = '\0';
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
strncpy(tab->var_buf[var_id].value, value, XNR_VAR_VAR_LEN);
|
||||
strncpy(tab->var_buf[var_id].name, name, XNR_VAR_NAME_LEN);
|
||||
tab->var_buf[var_id].value[XNR_VAR_VAR_LEN - 1] = '\0';
|
||||
tab->var_buf[var_id].name[XNR_VAR_NAME_LEN - 1] = '\0';
|
||||
}
|
||||
return var_id;
|
||||
}
|
||||
|
||||
char *xnr_var_value(xnr_var_tab_t *tab, char *name)
|
||||
{
|
||||
if (NULL == tab || NULL == name)
|
||||
return "nil";
|
||||
xnr_var_t *var = NULL;
|
||||
for (int i = 0; i < tab->capacity; i++) // 查找name是否存在
|
||||
{
|
||||
if (strcmp(tab->var_buf[i].name, name) == 0)
|
||||
{
|
||||
var = &tab->var_buf[i];
|
||||
}
|
||||
}
|
||||
if (NULL == var)
|
||||
return "nil";
|
||||
else
|
||||
return var->value;
|
||||
}
|
||||
|
||||
xnr_var_t *xnr_var(xnr_var_tab_t *tab, int id)
|
||||
{
|
||||
if (NULL == tab || (id >= tab->capacity))
|
||||
return NULL;
|
||||
return &tab->var_buf[id];
|
||||
}
|
||||
|
||||
int xnr_var_repalce(xnr_var_tab_t *tab, char *in, char *out, int out_len)
|
||||
{
|
||||
if (NULL == tab || NULL == in || out == NULL || 0 == out_len)
|
||||
return -1;
|
||||
int len = strlen(in);
|
||||
char name[XNR_VAR_NAME_LEN] = {0};
|
||||
int out_i = 0;
|
||||
for (unsigned int i = 0; (i < len) && (out_i < (out_len - 1)); i++)
|
||||
{
|
||||
if (in[i] == '$')
|
||||
{
|
||||
int k = 0;
|
||||
char end = ' ';
|
||||
unsigned int j = i + 1;
|
||||
if (in[j] == '{')
|
||||
{
|
||||
end = '}';
|
||||
j++;
|
||||
}
|
||||
while (isprint((int)in[j]) && // 可显示字符
|
||||
in[j] != end // 变量结尾
|
||||
)
|
||||
{
|
||||
if (k < (XNR_VAR_NAME_LEN - 1))
|
||||
{
|
||||
name[k++] = in[j++];
|
||||
}
|
||||
else
|
||||
{
|
||||
return -1; // name长度超限
|
||||
}
|
||||
}
|
||||
name[k] = '\0';
|
||||
char *value = xnr_var_value(tab, name); // 获取变量的值
|
||||
if (value != NULL)
|
||||
{
|
||||
int val_len = strlen(value);
|
||||
for (k = 0; (k < val_len) && (out_i < (out_len - 1)); k++)
|
||||
{
|
||||
out[out_i++] = value[k];
|
||||
}
|
||||
}
|
||||
if (end == '}')
|
||||
i = j;
|
||||
else
|
||||
i = j - 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
out[out_i++] = in[i];
|
||||
}
|
||||
}
|
||||
out[out_i] = '\0';
|
||||
return out_i;
|
||||
}
|
|
@ -1,69 +0,0 @@
|
|||
#ifndef XNR_ENV_H
|
||||
#define XNR_ENV_H
|
||||
|
||||
#include "xnr_conf.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
#ifndef XNR_VAR_NAME_LEN
|
||||
#define XNR_VAR_NAME_LEN (32)
|
||||
#endif
|
||||
#ifndef XNR_VAR_VAR_LEN
|
||||
#define XNR_VAR_VAR_LEN (64)
|
||||
#endif
|
||||
|
||||
typedef struct xnr_var
|
||||
{
|
||||
char name[XNR_VAR_NAME_LEN];
|
||||
char value[XNR_VAR_VAR_LEN];
|
||||
} xnr_var_t;
|
||||
|
||||
typedef struct xnr_var_tab
|
||||
{
|
||||
int capacity;
|
||||
xnr_var_t *var_buf;
|
||||
} xnr_var_tab_t;
|
||||
|
||||
/**
|
||||
* @description: 初始化
|
||||
* @param tab:变量表,var_buf:变量存储空间,num:空间大小
|
||||
* @return -1:失败,0:成功
|
||||
*/
|
||||
int xnr_var_init(xnr_var_tab_t *tab, xnr_var_t *var_buf, int num);
|
||||
|
||||
/**
|
||||
* @description: 设置变量值
|
||||
* @param tab:变量表,name:变量名,value:变量值
|
||||
* @return -1:失败,其他:var_id
|
||||
*/
|
||||
int xnr_var_set(xnr_var_tab_t *tab, char *name, char *value);
|
||||
|
||||
/**
|
||||
* @description: 获取变量值
|
||||
* @param tab:变量表,name:变量名
|
||||
* @return "nil":不存在此变量,其他:成功
|
||||
*/
|
||||
char *xnr_var_value(xnr_var_tab_t *tab, char *name);
|
||||
|
||||
/**
|
||||
* @description: 获取变量结构体
|
||||
* @param tab:变量表,id:变量id
|
||||
* @return NULL:不存在此变量,其他:成功
|
||||
*/
|
||||
xnr_var_t *xnr_var(xnr_var_tab_t *tab, int id);
|
||||
|
||||
/**
|
||||
* @description: 替换字符串中的变量,标识符可以是${name},$name
|
||||
* @param tab:变量表,in:输入字符串,out:输出缓存,out_len:输出缓存长度
|
||||
* @return -1:失败,其他:成功
|
||||
*/
|
||||
int xnr_var_repalce(xnr_var_tab_t *tab, char *in, char *out, int out_len);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
|
@ -5,50 +5,28 @@
|
|||
extern "C" {
|
||||
#endif
|
||||
|
||||
#ifndef XCMD_LINE_MAX_LENGTH
|
||||
#define XCMD_LINE_MAX_LENGTH (128) /* 命令行支持的最大字符数 */
|
||||
#endif
|
||||
|
||||
#ifndef XCMD_PRINT_BUF_MAX_LENGTH
|
||||
#define XCMD_PRINT_BUF_MAX_LENGTH (512) /* xcmd_print缓存 */
|
||||
#endif
|
||||
#define XCMD_PRINT_BUF_MAX_LENGTH (128) /* xcmd_print缓存 */
|
||||
|
||||
#ifndef XCMD_HISTORY_BUF_SZIE
|
||||
#define XCMD_HISTORY_BUF_SZIE (512) /* 支持的历史记录个数, 这个参数对内存的影响很大,建议arduino设置为0,0为不支持 */
|
||||
#endif
|
||||
#define XCMD_HISTORY_BUF_SZIE (256) /* 支持的历史记录缓存大小,实际历史记录个数取决于记录的命令长度,建议内存较小的单片机设置为0 */
|
||||
|
||||
#ifndef XCMD_PARAM_MAX_NUM
|
||||
#define XCMD_PARAM_MAX_NUM (16) /* 支持输入的参数个数 */
|
||||
#endif
|
||||
#define XCMD_PARAM_MAX_NUM (10) /* 支持输入的参数个数 */
|
||||
|
||||
#if XCMD_PRINT_BUF_MAX_LENGTH < (XCMD_LINE_MAX_LENGTH+32)
|
||||
#undef XCMD_PRINT_BUF_MAX_LENGTH
|
||||
#define XCMD_PRINT_BUF_MAX_LENGTH (XCMD_LINE_MAX_LENGTH+32) /* xcmd_print缓存 */
|
||||
#endif
|
||||
|
||||
#ifndef XCMD_DEFAULT_PROMPT
|
||||
#define XCMD_DEFAULT_PROMPT "$ " /*提示符*/
|
||||
#endif
|
||||
|
||||
#ifndef XCMD_DEFAULT_PROMPT_CLOLR
|
||||
#define XCMD_DEFAULT_PROMPT_CLOLR ANSI_BLUE /*提示符颜色*/
|
||||
#endif
|
||||
|
||||
#ifndef XCMD_VAR_NUM
|
||||
#define XCMD_VAR_NUM (32)
|
||||
#endif
|
||||
|
||||
#ifndef XCMD_VAR_NAME_BUF_SZIE
|
||||
#define XCMD_VAR_NAME_BUF_SZIE (32)
|
||||
#endif
|
||||
#define XCMD_VAR_NUM (16) /* 支持的变量的个数,可以为0 */
|
||||
#define XCMD_VAR_NAME_BUF_SZIE (32) /* 变量名最大长度,可以为0 */
|
||||
#define XCMD_VAR_VAR_SZIE (64) /* 变量最大长度,可以为0 */
|
||||
|
||||
#ifndef XCMD_VAR_VAR_SZIE
|
||||
#define XCMD_VAR_VAR_SZIE (64)
|
||||
#endif
|
||||
|
||||
#ifndef ENABLE_XCMD_EXPORT
|
||||
//#define ENABLE_XCMD_EXPORT /*使能XCMD_EXPORT_CMD和XCMD_EXPORT_KEY*/
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
|
|
@ -5,50 +5,28 @@
|
|||
extern "C" {
|
||||
#endif
|
||||
|
||||
#ifndef XCMD_LINE_MAX_LENGTH
|
||||
#define XCMD_LINE_MAX_LENGTH (64) /* 命令行支持的最大字符数 */
|
||||
#endif
|
||||
#define XCMD_LINE_MAX_LENGTH (256) /* 命令行支持的最大字符数 */
|
||||
|
||||
#ifndef XCMD_PRINT_BUF_MAX_LENGTH
|
||||
#define XCMD_PRINT_BUF_MAX_LENGTH (128) /* xcmd_print缓存 */
|
||||
#endif
|
||||
#define XCMD_PRINT_BUF_MAX_LENGTH (4096) /* xcmd_print缓存 */
|
||||
|
||||
#ifndef XCMD_HISTORY_BUF_SZIE
|
||||
#define XCMD_HISTORY_BUF_SZIE (256) /* 支持的历史记录个数, 这个参数对内存的影响很大,建议arduino设置为0,0为不支持 */
|
||||
#endif
|
||||
#define XCMD_HISTORY_BUF_SZIE (4096) /* 支持的历史记录缓存大小,实际历史记录个数取决于记录的命令长度,建议内存较小的单片机设置为0 */
|
||||
|
||||
#ifndef XCMD_PARAM_MAX_NUM
|
||||
#define XCMD_PARAM_MAX_NUM (8) /* 支持输入的参数个数 */
|
||||
#endif
|
||||
#define XCMD_PARAM_MAX_NUM (32) /* 支持输入的参数个数 */
|
||||
|
||||
#if XCMD_PRINT_BUF_MAX_LENGTH < (XCMD_LINE_MAX_LENGTH+32)
|
||||
#undef XCMD_PRINT_BUF_MAX_LENGTH
|
||||
#define XCMD_PRINT_BUF_MAX_LENGTH (XCMD_LINE_MAX_LENGTH+32) /* xcmd_print缓存 */
|
||||
#endif
|
||||
|
||||
#ifndef XCMD_DEFAULT_PROMPT
|
||||
#define XCMD_DEFAULT_PROMPT "$ " /*提示符*/
|
||||
#endif
|
||||
|
||||
#ifndef XCMD_DEFAULT_PROMPT_CLOLR
|
||||
#define XCMD_DEFAULT_PROMPT_CLOLR ANSI_BLUE /*提示符颜色*/
|
||||
#endif
|
||||
|
||||
#ifndef XCMD_VAR_NUM
|
||||
#define XCMD_VAR_NUM (8)
|
||||
#endif
|
||||
|
||||
#ifndef XCMD_VAR_NAME_BUF_SZIE
|
||||
#define XCMD_VAR_NAME_BUF_SZIE (32)
|
||||
#endif
|
||||
#define XCMD_VAR_NUM (512) /* 支持的变量的个数,可以为0 */
|
||||
#define XCMD_VAR_NAME_BUF_SZIE (64) /* 变量名最大长度,可以为0 */
|
||||
#define XCMD_VAR_VAR_SZIE (128) /* 变量最大长度,可以为0 */
|
||||
|
||||
#ifndef XCMD_VAR_VAR_SZIE
|
||||
#define XCMD_VAR_VAR_SZIE (64)
|
||||
#endif
|
||||
|
||||
#ifndef ENABLE_XCMD_EXPORT
|
||||
//#define ENABLE_XCMD_EXPORT /*使能XCMD_EXPORT_CMD和XCMD_EXPORT_KEY*/
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
|
16
src/xcmd.c
16
src/xcmd.c
|
@ -354,18 +354,26 @@ void xcmd_init(xcmder_t *xcmder, io_write_t write, io_read_t read)
|
|||
#ifndef ENABLE_XCMD_EXPORT
|
||||
g_cmd_list.head.next = NULL;
|
||||
#endif
|
||||
xnr_var_init(&xcmder->var_tab, xcmder->var_buf, XCMD_VAR_NUM);
|
||||
xnr_io_init(&xcmder->io, write, read);
|
||||
xnr_key_init(&xcmder->key);
|
||||
xnr_line_init(&xcmder->line, &xcmder->io);
|
||||
#if XCMD_HISTORY_BUF_SZIE != 0
|
||||
xnr_history_init(&xcmder->history, &xcmder->io);
|
||||
#endif
|
||||
#if XCMD_VAR_NUM!=0
|
||||
xnr_var_init(&xcmder->var_tab, xcmder->var_buf, XCMD_VAR_NUM);
|
||||
#endif
|
||||
#if XCMD_VAR_NUM==0
|
||||
char *var_val = ANSI_COLOR_TXT(XCMD_DEFAULT_PROMPT_CLOLR, XCMD_DEFAULT_PROMPT);
|
||||
#else
|
||||
xnr_var_set(&xcmder->var_tab, "prompt", ANSI_COLOR_TXT(XCMD_DEFAULT_PROMPT_CLOLR, XCMD_DEFAULT_PROMPT));
|
||||
char *var_val = xnr_var_value(&xcmder->var_tab, "prompt");
|
||||
#endif
|
||||
xnr_line_bind_prompt(&xcmder->line, var_val);
|
||||
default_cmds_init();
|
||||
default_keys_init();
|
||||
xcmd_exec(xcmder, "logo");
|
||||
xcmd_unregister_cmd("logo");
|
||||
xnr_var_set(&xcmder->var_tab, "prompt", ANSI_COLOR_TXT(XCMD_DEFAULT_PROMPT_CLOLR, XCMD_DEFAULT_PROMPT));
|
||||
char *var_val = xnr_var_value(&xcmder->var_tab, "prompt");
|
||||
xnr_line_bind_prompt(&xcmder->line, var_val);
|
||||
xnr_line_clear(&xcmder->line);
|
||||
xcmder->_initOK = 1;
|
||||
}
|
||||
|
|
|
@ -105,9 +105,13 @@ typedef struct xcmd
|
|||
{
|
||||
xnr_io_t io;
|
||||
xnr_key_t key;
|
||||
#if XCMD_VAR_NUM!=0
|
||||
xnr_var_tab_t var_tab;
|
||||
xnr_var_t var_buf[XCMD_VAR_NUM];
|
||||
#endif
|
||||
#if XCMD_HISTORY_BUF_SZIE != 0
|
||||
xnr_history_t history;
|
||||
#endif
|
||||
xnr_line_t line;
|
||||
cmd_func_t unknow_cmd_cbk; // 输入为命令序列,输出未处理
|
||||
cmd_func_t pre_cmd_cbk; // 输入为命令序列,输出重新赋值给argc
|
||||
|
|
|
@ -11,6 +11,7 @@ static int cmd_clear(int argc, char* argv[])
|
|||
xcmd_print(xcmder, "\033c");
|
||||
return 0;
|
||||
}
|
||||
XCMD_EXPORT_CMD(clear, cmd_clear, "clear screen")
|
||||
|
||||
static int cmd_help(int argc, char* argv[])
|
||||
{
|
||||
|
@ -22,6 +23,7 @@ static int cmd_help(int argc, char* argv[])
|
|||
}
|
||||
return 0;
|
||||
}
|
||||
XCMD_EXPORT_CMD(help, cmd_help, "show this list")
|
||||
|
||||
static int cmd_keys(int argc, char* argv[])
|
||||
{
|
||||
|
@ -34,6 +36,7 @@ static int cmd_keys(int argc, char* argv[])
|
|||
}
|
||||
return 0;
|
||||
}
|
||||
XCMD_EXPORT_CMD(keys, cmd_keys, "show keys")
|
||||
|
||||
static int cmd_logo(int argc, char* argv[])
|
||||
{
|
||||
|
@ -48,7 +51,9 @@ static int cmd_logo(int argc, char* argv[])
|
|||
xcmd_print(xcmder, "%-10s %s\r\n","Version", VERSION);
|
||||
return 0;
|
||||
}
|
||||
XCMD_EXPORT_CMD(logo, cmd_logo, "show logo")
|
||||
|
||||
#if XCMD_VAR_NUM!=0
|
||||
static int cmd_set(int argc, char* argv[])
|
||||
{
|
||||
xcmder_t *xcmder = XCMD_CURRENT();
|
||||
|
@ -58,6 +63,7 @@ static int cmd_set(int argc, char* argv[])
|
|||
}
|
||||
return 0;
|
||||
}
|
||||
XCMD_EXPORT_CMD(setvar, cmd_set, "set var")
|
||||
|
||||
static int cmd_var(int argc, char* argv[])
|
||||
{
|
||||
|
@ -74,13 +80,8 @@ static int cmd_var(int argc, char* argv[])
|
|||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
XCMD_EXPORT_CMD(clear, cmd_clear, "clear screen")
|
||||
XCMD_EXPORT_CMD(help, cmd_help, "show this list")
|
||||
XCMD_EXPORT_CMD(keys, cmd_keys, "show keys")
|
||||
XCMD_EXPORT_CMD(logo, cmd_logo, "show logo")
|
||||
XCMD_EXPORT_CMD(setvar, cmd_set, "set var")
|
||||
XCMD_EXPORT_CMD(var, cmd_var, "get all var")
|
||||
#endif
|
||||
|
||||
static xcmd_t cmds[] =
|
||||
{
|
||||
|
@ -89,9 +90,11 @@ static xcmd_t cmds[] =
|
|||
{"help", cmd_help, "show this list", NULL},
|
||||
{"keys", cmd_keys, "show keys", NULL},
|
||||
{"logo", cmd_logo, "show logo", NULL},
|
||||
#if XCMD_VAR_NUM!=0
|
||||
{"setvar", cmd_set, "set var", NULL},
|
||||
{"var", cmd_var, "get all var", NULL},
|
||||
#endif
|
||||
#endif
|
||||
};
|
||||
|
||||
void default_cmds_init(void)
|
||||
|
|
|
@ -30,8 +30,15 @@ static int xcmd_enter(int argc, char *argv[])
|
|||
char out_line[XNR_LINE_MAX_LENGTH] = {0};
|
||||
xcmd_print(xcmder, "\n\r");
|
||||
char *line = xnr_line_line(&xcmder->line);
|
||||
#if XCMD_HISTORY_BUF_SZIE != 0
|
||||
xnr_history_append(&xcmder->history, line);
|
||||
#endif
|
||||
#if XCMD_VAR_NUM!=0
|
||||
xnr_var_repalce(&xcmder->var_tab, line, out_line, XNR_LINE_MAX_LENGTH);
|
||||
#else
|
||||
strncpy(out_line, line, XNR_LINE_MAX_LENGTH);
|
||||
#endif
|
||||
|
||||
if (out_line[0])
|
||||
{
|
||||
xcmd_exec(xcmder, out_line);
|
||||
|
@ -61,6 +68,7 @@ static int xcmd_cursor_right(int argc, char *argv[])
|
|||
}
|
||||
XCMD_EXPORT_KEY(KEY_RIGHT, xcmd_cursor_right, "right")
|
||||
|
||||
#if XCMD_HISTORY_BUF_SZIE != 0
|
||||
static int xcmd_history_dw(int argc, char *argv[])
|
||||
{
|
||||
xcmder_t *xcmder = XCMD_CURRENT();
|
||||
|
@ -90,6 +98,7 @@ static int xcmd_history_up(int argc, char *argv[])
|
|||
return 0;
|
||||
}
|
||||
XCMD_EXPORT_KEY(KEY_UP, xcmd_history_up, "up")
|
||||
#endif
|
||||
|
||||
static int xcmd_auto_completion(int argc, char *argv[])
|
||||
{
|
||||
|
@ -155,9 +164,11 @@ static xcmd_key_t default_keys[] =
|
|||
{KEY_LEFT, xcmd_cursor_left, "left", NULL},
|
||||
{KEY_RIGHT, xcmd_cursor_right, "right", NULL},
|
||||
{KEY_TAB, xcmd_auto_completion, "tab", NULL},
|
||||
#if XCMD_HISTORY_BUF_SZIE != 0
|
||||
{KEY_DW, xcmd_history_dw, "down", NULL},
|
||||
{KEY_UP, xcmd_history_up, "up", NULL},
|
||||
#endif
|
||||
#endif
|
||||
};
|
||||
|
||||
void default_keys_init(void)
|
||||
|
|
|
@ -3,6 +3,8 @@
|
|||
|
||||
#include "xcmd_confg.h"
|
||||
|
||||
/* 注意请勿修改此处代码 */
|
||||
|
||||
//行缓存长度
|
||||
#ifndef XNR_LINE_MAX_LENGTH
|
||||
#define XNR_LINE_MAX_LENGTH (XCMD_LINE_MAX_LENGTH)
|
||||
|
|
Loading…
Reference in New Issue