mirror of
https://github.com/YGGverse/xash3d-fwgs.git
synced 2025-01-29 16:24:16 +00:00
engine: console: implement autocomplete for any arg count, add autocomplete for bind for both keys and commands
This commit is contained in:
parent
62fb743a20
commit
7aa163f713
@ -782,7 +782,7 @@ void pfnResetTutorMessageDecayData( void );
|
|||||||
//
|
//
|
||||||
// con_utils.c
|
// con_utils.c
|
||||||
//
|
//
|
||||||
qboolean Cmd_AutocompleteName( const char *source, char *buffer, size_t bufsize );
|
qboolean Cmd_AutocompleteName( const char *source, int arg, char *buffer, size_t bufsize );
|
||||||
void Con_CompleteCommand( field_t *field );
|
void Con_CompleteCommand( field_t *field );
|
||||||
void Cmd_AutoComplete( char *complete_string );
|
void Cmd_AutoComplete( char *complete_string );
|
||||||
void Cmd_AutoCompleteClear( void );
|
void Cmd_AutoCompleteClear( void );
|
||||||
|
@ -25,6 +25,7 @@ extern convar_t *con_gamemaps;
|
|||||||
typedef struct autocomplete_list_s
|
typedef struct autocomplete_list_s
|
||||||
{
|
{
|
||||||
const char *name;
|
const char *name;
|
||||||
|
int arg; // argument number to handle
|
||||||
qboolean (*func)( const char *s, char *name, int length );
|
qboolean (*func)( const char *s, char *name, int length );
|
||||||
} autocomplete_list_t;
|
} autocomplete_list_t;
|
||||||
|
|
||||||
@ -528,7 +529,137 @@ qboolean Cmd_GetItemsList( const char *s, char *completedname, int length )
|
|||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
/*
|
||||||
|
=====================================
|
||||||
|
Cmd_GetKeysList
|
||||||
|
|
||||||
|
Autocomplete for bind command
|
||||||
|
=====================================
|
||||||
|
*/
|
||||||
|
qboolean Cmd_GetKeysList( const char *s, char *completedname, int length )
|
||||||
|
{
|
||||||
|
size_t i, numkeys;
|
||||||
|
string keys[256];
|
||||||
|
string matchbuf;
|
||||||
|
|
||||||
|
// compare keys list with current keyword
|
||||||
|
for( i = 0, numkeys = 0; i < 255; i++ )
|
||||||
|
{
|
||||||
|
const char *keyname = Key_KeynumToString( i );
|
||||||
|
|
||||||
|
if(( *s == '*' ) || !Q_strnicmp( keyname, s, Q_strlen( s )))
|
||||||
|
Q_strcpy( keys[numkeys++], keyname );
|
||||||
|
}
|
||||||
|
|
||||||
|
if( !numkeys ) return false;
|
||||||
|
Q_strncpy( matchbuf, keys[0], sizeof( matchbuf ));
|
||||||
|
if( completedname && length )
|
||||||
|
Q_strncpy( completedname, matchbuf, length );
|
||||||
|
if( numkeys == 1 ) return true;
|
||||||
|
|
||||||
|
for( i = 0; i < numkeys; i++ )
|
||||||
|
{
|
||||||
|
Q_strncpy( matchbuf, keys[i], sizeof( matchbuf ));
|
||||||
|
Con_Printf( "%16s\n", matchbuf );
|
||||||
|
}
|
||||||
|
|
||||||
|
Con_Printf( "\n^3 %i keys found.\n", numkeys );
|
||||||
|
|
||||||
|
if( completedname && length )
|
||||||
|
{
|
||||||
|
for( i = 0; matchbuf[i]; i++ )
|
||||||
|
{
|
||||||
|
if( Q_tolower( completedname[i] ) != Q_tolower( matchbuf[i] ))
|
||||||
|
completedname[i] = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
#endif // XASH_DEDICATED
|
||||||
|
|
||||||
|
/*
|
||||||
|
===============
|
||||||
|
Con_AddCommandToList
|
||||||
|
|
||||||
|
===============
|
||||||
|
*/
|
||||||
|
static void Con_AddCommandToList( const char *s, const char *unused1, const char *unused2, void *_autocompleteList )
|
||||||
|
{
|
||||||
|
con_autocomplete_t *list = (con_autocomplete_t*)_autocompleteList;
|
||||||
|
|
||||||
|
if( *s == '@' ) return; // never show system cvars or cmds
|
||||||
|
if( list->matchCount >= CON_MAXCMDS ) return; // list is full
|
||||||
|
|
||||||
|
if( Q_strnicmp( s, list->completionString, Q_strlen( list->completionString ) ) )
|
||||||
|
return; // no match
|
||||||
|
|
||||||
|
list->cmds[list->matchCount++] = copystring( s );
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
=====================================
|
||||||
|
Cmd_GetCommandsList
|
||||||
|
|
||||||
|
Autocomplete for bind command
|
||||||
|
=====================================
|
||||||
|
*/
|
||||||
|
qboolean Cmd_GetCommandsList( const char *s, char *completedname, int length )
|
||||||
|
{
|
||||||
|
size_t i;
|
||||||
|
string matchbuf;
|
||||||
|
con_autocomplete_t list; // local autocomplete list
|
||||||
|
|
||||||
|
memset( &list, 0, sizeof( list ));
|
||||||
|
|
||||||
|
list.completionString = s;
|
||||||
|
|
||||||
|
// skip backslash
|
||||||
|
while( *list.completionString && (*list.completionString == '\\' || *list.completionString == '/') )
|
||||||
|
list.completionString++;
|
||||||
|
|
||||||
|
if( !Q_strlen( list.completionString ) )
|
||||||
|
return false;
|
||||||
|
|
||||||
|
// find matching commands and variables
|
||||||
|
Cmd_LookupCmds( NULL, &list, (setpair_t)Con_AddCommandToList );
|
||||||
|
Cvar_LookupVars( 0, NULL, &list, (setpair_t)Con_AddCommandToList );
|
||||||
|
|
||||||
|
if( !list.matchCount ) return false;
|
||||||
|
Q_strncpy( matchbuf, list.cmds[0], sizeof( matchbuf ));
|
||||||
|
if( completedname && length )
|
||||||
|
Q_strncpy( completedname, matchbuf, length );
|
||||||
|
if( list.matchCount == 1 ) return true;
|
||||||
|
|
||||||
|
for( i = 0; i < list.matchCount; i++ )
|
||||||
|
{
|
||||||
|
Q_strncpy( matchbuf, list.cmds[i], sizeof( matchbuf ));
|
||||||
|
Con_Printf( "%16s\n", matchbuf );
|
||||||
|
}
|
||||||
|
|
||||||
|
Con_Printf( "\n^3 %i commands found.\n", list.matchCount );
|
||||||
|
|
||||||
|
if( completedname && length )
|
||||||
|
{
|
||||||
|
for( i = 0; matchbuf[i]; i++ )
|
||||||
|
{
|
||||||
|
if( Q_tolower( completedname[i] ) != Q_tolower( matchbuf[i] ))
|
||||||
|
completedname[i] = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for( i = 0; i < list.matchCount; i++ )
|
||||||
|
{
|
||||||
|
if( list.cmds[i] != NULL )
|
||||||
|
{
|
||||||
|
Mem_Free( list.cmds[i] );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
=====================================
|
=====================================
|
||||||
@ -831,27 +962,30 @@ int Cmd_CheckMapsList( int fRefresh )
|
|||||||
|
|
||||||
autocomplete_list_t cmd_list[] =
|
autocomplete_list_t cmd_list[] =
|
||||||
{
|
{
|
||||||
{ "map_background", Cmd_GetMapList },
|
{ "map_background", 1, Cmd_GetMapList },
|
||||||
{ "changelevel2", Cmd_GetMapList },
|
{ "changelevel2", 1, Cmd_GetMapList },
|
||||||
{ "changelevel", Cmd_GetMapList },
|
{ "changelevel", 1, Cmd_GetMapList },
|
||||||
{ "playdemo", Cmd_GetDemoList, },
|
{ "playdemo", 1, Cmd_GetDemoList, },
|
||||||
{ "timedemo", Cmd_GetDemoList, },
|
{ "timedemo", 1, Cmd_GetDemoList, },
|
||||||
{ "playvol", Cmd_GetSoundList },
|
{ "playvol", 1, Cmd_GetSoundList },
|
||||||
{ "hpkval", Cmd_GetCustomList },
|
{ "hpkval", 1, Cmd_GetCustomList },
|
||||||
{ "entpatch", Cmd_GetMapList },
|
{ "entpatch", 1, Cmd_GetMapList },
|
||||||
{ "music", Cmd_GetMusicList, },
|
{ "music", 1, Cmd_GetMusicList, },
|
||||||
{ "movie", Cmd_GetMovieList },
|
{ "movie", 1, Cmd_GetMovieList },
|
||||||
{ "exec", Cmd_GetConfigList },
|
{ "exec", 1, Cmd_GetConfigList },
|
||||||
#ifndef XASH_DEDICATED
|
#ifndef XASH_DEDICATED
|
||||||
{ "give", Cmd_GetItemsList },
|
{ "give", 1, Cmd_GetItemsList },
|
||||||
{ "drop", Cmd_GetItemsList },
|
{ "drop", 1, Cmd_GetItemsList },
|
||||||
|
{ "bind", 1, Cmd_GetKeysList },
|
||||||
|
{ "unbind", 1, Cmd_GetKeysList },
|
||||||
|
{ "bind", 2, Cmd_GetCommandsList },
|
||||||
#endif
|
#endif
|
||||||
{ "game", Cmd_GetGamesList },
|
{ "game", 1, Cmd_GetGamesList },
|
||||||
{ "save", Cmd_GetSavesList },
|
{ "save", 1, Cmd_GetSavesList },
|
||||||
{ "load", Cmd_GetSavesList },
|
{ "load", 1, Cmd_GetSavesList },
|
||||||
{ "play", Cmd_GetSoundList },
|
{ "play", 1, Cmd_GetSoundList },
|
||||||
{ "map", Cmd_GetMapList },
|
{ "map", 1, Cmd_GetMapList },
|
||||||
{ "cd", Cmd_GetCDList },
|
{ "cd", 1, Cmd_GetCDList },
|
||||||
{ NULL }, // termiantor
|
{ NULL }, // termiantor
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -879,36 +1013,19 @@ Autocomplete filename
|
|||||||
for various cmds
|
for various cmds
|
||||||
============
|
============
|
||||||
*/
|
*/
|
||||||
qboolean Cmd_AutocompleteName( const char *source, char *buffer, size_t bufsize )
|
qboolean Cmd_AutocompleteName( const char *source, int arg, char *buffer, size_t bufsize )
|
||||||
{
|
{
|
||||||
autocomplete_list_t *list;
|
autocomplete_list_t *list;
|
||||||
|
|
||||||
for( list = cmd_list; list->name; list++ )
|
for( list = cmd_list; list->name; list++ )
|
||||||
{
|
{
|
||||||
if( Cmd_CheckName( list->name ))
|
if( list->arg == arg && Cmd_CheckName( list->name ))
|
||||||
return list->func( source, buffer, bufsize );
|
return list->func( source, buffer, bufsize );
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
===============
|
|
||||||
Con_AddCommandToList
|
|
||||||
|
|
||||||
===============
|
|
||||||
*/
|
|
||||||
static void Con_AddCommandToList( const char *s, const char *unused1, const char *unused2, void *unused3 )
|
|
||||||
{
|
|
||||||
if( *s == '@' ) return; // never show system cvars or cmds
|
|
||||||
if( con.matchCount >= CON_MAXCMDS ) return; // list is full
|
|
||||||
|
|
||||||
if( Q_strnicmp( s, con.completionString, Q_strlen( con.completionString ) ) )
|
|
||||||
return; // no match
|
|
||||||
|
|
||||||
con.cmds[con.matchCount++] = copystring( s );
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
=================
|
=================
|
||||||
Con_SortCmds
|
Con_SortCmds
|
||||||
@ -1008,16 +1125,11 @@ void Con_CompleteCommand( field_t *field )
|
|||||||
nextcmd = (con.completionField->buffer[Q_strlen( con.completionField->buffer ) - 1] == ' ') ? true : false;
|
nextcmd = (con.completionField->buffer[Q_strlen( con.completionField->buffer ) - 1] == ' ') ? true : false;
|
||||||
|
|
||||||
con.completionString = Cmd_Argv( 0 );
|
con.completionString = Cmd_Argv( 0 );
|
||||||
con.completionBuffer = Cmd_Argv( 1 );
|
|
||||||
|
|
||||||
// skip backslash
|
// skip backslash
|
||||||
while( *con.completionString && (*con.completionString == '\\' || *con.completionString == '/') )
|
while( *con.completionString && (*con.completionString == '\\' || *con.completionString == '/') )
|
||||||
con.completionString++;
|
con.completionString++;
|
||||||
|
|
||||||
// skip backslash
|
|
||||||
while( *con.completionBuffer && (*con.completionBuffer == '\\' || *con.completionBuffer == '/') )
|
|
||||||
con.completionBuffer++;
|
|
||||||
|
|
||||||
if( !Q_strlen( con.completionString ) )
|
if( !Q_strlen( con.completionString ) )
|
||||||
return;
|
return;
|
||||||
|
|
||||||
@ -1035,33 +1147,41 @@ void Con_CompleteCommand( field_t *field )
|
|||||||
con.shortestMatch[0] = 0;
|
con.shortestMatch[0] = 0;
|
||||||
|
|
||||||
// find matching commands and variables
|
// find matching commands and variables
|
||||||
Cmd_LookupCmds( NULL, NULL, (setpair_t)Con_AddCommandToList );
|
Cmd_LookupCmds( NULL, &con, (setpair_t)Con_AddCommandToList );
|
||||||
Cvar_LookupVars( 0, NULL, NULL, (setpair_t)Con_AddCommandToList );
|
Cvar_LookupVars( 0, NULL, &con, (setpair_t)Con_AddCommandToList );
|
||||||
|
|
||||||
if( !con.matchCount ) return; // no matches
|
if( !con.matchCount ) return; // no matches
|
||||||
|
|
||||||
memcpy( &temp, con.completionField, sizeof( field_t ) );
|
memcpy( &temp, con.completionField, sizeof( field_t ) );
|
||||||
|
|
||||||
// autocomplete second arg
|
// autocomplete second arg
|
||||||
if( (Cmd_Argc() == 2) || ((Cmd_Argc() == 1) && nextcmd) )
|
if( (Cmd_Argc() >= 2) || ((Cmd_Argc() == 1) && nextcmd) )
|
||||||
{
|
{
|
||||||
|
con.completionBuffer = Cmd_Argv( Cmd_Argc() - 1 );
|
||||||
|
|
||||||
|
// skip backslash
|
||||||
|
while( *con.completionBuffer && (*con.completionBuffer == '\\' || *con.completionBuffer == '/') )
|
||||||
|
con.completionBuffer++;
|
||||||
|
|
||||||
if( !Q_strlen( con.completionBuffer ) )
|
if( !Q_strlen( con.completionBuffer ) )
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if( Cmd_AutocompleteName( con.completionBuffer, filename, sizeof( filename ) ) )
|
if( Cmd_AutocompleteName( con.completionBuffer, Cmd_Argc() - 1, filename, sizeof( filename ) ) )
|
||||||
{
|
{
|
||||||
Q_sprintf( con.completionField->buffer, "%s %s", Cmd_Argv( 0 ), filename );
|
con.completionField->buffer[0] = 0;
|
||||||
|
|
||||||
|
for( i = 0; i < Cmd_Argc() - 1; i++ )
|
||||||
|
{
|
||||||
|
Q_strncat( con.completionField->buffer, Cmd_Argv( i ), sizeof( con.completionField->buffer ));
|
||||||
|
Q_strncat( con.completionField->buffer, " ", sizeof( con.completionField->buffer ));
|
||||||
|
}
|
||||||
|
Q_strncat( con.completionField->buffer, filename, sizeof( con.completionField->buffer ));
|
||||||
con.completionField->cursor = Q_strlen( con.completionField->buffer );
|
con.completionField->cursor = Q_strlen( con.completionField->buffer );
|
||||||
}
|
}
|
||||||
|
|
||||||
// don't adjusting cursor pos if we nothing found
|
// don't adjusting cursor pos if we nothing found
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
else if( Cmd_Argc() >= 3 )
|
|
||||||
{
|
|
||||||
// disable autocomplete for all next args
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if( con.matchCount == 1 )
|
if( con.matchCount == 1 )
|
||||||
{
|
{
|
||||||
|
Loading…
x
Reference in New Issue
Block a user