diff --git a/complete.c b/complete.c index 76e50fd6f..a51e7f432 100644 --- a/complete.c +++ b/complete.c @@ -1593,13 +1593,14 @@ static void complete_param_expand( wchar_t *str, /** Complete the specified string as an environment variable */ -static int complete_variable( const wchar_t *var, - array_list_t *comp ) +static int complete_variable( const wchar_t *whole_var, + int start_offset, + array_list_t *comp_list ) { int i; + const wchar_t *var = &whole_var[start_offset]; int varlen = wcslen( var ); int res = 0; - array_list_t names; al_init( &names ); env_get_names( &names, 0 ); @@ -1608,11 +1609,19 @@ static int complete_variable( const wchar_t *var, { wchar_t *name = (wchar_t *)al_get( &names, i ); int namelen = wcslen( name ); + int match=0, match_no_case=0; if( varlen > namelen ) continue; - if( wcsncmp( var, name, varlen) == 0 ) + match = ( wcsncmp( var, name, varlen) == 0 ); + + if( !match ) + { + match_no_case = ( wcsncasecmp( var, name, varlen) == 0 ); + } + + if( match || match_no_case ) { wchar_t *value_unescaped, *value; @@ -1620,20 +1629,37 @@ static int complete_variable( const wchar_t *var, if( value_unescaped ) { string_buffer_t desc; - + string_buffer_t comp; + int flags = 0; + int offset = 0; + + sb_init( &comp ); + if( match ) + { + sb_append( &comp, &name[varlen] ); + offset = varlen; + } + else + { + sb_append_substring( &comp, whole_var, start_offset ); + sb_append( &comp, name ); + flags = COMPLETE_NO_CASE; + } + value = expand_escape_variable( value_unescaped ); sb_init( &desc ); sb_printf( &desc, COMPLETE_VAR_DESC_VAL, value ); - completion_allocate( comp, - &name[varlen], + completion_allocate( comp_list, + (wchar_t *)comp.buff, (wchar_t *)desc.buff, - 0 ); + flags ); res =1; free( value ); sb_destroy( &desc ); + sb_destroy( &comp ); } } @@ -1660,7 +1686,7 @@ static int try_complete_variable( const wchar_t *cmd, if( cmd[i] == L'$' ) { /* wprintf( L"Var prefix \'%ls\'\n", &cmd[i+1] );*/ - return complete_variable( &cmd[i+1], comp ); + return complete_variable( cmd, i+1, comp ); } if( !isalnum(cmd[i]) && cmd[i]!=L'_' ) { @@ -1790,7 +1816,7 @@ static int try_complete_user( const wchar_t *cmd, void complete( const wchar_t *cmd, array_list_t *comp ) { - wchar_t *begin, *end, *prev_begin, *prev_end; + wchar_t *tok_begin, *tok_end, *cmdsubst_begin, *cmdsubst_end, *prev_begin, *prev_end; wchar_t *buff; tokenizer tok; wchar_t *current_token=0, *current_command=0, *prev_token=0; @@ -1802,7 +1828,7 @@ void complete( const wchar_t *cmd, int use_function = 1; int use_builtin = 1; int had_ddash = 0; - + CHECK( cmd, ); CHECK( comp, ); @@ -1812,35 +1838,30 @@ void complete( const wchar_t *cmd, cursor_pos = wcslen(cmd ); + parse_util_cmdsubst_extent( cmd, cursor_pos, &cmdsubst_begin, &cmdsubst_end ); + parse_util_token_extent( cmd, cursor_pos, &tok_begin, &tok_end, &prev_begin, &prev_end ); + + if( !cmdsubst_begin ) + done=1; + /** If we are completing a variable name or a tilde expansion user name, we do that and return. No need for any other competions. */ - if( try_complete_variable( cmd, comp ) || try_complete_user( cmd, comp )) - { - done=1; - } - - /* - Set on_command to true if cursor is over a command, and set the - name of the current command, and various other parsing to find - out what we should complete, and how it should be completed. - */ - if( !done ) { - parse_util_cmdsubst_extent( cmd, cursor_pos, &begin, &end ); - - if( !begin ) + if( try_complete_variable( tok_begin, comp ) || try_complete_user( tok_begin, comp )) + { done=1; + } } if( !done ) { - pos = cursor_pos-(begin-cmd); + pos = cursor_pos-(cmdsubst_begin-cmd); - buff = wcsndup( begin, end-begin ); + buff = wcsndup( cmdsubst_begin, cmdsubst_end-cmdsubst_begin ); if( !buff ) done=1; @@ -1948,9 +1969,7 @@ void complete( const wchar_t *cmd, Get the string to complete */ - parse_util_token_extent( cmd, cursor_pos, &begin, &end, &prev_begin, &prev_end ); - - current_token = wcsndup( begin, cursor_pos-(begin-cmd) ); + current_token = wcsndup( tok_begin, cursor_pos-(tok_begin-cmd) ); prev_token = prev_begin ? wcsndup( prev_begin, prev_end - prev_begin ): wcsdup(L""); diff --git a/reader.c b/reader.c index a617b9321..d8e7251f8 100644 --- a/reader.c +++ b/reader.c @@ -961,73 +961,73 @@ static void completion_insert( const wchar_t *val, int flags ) else { - get_param( data->buff, - data->buff_pos, - "e, - 0, 0, 0 ); + get_param( data->buff, + data->buff_pos, + "e, + 0, 0, 0 ); - if( quote == L'\0' ) - { - replaced = escape( val, 1 ); - } - else - { - int unescapable=0; - - const wchar_t *pin; - wchar_t *pout; - - replaced = pout = - malloc( sizeof(wchar_t)*(wcslen(val) + 1) ); - - for( pin=val; *pin; pin++ ) + if( quote == L'\0' ) { - switch( *pin ) - { - case L'\n': - case L'\t': - case L'\b': - case L'\r': - unescapable=1; - break; - default: - *pout++ = *pin; - break; - } - } - if( unescapable ) - { - free( replaced ); - wchar_t *tmp = escape( val, 1 ); - replaced = wcsdupcat( L" ", tmp ); - free( tmp); - replaced[0]=quote; + replaced = escape( val, 1 ); } else - *pout = 0; - } - - if( insert_str( replaced ) ) - { - /* - Print trailing space since this is the only completion - */ - if( add_space ) { + int unescapable=0; - if( (quote) && - (data->buff[data->buff_pos] != quote ) ) + const wchar_t *pin; + wchar_t *pout; + + replaced = pout = + malloc( sizeof(wchar_t)*(wcslen(val) + 1) ); + + for( pin=val; *pin; pin++ ) { - /* - This is a quoted parameter, first print a quote - */ - insert_char( quote ); + switch( *pin ) + { + case L'\n': + case L'\t': + case L'\b': + case L'\r': + unescapable=1; + break; + default: + *pout++ = *pin; + break; + } } - insert_char( L' ' ); + if( unescapable ) + { + free( replaced ); + wchar_t *tmp = escape( val, 1 ); + replaced = wcsdupcat( L" ", tmp ); + free( tmp); + replaced[0]=quote; + } + else + *pout = 0; } - } - free(replaced); + if( insert_str( replaced ) ) + { + /* + Print trailing space since this is the only completion + */ + if( add_space ) + { + + if( (quote) && + (data->buff[data->buff_pos] != quote ) ) + { + /* + This is a quoted parameter, first print a quote + */ + insert_char( quote ); + } + insert_char( L' ' ); + } + } + + free(replaced); } @@ -1231,22 +1231,42 @@ static int handle_completions( array_list_t *comp ) int done = 0; int count = 0; int flags=0; + wchar_t *begin, *end; + wchar_t *tok; - if( al_get_count( comp ) == 0 ) - { - reader_flash(); - return 0; - } + parse_util_token_extent( data->buff, data->buff_pos, &begin, 0, 0, 0 ); + end = data->buff+data->buff_pos; - if( al_get_count( comp ) == 1 ) - { - completion_t *c = (completion_t *)al_get( comp, 0 ); - completion_insert( c->completion, - c->flags ); - return 1; - } - context = halloc( 0, 0 ); + tok = halloc_wcsndup( context, begin, end-begin ); + + switch( al_get_count( comp ) ) + { + case 0: + { + reader_flash(); + done = 1; + break; + } + + case 1: + { + + completion_t *c = (completion_t *)al_get( comp, 0 ); + + if( !(c->flags & COMPLETE_NO_CASE) || expand_is_clean( tok ) ) + { + completion_insert( c->completion, + c->flags ); + } + done = 1; + len = 1; + } + } + + + if( !done ) + { for( i=0; ibuff, data->buff_pos, &begin, 0, 0, 0 ); - - if( begin ) + if( expand_is_clean( tok ) ) { - 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; iflags & COMPLETE_NO_CASE) ) - continue; + if( !(c->flags & COMPLETE_NO_CASE) ) + continue; - count++; + 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( base ) { - if( count > 1 ) - flags = flags | COMPLETE_NO_SPACE; - - base[len]=L'\0'; - completion_insert( base, flags ); - done = 1; + 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 ); + free( base ); - if( !done ) + if( !done ) + { + /* + There is no common prefix in the completions, and show_list + is true, so we print the list + */ + int len; + wchar_t * prefix; + wchar_t * prefix_start; + get_param( data->buff, + data->buff_pos, + 0, + &prefix_start, + 0, + 0 ); + + len = &data->buff[data->buff_pos]-prefix_start+1; + + if( len <= PREFIX_MAX_LEN ) { - /* - There is no common prefix in the completions, and show_list - is true, so we print the list - */ - int len; - wchar_t * prefix; - wchar_t * prefix_start; - get_param( data->buff, - data->buff_pos, - 0, - &prefix_start, - 0, - 0 ); + prefix = malloc( sizeof(wchar_t)*(len+1) ); + wcslcpy( prefix, prefix_start, len ); + prefix[len]=L'\0'; + } + else + { + wchar_t tmp[2]= + { + ellipsis_char, + 0 + } + ; - len = &data->buff[data->buff_pos]-prefix_start+1; - - if( len <= PREFIX_MAX_LEN ) - { - prefix = malloc( sizeof(wchar_t)*(len+1) ); - wcslcpy( prefix, prefix_start, len ); - prefix[len]=L'\0'; - } - else - { - wchar_t tmp[2]= - { - ellipsis_char, - 0 - } - ; - - prefix = wcsdupcat( tmp, - prefix_start + (len - PREFIX_MAX_LEN) ); - prefix[PREFIX_MAX_LEN] = 0; - - } - - { - int is_quoted; - - wchar_t quote; - get_param( data->buff, data->buff_pos, "e, 0, 0, 0 ); - is_quoted = (quote != L'\0'); - - write(1, "\n", 1 ); - - run_pager( prefix, is_quoted, comp ); - } - - free( prefix ); - s_reset( &data->screen ); - repaint(); + prefix = wcsdupcat( tmp, + prefix_start + (len - PREFIX_MAX_LEN) ); + prefix[PREFIX_MAX_LEN] = 0; } + { + int is_quoted; + + wchar_t quote; + get_param( data->buff, data->buff_pos, "e, 0, 0, 0 ); + is_quoted = (quote != L'\0'); + + write(1, "\n", 1 ); + + run_pager( prefix, is_quoted, comp ); + } + + free( prefix ); + s_reset( &data->screen ); + repaint(); + + } + - halloc_free( context ); + halloc_free( context ); return len; @@ -2354,11 +2371,11 @@ wchar_t *reader_readline() break; } /* - if( (last_char == R_COMPLETE) && (c != R_COMPLETE) && (!comp_empty) ) - { - halloc_destroy( comp ); - comp = 0; - } + if( (last_char == R_COMPLETE) && (c != R_COMPLETE) && (!comp_empty) ) + { + halloc_destroy( comp ); + comp = 0; + } */ if( last_char != R_YANK && last_char != R_YANK_POP ) yank=0; @@ -2881,8 +2898,8 @@ wchar_t *reader_readline() writestr( L"\n" ); /* - if( comp ) - halloc_free( comp ); + if( comp ) + halloc_free( comp ); */ if( !reader_exit_forced() ) { @@ -2960,21 +2977,21 @@ static int read_ni( int fd ) if( str ) { - string_buffer_t sb; - sb_init( &sb ); + string_buffer_t sb; + sb_init( &sb ); - if( !parser_test( str, 0, &sb, L"fish" ) ) - { - eval( str, 0, TOP ); - } - else - { - fwprintf( stderr, L"%ls", sb.buff ); - res = 1; - } - sb_destroy( &sb ); + if( !parser_test( str, 0, &sb, L"fish" ) ) + { + eval( str, 0, TOP ); + } + else + { + fwprintf( stderr, L"%ls", sb.buff ); + res = 1; + } + sb_destroy( &sb ); - free( str ); + free( str ); } else { diff --git a/wildcard.c b/wildcard.c index fcee957cb..150fce39a 100644 --- a/wildcard.c +++ b/wildcard.c @@ -802,10 +802,10 @@ static int test_flags( wchar_t *filename, } -int wildcard_expand( const wchar_t *wc, - const wchar_t *base_dir, - int flags, - array_list_t *out ) +static int wildcard_expand_internal( const wchar_t *wc, + const wchar_t *base_dir, + int flags, + array_list_t *out ) { /* Points to the end of the current wildcard segment */ @@ -854,7 +854,7 @@ int wildcard_expand( const wchar_t *wc, { wchar_t * foo = wcsdup( wc ); foo[len-1]=0; - int res = wildcard_expand( foo, base_dir, flags, out ); + int res = wildcard_expand_internal( foo, base_dir, flags, out ); free( foo ); return res; } @@ -1125,10 +1125,10 @@ int wildcard_expand( const wchar_t *wc, } } - new_res = wildcard_expand( new_wc, - new_dir, - flags, - out ); + new_res = wildcard_expand_internal( new_wc, + new_dir, + flags, + out ); if( new_res == -1 ) { @@ -1144,10 +1144,12 @@ int wildcard_expand( const wchar_t *wc, */ if( partial_match ) { - new_res = wildcard_expand( wcschr( wc, ANY_STRING_RECURSIVE ), - new_dir, - flags | WILDCARD_RECURSIVE, - out ); + + new_res = wildcard_expand_internal( wcschr( wc, ANY_STRING_RECURSIVE ), + new_dir, + flags | WILDCARD_RECURSIVE, + out ); + if( new_res == -1 ) { res = -1; @@ -1175,3 +1177,47 @@ int wildcard_expand( const wchar_t *wc, return res; } + +int wildcard_expand( const wchar_t *wc, + const wchar_t *base_dir, + int flags, + array_list_t *out ) +{ + int c = al_get_count( out ); + int res = wildcard_expand_internal( wc, base_dir, flags, out ); + int i; + + if( flags & ACCEPT_INCOMPLETE ) + { + wchar_t *wc_base; + wchar_t *wc_base_ptr = wcsrchr( wc, L'/' ); + + if( wc_base_ptr ) + { + string_buffer_t sb; + + sb_init( &sb ); + wc_base = wcsndup( wc, (wc_base_ptr-wc)+1 ); + + for( i=c; iflags & COMPLETE_NO_CASE ) + { + sb_clear( &sb ); + sb_printf( &sb, L"%ls%ls", wc_base, c->completion ); + + c->completion = halloc_wcsdup( out, (wchar_t *)sb.buff ); + } + } + + sb_destroy( &sb ); + free( wc_base ); + + } + + } + + return res; +}