<URL: http://bugs.freeciv.org/Ticket/Display.html?id=40673 >
The attached patch makes the /help command list all matching option or command names when the user uses it on an ambiguous name prefix. For example, from the server console: > help t Help argument 't' is ambiguous. Possible matches: team take timeoutincrease topology tinyisles temperature techlevel techpenalty timeout timeaddenemymove turnblock This is achieved by augmenting the function match_prefix() to take an int array that is filled in with the indices of all of the potential matches. The resulting function is renamed to match_prefix_full() and a convenience wrapper match_prefix() is added so that existing code works without modification. A function cmd_reply_matches() is added to stdinhand.c which takes the array of indices and constructs a simple reply message listing the matched names and sends it to the calling user. ----------------------------------------------------------------------- あいまいさはいとおしい。
server/stdinhand.c | 46 ++++++++++++++++++++++++++++++++++++++++++++-- utility/shared.c | 41 ++++++++++++++++++++++++++++++++++------- utility/shared.h | 10 ++++++++++ 3 files changed, 88 insertions(+), 9 deletions(-) diff --git a/server/stdinhand.c b/server/stdinhand.c index af02e70..6930d9c 100644 --- a/server/stdinhand.c +++ b/server/stdinhand.c @@ -4120,6 +4120,44 @@ static void show_help_command_list(struct connection *caller, } /************************************************************************** + Send a reply to the caller listing the matched names from an ambiguous + prefix. +**************************************************************************/ +static void cmd_reply_matches(enum command_id cmd, + struct connection *caller, + m_pre_accessor_fn_t accessor_fn, + int *matches, int num_matches) +{ + char buf[MAX_LEN_MSG]; + const char *src, *end; + char *dest; + int i; + + if (accessor_fn == NULL || matches == NULL || num_matches < 1) { + return; + } + + dest = buf; + end = buf + sizeof(buf) - 1; + + for (i = 0; i < num_matches && dest < end; i++) { + src = accessor_fn(matches[i]); + if (!src) { + continue; + } + if (dest != buf) { + *dest++ = ' '; + } + while (*src != '\0' && dest < end) { + *dest++ = *src++; + } + } + *dest = '\0'; + + cmd_reply(cmd, caller, C_COMMENT, _("Possible matches: %s"), buf); +} + +/************************************************************************** Additional 'help' arguments **************************************************************************/ enum HELP_GENERAL_ARGS { HELP_GENERAL_COMMANDS, HELP_GENERAL_OPTIONS, @@ -4153,14 +4191,16 @@ static const char *helparg_accessor(int i) { **************************************************************************/ static bool show_help(struct connection *caller, char *arg) { + int matches[64], num_matches = 0; enum m_pre_result match_result; int ind; assert(!may_use_nothing(caller)); /* no commands means no help, either */ - match_result = match_prefix(helparg_accessor, HELP_ARG_NUM, 0, - mystrncasecmp, NULL, arg, &ind); + match_result = match_prefix_full(helparg_accessor, HELP_ARG_NUM, 0, + mystrncasecmp, NULL, arg, &ind, matches, + ARRAY_SIZE(matches), &num_matches); if (match_result==M_PRE_EMPTY) { show_help_intro(caller, CMD_HELP); @@ -4169,6 +4209,8 @@ static bool show_help(struct connection *caller, char *arg) if (match_result==M_PRE_AMBIGUOUS) { cmd_reply(CMD_HELP, caller, C_FAIL, _("Help argument '%s' is ambiguous."), arg); + cmd_reply_matches(CMD_HELP, caller, helparg_accessor, + matches, num_matches); return FALSE; } if (match_result==M_PRE_FAIL) { diff --git a/utility/shared.c b/utility/shared.c index dc29a9e..fdb6ef3 100644 --- a/utility/shared.c +++ b/utility/shared.c @@ -1512,20 +1512,41 @@ const char *m_pre_description(enum m_pre_result result) } /*************************************************************************** + See match_prefix_full(). +***************************************************************************/ +enum m_pre_result match_prefix(m_pre_accessor_fn_t accessor_fn, + size_t n_names, + size_t max_len_name, + m_pre_strncmp_fn_t cmp_fn, + m_strlen_fn_t len_fn, + const char *prefix, + int *ind_result) +{ + return match_prefix_full(accessor_fn, n_names, max_len_name, cmp_fn, + len_fn, prefix, ind_result, NULL, 0, NULL); +} + +/*************************************************************************** Given n names, with maximum length max_len_name, accessed by accessor_fn(0) to accessor_fn(n-1), look for matching prefix according to given comparison function. Returns type of match or fail, and for return <= M_PRE_AMBIGUOUS sets *ind_result with matching index (or for ambiguous, first match). If max_len_name==0, treat as no maximum. + If the int array 'matches' is non-NULL, up to 'max_matches' ambiguous + matching names indices will be inserted into it. If 'pnum_matches' is + non-NULL, it will be set to the number of indices inserted into 'matches'. ***************************************************************************/ -enum m_pre_result match_prefix(m_pre_accessor_fn_t accessor_fn, - size_t n_names, - size_t max_len_name, - m_pre_strncmp_fn_t cmp_fn, - m_strlen_fn_t len_fn, - const char *prefix, - int *ind_result) +enum m_pre_result match_prefix_full(m_pre_accessor_fn_t accessor_fn, + size_t n_names, + size_t max_len_name, + m_pre_strncmp_fn_t cmp_fn, + m_strlen_fn_t len_fn, + const char *prefix, + int *ind_result, + int *matches, + int max_matches, + int *pnum_matches) { int i, len, nmatches; @@ -1552,6 +1573,9 @@ enum m_pre_result match_prefix(m_pre_accessor_fn_t accessor_fn, if (nmatches==0) { *ind_result = i; /* first match */ } + if (matches != NULL && nmatches < max_matches) { + matches[nmatches] = i; + } nmatches++; } } @@ -1559,6 +1583,9 @@ enum m_pre_result match_prefix(m_pre_accessor_fn_t accessor_fn, if (nmatches == 1) { return M_PRE_ONLY; } else if (nmatches > 1) { + if (pnum_matches != NULL) { + *pnum_matches = MIN(max_matches, nmatches); + } return M_PRE_AMBIGUOUS; } else { return M_PRE_FAIL; diff --git a/utility/shared.h b/utility/shared.h index df20992..fbc2d7d 100644 --- a/utility/shared.h +++ b/utility/shared.h @@ -235,6 +235,16 @@ enum m_pre_result match_prefix(m_pre_accessor_fn_t accessor_fn, m_strlen_fn_t len_fn, const char *prefix, int *ind_result); +enum m_pre_result match_prefix_full(m_pre_accessor_fn_t accessor_fn, + size_t n_names, + size_t max_len_name, + m_pre_strncmp_fn_t cmp_fn, + m_strlen_fn_t len_fn, + const char *prefix, + int *ind_result, + int *matches, + int max_matches, + int *pnum_matches); char *get_multicast_group(bool ipv6_prefered); void interpret_tilde(char* buf, size_t buf_size, const char* filename);
_______________________________________________ Freeciv-dev mailing list Freeciv-dev@gna.org https://mail.gna.org/listinfo/freeciv-dev