First phase of using a real struct for passing around completions - only use it on things returned by complete(), e.g. use it in the reader

darcs-hash:20070209093350-ac50b-d91fe87be4612a56bff2139349cefa28a504cbb7.gz
This commit is contained in:
axel 2007-02-09 19:33:50 +10:00
parent 08eb92707a
commit 104ec963c2
3 changed files with 161 additions and 37 deletions

View file

@ -2069,6 +2069,49 @@ static int try_complete_user( const wchar_t *cmd,
return res; return res;
} }
static completion_t *completion_allocate( void *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 );
res->description = halloc_wcsdup( context, desc );
res->flags = flags;
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;
completion_t *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;
item = completion_allocate( comp, next, desc, flags );
free( next );
al_set( comp, i, item );
}
}
void complete( const wchar_t *cmd, void complete( const wchar_t *cmd,
array_list_t *comp ) array_list_t *comp )
{ {
@ -2337,6 +2380,9 @@ void complete( const wchar_t *cmd,
condition_cache_clear(); condition_cache_clear();
glorf( comp );
} }
/** /**

View file

@ -66,6 +66,44 @@
*/ */
#define PROG_COMPLETE_SEP L'\t' #define PROG_COMPLETE_SEP L'\t'
/**
Do not insert space afterwards if this is the only completion. (The
default is to try insert a space)
*/
#define COMPLETE_NO_SPACE 1
/**
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()
function. It is strictly for internal use in the completion code.
*/
#define COMPLETE_WHOLE_ARGUMENT 4
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.
*/
int flags;
}
completion_t;
/** /**
Add a completion. Add a completion.

114
reader.c
View file

@ -99,6 +99,8 @@ commence.
#include "output.h" #include "output.h"
#include "signal.h" #include "signal.h"
#include "screen.h" #include "screen.h"
#include "halloc.h"
#include "halloc_util.h"
#include "parse_util.h" #include "parse_util.h"
@ -980,12 +982,18 @@ static void run_pager( wchar_t *prefix, int is_quoted, array_list_t *comp )
string_buffer_t msg; string_buffer_t msg;
wchar_t * prefix_esc; wchar_t * prefix_esc;
char *foo; char *foo;
io_data_t *in;
wchar_t *escaped_separator;
if( !prefix || (wcslen(prefix)==0)) if( !prefix || (wcslen(prefix)==0))
{
prefix_esc = wcsdup(L"\"\""); prefix_esc = wcsdup(L"\"\"");
}
else else
{
prefix_esc = escape( prefix,1); prefix_esc = escape( prefix,1);
}
sb_init( &cmd ); sb_init( &cmd );
sb_init( &msg ); sb_init( &msg );
sb_printf( &cmd, sb_printf( &cmd,
@ -996,15 +1004,53 @@ static void run_pager( wchar_t *prefix, int is_quoted, array_list_t *comp )
free( prefix_esc ); free( prefix_esc );
io_data_t *in= io_buffer_create( 1 ); in= io_buffer_create( 1 );
in->fd = 3; in->fd = 3;
escaped_separator = escape( COMPLETE_SEP_STR, 1);
for( i=0; i<al_get_count( comp); i++ ) for( i=0; i<al_get_count( comp ); i++ )
{ {
wchar_t *el = escape((wchar_t*)al_get( comp, i ), 1);
sb_printf( &msg, L"%ls\n", el ); completion_t *el = (completion_t *)al_get( comp, i );
free( el );
wchar_t *foo=0;
wchar_t *baz=0;
if( el && el->completion )
{
foo = escape( el->completion, 1 );
}
if( el && el->description )
{
baz = escape( el->description, 1 );
}
if( !foo )
{
debug( 0, L"Run pager called with bad argument." );
bugreport();
show_stackframe();
}
else if( baz )
{
sb_printf( &msg, L"%ls%ls%ls\n",
foo,
escaped_separator,
baz );
}
else
{
sb_printf( &msg, L"%ls\n",
foo );
}
free( foo );
free( baz );
} }
free( escaped_separator );
foo = wcs2str( (wchar_t *)msg.buff ); foo = wcs2str( (wchar_t *)msg.buff );
b_append( in->param2.out_buffer, foo, strlen(foo) ); b_append( in->param2.out_buffer, foo, strlen(foo) );
@ -1100,24 +1146,21 @@ static int handle_completions( array_list_t *comp )
} }
else if( al_get_count( comp ) == 1 ) else if( al_get_count( comp ) == 1 )
{ {
wchar_t *comp_str = wcsdup((wchar_t *)al_get( comp, 0 )); completion_t *c = (completion_t *)al_get( comp, 0 );
wchar_t *woot = wcschr( comp_str, COMPLETE_SEP ); completion_insert( c->completion,
if( woot != 0 ) !(c->flags & COMPLETE_NO_SPACE) );
*woot = L'\0';
completion_insert( comp_str,
( wcslen(comp_str) == 0 ) ||
( wcschr( L"/=@:",
comp_str[wcslen(comp_str)-1] ) == 0 ) );
free( comp_str );
return 1; return 1;
} }
else else
{ {
wchar_t *base = wcsdup( (wchar_t *)al_get( comp, 0 ) ); completion_t *c = (completion_t *)al_get( comp, 0 );
wchar_t *base = wcsdup( c->completion );
int len = wcslen( base ); int len = wcslen( base );
for( i=1; i<al_get_count( comp ); i++ ) for( i=1; i<al_get_count( comp ); i++ )
{ {
int new_len = comp_len( base, (wchar_t *)al_get( comp, i ) ); completion_t *c = (completion_t *)al_get( comp, i );
int new_len = comp_len( base, c->completion );
len = new_len < len ? new_len: len; len = new_len < len ? new_len: len;
} }
if( len > 0 ) if( len > 0 )
@ -2049,7 +2092,7 @@ wchar_t *reader_readline()
int i; int i;
int last_char=0, yank=0; int last_char=0, yank=0;
wchar_t *yank_str; wchar_t *yank_str;
array_list_t comp; array_list_t *comp=0;
int comp_empty=1; int comp_empty=1;
int finished=0; int finished=0;
struct termios old_modes; struct termios old_modes;
@ -2057,9 +2100,6 @@ wchar_t *reader_readline()
check_size(); check_size();
data->search_buff[0]=data->buff[data->buff_len]='\0'; data->search_buff[0]=data->buff[data->buff_len]='\0';
al_init( &comp );
s_reset( &data->screen ); s_reset( &data->screen );
exec_prompt(); exec_prompt();
@ -2131,14 +2171,13 @@ wchar_t *reader_readline()
if( c != 0 ) if( c != 0 )
break; break;
} }
/*
if( (last_char == R_COMPLETE) && (c != R_COMPLETE) && (!comp_empty) ) if( (last_char == R_COMPLETE) && (c != R_COMPLETE) && (!comp_empty) )
{ {
al_foreach( &comp, &free ); halloc_destroy( comp );
al_truncate( &comp, 0 ); comp = 0;
comp_empty = 1;
} }
*/
if( last_char != R_YANK && last_char != R_YANK_POP ) if( last_char != R_YANK && last_char != R_YANK_POP )
yank=0; yank=0;
@ -2233,7 +2272,7 @@ wchar_t *reader_readline()
wchar_t *buffcpy; wchar_t *buffcpy;
int len; int len;
int cursor_steps; int cursor_steps;
parse_util_cmdsubst_extent( data->buff, data->buff_pos, &begin, &end ); parse_util_cmdsubst_extent( data->buff, data->buff_pos, &begin, &end );
parse_util_token_extent( begin, data->buff_pos - (begin-data->buff), &token_begin, &token_end, 0, 0 ); parse_util_token_extent( begin, data->buff_pos - (begin-data->buff), &token_begin, &token_end, 0, 0 );
@ -2250,19 +2289,17 @@ wchar_t *reader_readline()
len = data->buff_pos - (begin-data->buff); len = data->buff_pos - (begin-data->buff);
buffcpy = wcsndup( begin, len ); buffcpy = wcsndup( begin, len );
data->complete_func( buffcpy, &comp ); comp = al_halloc( 0 );
data->complete_func( buffcpy, comp );
sort_list( &comp ); // sort_list( comp );
remove_duplicates( &comp ); // remove_duplicates( comp );
free( buffcpy ); free( buffcpy );
comp_empty = handle_completions( comp );
} halloc_free( comp );
if( (comp_empty = comp = 0;
handle_completions( &comp ) ) )
{
al_foreach( &comp, &free );
al_truncate( &comp, 0 );
} }
break; break;
@ -2661,7 +2698,10 @@ wchar_t *reader_readline()
} }
writestr( L"\n" ); writestr( L"\n" );
al_destroy( &comp ); /*
if( comp )
halloc_free( comp );
*/
if( !reader_exit_forced() ) if( !reader_exit_forced() )
{ {
if( tcsetattr(0,TCSANOW,&old_modes)) /* return to previous mode */ if( tcsetattr(0,TCSANOW,&old_modes)) /* return to previous mode */