From 5d11f3332d8567b551d37cf066fb27c6ba63b96d Mon Sep 17 00:00:00 2001 From: Andre Renaud Date: Thu, 29 Jan 2026 09:52:28 +1300 Subject: [PATCH 1/4] Try and play nicer with UTF-8 input sequences --- embedded_cli.c | 2 +- examples/posix_demo.c | 2 +- tests/embedded_cli_test.c | 17 ++++++++++++++++- 3 files changed, 18 insertions(+), 3 deletions(-) diff --git a/embedded_cli.c b/embedded_cli.c index 6313a20..a410a8b 100644 --- a/embedded_cli.c +++ b/embedded_cli.c @@ -399,7 +399,7 @@ bool embedded_cli_insert_char(struct embedded_cli *cli, char ch) cli_putchar(cli, '\n', true); break; default: - if (ch > 0) + if (ch < 0 || ch >= 32) embedded_cli_insert_default_char(cli, ch); } } diff --git a/examples/posix_demo.c b/examples/posix_demo.c index 30b0142..996c8d4 100644 --- a/examples/posix_demo.c +++ b/examples/posix_demo.c @@ -95,7 +95,7 @@ int main(void) cli_argc = embedded_cli_argc(&cli, &cli_argv); printf("Got %d args\n", cli_argc); for (int i = 0; i < cli_argc; i++) { - printf("Arg %d/%d: '%s'\n", i, cli_argc, cli_argv[i]); + printf("Arg %d/%d: [%lu bytes] '%s'\n", i, cli_argc, strlen(cli_argv[i]), cli_argv[i]); } done = cli_argc >= 1 && (strcmp(cli_argv[0], "quit") == 0); diff --git a/tests/embedded_cli_test.c b/tests/embedded_cli_test.c index b080ec5..f4b5608 100644 --- a/tests/embedded_cli_test.c +++ b/tests/embedded_cli_test.c @@ -300,6 +300,20 @@ static void test_max_chars(void) TEST_ASSERT(cli.buffer[sizeof(cli.buffer) - 2] == 'f'); } +static void test_utf8(void) +{ + struct embedded_cli cli; + char **argv; + embedded_cli_init(&cli, NULL, NULL, NULL); + test_insert_line(&cli, "normal ñ ü 中文 text\n"); + int argc = embedded_cli_argc(&cli, &argv); + TEST_ASSERT(argc == 5); + TEST_ASSERT(strcmp(argv[0], "normal") == 0); + TEST_ASSERT(strcmp(argv[1], "ñ") == 0); + TEST_ASSERT(strcmp(argv[2], "ü") == 0); + TEST_ASSERT(strcmp(argv[3], "中文") == 0); +} + TEST_LIST = { {"simple", test_simple}, {"argc", test_argc}, @@ -317,5 +331,6 @@ TEST_LIST = { {"quotes", test_quotes}, {"too_many_args", test_too_many_args}, {"max_chars", test_max_chars}, - {NULL, NULL}, + {"utf8", test_utf8}, + {NULL, NULL} }; \ No newline at end of file From 4a698bf61cde86bdb0f3676400eda8888ff9be25 Mon Sep 17 00:00:00 2001 From: Andre Renaud Date: Thu, 29 Jan 2026 09:54:15 +1300 Subject: [PATCH 2/4] Missed one of the utf8 strings --- tests/embedded_cli_test.c | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/embedded_cli_test.c b/tests/embedded_cli_test.c index f4b5608..c71e53f 100644 --- a/tests/embedded_cli_test.c +++ b/tests/embedded_cli_test.c @@ -312,6 +312,7 @@ static void test_utf8(void) TEST_ASSERT(strcmp(argv[1], "ñ") == 0); TEST_ASSERT(strcmp(argv[2], "ü") == 0); TEST_ASSERT(strcmp(argv[3], "中文") == 0); + TEST_ASSERT(strcmp(argv[4], "text") == 0); } TEST_LIST = { From 3262389b91748e9b4ca4d0d8d9ebb8ea56538245 Mon Sep 17 00:00:00 2001 From: Andre Renaud Date: Thu, 29 Jan 2026 09:57:47 +1300 Subject: [PATCH 3/4] Fix up formatting --- examples/posix_demo.c | 3 ++- tests/embedded_cli_test.c | 34 ++++++++++++++++------------------ 2 files changed, 18 insertions(+), 19 deletions(-) diff --git a/examples/posix_demo.c b/examples/posix_demo.c index 996c8d4..e500faf 100644 --- a/examples/posix_demo.c +++ b/examples/posix_demo.c @@ -95,7 +95,8 @@ int main(void) cli_argc = embedded_cli_argc(&cli, &cli_argv); printf("Got %d args\n", cli_argc); for (int i = 0; i < cli_argc; i++) { - printf("Arg %d/%d: [%lu bytes] '%s'\n", i, cli_argc, strlen(cli_argv[i]), cli_argv[i]); + printf("Arg %d/%d: [%lu bytes] '%s'\n", i, cli_argc, + strlen(cli_argv[i]), cli_argv[i]); } done = cli_argc >= 1 && (strcmp(cli_argv[0], "quit") == 0); diff --git a/tests/embedded_cli_test.c b/tests/embedded_cli_test.c index c71e53f..62c1ff2 100644 --- a/tests/embedded_cli_test.c +++ b/tests/embedded_cli_test.c @@ -315,23 +315,21 @@ static void test_utf8(void) TEST_ASSERT(strcmp(argv[4], "text") == 0); } -TEST_LIST = { - {"simple", test_simple}, - {"argc", test_argc}, - {"delete", test_delete}, - {"cursor_left", test_cursor_left}, - {"cursor_right", test_cursor_right}, +TEST_LIST = {{"simple", test_simple}, + {"argc", test_argc}, + {"delete", test_delete}, + {"cursor_left", test_cursor_left}, + {"cursor_right", test_cursor_right}, #if EMBEDDED_CLI_HISTORY_LEN - {"history", test_history}, - {"history_keys", test_history_keys}, - {"search", test_search}, - {"up_down", test_up_down}, + {"history", test_history}, + {"history_keys", test_history_keys}, + {"search", test_search}, + {"up_down", test_up_down}, #endif - {"multiple", test_multiple}, - {"echo", test_echo}, - {"quotes", test_quotes}, - {"too_many_args", test_too_many_args}, - {"max_chars", test_max_chars}, - {"utf8", test_utf8}, - {NULL, NULL} -}; \ No newline at end of file + {"multiple", test_multiple}, + {"echo", test_echo}, + {"quotes", test_quotes}, + {"too_many_args", test_too_many_args}, + {"max_chars", test_max_chars}, + {"utf8", test_utf8}, + {NULL, NULL}}; \ No newline at end of file From 414bee082de406368d1f620697661ecf016b968f Mon Sep 17 00:00:00 2001 From: Andre Renaud Date: Thu, 29 Jan 2026 10:16:22 +1300 Subject: [PATCH 4/4] Added a test for unknown control sequences, update a couple of minor bugs --- embedded_cli.c | 7 +++++-- embedded_cli.h | 2 +- tests/embedded_cli_test.c | 3 +++ 3 files changed, 9 insertions(+), 3 deletions(-) diff --git a/embedded_cli.c b/embedded_cli.c index a410a8b..a594a39 100644 --- a/embedded_cli.c +++ b/embedded_cli.c @@ -146,10 +146,13 @@ const char *embedded_cli_get_history(struct embedded_cli *cli, if (len == 0) return NULL; pos += len + 1; - if (pos == sizeof(cli->history)) + if (pos >= sizeof(cli->history)) return NULL; } + if (cli->history[pos] == '\0') + return NULL; + return &cli->history[pos]; #else (void)cli; @@ -168,7 +171,7 @@ static void embedded_cli_extend_history(struct embedded_cli *cli) if (strcmp(cli->buffer, cli->history) == 0) return; memmove(&cli->history[len + 1], &cli->history[0], - sizeof(cli->history) - len + 1); + sizeof(cli->history) - (len + 1)); memcpy(cli->history, cli->buffer, len + 1); // Make sure it's always nul terminated cli->history[sizeof(cli->history) - 1] = '\0'; diff --git a/embedded_cli.h b/embedded_cli.h index b232e4f..c2bc5f6 100644 --- a/embedded_cli.h +++ b/embedded_cli.h @@ -133,7 +133,7 @@ const char *embedded_cli_get_line(const struct embedded_cli *cli); /** * Parses the internal buffer and returns it as an argc/argc combo - * @return number of values in argv (maximum of EMBEDDED_CLI_MAX_ARGC) + * @return number of values in argv (maximum of EMBEDDED_CLI_MAX_ARGC - 1) */ int embedded_cli_argc(struct embedded_cli *cli, char ***argv); diff --git a/tests/embedded_cli_test.c b/tests/embedded_cli_test.c index 62c1ff2..e62b4bf 100644 --- a/tests/embedded_cli_test.c +++ b/tests/embedded_cli_test.c @@ -18,6 +18,7 @@ #define CTRL_L "\x0c" #define CTRL_R "\x12" #define CTRL_U "\x15" +#define CTRL_X "\x18" static void cli_equals(const struct embedded_cli *cli, const char *line) { @@ -214,6 +215,8 @@ static void test_multiple(void) {"abc" LEFT LEFT CTRL_L "\n", "abc"}, {"abc" CTRL_U "\n", ""}, {"abc" LEFT LEFT CTRL_U "\n", "bc"}, + // The check below ensures we ignore unknown control sequences + {CTRL_X " " CTRL_X " " CTRL_X "\n", " "}, {NULL, NULL}, };