diff --git a/AUTHORS b/AUTHORS index 95b1de351..f89166aa2 100644 --- a/AUTHORS +++ b/AUTHORS @@ -159,7 +159,8 @@ Completion for fish shell by Hoang Nguyen (a.k.a. FollieHiyuki). Alexandr Keyp (a.k.a. IAmKapuze) contributed improvements for :compare. -高浩亮 (a.k.a. haolian9) enabled mouse handling. +高浩亮 (a.k.a. haolian9) enabled mouse handling and fixed displaying of +foreign commands in `:commands {prefix}`. Zhipeng Xue fixed a couple of potential NULL dereferences. diff --git a/ChangeLog b/ChangeLog index f0e43cf30..fb88391da 100644 --- a/ChangeLog +++ b/ChangeLog @@ -167,6 +167,9 @@ Fixed running tests with locales that use comma for decimal point. Thanks to PRESFIL. + Fixed foreign commands missing from `:commands {prefix}` output. Patch by + 高浩亮 (a.k.a. haolian9). + 0.13-beta to 0.13 (2023-04-04) Made "withicase" and "withrcase" affect how files are sorted before diff --git a/src/engine/cmds.c b/src/engine/cmds.c index 11eff14f7..a2a3ad1bf 100644 --- a/src/engine/cmds.c +++ b/src/engine/cmds.c @@ -84,6 +84,8 @@ static int delcommand_cmd(const cmd_info_t *cmd_info); TSTATIC char ** dispatch_line(const char args[], int *count, char sep, int regexp, int quotes, int noescaping, int comments, int *last_arg, int (**positions)[2]); +static int is_builtin_like_cmd(const cmd_t *cmd); +static int is_custom_cmd(const cmd_t *cmd); static int is_separator(char c, char sep); void @@ -1122,8 +1124,7 @@ vle_cmds_add_user(const char name[], const char body[], const char descr[], cmd_t *cur = &inner->head; while(cur->next != NULL && (cmp = strcmp(cur->next->name, name)) < 0) { - int builtin_like = (cur->next->type == BUILTIN_CMD) - || (cur->next->type == FOREIGN_CMD); + const int builtin_like = is_builtin_like_cmd(cur->next); if(has_emark && builtin_like && cur->next->emark && strncmp(name, cur->next->name, len - 1) == 0) { @@ -1143,7 +1144,7 @@ vle_cmds_add_user(const char name[], const char body[], const char descr[], if(cmp == 0) { cur = cur->next; - if(cur->type == BUILTIN_CMD || cur->type == FOREIGN_CMD) + if(is_builtin_like_cmd(cur)) return CMDS_ERR_NO_BUILTIN_REDEFINE; if(!overwrite) return CMDS_ERR_NEED_BANG; @@ -1621,7 +1622,7 @@ vle_cmds_print_udcs(const char beginning[]) void *ptr; size_t new_size; - if(strncmp(cur->name, beginning, len) != 0 || cur->type != USER_CMD) + if(strncmp(cur->name, beginning, len) != 0 || !is_custom_cmd(cur)) { cur = cur->next; continue; @@ -1637,20 +1638,52 @@ vle_cmds_print_udcs(const char beginning[]) content_len = strlen(content); } - new_size = content_len + 1 + strlen(cur->name) + 10 + strlen(cur->cmd) + 1; + + const char *detail = ""; + if(cur->type == USER_CMD) + { + detail = cur->cmd; + } + else if(cur->type == FOREIGN_CMD) + { + detail = cur->descr; + } + else + { + assert(0 && "Expected user or foreign command type."); + } + + new_size = content_len + 1 + strlen(cur->name) + 10 + strlen(detail) + 1; ptr = realloc(content, new_size); if(ptr != NULL) { content = ptr; content_len += sprintf(content + content_len, "\n%-*s %s", 10, cur->name, - cur->cmd); + detail); } + cur = cur->next; } return content; } +/* Checks that a command has all the features of a builtin one. Returns + * non-zero if so. */ +static int +is_builtin_like_cmd(const cmd_t *cmd) +{ + return (cmd->type == BUILTIN_CMD || cmd->type == FOREIGN_CMD); +} + +/* Checks that a command's definition is not part of the code base. Returns + * non-zero if so. */ +static int +is_custom_cmd(const cmd_t *cmd) +{ + return (cmd->type == USER_CMD || cmd->type == FOREIGN_CMD); +} + char * vle_cmds_past_arg(const char args[]) { diff --git a/tests/cmds/foreign.c b/tests/cmds/foreign.c index f3ec52c36..51cd85357 100644 --- a/tests/cmds/foreign.c +++ b/tests/cmds/foreign.c @@ -1,6 +1,7 @@ #include #include /* NULL */ +#include /* free() */ #include "../../src/engine/cmds.h" #include "../../src/engine/completion.h" @@ -102,6 +103,27 @@ TEST(foreign_command_is_listed_with_udcs) free_string_array(list, len); } +TEST(foreign_command_is_printed_with_udcs) +{ + cmd_add_t command = { + .name = "foreign", + .abbr = NULL, + .id = -1, + .descr = "descr", + .flags = HAS_RANGE, + .handler = &foreign_cmd, + .min_args = 0, + .max_args = NOT_DEF, + }; + assert_success(vle_cmds_add_foreign(&command)); + + char *desc = vle_cmds_print_udcs("fore"); + + assert_string_equal("Command -- Action\nforeign descr", desc); + + free(desc); +} + static int foreign_cmd(const cmd_info_t *cmd_info) {