mirror of
https://github.com/fish-shell/fish-shell
synced 2025-01-13 13:39:02 +00:00
Eliminated halloc usage from complete.cpp
This commit is contained in:
parent
4f8b4379f5
commit
1bbe901bcd
1 changed files with 108 additions and 172 deletions
280
complete.cpp
280
complete.cpp
|
@ -41,8 +41,6 @@
|
||||||
#include "intern.h"
|
#include "intern.h"
|
||||||
#include "parse_util.h"
|
#include "parse_util.h"
|
||||||
#include "parser_keywords.h"
|
#include "parser_keywords.h"
|
||||||
#include "halloc.h"
|
|
||||||
#include "halloc_util.h"
|
|
||||||
#include "wutil.h"
|
#include "wutil.h"
|
||||||
#include "path.h"
|
#include "path.h"
|
||||||
#include "builtin_scripts.h"
|
#include "builtin_scripts.h"
|
||||||
|
@ -131,29 +129,33 @@ typedef struct complete_entry_opt
|
||||||
/** Short style option */
|
/** Short style option */
|
||||||
wchar_t short_opt;
|
wchar_t short_opt;
|
||||||
/** Long style option */
|
/** Long style option */
|
||||||
const wchar_t *long_opt;
|
wcstring long_opt;
|
||||||
/** Arguments to the option */
|
/** Arguments to the option */
|
||||||
const wchar_t *comp;
|
wcstring comp;
|
||||||
/** Description of the completion */
|
/** Description of the completion */
|
||||||
const wchar_t *desc;
|
wcstring desc;
|
||||||
/** Condition under which to use the option */
|
/** Condition under which to use the option */
|
||||||
const wchar_t *condition;
|
wcstring condition;
|
||||||
/** Must be one of the values SHARED, NO_FILES, NO_COMMON,
|
/** Must be one of the values SHARED, NO_FILES, NO_COMMON,
|
||||||
EXCLUSIVE, and determines how completions should be performed
|
EXCLUSIVE, and determines how completions should be performed
|
||||||
on the argument after the switch. */
|
on the argument after the switch. */
|
||||||
int result_mode;
|
int result_mode;
|
||||||
/** True if old style long options are used */
|
/** True if old style long options are used */
|
||||||
int old_mode;
|
int old_mode;
|
||||||
/** Next option in the linked list */
|
|
||||||
struct complete_entry_opt *next;
|
|
||||||
/** Completion flags */
|
/** Completion flags */
|
||||||
int flags;
|
int flags;
|
||||||
}
|
|
||||||
complete_entry_opt_t;
|
const wchar_t *localized_desc() const
|
||||||
|
{
|
||||||
|
const wchar_t *tmp = desc.c_str();
|
||||||
|
return C_(tmp);
|
||||||
|
}
|
||||||
|
} complete_entry_opt_t;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Struct describing a command completion
|
Struct describing a command completion
|
||||||
*/
|
*/
|
||||||
|
typedef std::list<complete_entry_opt_t> option_list_t;
|
||||||
struct completion_entry_t
|
struct completion_entry_t
|
||||||
{
|
{
|
||||||
/** True if command is a path */
|
/** True if command is a path */
|
||||||
|
@ -163,8 +165,10 @@ struct completion_entry_t
|
||||||
wcstring cmd;
|
wcstring cmd;
|
||||||
/** String containing all short option characters */
|
/** String containing all short option characters */
|
||||||
wcstring short_opt_str;
|
wcstring short_opt_str;
|
||||||
/** Linked list of all options */
|
|
||||||
complete_entry_opt_t *first_option;
|
/** List of all options */
|
||||||
|
option_list_t options;
|
||||||
|
|
||||||
/** True if no other options than the ones supplied are possible */
|
/** True if no other options than the ones supplied are possible */
|
||||||
int authoritative;
|
int authoritative;
|
||||||
};
|
};
|
||||||
|
@ -177,7 +181,7 @@ static completion_entry_list_t completion_entries;
|
||||||
Table of completions conditions that have already been tested and
|
Table of completions conditions that have already been tested and
|
||||||
the corresponding test results
|
the corresponding test results
|
||||||
*/
|
*/
|
||||||
static hash_table_t *condition_cache=0;
|
static std::map<wcstring, bool> condition_cache;
|
||||||
|
|
||||||
/* Autoloader for completions */
|
/* Autoloader for completions */
|
||||||
class completion_autoload_t : public autoload_t {
|
class completion_autoload_t : public autoload_t {
|
||||||
|
@ -222,12 +226,7 @@ static void complete_init()
|
||||||
*/
|
*/
|
||||||
static void condition_cache_clear()
|
static void condition_cache_clear()
|
||||||
{
|
{
|
||||||
if( condition_cache )
|
condition_cache.clear();
|
||||||
{
|
|
||||||
hash_destroy( condition_cache );
|
|
||||||
free( condition_cache );
|
|
||||||
condition_cache = 0;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -236,63 +235,27 @@ static void condition_cache_clear()
|
||||||
be evaluated once. condition_cache_clear must be called after a
|
be evaluated once. condition_cache_clear must be called after a
|
||||||
completion run to make sure that there are no stale completions.
|
completion run to make sure that there are no stale completions.
|
||||||
*/
|
*/
|
||||||
static int condition_test( const wchar_t *condition )
|
static int condition_test( const wcstring &condition )
|
||||||
{
|
{
|
||||||
const void *test_res;
|
ASSERT_IS_MAIN_THREAD();
|
||||||
|
|
||||||
if( !condition || !wcslen(condition) )
|
if( condition.empty() )
|
||||||
{
|
{
|
||||||
// fwprintf( stderr, L"No condition specified\n" );
|
// fwprintf( stderr, L"No condition specified\n" );
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if( !condition_cache )
|
bool test_res;
|
||||||
{
|
std::map<wcstring, bool>::iterator cached_entry = condition_cache.find(condition);
|
||||||
condition_cache = (hash_table_t *)malloc( sizeof( hash_table_t ) );
|
if (cached_entry == condition_cache.end()) {
|
||||||
if( !condition_cache )
|
/* Compute new value and reinsert it */
|
||||||
{
|
test_res = (0 == exec_subshell( condition));
|
||||||
DIE_MEM();
|
condition_cache[condition] = test_res;
|
||||||
|
} else {
|
||||||
}
|
/* Use the old value */
|
||||||
|
test_res = cached_entry->second;
|
||||||
hash_init( condition_cache,
|
}
|
||||||
&hash_wcs_func,
|
return test_res;
|
||||||
&hash_wcs_cmp );
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
test_res = hash_get( condition_cache, condition );
|
|
||||||
|
|
||||||
if (test_res == CC_NOT_TESTED )
|
|
||||||
{
|
|
||||||
test_res = exec_subshell( condition)?CC_FALSE:CC_TRUE;
|
|
||||||
hash_put( condition_cache, condition, test_res );
|
|
||||||
|
|
||||||
/*
|
|
||||||
Restore previous status information
|
|
||||||
*/
|
|
||||||
}
|
|
||||||
|
|
||||||
if( wcscmp( (const wchar_t *)test_res, CC_TRUE ) == 0 )
|
|
||||||
{
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
Recursively free all complete_entry_opt_t structs and their contents
|
|
||||||
*/
|
|
||||||
static void complete_free_opt_recursive( complete_entry_opt_t *o )
|
|
||||||
{
|
|
||||||
if( !o )
|
|
||||||
return;
|
|
||||||
|
|
||||||
complete_free_opt_recursive( o->next );
|
|
||||||
halloc_free( o );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -327,7 +290,6 @@ static completion_entry_t *complete_get_exact_entry( const wchar_t *cmd,
|
||||||
{
|
{
|
||||||
c = new completion_entry_t();
|
c = new completion_entry_t();
|
||||||
completion_entries.push_front(c);
|
completion_entries.push_front(c);
|
||||||
c->first_option = 0;
|
|
||||||
c->cmd = cmd;
|
c->cmd = cmd;
|
||||||
c->cmd_type = cmd_type;
|
c->cmd_type = cmd_type;
|
||||||
c->short_opt_str = L"";
|
c->short_opt_str = L"";
|
||||||
|
@ -361,17 +323,14 @@ void complete_add( const wchar_t *cmd,
|
||||||
const wchar_t *desc,
|
const wchar_t *desc,
|
||||||
int flags )
|
int flags )
|
||||||
{
|
{
|
||||||
completion_entry_t *c;
|
|
||||||
complete_entry_opt_t *opt;
|
|
||||||
|
|
||||||
CHECK( cmd, );
|
CHECK( cmd, );
|
||||||
|
|
||||||
|
completion_entry_t *c;
|
||||||
c = complete_get_exact_entry( cmd, cmd_type );
|
c = complete_get_exact_entry( cmd, cmd_type );
|
||||||
|
|
||||||
opt = (complete_entry_opt_t *)halloc( 0, sizeof( complete_entry_opt_t ) );
|
c->options.push_front(complete_entry_opt_t());
|
||||||
|
complete_entry_opt_t &opt = c->options.front();
|
||||||
opt->next = c->first_option;
|
|
||||||
c->first_option = opt;
|
|
||||||
if( short_opt != L'\0' )
|
if( short_opt != L'\0' )
|
||||||
{
|
{
|
||||||
int len = 1 + ((result_mode & NO_COMMON) != 0);
|
int len = 1 + ((result_mode & NO_COMMON) != 0);
|
||||||
|
@ -383,24 +342,15 @@ void complete_add( const wchar_t *cmd,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
opt->short_opt = short_opt;
|
opt.short_opt = short_opt;
|
||||||
opt->result_mode = result_mode;
|
opt.result_mode = result_mode;
|
||||||
opt->old_mode=old_mode;
|
opt.old_mode=old_mode;
|
||||||
|
|
||||||
opt->comp = comp?halloc_wcsdup(opt, comp):L"";
|
if (comp) opt.comp = comp;
|
||||||
opt->condition = condition?halloc_wcsdup(opt, condition):L"";
|
if (condition) opt.condition = condition;
|
||||||
opt->long_opt = long_opt?halloc_wcsdup(opt, long_opt):L"" ;
|
if (long_opt) opt.long_opt = long_opt;
|
||||||
opt->flags = flags;
|
if (desc) opt.desc = desc;
|
||||||
|
opt.flags = flags;
|
||||||
if( desc && wcslen( desc ) )
|
|
||||||
{
|
|
||||||
opt->desc = halloc_wcsdup( opt, desc );
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
opt->desc = L"";
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -411,31 +361,25 @@ void complete_add( const wchar_t *cmd,
|
||||||
static bool complete_remove_entry( completion_entry_t *e, wchar_t short_opt, const wchar_t *long_opt )
|
static bool complete_remove_entry( completion_entry_t *e, wchar_t short_opt, const wchar_t *long_opt )
|
||||||
{
|
{
|
||||||
|
|
||||||
complete_entry_opt_t *o, *oprev=0, *onext=0;
|
|
||||||
|
|
||||||
if(( short_opt == 0 ) && (long_opt == 0 ) )
|
if(( short_opt == 0 ) && (long_opt == 0 ) )
|
||||||
{
|
{
|
||||||
complete_free_opt_recursive( e->first_option );
|
e->options.clear();
|
||||||
e->first_option=0;
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
for (option_list_t::iterator iter = e->options.begin(); iter != e->options.end(); )
|
||||||
for( o= e->first_option; o; o=onext )
|
|
||||||
{
|
{
|
||||||
onext=o->next;
|
complete_entry_opt_t &o = *iter;
|
||||||
|
if(short_opt==o.short_opt || long_opt == o.long_opt)
|
||||||
if( ( short_opt==o->short_opt ) ||
|
|
||||||
( wcscmp( long_opt, o->long_opt ) == 0 ) )
|
|
||||||
{
|
{
|
||||||
/* fwprintf( stderr,
|
/* fwprintf( stderr,
|
||||||
L"remove option -%lc --%ls\n",
|
L"remove option -%lc --%ls\n",
|
||||||
o->short_opt?o->short_opt:L' ',
|
o->short_opt?o->short_opt:L' ',
|
||||||
o->long_opt );
|
o->long_opt );
|
||||||
*/
|
*/
|
||||||
if( o->short_opt )
|
if( o.short_opt )
|
||||||
{
|
{
|
||||||
size_t idx = e->short_opt_str.find(o->short_opt);
|
size_t idx = e->short_opt_str.find(o.short_opt);
|
||||||
if (idx != wcstring::npos)
|
if (idx != wcstring::npos)
|
||||||
{
|
{
|
||||||
/* Consume all colons */
|
/* Consume all colons */
|
||||||
|
@ -445,25 +389,18 @@ static bool complete_remove_entry( completion_entry_t *e, wchar_t short_opt, con
|
||||||
e->short_opt_str.erase(idx, first_non_colon - idx);
|
e->short_opt_str.erase(idx, first_non_colon - idx);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if( oprev == 0 )
|
/* Destroy this option and go to the next one */
|
||||||
{
|
iter = e->options.erase(iter);
|
||||||
e->first_option = o->next;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
oprev->next = o->next;
|
|
||||||
}
|
|
||||||
free( o );
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
oprev = o;
|
/* Just go to the next one */
|
||||||
|
iter++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return e->options.empty();
|
||||||
return e->first_option == 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -514,12 +451,11 @@ int complete_is_valid_option( const wchar_t *str,
|
||||||
array_list_t *errors,
|
array_list_t *errors,
|
||||||
bool allow_autoload )
|
bool allow_autoload )
|
||||||
{
|
{
|
||||||
complete_entry_opt_t *o;
|
|
||||||
wcstring cmd, path;
|
wcstring cmd, path;
|
||||||
int found_match = 0;
|
int found_match = 0;
|
||||||
int authoritative = 1;
|
int authoritative = 1;
|
||||||
int opt_found=0;
|
int opt_found=0;
|
||||||
hash_table_t gnu_match_hash;
|
std::set<wcstring> gnu_match_set;
|
||||||
int is_gnu_opt=0;
|
int is_gnu_opt=0;
|
||||||
int is_old_opt=0;
|
int is_old_opt=0;
|
||||||
int is_short_opt=0;
|
int is_short_opt=0;
|
||||||
|
@ -566,10 +502,6 @@ int complete_is_valid_option( const wchar_t *str,
|
||||||
|
|
||||||
short_validated.resize(wcslen(opt), 0);
|
short_validated.resize(wcslen(opt), 0);
|
||||||
|
|
||||||
hash_init( &gnu_match_hash,
|
|
||||||
&hash_wcs_func,
|
|
||||||
&hash_wcs_cmp );
|
|
||||||
|
|
||||||
is_gnu_opt = opt[1]==L'-';
|
is_gnu_opt = opt[1]==L'-';
|
||||||
if( is_gnu_opt )
|
if( is_gnu_opt )
|
||||||
{
|
{
|
||||||
|
@ -614,19 +546,20 @@ int complete_is_valid_option( const wchar_t *str,
|
||||||
if( is_gnu_opt )
|
if( is_gnu_opt )
|
||||||
{
|
{
|
||||||
|
|
||||||
for( o = i->first_option; o; o=o->next )
|
for (option_list_t::const_iterator iter = i->options.begin(); iter != i->options.end(); iter++)
|
||||||
{
|
{
|
||||||
if( o->old_mode )
|
const complete_entry_opt_t &o = *iter;
|
||||||
|
if( o.old_mode )
|
||||||
{
|
{
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if( wcsncmp( &opt[2], o->long_opt, gnu_opt_len )==0)
|
if( wcsncmp( &opt[2], o.long_opt.c_str(), gnu_opt_len )==0)
|
||||||
{
|
{
|
||||||
hash_put( &gnu_match_hash, o->long_opt, L"" );
|
gnu_match_set.insert(o.long_opt);
|
||||||
if( (wcsncmp( &opt[2],
|
if( (wcsncmp( &opt[2],
|
||||||
o->long_opt,
|
o.long_opt.c_str(),
|
||||||
wcslen( o->long_opt) )==0) )
|
o.long_opt.size())==0) )
|
||||||
{
|
{
|
||||||
is_gnu_exact=1;
|
is_gnu_exact=1;
|
||||||
}
|
}
|
||||||
|
@ -636,13 +569,15 @@ int complete_is_valid_option( const wchar_t *str,
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
/* Check for old style options */
|
/* Check for old style options */
|
||||||
for( o = i->first_option; o; o=o->next )
|
for (option_list_t::const_iterator iter = i->options.begin(); iter != i->options.end(); iter++)
|
||||||
{
|
{
|
||||||
if( !o->old_mode )
|
const complete_entry_opt_t &o = *iter;
|
||||||
|
|
||||||
|
if( !o.old_mode )
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
|
||||||
if( wcscmp( &opt[1], o->long_opt )==0)
|
if( wcscmp( &opt[1], o.long_opt.c_str() )==0)
|
||||||
{
|
{
|
||||||
opt_found = 1;
|
opt_found = 1;
|
||||||
is_old_opt = 1;
|
is_old_opt = 1;
|
||||||
|
@ -720,10 +655,10 @@ int complete_is_valid_option( const wchar_t *str,
|
||||||
|
|
||||||
if( is_gnu_opt )
|
if( is_gnu_opt )
|
||||||
{
|
{
|
||||||
opt_found = is_gnu_exact || (hash_get_count( &gnu_match_hash )==1);
|
opt_found = is_gnu_exact || (gnu_match_set.size() == 1);
|
||||||
if( errors && !opt_found )
|
if( errors && !opt_found )
|
||||||
{
|
{
|
||||||
if( hash_get_count( &gnu_match_hash )==0)
|
if( gnu_match_set.empty())
|
||||||
{
|
{
|
||||||
al_push( errors,
|
al_push( errors,
|
||||||
wcsdupcat( _(L"Unknown option: "), L"'", opt, L"\'" ) );
|
wcsdupcat( _(L"Unknown option: "), L"'", opt, L"\'" ) );
|
||||||
|
@ -737,8 +672,6 @@ int complete_is_valid_option( const wchar_t *str,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
hash_destroy( &gnu_match_hash );
|
|
||||||
|
|
||||||
return (authoritative && found_match)?opt_found:1;
|
return (authoritative && found_match)?opt_found:1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1093,9 +1026,9 @@ static void complete_cmd( const wchar_t *cmd,
|
||||||
\param desc Description of the completion
|
\param desc Description of the completion
|
||||||
\param comp_out The list into which the results will be inserted
|
\param comp_out The list into which the results will be inserted
|
||||||
*/
|
*/
|
||||||
static void complete_from_args( const wchar_t *str,
|
static void complete_from_args( const wcstring &str,
|
||||||
const wchar_t *args,
|
const wcstring &args,
|
||||||
const wchar_t *desc,
|
const wcstring &desc,
|
||||||
std::vector<completion_t> &comp_out,
|
std::vector<completion_t> &comp_out,
|
||||||
int flags )
|
int flags )
|
||||||
{
|
{
|
||||||
|
@ -1104,11 +1037,11 @@ static void complete_from_args( const wchar_t *str,
|
||||||
|
|
||||||
parser_t parser(PARSER_TYPE_COMPLETIONS_ONLY);
|
parser_t parser(PARSER_TYPE_COMPLETIONS_ONLY);
|
||||||
proc_push_interactive(0);
|
proc_push_interactive(0);
|
||||||
parser.eval_args( args, possible_comp );
|
parser.eval_args( args.c_str(), possible_comp );
|
||||||
|
|
||||||
proc_pop_interactive();
|
proc_pop_interactive();
|
||||||
|
|
||||||
complete_strings( comp_out, str, desc, 0, possible_comp, flags );
|
complete_strings( comp_out, str.c_str(), desc.c_str(), 0, possible_comp, flags );
|
||||||
|
|
||||||
// al_foreach( &possible_comp, &free );
|
// al_foreach( &possible_comp, &free );
|
||||||
// al_destroy( &possible_comp );
|
// al_destroy( &possible_comp );
|
||||||
|
@ -1117,10 +1050,10 @@ static void complete_from_args( const wchar_t *str,
|
||||||
/**
|
/**
|
||||||
Match against an old style long option
|
Match against an old style long option
|
||||||
*/
|
*/
|
||||||
static int param_match_old( complete_entry_opt_t *e,
|
static int param_match_old( const complete_entry_opt_t *e,
|
||||||
const wchar_t *optstr )
|
const wchar_t *optstr )
|
||||||
{
|
{
|
||||||
return (optstr[0] == L'-') && (wcscmp( e->long_opt, &optstr[1] ) == 0);
|
return (optstr[0] == L'-') && (e->long_opt == &optstr[1]);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -1135,7 +1068,7 @@ static int param_match( const complete_entry_opt_t *e,
|
||||||
|
|
||||||
if( !e->old_mode && (wcsncmp( L"--", optstr, 2 ) == 0 ))
|
if( !e->old_mode && (wcsncmp( L"--", optstr, 2 ) == 0 ))
|
||||||
{
|
{
|
||||||
if( wcscmp( e->long_opt, &optstr[2] ) == 0 )
|
if( e->long_opt == &optstr[2])
|
||||||
{
|
{
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
@ -1154,9 +1087,9 @@ static wchar_t *param_match2( const complete_entry_opt_t *e,
|
||||||
return (wchar_t *)&optstr[2];
|
return (wchar_t *)&optstr[2];
|
||||||
if( !e->old_mode && (wcsncmp( L"--", optstr, 2 ) == 0) )
|
if( !e->old_mode && (wcsncmp( L"--", optstr, 2 ) == 0) )
|
||||||
{
|
{
|
||||||
int len = wcslen( e->long_opt );
|
size_t len = e->long_opt.size();
|
||||||
|
|
||||||
if( wcsncmp( e->long_opt, &optstr[2],len ) == 0 )
|
if( wcsncmp( e->long_opt.c_str(), &optstr[2],len ) == 0 )
|
||||||
{
|
{
|
||||||
if( optstr[len+2] == L'=' )
|
if( optstr[len+2] == L'=' )
|
||||||
return (wchar_t *)&optstr[len+3];
|
return (wchar_t *)&optstr[len+3];
|
||||||
|
@ -1220,7 +1153,6 @@ static int complete_param( const wchar_t *cmd_orig,
|
||||||
int use_switches,
|
int use_switches,
|
||||||
std::vector<completion_t> &comp_out )
|
std::vector<completion_t> &comp_out )
|
||||||
{
|
{
|
||||||
complete_entry_opt_t *o;
|
|
||||||
|
|
||||||
int use_common=1, use_files=1;
|
int use_common=1, use_files=1;
|
||||||
|
|
||||||
|
@ -1247,14 +1179,15 @@ static int complete_param( const wchar_t *cmd_orig,
|
||||||
{
|
{
|
||||||
/* Check if we are entering a combined option and argument
|
/* Check if we are entering a combined option and argument
|
||||||
(like --color=auto or -I/usr/include) */
|
(like --color=auto or -I/usr/include) */
|
||||||
for( o = i->first_option; o; o=o->next )
|
for (option_list_t::const_iterator oiter = i->options.begin(); oiter != i->options.end(); oiter++)
|
||||||
{
|
{
|
||||||
|
const complete_entry_opt_t *o = &*oiter;
|
||||||
wchar_t *arg;
|
wchar_t *arg;
|
||||||
if( (arg=param_match2( o, str ))!=0 && condition_test( o->condition ))
|
if( (arg=param_match2( o, str ))!=0 && condition_test( o->condition ))
|
||||||
{
|
{
|
||||||
use_common &= ((o->result_mode & NO_COMMON )==0);
|
use_common &= ((o->result_mode & NO_COMMON )==0);
|
||||||
use_files &= ((o->result_mode & NO_FILES )==0);
|
use_files &= ((o->result_mode & NO_FILES )==0);
|
||||||
complete_from_args( arg, o->comp, C_(o->desc), comp_out, o->flags );
|
complete_from_args( arg, o->comp, o->localized_desc(), comp_out, o->flags );
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -1268,8 +1201,9 @@ static int complete_param( const wchar_t *cmd_orig,
|
||||||
If we are using old style long options, check for them
|
If we are using old style long options, check for them
|
||||||
first
|
first
|
||||||
*/
|
*/
|
||||||
for( o = i->first_option; o; o=o->next )
|
for (option_list_t::const_iterator oiter = i->options.begin(); oiter != i->options.end(); oiter++)
|
||||||
{
|
{
|
||||||
|
const complete_entry_opt_t *o = &*oiter;
|
||||||
if( o->old_mode )
|
if( o->old_mode )
|
||||||
{
|
{
|
||||||
if( param_match_old( o, popt ) && condition_test( o->condition ))
|
if( param_match_old( o, popt ) && condition_test( o->condition ))
|
||||||
|
@ -1277,7 +1211,7 @@ static int complete_param( const wchar_t *cmd_orig,
|
||||||
old_style_match = 1;
|
old_style_match = 1;
|
||||||
use_common &= ((o->result_mode & NO_COMMON )==0);
|
use_common &= ((o->result_mode & NO_COMMON )==0);
|
||||||
use_files &= ((o->result_mode & NO_FILES )==0);
|
use_files &= ((o->result_mode & NO_FILES )==0);
|
||||||
complete_from_args( str, o->comp, C_(o->desc), comp_out, o->flags );
|
complete_from_args( str, o->comp, o->localized_desc(), comp_out, o->flags );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1289,21 +1223,22 @@ static int complete_param( const wchar_t *cmd_orig,
|
||||||
*/
|
*/
|
||||||
if( !old_style_match )
|
if( !old_style_match )
|
||||||
{
|
{
|
||||||
for( o = i->first_option; o; o=o->next )
|
for (option_list_t::const_iterator oiter = i->options.begin(); oiter != i->options.end(); oiter++)
|
||||||
{
|
{
|
||||||
|
const complete_entry_opt_t *o = &*oiter;
|
||||||
/*
|
/*
|
||||||
Gnu-style options with _optional_ arguments must
|
Gnu-style options with _optional_ arguments must
|
||||||
be specified as a single token, so that it can
|
be specified as a single token, so that it can
|
||||||
be differed from a regular argument.
|
be differed from a regular argument.
|
||||||
*/
|
*/
|
||||||
if( !o->old_mode && wcslen(o->long_opt) && !(o->result_mode & NO_COMMON) )
|
if( !o->old_mode && ! o->long_opt.empty() && !(o->result_mode & NO_COMMON) )
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if( param_match( o, popt ) && condition_test( o->condition ))
|
if( param_match( o, popt ) && condition_test( o->condition ))
|
||||||
{
|
{
|
||||||
use_common &= ((o->result_mode & NO_COMMON )==0);
|
use_common &= ((o->result_mode & NO_COMMON )==0);
|
||||||
use_files &= ((o->result_mode & NO_FILES )==0);
|
use_files &= ((o->result_mode & NO_FILES )==0);
|
||||||
complete_from_args( str, o->comp, C_(o->desc), comp_out, o->flags );
|
complete_from_args( str, o->comp.c_str(), o->localized_desc(), comp_out, o->flags );
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1314,8 +1249,9 @@ static int complete_param( const wchar_t *cmd_orig,
|
||||||
if( use_common )
|
if( use_common )
|
||||||
{
|
{
|
||||||
|
|
||||||
for( o = i->first_option; o; o=o->next )
|
for (option_list_t::const_iterator oiter = i->options.begin(); oiter != i->options.end(); oiter++)
|
||||||
{
|
{
|
||||||
|
const complete_entry_opt_t *o = &*oiter;
|
||||||
/*
|
/*
|
||||||
If this entry is for the base command,
|
If this entry is for the base command,
|
||||||
check if any of the arguments match
|
check if any of the arguments match
|
||||||
|
@ -1328,7 +1264,7 @@ static int complete_param( const wchar_t *cmd_orig,
|
||||||
if( (o->short_opt == L'\0' ) && (o->long_opt[0]==L'\0'))
|
if( (o->short_opt == L'\0' ) && (o->long_opt[0]==L'\0'))
|
||||||
{
|
{
|
||||||
use_files &= ((o->result_mode & NO_FILES )==0);
|
use_files &= ((o->result_mode & NO_FILES )==0);
|
||||||
complete_from_args( str, o->comp, C_(o->desc), comp_out, o->flags );
|
complete_from_args( str, o->comp, o->localized_desc(), comp_out, o->flags );
|
||||||
}
|
}
|
||||||
|
|
||||||
if( wcslen(str) > 0 && use_switches )
|
if( wcslen(str) > 0 && use_switches )
|
||||||
|
@ -1339,7 +1275,7 @@ static int complete_param( const wchar_t *cmd_orig,
|
||||||
if( o->short_opt != L'\0' &&
|
if( o->short_opt != L'\0' &&
|
||||||
short_ok( str, o->short_opt, i->short_opt_str ) )
|
short_ok( str, o->short_opt, i->short_opt_str ) )
|
||||||
{
|
{
|
||||||
const wchar_t *desc = C_(o->desc );
|
const wchar_t *desc = o->localized_desc();
|
||||||
wchar_t completion[2];
|
wchar_t completion[2];
|
||||||
completion[0] = o->short_opt;
|
completion[0] = o->short_opt;
|
||||||
completion[1] = 0;
|
completion[1] = 0;
|
||||||
|
@ -1380,7 +1316,7 @@ static int complete_param( const wchar_t *cmd_orig,
|
||||||
else
|
else
|
||||||
flags = COMPLETE_NO_CASE;
|
flags = COMPLETE_NO_CASE;
|
||||||
|
|
||||||
has_arg = !!wcslen( o->comp );
|
has_arg = ! o->comp.empty();
|
||||||
req_arg = (o->result_mode & NO_COMMON );
|
req_arg = (o->result_mode & NO_COMMON );
|
||||||
|
|
||||||
if( !o->old_mode && ( has_arg && !req_arg ) )
|
if( !o->old_mode && ( has_arg && !req_arg ) )
|
||||||
|
@ -1404,7 +1340,7 @@ static int complete_param( const wchar_t *cmd_orig,
|
||||||
|
|
||||||
completion_allocate( comp_out,
|
completion_allocate( comp_out,
|
||||||
(wchar_t *)completion.buff,
|
(wchar_t *)completion.buff,
|
||||||
C_(o->desc),
|
C_(o->desc.c_str()),
|
||||||
flags );
|
flags );
|
||||||
|
|
||||||
sb_destroy( &completion );
|
sb_destroy( &completion );
|
||||||
|
@ -1413,7 +1349,7 @@ static int complete_param( const wchar_t *cmd_orig,
|
||||||
|
|
||||||
completion_allocate( comp_out,
|
completion_allocate( comp_out,
|
||||||
whole_opt.c_str() + offset,
|
whole_opt.c_str() + offset,
|
||||||
C_(o->desc),
|
C_(o->desc.c_str()),
|
||||||
flags );
|
flags );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1929,9 +1865,9 @@ void complete_print( string_buffer_t *out )
|
||||||
for (completion_entry_list_t::iterator iter = completion_entries.begin(); iter != completion_entries.end(); iter++)
|
for (completion_entry_list_t::iterator iter = completion_entries.begin(); iter != completion_entries.end(); iter++)
|
||||||
{
|
{
|
||||||
completion_entry_t *e = *iter;
|
completion_entry_t *e = *iter;
|
||||||
complete_entry_opt_t *o;
|
for (option_list_t::const_iterator oiter = e->options.begin(); oiter != e->options.end(); oiter++)
|
||||||
for( o= e->first_option; o; o=o->next )
|
{
|
||||||
{
|
const complete_entry_opt_t *o = &*oiter;
|
||||||
const wchar_t *modestr[] =
|
const wchar_t *modestr[] =
|
||||||
{
|
{
|
||||||
L"",
|
L"",
|
||||||
|
@ -1964,7 +1900,7 @@ void complete_print( string_buffer_t *out )
|
||||||
|
|
||||||
append_switch( out,
|
append_switch( out,
|
||||||
L"description",
|
L"description",
|
||||||
C_(o->desc) );
|
C_(o->desc.c_str()) );
|
||||||
|
|
||||||
append_switch( out,
|
append_switch( out,
|
||||||
L"arguments",
|
L"arguments",
|
||||||
|
|
Loading…
Reference in a new issue