From 443196e66b75fd3be19a87de1eceb2bdc38e9aae Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 28 Jun 2001 04:05:14 +0000 Subject: [PATCH] very nice command line tab completeion from Shawn Walker --- include/QF/cmd.h | 9 +++ include/QF/console.h | 10 +++ include/QF/cvar.h | 6 ++ libs/util/cmd.c | 153 ++++++++++++++++++++++++++++++++++++++++++- libs/util/console.c | 46 +++++++++++++ libs/util/cvar.c | 57 ++++++++++++++++ nq/source/console.c | 83 +++++++++++++++++++++++ nq/source/keys.c | 27 +------- qw/source/console.c | 86 +++++++++++++++++++++++- qw/source/keys.c | 27 +------- 10 files changed, 448 insertions(+), 56 deletions(-) diff --git a/include/QF/cmd.h b/include/QF/cmd.h index 077cf393f..e8a9b58c5 100644 --- a/include/QF/cmd.h +++ b/include/QF/cmd.h @@ -105,6 +105,15 @@ char *Cmd_CompleteCommand (char *partial); // attempts to match a partial command for automatic command line completion // returns NULL if nothing fits +int Cmd_CompleteAliasCountPossible (char *partial); +char **Cmd_CompleteAliasBuildList (char *partial); +int Cmd_CompleteCountPossible (char *partial); +char **Cmd_CompleteBuildList (char *partial); +char *Cmd_CompleteAlias (char *partial); +// Enhanced console completion by Fett erich@heintz.com +// Added by EvilTypeGuy eviltypeguy@qeradiant.com + + int Cmd_Argc (void); char *Cmd_Argv (int arg); char *Cmd_Args (void); diff --git a/include/QF/console.h b/include/QF/console.h index 3e2e926b6..48a1331a7 100644 --- a/include/QF/console.h +++ b/include/QF/console.h @@ -71,6 +71,16 @@ void Con_DrawNotify (void); void Con_ClearNotify (void); void Con_ToggleConsole_f (void); +// wrapper function to attempt to either complete the command line +// or to list possible matches grouped by type +// (i.e. will display possible variables, aliases, commands +// that match what they've typed so far) +void Con_CompleteCommandLine(void); + +// Generic libs/util/console.c function to display a list +// formatted in columns on the console +void Con_DisplayList(char **list, int con_linewidth); + extern struct cvar_s *developer; #endif // __console_h diff --git a/include/QF/cvar.h b/include/QF/cvar.h index dd10e5b22..7ceff0c98 100644 --- a/include/QF/cvar.h +++ b/include/QF/cvar.h @@ -110,6 +110,12 @@ qboolean Cvar_Command (void); // with the archive flag set to true. void Cvar_WriteVariables (VFile *f); +// Added by EvilTypeGuy - functions for tab completion system +// Thanks to Fett erich@heintz.com +// Thanks to taniwha +int Cvar_CompleteCountPossible (char *partial); +char **Cvar_CompleteBuildList (char *partial); + // Returns a pointer to the Cvar, NULL if not found cvar_t *Cvar_FindVar (char *var_name); diff --git a/libs/util/cmd.c b/libs/util/cmd.c index 5bf463381..d860defa1 100644 --- a/libs/util/cmd.c +++ b/libs/util/cmd.c @@ -625,9 +625,9 @@ Cmd_Exists (char *cmd_name) char * Cmd_CompleteCommand (char *partial) { - cmd_function_t *cmd; - int len; - cmdalias_t *a; + cmd_function_t *cmd; + int len; + cmdalias_t *a; len = strlen (partial); @@ -653,6 +653,153 @@ Cmd_CompleteCommand (char *partial) return NULL; } +/* + Cmd_CompleteCountPossible + + New function for tab-completion system + Added by EvilTypeGuy + Thanks to Fett erich@heintz.com + Thanks to taniwha + +*/ +int +Cmd_CompleteCountPossible (char *partial) +{ + cmd_function_t *cmd; + int len; + int h; + + h = 0; + len = strlen(partial); + + if (!len) + return 0; + + // Loop through the command list and count all partial matches + for (cmd = cmd_functions; cmd; cmd = cmd->next) + if (!strncasecmp(partial, cmd->name, len)) + h++; + + return h; +} + +/* + Cmd_CompleteBuildList + + New function for tab-completion system + Added by EvilTypeGuy + Thanks to Fett erich@heintz.com + Thanks to taniwha + +*/ +char ** +Cmd_CompleteBuildList (char *partial) +{ + cmd_function_t *cmd; + int len = 0; + int bpos = 0; + int sizeofbuf = (Cmd_CompleteCountPossible (partial) + 1) * sizeof (char *); + char **buf; + + len = strlen(partial); + buf = malloc(sizeofbuf + sizeof (char *)); + // Loop through the alias list and print all matches + for (cmd = cmd_functions; cmd; cmd = cmd->next) + if (!strncasecmp(partial, cmd->name, len)) + buf[bpos++] = cmd->name; + + buf[bpos] = NULL; + return buf; +} + +/* + Cmd_CompleteAlias + + New function for tab-completion system + Added by EvilTypeGuy + Thanks to Fett erich@heintz.com + Thanks to taniwha + +*/ +char +*Cmd_CompleteAlias (char * partial) +{ + cmdalias_t *alias; + int len; + + len = strlen(partial); + + if (!len) + return NULL; + + // Check functions + for (alias = cmd_alias; alias; alias = alias->next) + if (!strncasecmp(partial, alias->name, len)) + return alias->name; + + return NULL; +} + +/* + Cmd_CompleteAliasCountPossible + + New function for tab-completion system + Added by EvilTypeGuy + Thanks to Fett erich@heintz.com + Thanks to taniwha + +*/ +int +Cmd_CompleteAliasCountPossible (char *partial) +{ + cmdalias_t *alias; + int len; + int h; + + h = 0; + + len = strlen(partial); + + if (!len) + return 0; + + // Loop through the command list and count all partial matches + for (alias = cmd_alias; alias; alias = alias->next) + if (!strncasecmp(partial, alias->name, len)) + h++; + + return h; +} + +/* + Cmd_CompleteAliasBuildList + + New function for tab-completion system + Added by EvilTypeGuy + Thanks to Fett erich@heintz.com + Thanks to taniwha + +*/ +char ** +Cmd_CompleteAliasBuildList (char *partial) +{ + cmdalias_t *alias; + int len = 0; + int bpos = 0; + int sizeofbuf = (Cmd_CompleteAliasCountPossible (partial) + 1) * sizeof (char *); + char **buf; + + len = strlen(partial); + buf = malloc(sizeofbuf + sizeof (char *)); + // Loop through the alias list and print all matches + for (alias = cmd_alias; alias; alias = alias->next) + if (!strncasecmp(partial, alias->name, len)) + buf[bpos++] = alias->name; + + buf[bpos] = NULL; + return buf; +} + /* Cmd_ExpandVariables diff --git a/libs/util/console.c b/libs/util/console.c index 2616c09bf..fa69c405c 100644 --- a/libs/util/console.c +++ b/libs/util/console.c @@ -85,3 +85,49 @@ Con_DPrintf (char *fmt, ...) Con_Print (msg); } + +/* + Con_DisplayList + + New function for tab-completion system + Added by EvilTypeGuy + MEGA Thanks to Taniwha + +*/ +void +Con_DisplayList(char **list, int con_linewidth) +{ + int i = 0; + int pos = 0; + int len = 0; + int maxlen = 0; + int width = (con_linewidth - 4); + char **walk = list; + + while (*walk) { + len = strlen(*walk); + if (len > maxlen) + maxlen = len; + walk++; + } + maxlen += 1; + + while (*list) { + len = strlen(*list); + if (pos + maxlen >= width) { + Con_Printf("\n"); + pos = 0; + } + + Con_Printf("%s", *list); + for (i = 0; i < (maxlen - len); i++) + Con_Printf(" "); + + pos += maxlen; + list++; + } + + if (pos) + Con_Printf("\n\n"); +} + diff --git a/libs/util/cvar.c b/libs/util/cvar.c index d7c37ec9c..04a10b3e6 100644 --- a/libs/util/cvar.c +++ b/libs/util/cvar.c @@ -178,6 +178,63 @@ Cvar_CompleteVariable (char *partial) return NULL; } +/* + CVar_CompleteCountPossible + + New function for tab-completion system + Added by EvilTypeGuy + Thanks to Fett erich@heintz.com + +*/ +int +Cvar_CompleteCountPossible (char *partial) +{ + cvar_t *cvar; + int len; + int h; + + h = 0; + len = strlen(partial); + + if (!len) + return 0; + + // Loop through the cvars and count all possible matches + for (cvar = cvar_vars; cvar; cvar = cvar->next) + if (!strncasecmp(partial, cvar->name, len)) + h++; + + return h; +} + +/* + CVar_CompleteBuildList + + New function for tab-completion system + Added by EvilTypeGuy + Thanks to Fett erich@heintz.com + Thanks to taniwha + +*/ +char ** +Cvar_CompleteBuildList (char *partial) +{ + cvar_t *cvar; + int len = 0; + int bpos = 0; + int sizeofbuf = (Cvar_CompleteCountPossible (partial) + 1) * sizeof (char *); + char **buf; + + len = strlen(partial); + buf = malloc(sizeofbuf + sizeof (char *)); + // Loop through the alias list and print all matches + for (cvar = cvar_vars; cvar; cvar = cvar->next) + if (!strncasecmp(partial, cvar->name, len)) + buf[bpos++] = cvar->name; + + buf[bpos] = NULL; + return buf; +} /* Cvar_Set diff --git a/nq/source/console.c b/nq/source/console.c index 1cf0039b4..4b4cb4767 100644 --- a/nq/source/console.c +++ b/nq/source/console.c @@ -560,3 +560,86 @@ Con_DrawDownload (int lines) for (i = 0; i < strlen (dlbar); i++) Draw_Character8 ((i + 1) << 3, y, dlbar[i]); } + +/* + Con_CompleteCommandLine + + New function for tab-completion system + Added by EvilTypeGuy + Thanks to Fett erich@heintz.com + Thanks to taniwha + +*/void +Con_CompleteCommandLine (void) +{ + char *cmd = ""; + char *s; + char **list; + int c, v, a, i; + + s = key_lines[edit_line] + 1; + if (*s == '\\' || *s == '/') + s++; + + // Count number of possible matches + c = Cmd_CompleteCountPossible(s); + v = Cvar_CompleteCountPossible(s); + a = Cmd_CompleteAliasCountPossible(s); + + if (!(c + v + a)) // No possible matches + return; + + if (c + v + a > 1) { + // 'quakebar' + Con_Printf("\n\35"); + for (i = 0; i < con_linewidth - 4; i++) + Con_Printf("\36"); + Con_Printf("\37\n"); + + // Print Possible Commands + if (c) { + Con_Printf("%i possible command%s\n", c, (c > 1) ? "s: " : ":"); + list = Cmd_CompleteBuildList(s); + Con_DisplayList(list, con_linewidth); + free(list); + } + + if (v) { + Con_Printf("%i possible variable%s\n", v, (v > 1) ? "s: " : ":"); + list = Cvar_CompleteBuildList(s); + Con_DisplayList(list, con_linewidth); + free(list); + } + + if (a) { + Con_Printf("%i possible aliases%s\n", a, (a > 1) ? "s: " : ":"); + list = Cmd_CompleteAliasBuildList(s); + Con_DisplayList(list, con_linewidth); + free(list); + } + return; + } + + // The number of possible matches has been narrowed down to 1 + // So just use the original QF functions + + if (c) + cmd = Cmd_CompleteCommand(s); + + if (v) + cmd = Cvar_CompleteVariable(s); + + if (a) + cmd = Cmd_CompleteAlias(s); + + if (cmd) { + key_lines[edit_line][1] = '/'; + strcpy(key_lines[edit_line] + 2, cmd); + key_linepos = strlen (cmd) + 2; + key_lines[edit_line][key_linepos] = ' '; + key_linepos++; + key_lines[edit_line][key_linepos] = 0; + return; + } +} + diff --git a/nq/source/keys.c b/nq/source/keys.c index a925dc32f..0e9ada7c3 100644 --- a/nq/source/keys.c +++ b/nq/source/keys.c @@ -229,31 +229,6 @@ CheckForCommand (void) return true; } - -void -CompleteCommand (void) -{ - char *cmd, *s; - - s = key_lines[edit_line] + 1; - if (*s == '\\' || *s == '/') - s++; - - cmd = Cmd_CompleteCommand (s); - if (!cmd) - cmd = Cvar_CompleteVariable (s); - if (cmd) { - key_lines[edit_line][1] = '/'; - strcpy (key_lines[edit_line] + 2, cmd); - key_linepos = strlen (cmd) + 2; - key_lines[edit_line][key_linepos] = ' '; - key_linepos++; - key_lines[edit_line][key_linepos] = 0; - return; - } -} - - /* Key_Console @@ -306,7 +281,7 @@ Key_Console (int key) case K_TAB: // command completion - CompleteCommand (); + Con_CompleteCommandLine(); // New tab command completion return; case K_BACKSPACE: diff --git a/qw/source/console.c b/qw/source/console.c index 1cf0039b4..590ca12f0 100644 --- a/qw/source/console.c +++ b/qw/source/console.c @@ -496,7 +496,7 @@ Con_DrawConsole (int lines) y -= 8; rows--; } - + row = con->display; for (i = 0; i < rows; i++, y -= 8, row--) { if (row < 0) @@ -560,3 +560,87 @@ Con_DrawDownload (int lines) for (i = 0; i < strlen (dlbar); i++) Draw_Character8 ((i + 1) << 3, y, dlbar[i]); } + +/* + Con_CompleteCommandLine + + New function for tab-completion system + Added by EvilTypeGuy + Thanks to Fett erich@heintz.com + Thanks to taniwha + +*/ +void +Con_CompleteCommandLine (void) +{ + char *cmd = ""; + char *s; + char **list; + int c, v, a, i; + + s = key_lines[edit_line] + 1; + if (*s == '\\' || *s == '/') + s++; + + // Count number of possible matches + c = Cmd_CompleteCountPossible(s); + v = Cvar_CompleteCountPossible(s); + a = Cmd_CompleteAliasCountPossible(s); + + if (!(c + v + a)) // No possible matches + return; + + if (c + v + a > 1) { + // 'quakebar' + Con_Printf("\n\35"); + for (i = 0; i < con_linewidth - 4; i++) + Con_Printf("\36"); + Con_Printf("\37\n"); + + // Print Possible Commands + if (c) { + Con_Printf("%i possible command%s\n", c, (c > 1) ? "s: " : ":"); + list = Cmd_CompleteBuildList(s); + Con_DisplayList(list, con_linewidth); + free(list); + } + + if (v) { + Con_Printf("%i possible variable%s\n", v, (v > 1) ? "s: " : ":"); + list = Cvar_CompleteBuildList(s); + Con_DisplayList(list, con_linewidth); + free(list); + } + + if (a) { + Con_Printf("%i possible aliases%s\n", a, (a > 1) ? "s: " : ":"); + list = Cmd_CompleteAliasBuildList(s); + Con_DisplayList(list, con_linewidth); + free(list); + } + return; + } + + // The number of possible matches has been narrowed down to 1 + // So just use the original QF functions + + if (c) + cmd = Cmd_CompleteCommand(s); + + if (v) + cmd = Cvar_CompleteVariable(s); + + if (a) + cmd = Cmd_CompleteAlias(s); + + if (cmd) { + key_lines[edit_line][1] = '/'; + strcpy(key_lines[edit_line] + 2, cmd); + key_linepos = strlen (cmd) + 2; + key_lines[edit_line][key_linepos] = ' '; + key_linepos++; + key_lines[edit_line][key_linepos] = 0; + return; + } +} + diff --git a/qw/source/keys.c b/qw/source/keys.c index 74f67aebf..5775c8a18 100644 --- a/qw/source/keys.c +++ b/qw/source/keys.c @@ -230,31 +230,6 @@ CheckForCommand (void) return true; } - -void -CompleteCommand (void) -{ - char *cmd, *s; - - s = key_lines[edit_line] + 1; - if (*s == '\\' || *s == '/') - s++; - - cmd = Cmd_CompleteCommand (s); - if (!cmd) - cmd = Cvar_CompleteVariable (s); - if (cmd) { - key_lines[edit_line][1] = '/'; - strcpy (key_lines[edit_line] + 2, cmd); - key_linepos = strlen (cmd) + 2; - key_lines[edit_line][key_linepos] = ' '; - key_linepos++; - key_lines[edit_line][key_linepos] = 0; - return; - } -} - - /* Key_Console @@ -307,7 +282,7 @@ Key_Console (int key) case K_TAB: // command completion - CompleteCommand (); + Con_CompleteCommandLine(); // New tab command completion return; case K_BACKSPACE: