From c79335a2a108886685d78a4395cdfdd6321c300f Mon Sep 17 00:00:00 2001 From: LokLiang Date: Thu, 10 Apr 2025 09:50:56 +0800 Subject: [PATCH] =?UTF-8?q?=E5=A2=9E=E5=BC=BA=E5=91=BD=E4=BB=A4=E5=8F=82?= =?UTF-8?q?=E6=95=B0=E8=BE=93=E5=87=BA=E7=9A=84=E9=A2=9C=E8=89=B2=E6=98=BE?= =?UTF-8?q?=E7=A4=BA=EF=BC=8C=E6=B7=BB=E5=8A=A0=E5=8F=98=E9=87=8F=E8=87=AA?= =?UTF-8?q?=E5=8A=A8=E8=A1=A5=E5=85=A8=E6=8F=90=E7=A4=BA=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- components/system/source/shell/sh.c | 2 +- components/system/source/shell/sh_vset.c | 18 +++++- components/system/source/shell/sh_vset.h | 77 ++++++++++++++++++++++++ 3 files changed, 95 insertions(+), 2 deletions(-) diff --git a/components/system/source/shell/sh.c b/components/system/source/shell/sh.c index 602fc86..49eec14 100755 --- a/components/system/source/shell/sh.c +++ b/components/system/source/shell/sh.c @@ -3131,7 +3131,7 @@ SH_CMD_FN(_cmd_tree) // 打印收到的参数 for (int i = 0; i < argc; i++) { - sh_echo(sh_hdl, "%s%s%s", i ? "" : "'", argv[i], i + 1 < argc ? " " : "'\r\n"); + sh_echo(sh_hdl, "%s" _COLOR_Y "%s" _COLOR_END "%s", i ? "" : "'", argv[i], i + 1 < argc ? " " : "'\r\n"); } // 打印命令树 diff --git a/components/system/source/shell/sh_vset.c b/components/system/source/shell/sh_vset.c index 8e8a955..1e6e00f 100755 --- a/components/system/source/shell/sh_vset.c +++ b/components/system/source/shell/sh_vset.c @@ -239,6 +239,22 @@ bool vset_option_cp(sh_t *sh_hdl, int argc, const char *argv[], bool flag, const } } +/** + * @brief 对应 SET_VAR 所设置的变量的可用自动补全函数,默认补全一个 '?' 号 + * + * @param sh_hdl 原参数 + * @param argc 原参数 + * @param argv 原参数指针值,可能被更新 + * @param flag 原参数 + */ +void vset_cp_hint(sh_t *sh_hdl, int argc, const char *argv[], bool flag) +{ + if (argc + flag == 1) + { + sh_completion_resource(sh_hdl, NULL, "? ", NULL); + } +} + int vset_unsigned(void *dest, __type_attr_t attr, vset_cb cb, const char *argv[], unsigned int low, unsigned int high) { SYS_ASSERT(s_sh_hdl, "未使用 vset_init() 初始化"); @@ -971,7 +987,6 @@ static int _set_dest_string(void *dest, __type_attr_t attr, vset_cb cb, const ch switch (attr) { case __TYPE_ATTR_STR: - memset(dest, 0, bufsize); if (memcmp(dest, str, str_size)) { if (cb) @@ -981,6 +996,7 @@ static int _set_dest_string(void *dest, __type_attr_t attr, vset_cb cb, const ch memcpy(value, str, str_size); _PARAM_CB(); } + memset(dest, 0, bufsize); memcpy(dest, str, str_size); global_cb = s_global_cb; } diff --git a/components/system/source/shell/sh_vset.h b/components/system/source/shell/sh_vset.h index 0cc67bf..d0f20fb 100755 --- a/components/system/source/shell/sh_vset.h +++ b/components/system/source/shell/sh_vset.h @@ -172,6 +172,83 @@ void vset_init(sh_t *sh_hdl, vset_global_cb global_cb); void vset_force_cb(void); +/** 定义设置变量的简化形式 ***************************************************************************************/ + +/* 对应 SET_VAR 所设置的变量的可用自动补全函数,默认补全一个 '?' 号 */ +void vset_cp_hint(sh_t *sh_hdl, int argc, const char *argv[], bool flag); + +/** + * @brief 实例化一个变量的设置函数。 + * @param NAME 函数名称 + * @param VAR 静态变量地址,支持的类型有:无符号整形、带符号整型、单精度的浮点数 + * @param LOW 变量的最小值。变量值可用 + * @param HIGH 变量的最大值。变量值可用 + * @param CB 设置变量的回调函数。注意:只有在设置变量的值合法并且新的值与原值不相等时才会被调用。也可取值为 NULL + */ +#define VSET_VAR(NAME, VAR, LOW, HIGH, CB) \ + SH_CMD_FN(NAME) { return SET_VAR_CB(VAR, LOW, HIGH, CB); } \ + SH_CMD_CP_FN(_SH_CONCAT(NAME, _tab)) { vset_cp_hint(sh_hdl, argc, argv, flag); } + +/** + * @brief 实例化一个字符串的设置函数。 + * @param NAME 函数名称 + * @param VAR 静态字符串数组的地址 + * @param CB 设置变量的回调函数。注意:只有在设置变量的值合法并且新的值与原值不相等时才会被调用。也可取值为 NULL + */ +#define VSET_STR(NAME, VAR, CB) \ + SH_CMD_FN(NAME) { return SET_VAR_CB(VAR, 0, 0, CB); } \ + SH_CMD_CP_FN(_SH_CONCAT(NAME, _tab)) { vset_cp_hint(sh_hdl, argc, argv, flag); } + +/** + * @brief 实例化一个枚举型变量的设置函数。 + * @param NAME 函数名称 + * @param VAR 静态变量地址,支持的类型有:无符号整形、带符号整型,不支持浮点数 + * @param ENUM_STR 枚举型变量的可选值 + * @param CB 设置变量的回调函数。注意:只有在设置变量的值合法并且新的值与原值不相等时才会被调用。也可取值为 NULL + */ +#define VSET_ENUM(NAME, VAR, ENUM, CB) \ + SH_CMD_FN(NAME) { return SET_ENUM_CB(VAR, ENUM, CB); } \ + SH_CMD_CP_FN(_SH_CONCAT(NAME, _tab)) { SET_CP_ENUM(ENUM); } + +/** + * @brief 实例化一个选项的设置函数。 + * @param NAME 函数名称 + * @param ... 可变参数,选项描述结构体的数组。成员格式: {"选项", "选项的帮助信息", 设置函数, 枚举型变量的可选值 } + * @example + * @code + * static int _vset_int(const char *argv[]) { return SET_VAR_CB(&g_int32, -10, 10, _vset_cb_int32); } + * static int _vset_str(const char *argv[]) { return SET_VAR_CB(&g_str, 0, 0, _vset_cb_char); } + * static int _vset_enum(const char *argv[]) { return SET_ENUM_CB(&g_int32, s_enum_str, _vset_cb_int32); } + * VSET_OPTION( + * _example, + * {"--int32", "int32_t 类型的变量", _vset_int, NULL}, + * {"--str", "字符串 类型的变量", _vset_str, NULL}, + * {"--enum", "枚举类型的变量", _vset_enum, s_enum_str}) + * @endcode + */ +#define VSET_OPTION(NAME, ...) \ + static sh_vset_param_t const _SH_CONCAT(_opts_, NAME)[] = { \ + __VA_ARGS__}; \ + SH_CMD_FN(NAME) { return PSET_FN(_SH_CONCAT(_opts_, NAME)); } \ + SH_CMD_CP_FN(_SH_CONCAT(NAME, _tab)) { PSET_CP(_SH_CONCAT(_opts_, NAME)); } + +/** + * @brief 可替代 SH_SETUP_CMD 定义命令列表 SH_REGISTER_CMD 或 SH_DEF_SUB_CMD 中的成员 + * @param CMD 命令(字符串,不要有空格) + * @param HELP 命令的帮助信息(字符串) + * @param FUNC 由 VSET_VAR()、VSET_STR()、VSET_ENUM()、VSET_OPTION() 定义的函数 + * @example + * @code + * SH_DEF_SUB_CMD(_register_sample, + * VSET_SETUP_CMD("ex1", "设置单个 数值 变量", _ex1), // ex1 <数值> + * VSET_SETUP_CMD("ex2", "设置单个 字符串 变量", _ex2), // ex2 <字符串> + * VSET_SETUP_CMD("ex3", "设置单个 枚举 变量", _ex3), // ex3 <枚举> + * VSET_SETUP_CMD("ex4", "设置有多个选项的变量", _ex4), // ex4 [选项<值>] [选项<值>] ... + * ); + * @endcode + */ +#define VSET_SETUP_CMD(CMD, HELP, FUNC) SH_SETUP_CMD(CMD, HELP, FUNC, FUNC##_tab) + /** * @note 对本函数的进一步说明。 *