Initial checkin of code for using case insensitive completion as a fallback for regular completion. Some types of completions don't yet support the feature.

darcs-hash:20070228214327-ac50b-9b5c69a1c3e0c11b560f8c61be0441d2ee9d6404.gz
This commit is contained in:
axel
2007-03-01 07:43:27 +10:00
parent 6616543991
commit 2aea1d5a84
5 changed files with 255 additions and 53 deletions

View File

@@ -50,7 +50,8 @@ static void builtin_complete_add2( const wchar_t *cmd,
int result_mode,
const wchar_t *condition,
const wchar_t *comp,
const wchar_t *desc )
const wchar_t *desc,
int flags )
{
int i;
const wchar_t *s;
@@ -65,7 +66,8 @@ static void builtin_complete_add2( const wchar_t *cmd,
result_mode,
condition,
comp,
desc );
desc,
flags );
}
for( i=0; i<al_get_count( gnu_opt ); i++ )
@@ -78,7 +80,8 @@ static void builtin_complete_add2( const wchar_t *cmd,
result_mode,
condition,
comp,
desc );
desc,
flags );
}
for( i=0; i<al_get_count( old_opt ); i++ )
@@ -91,7 +94,8 @@ static void builtin_complete_add2( const wchar_t *cmd,
result_mode,
condition,
comp,
desc );
desc,
flags );
}
if( al_get_count( old_opt )+al_get_count( gnu_opt )+wcslen(short_opt) == 0 )
@@ -104,7 +108,8 @@ static void builtin_complete_add2( const wchar_t *cmd,
result_mode,
condition,
comp,
desc );
desc,
flags );
}
}
@@ -120,7 +125,8 @@ static void builtin_complete_add( array_list_t *cmd,
int authorative,
const wchar_t *condition,
const wchar_t *comp,
const wchar_t *desc )
const wchar_t *desc,
int flags )
{
int i;
@@ -134,7 +140,8 @@ static void builtin_complete_add( array_list_t *cmd,
result_mode,
condition,
comp,
desc );
desc,
flags );
if( authorative != -1 )
{
@@ -155,7 +162,8 @@ static void builtin_complete_add( array_list_t *cmd,
result_mode,
condition,
comp,
desc );
desc,
flags );
if( authorative != -1 )
{
@@ -287,6 +295,7 @@ static int builtin_complete( wchar_t **argv )
int result_mode=SHARED;
int remove = 0;
int authorative = -1;
int flags = COMPLETE_AUTO_SPACE;
string_buffer_t short_opt;
array_list_t gnu_opt, old_opt;
@@ -602,7 +611,8 @@ static int builtin_complete( wchar_t **argv )
authorative,
condition,
comp,
desc );
desc,
flags );
}
}

View File

@@ -138,6 +138,8 @@ typedef struct complete_entry_opt
int old_mode;
/** Next option in the linked list */
struct complete_entry_opt *next;
/** Completion flags */
int flags;
}
complete_entry_opt_t;
@@ -395,7 +397,8 @@ void complete_add( const wchar_t *cmd,
int result_mode,
const wchar_t *condition,
const wchar_t *comp,
const wchar_t *desc )
const wchar_t *desc,
int flags )
{
complete_entry_t *c;
complete_entry_opt_t *opt;
@@ -429,6 +432,7 @@ void complete_add( const wchar_t *cmd,
opt->comp = comp?halloc_wcsdup(opt, comp):L"";
opt->condition = condition?halloc_wcsdup(opt, condition):L"";
opt->long_opt = long_opt?halloc_wcsdup(opt, long_opt):L"" ;
opt->flags = flags;
if( desc && wcslen( desc ) )
{
@@ -1205,7 +1209,8 @@ static void complete_cmd( const wchar_t *cmd,
static void complete_from_args( const wchar_t *str,
const wchar_t *args,
const wchar_t *desc,
array_list_t *comp_out )
array_list_t *comp_out,
int flags )
{
array_list_t possible_comp;
@@ -1216,7 +1221,7 @@ static void complete_from_args( const wchar_t *str,
eval_args( args, &possible_comp );
proc_pop_interactive();
complete_strings( comp_out, str, desc, 0, &possible_comp, COMPLETE_AUTO_SPACE );
complete_strings( comp_out, str, desc, 0, &possible_comp, flags );
al_foreach( &possible_comp, &free );
al_destroy( &possible_comp );
@@ -1384,7 +1389,7 @@ static int complete_param( const wchar_t *cmd_orig,
{
use_common &= ((o->result_mode & NO_COMMON )==0);
use_files &= ((o->result_mode & NO_FILES )==0);
complete_from_args( arg, o->comp, C_(o->desc), comp_out );
complete_from_args( arg, o->comp, C_(o->desc), comp_out, o->flags );
}
}
@@ -1407,7 +1412,7 @@ static int complete_param( const wchar_t *cmd_orig,
old_style_match = 1;
use_common &= ((o->result_mode & NO_COMMON )==0);
use_files &= ((o->result_mode & NO_FILES )==0);
complete_from_args( str, o->comp, C_(o->desc), comp_out );
complete_from_args( str, o->comp, C_(o->desc), comp_out, o->flags );
}
}
}
@@ -1433,7 +1438,7 @@ static int complete_param( const wchar_t *cmd_orig,
{
use_common &= ((o->result_mode & NO_COMMON )==0);
use_files &= ((o->result_mode & NO_FILES )==0);
complete_from_args( str, o->comp, C_(o->desc), comp_out );
complete_from_args( str, o->comp, C_(o->desc), comp_out, o->flags );
}
}
@@ -1458,7 +1463,7 @@ static int complete_param( const wchar_t *cmd_orig,
if( (o->short_opt == L'\0' ) && (o->long_opt[0]==L'\0'))
{
use_files &= ((o->result_mode & NO_FILES )==0);
complete_from_args( str, o->comp, C_(o->desc), comp_out );
complete_from_args( str, o->comp, C_(o->desc), comp_out, o->flags );
}
if( wcslen(str) > 0 && use_switches )
@@ -1483,19 +1488,38 @@ static int complete_param( const wchar_t *cmd_orig,
*/
if( o->long_opt[0] != L'\0' )
{
int match=0, match_no_case=0;
string_buffer_t *whole_opt = sb_halloc( context );
sb_append2( whole_opt, o->old_mode?L"-":L"--", o->long_opt, (void *)0 );
if( wcsncmp( str, (wchar_t *)whole_opt->buff, wcslen(str) )==0)
match = wcsncmp( str, (wchar_t *)whole_opt->buff, wcslen(str) )==0;
if( !match )
{
match_no_case = wcsncasecmp( str, (wchar_t *)whole_opt->buff, wcslen(str) )==0;
}
if( match || match_no_case )
{
int has_arg=0; /* Does this switch have any known arguments */
int req_arg=0; /* Does this switch _require_ an argument */
int offset = 0;
int flags = 0;
if( match )
offset = wcslen( str );
else
flags = COMPLETE_NO_CASE;
has_arg = !!wcslen( o->comp );
req_arg = (o->result_mode & NO_COMMON );
if( !o->old_mode && ( has_arg && !req_arg ) )
{
/*
Optional arguments to a switch can
only be handled using the '=', so we
@@ -1507,23 +1531,24 @@ static int complete_param( const wchar_t *cmd_orig,
*/
string_buffer_t completion;
sb_init( &completion );
sb_printf( &completion,
L"%ls=",
((wchar_t *)whole_opt->buff)+wcslen(str) );
((wchar_t *)whole_opt->buff)+offset );
completion_allocate( comp_out,
(wchar_t *)completion.buff,
C_(o->desc),
0 );
flags );
sb_destroy( &completion );
}
completion_allocate( comp_out,
((wchar_t *)whole_opt->buff) + wcslen(str),
((wchar_t *)whole_opt->buff) + offset,
C_(o->desc),
0 );
flags );
}
}
}

View File

@@ -75,8 +75,8 @@
/**
This compeltion is case insensitive
*/
#define COMPLETE_NO_CASE 2
/**
This compeltion is the whole argument, not just the remainder. This
flag must never be set on completions returned from the complete()
@@ -169,7 +169,8 @@ void complete_add( const wchar_t *cmd,
int result_mode,
const wchar_t *condition,
const wchar_t *comp,
const wchar_t *desc );
const wchar_t *desc,
int flags );
/**
Sets whether the completion list for this command is complete. If
true, any options not matching one of the provided options will be

186
reader.c
View File

@@ -751,6 +751,19 @@ static int comp_len( const wchar_t *a, const wchar_t *b )
return i;
}
/**
Calculate the case insensitive length of the common prefix substring of two strings.
*/
static int comp_ilen( const wchar_t *a, const wchar_t *b )
{
int i;
for( i=0;
a[i] != '\0' && b[i] != '\0' && towlower(a[i])==towlower(b[i]);
i++ )
;
return i;
}
/**
Find the outermost quoting style of current token. Returns 0 if
token is not quoted.
@@ -887,11 +900,46 @@ static void get_param( wchar_t *cmd,
just the common prefix of several completions. If the former, end by
printing a space (and an end quote if the parameter is quoted).
*/
static void completion_insert( const wchar_t *val, int is_complete )
static void completion_insert( const wchar_t *val, int flags )
{
wchar_t *replaced;
wchar_t quote;
int add_space = !(flags & COMPLETE_NO_SPACE);
int do_replace = (flags&COMPLETE_NO_CASE);
if( do_replace )
{
int tok_start, tok_len;
wchar_t *begin, *end;
string_buffer_t sb;
parse_util_token_extent( data->buff, data->buff_pos, &begin, 0, 0, 0 );
end = data->buff+data->buff_pos;
tok_start = begin - data->buff;
tok_len = end-begin;
sb_init( &sb );
sb_append_substring( &sb, data->buff, begin - data->buff );
sb_append( &sb, val );
if( add_space )
{
sb_append( &sb, L" " );
}
sb_append( &sb, end );
reader_set_buffer( (wchar_t *)sb.buff, (begin-data->buff)+wcslen(val)+!!add_space );
sb_destroy( &sb );
reader_super_highlight_me_plenty( data->buff_pos, 0 );
repaint();
}
else
{
get_param( data->buff,
data->buff_pos,
@@ -944,7 +992,7 @@ static void completion_insert( const wchar_t *val, int is_complete )
/*
Print trailing space since this is the only completion
*/
if( is_complete )
if( add_space )
{
if( (quote) &&
@@ -960,6 +1008,9 @@ static void completion_insert( const wchar_t *val, int is_complete )
}
free(replaced);
}
}
/**
@@ -1009,15 +1060,34 @@ static void run_pager( wchar_t *prefix, int is_quoted, array_list_t *comp )
for( i=0; i<al_get_count( comp ); i++ )
{
int base_len=-1;
completion_t *el = (completion_t *)al_get( comp, i );
wchar_t *foo=0;
wchar_t *baz=0;
if( el && el->completion )
{
if( el->flags & COMPLETE_NO_CASE )
{
if( base_len == -1 )
{
wchar_t *begin;
parse_util_token_extent( data->buff, data->buff_pos, &begin, 0, 0, 0 );
base_len = data->buff_pos - (begin-data->buff);
}
foo = escape( el->completion + base_len, 1 );
}
else
{
foo = escape( el->completion, 1 );
}
}
if( el && el->description )
{
@@ -1135,40 +1205,119 @@ static void reader_flash()
static int handle_completions( array_list_t *comp )
{
int i;
void *context = 0;
wchar_t *base = 0;
int len = 0;
int done = 0;
int count = 0;
int flags=0;
if( al_get_count( comp ) == 0 )
{
reader_flash();
return 0;
}
else if( al_get_count( comp ) == 1 )
if( al_get_count( comp ) == 1 )
{
completion_t *c = (completion_t *)al_get( comp, 0 );
completion_insert( c->completion,
!(c->flags & COMPLETE_NO_SPACE) );
c->flags );
return 1;
}
else
{
completion_t *c = (completion_t *)al_get( comp, 0 );
wchar_t *base = wcsdup( c->completion );
int len = wcslen( base );
for( i=1; i<al_get_count( comp ); i++ )
context = halloc( 0, 0 );
for( i=0; i<al_get_count( comp ); i++ )
{
completion_t *c = (completion_t *)al_get( comp, i );
int new_len = comp_len( base, c->completion );
int new_len;
if( c->flags & COMPLETE_NO_CASE )
continue;
count++;
if( base )
{
new_len = comp_len( base, c->completion );
len = new_len < len ? new_len: len;
}
else
{
base = wcsdup( c->completion );
len = wcslen( base );
flags = c->flags;
}
}
if( len > 0 )
{
if( count > 1 )
flags = flags | COMPLETE_NO_SPACE;
base[len]=L'\0';
wchar_t *woot = wcschr( base, COMPLETE_SEP );
if( woot != 0 )
*woot = L'\0';
completion_insert(base, 0);
completion_insert(base, flags);
done = 1;
}
if( base == 0 )
{
wchar_t *begin, *end;
parse_util_token_extent( data->buff, data->buff_pos, &begin, 0, 0, 0 );
if( begin )
{
end = data->buff+data->buff_pos;
wchar_t *tok = halloc_wcsndup( context, begin, end-begin );
if( expand_is_clean( tok ) )
{
int offset = wcslen( tok );
count = 0;
for( i=0; i<al_get_count( comp ); i++ )
{
completion_t *c = (completion_t *)al_get( comp, i );
int new_len;
if( !(c->flags & COMPLETE_NO_CASE) )
continue;
count++;
if( base )
{
new_len = offset + comp_ilen( base+offset, c->completion+offset );
len = new_len < len ? new_len: len;
}
else
{
base = wcsdup( c->completion );
len = wcslen( base );
flags = c->flags;
}
}
if( len > offset )
{
if( count > 1 )
flags = flags | COMPLETE_NO_SPACE;
base[len]=L'\0';
completion_insert( base, flags );
done = 1;
}
}
}
}
free( base );
if( !done )
{
/*
There is no common prefix in the completions, and show_list
@@ -1225,9 +1374,12 @@ static int handle_completions( array_list_t *comp )
}
free( base );
halloc_free( context );
return len;
}
}

View File

@@ -288,6 +288,12 @@ static int wildcard_complete_internal( const wchar_t *orig,
out_completion = wcsdup( str );
}
if( flags & COMPLETE_NO_CASE )
{
free( out_completion );
out_completion = wcsdup( orig );
}
if( out_completion )
{
completion_allocate( out,
@@ -329,6 +335,10 @@ static int wildcard_complete_internal( const wchar_t *orig,
{
return wildcard_complete_internal( orig, str+1, wc+1, 0, desc, desc_func, out, flags );
}
else if( towlower(*wc) == towlower(*str) )
{
return wildcard_complete_internal( orig, str+1, wc+1, 0, desc, desc_func, out, flags | COMPLETE_NO_CASE );
}
return 0;
}
@@ -339,7 +349,11 @@ int wildcard_complete( const wchar_t *str,
array_list_t *out,
int flags )
{
return wildcard_complete_internal( str, str, wc, 1, desc, desc_func, out, flags );
int res;
res = wildcard_complete_internal( str, str, wc, 1, desc, desc_func, out, flags );
return res;
}