Fourth phase of using a real struct for passing around completions - make expand_string return a completion_t struct. Also make the reader sort and remove duplicates again

darcs-hash:20070218232520-ac50b-e23339ec5bba673681eced110e1b0b344eb5d976.gz
This commit is contained in:
axel 2007-02-19 09:25:20 +10:00
parent 680cf17570
commit 6859e012d9
4 changed files with 150 additions and 175 deletions

View file

@ -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; i<al_get_count( src ); i++ )
{
wchar_t *next = (wchar_t *)al_get( src, i );
completion_allocate2( dest, next, COMPLETE_SEP );
free( next );
}
}
/**
Copy any strings in possible_comp which have the specified prefix
to the list comp_out. The prefix may contain wildcards.
to the list comp_out. The prefix may contain wildcards. The output
will consist of completion_t structs.
There are three ways to specify descriptions for each
completion. Firstly, if a description has already been added to the
@ -1152,47 +1171,6 @@ const wchar_t *complete_get_desc( const wchar_t *filename )
\param desc_func the function that generates a description for those completions witout an embedded description
\param possible_comp the list of possible completions to iterate over
*/
static void copy_strings_with_prefix( array_list_t *comp_out,
const wchar_t *wc_escaped,
const wchar_t *desc,
const wchar_t *(*desc_func)(const wchar_t *),
array_list_t *possible_comp )
{
int i;
wchar_t *wc, *tmp;
tmp = expand_one( 0,
wcsdup(wc_escaped), EXPAND_SKIP_CMDSUBST | EXPAND_SKIP_WILDCARDS);
if(!tmp)
return;
wc = parse_util_unescape_wildcards( tmp );
free(tmp);
for( i=0; i<al_get_count( possible_comp ); i++ )
{
wchar_t *next_str = (wchar_t *)al_get( possible_comp, i );
if( next_str )
wildcard_complete( next_str, wc, desc, desc_func, comp_out );
}
free( wc );
}
static void completion_convert_list( array_list_t *src, array_list_t *dest )
{
int i;
for( i=0; i<al_get_count( src ); i++ )
{
wchar_t *next = (wchar_t *)al_get( src, i );
completion_allocate2( dest, next, COMPLETE_SEP );
free( next );
}
}
static void complete_strings( array_list_t *comp_out,
const wchar_t *wc_escaped,
@ -1271,18 +1249,9 @@ static void complete_cmd_desc( const wchar_t *cmd, array_list_t *comp )
for( i=0; i<al_get_count( comp ); i++ )
{
wchar_t *el = (wchar_t *)al_get( comp, i );
wchar_t *cmd_end = wcschr( el,
COMPLETE_SEP );
if( !cmd_end )
{
skip = 0;
break;
}
cmd_end++;
if( wcscmp( cmd_end, COMPLETE_DIRECTORY_DESC ) != 0 )
completion_t *c = (completion_t *)al_get( comp, i );
if( wcscmp( c->description, 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; i<al_get_count(comp); i++ )
{
wchar_t *el = (wchar_t *)al_get( comp, i );
wchar_t *cmd_end = wcschr( el,
COMPLETE_SEP );
wchar_t *new_desc;
completion_t *c = (completion_t *)al_get( comp, i );
const wchar_t *el = c->completion;
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<al_get_count( comp ); i++ )
{
wchar_t *next = (wchar_t *)al_get( comp, i );
wchar_t *desc;
void *item;
int flags = 0;
desc = wcschr( next, COMPLETE_SEP );
if( desc )
{
*desc = 0;
desc++;
}
if( ( wcslen(next) > 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 )

View file

@ -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

View file

@ -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<al_get_count( comp ); i++ )
{
wchar_t *next = (wchar_t *)al_get( comp, i );
wchar_t *desc;
void *item;
int flags = 0;
desc = wcschr( next, COMPLETE_SEP );
if( desc )
{
*desc = 0;
desc++;
}
if( ( wcslen(next) > 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;

View file

@ -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 );