diff --git a/complete.c b/complete.c index 63f626bea..72b161d6c 100644 --- a/complete.c +++ b/complete.c @@ -238,10 +238,10 @@ static void clear_hash_entry( void *key, void *data ); Create a new completion entry */ -static void completion_allocate( array_list_t *context, - const wchar_t *comp, - const wchar_t *desc, - int flags ) +void completion_allocate( array_list_t *context, + const wchar_t *comp, + const wchar_t *desc, + int flags ) { completion_t *res = halloc( context, sizeof( completion_t) ); res->completion = halloc_wcsdup( context, comp ); @@ -250,9 +250,9 @@ static void completion_allocate( array_list_t *context, al_push( context, res ); } -static void completion_allocate2( array_list_t *context, - wchar_t *comp, - wchar_t sep ) +void completion_allocate2( array_list_t *context, + wchar_t *comp, + wchar_t sep ) { completion_t *res = halloc( context, sizeof( completion_t) ); wchar_t *sep_pos = wcschr( comp, sep ); @@ -1135,9 +1135,28 @@ const wchar_t *complete_get_desc( const wchar_t *filename ) return (wchar_t *)get_desc_buff->buff; } + +/** + Convert all string completions in src into completion_t structs in + dest. All source strings will be free'd. +*/ +static void completion_convert_list( array_list_t *src, array_list_t *dest ) +{ + int i; + + for( i=0; idescription, COMPLETE_DIRECTORY_DESC ) != 0 ) { skip = 0; break; @@ -1358,31 +1327,17 @@ static void complete_cmd_desc( const wchar_t *cmd, array_list_t *comp ) */ for( i=0; icompletion; - if( cmd_end ) - *cmd_end = 0; + wchar_t *new_desc; new_desc = (wchar_t *)hash_get( &lookup, el ); - + if( new_desc ) { - wchar_t *new_el = wcsdupcat2( el, - COMPLETE_SEP_STR, - new_desc, - (void *)0 ); - - al_set( comp, i, new_el ); - free( el ); - } - else - { - if( cmd_end ) - *cmd_end = COMPLETE_SEP; + c->description = halloc_wcsdup( comp, new_desc ); } } } @@ -1428,7 +1383,6 @@ static void complete_cmd( const wchar_t *cmd, wchar_t *nxt_path; wchar_t *state; array_list_t possible_comp; - array_list_t tmp; wchar_t *nxt_completion; wchar_t *cdpath = env_get(L"CDPATH"); @@ -1440,18 +1394,13 @@ static void complete_cmd( const wchar_t *cmd, if( use_command ) { - array_list_t tmp; - al_init( &tmp ); - if( expand_string( 0, wcsdup(cmd), - &tmp, + comp, ACCEPT_INCOMPLETE | EXECUTABLES_ONLY ) != EXPAND_ERROR ) { - complete_cmd_desc( cmd, &tmp ); - completion_convert_list( &tmp, comp ); + complete_cmd_desc( cmd, comp ); } - al_destroy( &tmp ); } } else @@ -1476,20 +1425,15 @@ static void complete_cmd( const wchar_t *cmd, if( ! nxt_completion ) continue; - al_init( &tmp ); - if( expand_string( 0, nxt_completion, - &tmp, + comp, ACCEPT_INCOMPLETE | EXECUTABLES_ONLY ) != EXPAND_ERROR ) { - complete_cmd_desc( cmd, &tmp ); - completion_convert_list( &tmp, comp ); + complete_cmd_desc( cmd, comp ); } - al_destroy( &tmp ); - } free( path_cpy ); @@ -1540,18 +1484,12 @@ static void complete_cmd( const wchar_t *cmd, continue; } - al_init( &tmp ); if( expand_string( 0, nxt_completion, - &tmp, + comp, ACCEPT_INCOMPLETE | DIRECTORIES_ONLY ) != EXPAND_ERROR ) { - /* - Don't care if we fail - completions are just hints - */ - completion_convert_list( &tmp, comp ); } - al_destroy( &tmp ); } } } @@ -1914,8 +1852,7 @@ static void complete_param_expand( wchar_t *str, int do_file ) { wchar_t *comp_str; - array_list_t tmp; - al_init( &tmp ); + int flags; if( (wcsncmp( str, L"--", 2 )) == 0 && (comp_str = wcschr(str, L'=' ) ) ) { @@ -1926,20 +1863,18 @@ static void complete_param_expand( wchar_t *str, comp_str = str; } + flags = EXPAND_SKIP_CMDSUBST | + ACCEPT_INCOMPLETE | + (do_file?0:EXPAND_SKIP_WILDCARDS); + if( expand_string( 0, wcsdup(comp_str), - &tmp, - EXPAND_SKIP_CMDSUBST | ACCEPT_INCOMPLETE | (do_file?0:EXPAND_SKIP_WILDCARDS) ) != EXPAND_ERROR ) - { - completion_convert_list( &tmp, comp_out ); - } - else + comp_out, + flags ) == EXPAND_ERROR ) { debug( 3, L"Error while expanding string '%ls'", comp_str ); } - al_destroy( &tmp ); - } @@ -2136,40 +2071,9 @@ static int try_complete_user( const wchar_t *cmd, } } - return res; -} + return res;} -static void glorf( array_list_t *comp ) -{ - int i; - for( i=0; i 0 ) && ( wcschr( L"/=@:", next[wcslen(next)-1] ) != 0 ) ) - flags |= COMPLETE_NO_SPACE; - - completion_allocate( comp, next, desc, flags ); - item = al_pop( comp ); - al_set( comp, i, item ); - free( next ); - - } -} - void complete( const wchar_t *cmd, array_list_t *comp ) diff --git a/complete.h b/complete.h index 181e54b52..74a4d8b25 100644 --- a/complete.h +++ b/complete.h @@ -86,20 +86,29 @@ typedef struct { + /** The completion string */ const wchar_t *completion; + /** The description for this completion */ const wchar_t *description; + /** - Determines whether a spece should be inserted after this - compeltion if it is the only possible completion. Can be one of - COMPLETE_SPACE_YES, COMPLETE_SPACE_NO and COMPLETE_SPACE_AUTO. + Flags determining the completion behaviour. + + Determines whether a space should be inserted after this + compeltion if it is the only possible completion using the + COMPLETE_NO_SPACE flag. + + The COMPLETE_NO_CASE can be used to signal that this completion + is case insensitive. */ int flags; + } completion_t; @@ -227,4 +236,29 @@ int complete_is_valid_argument( const wchar_t *str, */ void complete_load( const wchar_t *cmd, int reload ); +/** + Create a new completion entry + + \param context The halloc context to use for allocating new memory + \pram comp The completion string + \param desc The description of the completion + \param flags completion flags +*/ +void completion_allocate( array_list_t *context, + const wchar_t *comp, + const wchar_t *desc, + int flags ); + + +/** + Create a new completion entry from an existing text entry + + \param context The halloc context to use for allocating new memory + \param comp the completion and possibly the description for it + \param sep the separator character between completion and description +*/ +void completion_allocate2( array_list_t *context, + wchar_t *comp, + wchar_t sep ); + #endif diff --git a/expand.c b/expand.c index f3b55b373..f9d675220 100644 --- a/expand.c +++ b/expand.c @@ -1519,6 +1519,37 @@ static void remove_internal_separator( const void *s, int conv ) *out=0; } +static void glorf( array_list_t *comp, int from ) +{ + int i; + for( i=from; i 0 ) && ( wcschr( L"/=@:", next[wcslen(next)-1] ) != 0 ) ) + flags |= COMPLETE_NO_SPACE; + + completion_allocate( comp, next, desc, flags ); + item = al_pop( comp ); + al_set( comp, i, item ); + free( next ); + } +} + + + /** The real expansion function. expand_one is just a wrapper around this one. */ @@ -1535,6 +1566,8 @@ int expand_string( void *context, int res = EXPAND_OK; int start_count = al_get_count( end_out ); + int end_out_count = al_get_count( end_out ); + CHECK( str, EXPAND_ERROR ); CHECK( end_out, EXPAND_ERROR ); @@ -1787,6 +1820,13 @@ int expand_string( void *context, halloc_register( context, (void *)al_get( end_out, i ) ); } } + + if( flags & ACCEPT_INCOMPLETE) + { + glorf( end_out, end_out_count ); + } + + return res; diff --git a/reader.c b/reader.c index 589109879..b76a9972e 100644 --- a/reader.c +++ b/reader.c @@ -472,22 +472,22 @@ static int check_size() return 1; } -/** - Compare two completions, ignoring their description. -*/ -static int fldcmp( wchar_t *a, wchar_t *b ) -{ - while( 1 ) - { - if( *a != *b ) - return *a-*b; - if( ( (*a == COMPLETE_SEP) || (*a == L'\0') ) && - ( (*b == COMPLETE_SEP) || (*b == L'\0') ) ) - return 0; - a++; - b++; - } +static int completion_cmp( const void *a, const void *b ) +{ + completion_t *c= *((completion_t **)a); + completion_t *d= *((completion_t **)b); + + return wcsfilecmp( c->completion, d->completion ); + +} + +static void sort_completion_list( array_list_t *comp ) +{ + qsort( comp->arr, + al_get_count( comp ), + sizeof( void*), + &completion_cmp ); } /** @@ -497,23 +497,19 @@ static int fldcmp( wchar_t *a, wchar_t *b ) static void remove_duplicates( array_list_t *l ) { int in, out; - wchar_t *prev; + const wchar_t *prev; if( al_get_count( l ) == 0 ) return; prev = (wchar_t *)al_get( l, 0 ); for( in=1, out=1; in < al_get_count( l ); in++ ) { - wchar_t *curr = (wchar_t *)al_get( l, in ); + completion_t *curr = (completion_t *)al_get( l, in ); - if( fldcmp( prev, curr )==0 ) - { - free( curr ); - } - else + if( wcscmp( prev, curr->completion )!=0 ) { al_set( l, out++, curr ); - prev = curr; + prev = curr->completion; } } al_truncate( l, out ); @@ -745,7 +741,7 @@ static int insert_char( int c ) /** Calculate the length of the common prefix substring of two strings. */ -static int comp_len( wchar_t *a, wchar_t *b ) +static int comp_len( const wchar_t *a, const wchar_t *b ) { int i; for( i=0; @@ -891,7 +887,7 @@ 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( wchar_t *val, int is_complete ) +static void completion_insert( const wchar_t *val, int is_complete ) { wchar_t *replaced; @@ -910,7 +906,8 @@ static void completion_insert( wchar_t *val, int is_complete ) { int unescapable=0; - wchar_t *pin, *pout; + const wchar_t *pin; + wchar_t *pout; replaced = pout = malloc( sizeof(wchar_t)*(wcslen(val) + 1) ); @@ -2292,8 +2289,8 @@ wchar_t *reader_readline() comp = al_halloc( 0 ); data->complete_func( buffcpy, comp ); -// sort_list( comp ); -// remove_duplicates( comp ); + sort_completion_list( comp ); + remove_duplicates( comp ); free( buffcpy ); comp_empty = handle_completions( comp );