mirror of
https://git.code.sf.net/p/quake/quakeforge
synced 2024-11-10 15:22:04 +00:00
very nice command line tab completeion from Shawn Walker
<eviltypeguy@qeradiant.com>
This commit is contained in:
parent
01a9372add
commit
443196e66b
10 changed files with 448 additions and 56 deletions
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
153
libs/util/cmd.c
153
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
|
||||
|
||||
|
|
|
@ -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");
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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:
|
||||
|
|
Loading…
Reference in a new issue