mirror of
https://github.com/fish-shell/fish-shell
synced 2024-12-26 12:53:13 +00:00
Add canse insensitive tilde completion
darcs-hash:20080113193221-75c98-169804fe128001f73eaee6fab28bfb99dca7c93e.gz
This commit is contained in:
parent
c2b28063e1
commit
f5540ff958
3 changed files with 153 additions and 62 deletions
44
complete.c
44
complete.c
|
@ -58,7 +58,7 @@ These functions are used for storing and retrieving tab-completion data, as well
|
||||||
/**
|
/**
|
||||||
Description for ~USER completion
|
Description for ~USER completion
|
||||||
*/
|
*/
|
||||||
#define COMPLETE_USER_DESC _( L"Home for %s" )
|
#define COMPLETE_USER_DESC _( L"Home for %ls" )
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Description for short variables. The value is concatenated to this description
|
Description for short variables. The value is concatenated to this description
|
||||||
|
@ -1613,8 +1613,8 @@ static void complete_param_expand( wchar_t *str,
|
||||||
Complete the specified string as an environment variable
|
Complete the specified string as an environment variable
|
||||||
*/
|
*/
|
||||||
static int complete_variable( const wchar_t *whole_var,
|
static int complete_variable( const wchar_t *whole_var,
|
||||||
int start_offset,
|
int start_offset,
|
||||||
array_list_t *comp_list )
|
array_list_t *comp_list )
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
const wchar_t *var = &whole_var[start_offset];
|
const wchar_t *var = &whole_var[start_offset];
|
||||||
|
@ -1796,26 +1796,42 @@ static int try_complete_user( const wchar_t *cmd,
|
||||||
{
|
{
|
||||||
if( wcsncmp( user_name, pw_name, name_len )==0 )
|
if( wcsncmp( user_name, pw_name, name_len )==0 )
|
||||||
{
|
{
|
||||||
string_buffer_t desc;
|
string_buffer_t desc;
|
||||||
string_buffer_t name;
|
|
||||||
|
|
||||||
sb_init( &name );
|
|
||||||
sb_printf( &name,
|
|
||||||
L"%ls/",
|
|
||||||
&pw_name[name_len] );
|
|
||||||
|
|
||||||
sb_init( &desc );
|
sb_init( &desc );
|
||||||
sb_printf( &desc,
|
sb_printf( &desc,
|
||||||
COMPLETE_USER_DESC,
|
COMPLETE_USER_DESC,
|
||||||
pw->pw_gecos );
|
pw_name );
|
||||||
|
|
||||||
completion_allocate( comp,
|
completion_allocate( comp,
|
||||||
(wchar_t *)name.buff,
|
&pw_name[name_len],
|
||||||
(wchar_t *)desc.buff,
|
(wchar_t *)desc.buff,
|
||||||
0 );
|
COMPLETE_NO_SPACE );
|
||||||
|
|
||||||
res=1;
|
res=1;
|
||||||
|
|
||||||
|
sb_destroy( &desc );
|
||||||
|
}
|
||||||
|
else if( wcsncasecmp( user_name, pw_name, name_len )==0 )
|
||||||
|
{
|
||||||
|
string_buffer_t name;
|
||||||
|
string_buffer_t desc;
|
||||||
|
|
||||||
|
sb_init( &name );
|
||||||
|
sb_init( &desc );
|
||||||
|
sb_printf( &name,
|
||||||
|
L"~%ls",
|
||||||
|
pw_name );
|
||||||
|
sb_printf( &desc,
|
||||||
|
COMPLETE_USER_DESC,
|
||||||
|
pw_name );
|
||||||
|
|
||||||
|
completion_allocate( comp,
|
||||||
|
(wchar_t *)name.buff,
|
||||||
|
(wchar_t *)desc.buff,
|
||||||
|
COMPLETE_NO_CASE | COMPLETE_DONT_ESCAPE | COMPLETE_NO_SPACE );
|
||||||
|
res=1;
|
||||||
|
|
||||||
sb_destroy( &desc );
|
sb_destroy( &desc );
|
||||||
sb_destroy( &name );
|
sb_destroy( &name );
|
||||||
|
|
||||||
|
|
|
@ -94,6 +94,13 @@
|
||||||
*/
|
*/
|
||||||
#define COMPLETE_AUTO_SPACE 8
|
#define COMPLETE_AUTO_SPACE 8
|
||||||
|
|
||||||
|
/**
|
||||||
|
This completion should be inserted as-is, without escaping.
|
||||||
|
*/
|
||||||
|
#define COMPLETE_DONT_ESCAPE 16
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
|
|
||||||
|
|
164
reader.c
164
reader.c
|
@ -998,7 +998,10 @@ static void completion_insert( const wchar_t *val, int flags )
|
||||||
|
|
||||||
wchar_t quote;
|
wchar_t quote;
|
||||||
int add_space = !(flags & COMPLETE_NO_SPACE);
|
int add_space = !(flags & COMPLETE_NO_SPACE);
|
||||||
int do_replace = (flags&COMPLETE_NO_CASE);
|
int do_replace = (flags & COMPLETE_NO_CASE);
|
||||||
|
int do_escape = !(flags & COMPLETE_DONT_ESCAPE);
|
||||||
|
|
||||||
|
// debug( 0, L"Insert completion %ls with flags %d", val, flags);
|
||||||
|
|
||||||
if( do_replace )
|
if( do_replace )
|
||||||
{
|
{
|
||||||
|
@ -1017,11 +1020,18 @@ static void completion_insert( const wchar_t *val, int flags )
|
||||||
sb_init( &sb );
|
sb_init( &sb );
|
||||||
sb_append_substring( &sb, data->buff, begin - data->buff );
|
sb_append_substring( &sb, data->buff, begin - data->buff );
|
||||||
|
|
||||||
escaped = escape( val, ESCAPE_ALL | ESCAPE_NO_QUOTED );
|
if( do_escape )
|
||||||
|
{
|
||||||
sb_append( &sb, escaped );
|
escaped = escape( val, ESCAPE_ALL | ESCAPE_NO_QUOTED );
|
||||||
free( escaped );
|
sb_append( &sb, escaped );
|
||||||
|
free( escaped );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
sb_append( &sb, val );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
if( add_space )
|
if( add_space )
|
||||||
{
|
{
|
||||||
sb_append( &sb, L" " );
|
sb_append( &sb, L" " );
|
||||||
|
@ -1039,52 +1049,60 @@ static void completion_insert( const wchar_t *val, int flags )
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
||||||
get_param( data->buff,
|
if( do_escape )
|
||||||
|
{
|
||||||
|
|
||||||
|
get_param( data->buff,
|
||||||
data->buff_pos,
|
data->buff_pos,
|
||||||
"e,
|
"e,
|
||||||
0, 0, 0 );
|
0, 0, 0 );
|
||||||
|
|
||||||
if( quote == L'\0' )
|
if( quote == L'\0' )
|
||||||
{
|
{
|
||||||
replaced = escape( val, ESCAPE_ALL | ESCAPE_NO_QUOTED );
|
replaced = escape( val, ESCAPE_ALL | ESCAPE_NO_QUOTED );
|
||||||
|
}
|
||||||
|
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++ )
|
||||||
|
{
|
||||||
|
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, ESCAPE_ALL | ESCAPE_NO_QUOTED );
|
||||||
|
replaced = wcsdupcat( L" ", tmp );
|
||||||
|
free( tmp);
|
||||||
|
replaced[0]=quote;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
*pout = 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
int unescapable=0;
|
replaced = wcsdup(val);
|
||||||
|
|
||||||
const wchar_t *pin;
|
|
||||||
wchar_t *pout;
|
|
||||||
|
|
||||||
replaced = pout =
|
|
||||||
malloc( sizeof(wchar_t)*(wcslen(val) + 1) );
|
|
||||||
|
|
||||||
for( pin=val; *pin; pin++ )
|
|
||||||
{
|
|
||||||
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, ESCAPE_ALL | ESCAPE_NO_QUOTED );
|
|
||||||
replaced = wcsdupcat( L" ", tmp );
|
|
||||||
free( tmp);
|
|
||||||
replaced[0]=quote;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
*pout = 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if( insert_str( replaced ) )
|
if( insert_str( replaced ) )
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
|
@ -1292,6 +1310,27 @@ static void reader_flash()
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#define UNCLEAN L"$*?({})"
|
||||||
|
|
||||||
|
int reader_can_replace( const wchar_t *in )
|
||||||
|
{
|
||||||
|
|
||||||
|
const wchar_t * str = in;
|
||||||
|
|
||||||
|
CHECK( in, 1 );
|
||||||
|
|
||||||
|
/*
|
||||||
|
Test characters that have a special meaning in any character position
|
||||||
|
*/
|
||||||
|
while( *str )
|
||||||
|
{
|
||||||
|
if( wcschr( UNCLEAN, *str ) )
|
||||||
|
return 0;
|
||||||
|
str++;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Handle the list of completions. This means the following:
|
Handle the list of completions. This means the following:
|
||||||
|
@ -1327,24 +1366,39 @@ static int handle_completions( array_list_t *comp )
|
||||||
context = halloc( 0, 0 );
|
context = halloc( 0, 0 );
|
||||||
tok = halloc_wcsndup( context, begin, end-begin );
|
tok = halloc_wcsndup( context, begin, end-begin );
|
||||||
|
|
||||||
|
/*
|
||||||
|
Check trivial cases
|
||||||
|
*/
|
||||||
switch( al_get_count( comp ) )
|
switch( al_get_count( comp ) )
|
||||||
{
|
{
|
||||||
|
/*
|
||||||
|
No suitable completions found, flash screen and retur
|
||||||
|
*/
|
||||||
case 0:
|
case 0:
|
||||||
{
|
{
|
||||||
reader_flash();
|
reader_flash();
|
||||||
done = 1;
|
done = 1;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
Exactly one suitable completion found - insert it
|
||||||
|
*/
|
||||||
case 1:
|
case 1:
|
||||||
{
|
{
|
||||||
|
|
||||||
completion_t *c = (completion_t *)al_get( comp, 0 );
|
completion_t *c = (completion_t *)al_get( comp, 0 );
|
||||||
|
|
||||||
if( !(c->flags & COMPLETE_NO_CASE) || expand_is_clean( tok ) )
|
/*
|
||||||
|
If this is a replacement completion, check
|
||||||
|
that we know how to replace it, e.g. that
|
||||||
|
the token doesn't contain evil operators
|
||||||
|
like {}
|
||||||
|
*/
|
||||||
|
if( !(c->flags & COMPLETE_NO_CASE) || reader_can_replace( tok ) )
|
||||||
{
|
{
|
||||||
completion_insert( c->completion,
|
completion_insert( c->completion,
|
||||||
c->flags );
|
c->flags );
|
||||||
}
|
}
|
||||||
done = 1;
|
done = 1;
|
||||||
len = 1;
|
len = 1;
|
||||||
|
@ -1355,12 +1409,17 @@ static int handle_completions( array_list_t *comp )
|
||||||
|
|
||||||
if( !done )
|
if( !done )
|
||||||
{
|
{
|
||||||
|
/*
|
||||||
|
Try to find something to insert whith the correct case
|
||||||
|
*/
|
||||||
for( i=0; i<al_get_count( comp ); i++ )
|
for( i=0; i<al_get_count( comp ); i++ )
|
||||||
{
|
{
|
||||||
completion_t *c = (completion_t *)al_get( comp, i );
|
completion_t *c = (completion_t *)al_get( comp, i );
|
||||||
int new_len;
|
int new_len;
|
||||||
|
|
||||||
|
/*
|
||||||
|
Ignore case insensitive completions for now
|
||||||
|
*/
|
||||||
if( c->flags & COMPLETE_NO_CASE )
|
if( c->flags & COMPLETE_NO_CASE )
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
@ -1379,6 +1438,9 @@ static int handle_completions( array_list_t *comp )
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
If we found something to insert, do it.
|
||||||
|
*/
|
||||||
if( len > 0 )
|
if( len > 0 )
|
||||||
{
|
{
|
||||||
if( count > 1 )
|
if( count > 1 )
|
||||||
|
@ -1390,14 +1452,18 @@ static int handle_completions( array_list_t *comp )
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
if( !done && base == 0 )
|
if( !done && base == 0 )
|
||||||
{
|
{
|
||||||
|
/*
|
||||||
|
Try to find something to insert ignoring case
|
||||||
|
*/
|
||||||
|
|
||||||
if( begin )
|
if( begin )
|
||||||
{
|
{
|
||||||
|
|
||||||
if( expand_is_clean( tok ) )
|
if( reader_can_replace( tok ) )
|
||||||
{
|
{
|
||||||
int offset = wcslen( tok );
|
int offset = wcslen( tok );
|
||||||
|
|
||||||
|
@ -2602,9 +2668,11 @@ wchar_t *reader_readline()
|
||||||
|
|
||||||
comp = al_halloc( 0 );
|
comp = al_halloc( 0 );
|
||||||
data->complete_func( buffcpy, comp );
|
data->complete_func( buffcpy, comp );
|
||||||
|
|
||||||
|
|
||||||
sort_completion_list( comp );
|
sort_completion_list( comp );
|
||||||
remove_duplicates( comp );
|
remove_duplicates( comp );
|
||||||
|
|
||||||
|
|
||||||
free( buffcpy );
|
free( buffcpy );
|
||||||
comp_empty = handle_completions( comp );
|
comp_empty = handle_completions( comp );
|
||||||
|
|
Loading…
Reference in a new issue