From c8c8995b705acb272947ab6ddf072a442eba7ea4 Mon Sep 17 00:00:00 2001 From: Michiel van Baak Date: Wed, 10 Dec 2008 17:09:15 +0000 Subject: add tab completion for 'core set debug X filename.c' (closes issue #13969) Reported by: jtodd Patches: 20081205__bug13969.diff.txt uploaded by Corydon76 (license 14) Tested by: mvanbaak, eliel git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@162687 65c4cc65-6c06-0410-ace0-fbb531ad65f3 --- include/asterisk.h | 1 + main/asterisk.c | 18 ++++++++++++ main/cli.c | 80 ++++++++++++++++++++++++++++++++++++++++++++++++------ 3 files changed, 91 insertions(+), 8 deletions(-) diff --git a/include/asterisk.h b/include/asterisk.h index d83cc3dda..7ebc96d1c 100644 --- a/include/asterisk.h +++ b/include/asterisk.h @@ -89,6 +89,7 @@ void ast_unregister_file_version(const char *file); */ const char *ast_file_version_find(const char *file); +char *ast_complete_source_filename(const char *partial, int n); /*! * \brief Register/unregister a source code file with the core. diff --git a/main/asterisk.c b/main/asterisk.c index 89fd7a9aa..81e08722c 100644 --- a/main/asterisk.c +++ b/main/asterisk.c @@ -319,6 +319,24 @@ void ast_unregister_file_version(const char *file) ast_free(find); } +char *ast_complete_source_filename(const char *partial, int n) +{ + struct file_version *find; + size_t len = strlen(partial); + int count = 0; + char *res = NULL; + + AST_RWLIST_RDLOCK(&file_versions); + AST_RWLIST_TRAVERSE(&file_versions, find, list) { + if (!strncasecmp(find->file, partial, len) && ++count > n) { + res = ast_strdup(find->file); + break; + } + } + AST_RWLIST_UNLOCK(&file_versions); + return res; +} + /*! \brief Find version for given module name */ const char *ast_file_version_find(const char *file) { diff --git a/main/cli.c b/main/cli.c index e590046e8..063eeaae2 100644 --- a/main/cli.c +++ b/main/cli.c @@ -317,6 +317,46 @@ static struct ast_debug_file *find_debug_file(const char *fn, unsigned int debug return df; } +static char *complete_number(const char *partial, unsigned int min, unsigned int max, int n) +{ + int i, count = 0; + unsigned int prospective[2]; + unsigned int part = strtoul(partial, NULL, 10); + char next[12]; + + if (part < min || part > max) { + return NULL; + } + + for (i = 0; i < 21; i++) { + if (i == 0) { + prospective[0] = prospective[1] = part; + } else if (part == 0 && !ast_strlen_zero(partial)) { + break; + } else if (i < 11) { + prospective[0] = prospective[1] = part * 10 + (i - 1); + } else { + prospective[0] = (part * 10 + (i - 11)) * 10; + prospective[1] = prospective[0] + 9; + } + if (i < 11 && (prospective[0] < min || prospective[0] > max)) { + continue; + } else if (prospective[1] < min || prospective[0] > max) { + continue; + } + + if (++count > n) { + if (i < 11) { + snprintf(next, sizeof(next), "%u", prospective[0]); + } else { + snprintf(next, sizeof(next), "%u...", prospective[0] / 10); + } + return ast_strdup(next); + } + } + return NULL; +} + static char *handle_verbose(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) { int oldval; @@ -325,6 +365,7 @@ static char *handle_verbose(struct ast_cli_entry *e, int cmd, struct ast_cli_arg int fd = a->fd; int argc = a->argc; char **argv = a->argv; + char *argv3 = a->argv ? S_OR(a->argv[3], "") : ""; int *dst; char *what; struct debug_file_list *dfl; @@ -333,7 +374,7 @@ static char *handle_verbose(struct ast_cli_entry *e, int cmd, struct ast_cli_arg switch (cmd) { case CLI_INIT: - e->command = "core set {debug|verbose} [off|atleast]"; + e->command = "core set {debug|verbose}"; e->usage = "Usage: core set {debug|verbose} [atleast] [filename]\n" " core set {debug|verbose} off\n" @@ -344,6 +385,29 @@ static char *handle_verbose(struct ast_cli_entry *e, int cmd, struct ast_cli_arg return NULL; case CLI_GENERATE: + if (a->pos == 3 || (a->pos == 4 && !strcasecmp(a->argv[3], "atleast"))) { + char *pos = a->pos == 3 ? argv3 : S_OR(a->argv[4], ""); + int numbermatch = (ast_strlen_zero(pos) || strchr("123456789", pos[0])) ? 0 : 21; + if (a->n < 21 && numbermatch == 0) { + return complete_number(pos, 0, 0x7fffffff, a->n); + } else if (pos[0] == '0') { + if (a->n == 0) { + return ast_strdup("0"); + } else { + return NULL; + } + } else if (a->n == (21 - numbermatch)) { + if (a->pos == 3 && !strncasecmp(argv3, "off", strlen(argv3))) { + return ast_strdup("off"); + } else if (a->pos == 3 && !strncasecmp(argv3, "atleast", strlen(argv3))) { + return ast_strdup("atleast"); + } + } else if (a->n == (22 - numbermatch) && a->pos == 3 && ast_strlen_zero(argv3)) { + return ast_strdup("atleast"); + } + } else if (a->pos == 4 || (a->pos == 5 && !strcasecmp(argv3, "atleast"))) { + return ast_complete_source_filename(a->pos == 4 ? S_OR(a->argv[4], "") : S_OR(a->argv[5], ""), a->n); + } return NULL; } /* all the above return, so we proceed with the handler. @@ -352,7 +416,7 @@ static char *handle_verbose(struct ast_cli_entry *e, int cmd, struct ast_cli_arg if (argc < e->args) return CLI_SHOWUSAGE; - if (!strcasecmp(argv[e->args - 2], "debug")) { + if (!strcasecmp(argv[e->args - 1], "debug")) { dst = &option_debug; oldval = option_debug; what = "Core debug"; @@ -361,7 +425,7 @@ static char *handle_verbose(struct ast_cli_entry *e, int cmd, struct ast_cli_arg oldval = option_verbose; what = "Verbosity"; } - if (argc == e->args && !strcasecmp(argv[e->args - 1], "off")) { + if (argc == e->args + 1 && !strcasecmp(argv[e->args], "off")) { unsigned int debug = (*what == 'C'); newlevel = 0; @@ -375,17 +439,17 @@ static char *handle_verbose(struct ast_cli_entry *e, int cmd, struct ast_cli_arg goto done; } - if (!strcasecmp(argv[e->args-1], "atleast")) + if (!strcasecmp(argv[e->args], "atleast")) atleast = 1; - if (argc != e->args + atleast && argc != e->args + atleast + 1) + if (argc != e->args + atleast + 1 && argc != e->args + atleast + 2) return CLI_SHOWUSAGE; - if (sscanf(argv[e->args + atleast - 1], "%d", &newlevel) != 1) + if (sscanf(argv[e->args + atleast], "%d", &newlevel) != 1) return CLI_SHOWUSAGE; - if (argc == e->args + atleast + 1) { + if (argc == e->args + atleast + 2) { unsigned int debug = (*what == 'C'); dfl = debug ? &debug_files : &verbose_files; - fn = argv[e->args + atleast]; + fn = argv[e->args + atleast + 1]; AST_RWLIST_WRLOCK(dfl); -- cgit v1.2.3