Improve the status builtin

darcs-hash:20060130195310-ac50b-5da6881a847170242be56555646bbf037218d545.gz
This commit is contained in:
axel 2006-01-31 05:53:10 +10:00
parent f59e9baab9
commit 028e1f36a1
6 changed files with 1607 additions and 1585 deletions

1384
builtin.c

File diff suppressed because it is too large Load Diff

View File

@ -141,7 +141,7 @@
#define CC_FALSE L"false"
/**
Struct describing a completion option entry.
Struct describing a completion option entry.
If short_opt and long_opt are both zero, the comp field must not be
empty and contains a list of arguments to the command.
@ -149,7 +149,7 @@
If either short_opt or long_opt are non-zero, they specify a switch
for the command. If \c comp is also not empty, it contains a list
of arguments that may only follow after the specified switch.
*/
typedef struct complete_entry_opt
{
@ -228,9 +228,9 @@ static void condition_cache_clear()
if( condition_cache )
{
hash_destroy( condition_cache );
free( condition_cache );
free( condition_cache );
condition_cache = 0;
}
}
}
/**
@ -242,38 +242,38 @@ static void condition_cache_clear()
static int condition_test( const wchar_t *condition )
{
const void *test_res;
if( !condition || !wcslen(condition) )
{
// fwprintf( stderr, L"No condition specified\n" );
return 1;
}
if( !condition_cache )
{
condition_cache = malloc( sizeof( hash_table_t ) );
if( !condition_cache )
{
die_mem();
}
hash_init( condition_cache,
hash_init( condition_cache,
&hash_wcs_func,
&hash_wcs_cmp );
}
test_res = hash_get( condition_cache, condition );
if (test_res == CC_NOT_TESTED )
{
test_res = exec_subshell( condition, 0 )?CC_FALSE:CC_TRUE;
// debug( 1, L"Eval returns %ls for '%ls'", test_res, condition );
// debug( 1, L"Eval returns %ls for '%ls'", test_res, condition );
hash_put( condition_cache, condition, test_res );
/*
Restore previous status information
*/
@ -281,13 +281,13 @@ static int condition_test( const wchar_t *condition )
if( test_res == CC_TRUE )
{
// debug( 1, L"Use conditional completion on condition %ls", condition );
return 1;
// debug( 1, L"Use conditional completion on condition %ls", condition );
return 1;
}
// debug( 1, L"Skip conditional completion on condition %ls", condition );
return 0;
}
@ -341,15 +341,15 @@ void complete_destroy()
complete_free_entry( prev );
}
first_entry = 0;
if( suffix_hash )
{
hash_foreach( suffix_hash, &clear_hash_entry );
hash_destroy( suffix_hash );
free( suffix_hash );
free( suffix_hash );
suffix_hash=0;
}
if( loaded_completions )
{
hash_foreach( loaded_completions,
@ -404,8 +404,8 @@ void complete_add( const wchar_t *cmd,
{
if( !(c = malloc( sizeof(complete_entry) )))
die_mem();
c->next = first_entry;
first_entry = c;
@ -419,7 +419,7 @@ void complete_add( const wchar_t *cmd,
/* wprintf( L"Add completion to option (short %lc, long %ls)\n", short_opt, long_opt );*/
if( !(opt = malloc( sizeof( complete_entry_opt ) )))
die_mem();
opt->next = c->first_option;
c->first_option = opt;
c->authorative = authorative;
@ -526,12 +526,12 @@ void complete_remove( const wchar_t *cmd,
}
else
{
eprev->next = e->next;
eprev->next = e->next;
}
free( e->short_opt_str );
free( e );
e=0;
e=0;
}
}
@ -615,12 +615,12 @@ int complete_is_valid_option( const wchar_t *str,
return 0;
}
if( !(short_validated = malloc( wcslen( opt ) )))
die_mem();
memset( short_validated, 0, wcslen( opt ) );
hash_init( &gnu_match_hash,
@ -899,7 +899,7 @@ static const wchar_t *complete_get_desc_suffix( const wchar_t *suff_orig )
const wchar_t *complete_get_desc( const wchar_t *filename )
{
struct stat buf;
if( !get_desc_buff )
{
get_desc_buff = malloc(sizeof(string_buffer_t) );
@ -909,17 +909,17 @@ const wchar_t *complete_get_desc( const wchar_t *filename )
{
sb_clear( get_desc_buff );
}
if( lwstat( filename, &buf )==0)
{
{
if( S_ISCHR(buf.st_mode) )
{
sb_printf( get_desc_buff, L"%lc%ls", COMPLETE_SEP, COMPLETE_CHAR_DESC );
sb_printf( get_desc_buff, L"%lc%ls", COMPLETE_SEP, COMPLETE_CHAR_DESC );
}
else if( S_ISBLK(buf.st_mode) )
sb_printf( get_desc_buff, L"%lc%ls", COMPLETE_SEP, COMPLETE_BLOCK_DESC );
sb_printf( get_desc_buff, L"%lc%ls", COMPLETE_SEP, COMPLETE_BLOCK_DESC );
else if( S_ISFIFO(buf.st_mode) )
sb_printf( get_desc_buff, L"%lc%ls", COMPLETE_SEP, COMPLETE_FIFO_DESC );
sb_printf( get_desc_buff, L"%lc%ls", COMPLETE_SEP, COMPLETE_FIFO_DESC );
else if( S_ISLNK(buf.st_mode))
{
struct stat buf2;
@ -931,7 +931,7 @@ const wchar_t *complete_get_desc( const wchar_t *filename )
sb_printf( get_desc_buff, L"/%lc%ls", COMPLETE_SEP, COMPLETE_SYMLINK_DESC );
}
else if( waccess( filename, X_OK ) == 0 )
sb_printf( get_desc_buff, L"%lc%ls", COMPLETE_SEP, COMPLETE_EXEC_LINK_DESC );
sb_printf( get_desc_buff, L"%lc%ls", COMPLETE_SEP, COMPLETE_EXEC_LINK_DESC );
else
sb_printf( get_desc_buff, L"%lc%ls", COMPLETE_SEP, COMPLETE_SYMLINK_DESC );
}
@ -951,7 +951,7 @@ const wchar_t *complete_get_desc( const wchar_t *filename )
{
sb_printf( get_desc_buff, L"%lc%ls", COMPLETE_SEP, COMPLETE_LOOP_SYMLINK_DESC );
}
/*
Some kind of broken symlink. We ignore it
here, and it will get a 'file' description,
@ -981,16 +981,16 @@ const wchar_t *complete_get_desc( const wchar_t *filename )
sb_printf( get_desc_buff,
L"%lc%ls",
COMPLETE_SEP,
complete_get_desc_suffix( suffix ) );
complete_get_desc_suffix( suffix ) );
}
else
{
{
sb_printf( get_desc_buff,
L"%lc%ls",
COMPLETE_SEP,
L"%lc%ls",
COMPLETE_SEP,
COMPLETE_FILE_DESC );
}
}
return (wchar_t *)get_desc_buff->buff;
@ -998,7 +998,7 @@ const wchar_t *complete_get_desc( const wchar_t *filename )
/**
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.
There are three ways to specify descriptions for each
completion. Firstly, if a description has already been added to the
@ -1068,7 +1068,7 @@ static void complete_cmd_desc( const wchar_t *cmd, array_list_t *comp )
cmd_start++;
else
cmd_start = cmd;
cmd_len = wcslen(cmd_start);
/*
@ -1083,9 +1083,9 @@ static void complete_cmd_desc( const wchar_t *cmd, array_list_t *comp )
{
return;
}
esc = expand_escape( cmd_start, 1 );
esc = expand_escape( cmd_start, 1 );
if( whatis_path )
{
apropos_cmd =wcsdupcat2( L"grep ^/dev/null -F <", whatis_path, L" ", esc, 0 );
@ -1094,8 +1094,8 @@ static void complete_cmd_desc( const wchar_t *cmd, array_list_t *comp )
{
apropos_cmd = wcsdupcat( L"apropos ^/dev/null ", esc );
}
free(esc);
free(esc);
al_init( &list );
hash_init( &lookup, &hash_wcs_func, &hash_wcs_cmp );
@ -1111,23 +1111,23 @@ static void complete_cmd_desc( const wchar_t *cmd, array_list_t *comp )
Then discard anything that is not a possible completion and put
the result into a hashtable with the completion as key and the
description as value.
Should be reasonably fast, since no memory allocations are needed.
*/
for( i=0; i<al_get_count( &list); i++ )
{
wchar_t *el = (wchar_t *)al_get( &list, i );
wchar_t *key, *key_end, *val_begin;
if( !el )
continue;
//fwprintf( stderr, L"%ls\n", el );
if( wcsncmp( el, cmd_start, cmd_len ) != 0 )
continue;
//fwprintf( stderr, L"%ls\n", el );
key = el + cmd_len;
key_end = wcschr( el, L' ' );
if( !key_end )
{
@ -1137,71 +1137,71 @@ static void complete_cmd_desc( const wchar_t *cmd, array_list_t *comp )
continue;
}
}
*key_end = 0;
val_begin=key_end+1;
//fwprintf( stderr, L"Key %ls\n", el );
while( *val_begin != L'-' && *val_begin)
{
val_begin++;
}
if( !*val_begin )
{
continue;
}
val_begin++;
while( *val_begin == L' ' || *val_begin == L'\t' )
{
val_begin++;
}
if( !*val_begin )
{
continue;
}
/*
And once again I make sure the first character is uppercased
because I like it that way, and I get to decide these
things.
*/
val_begin[0]=towupper(val_begin[0]);
hash_put( &lookup, key, val_begin );
hash_put( &lookup, key, val_begin );
}
/*
Then do a lookup on every completion and if a match is found,
change to the new description.
change to the new description.
This needs to do a reallocation for every description added, but
there shouldn't be that many completions, so it should be ok.
*/
for( i=0; i<al_get_count(comp); i++ )
{
wchar_t *el = (wchar_t *)al_get( comp, i );
wchar_t *cmd_end = wcschr( el,
wchar_t *cmd_end = wcschr( el,
COMPLETE_SEP );
wchar_t *new_desc;
if( cmd_end )
*cmd_end = 0;
new_desc = (wchar_t *)hash_get( &lookup,
el );
if( new_desc )
{
wchar_t *new_el = wcsdupcat2( el,
COMPLETE_SEP_STR,
new_desc,
new_desc,
0 );
al_set( comp, i, new_el );
free( el );
free( el );
}
else
{
@ -1209,11 +1209,11 @@ static void complete_cmd_desc( const wchar_t *cmd, array_list_t *comp )
*cmd_end = COMPLETE_SEP;
}
}
hash_destroy( &lookup );
al_foreach( &list,
al_foreach( &list,
(void(*)(const void *))&free );
al_destroy( &list );
al_destroy( &list );
free( apropos_cmd );
}
@ -1248,16 +1248,16 @@ static void complete_cmd( const wchar_t *cmd,
int i;
array_list_t tmp;
wchar_t *nxt_completion;
wchar_t *cdpath = env_get(L"CDPATH");
wchar_t *cdpath_cpy = wcsdup( cdpath?cdpath:L"." );
if( (wcschr( cmd, L'/') != 0) || (cmd[0] == L'~' ) )
{
array_list_t tmp;
al_init( &tmp );
if( expand_string( wcsdup(cmd),
if( expand_string( wcsdup(cmd),
comp,
ACCEPT_INCOMPLETE | EXECUTABLES_ONLY ) != EXPAND_ERROR )
{
@ -1269,7 +1269,7 @@ static void complete_cmd( const wchar_t *cmd,
{
path = env_get(L"PATH");
path_cpy = wcsdup( path );
for( nxt_path = wcstok( path_cpy, ARRAY_SEP_STR, &state );
nxt_path != 0;
nxt_path = wcstok( 0, ARRAY_SEP_STR, &state) )
@ -1280,12 +1280,12 @@ static void complete_cmd( const wchar_t *cmd,
0 );
if( ! nxt_completion )
continue;
al_init( &tmp );
if( expand_string( nxt_completion,
&tmp,
ACCEPT_INCOMPLETE |
if( expand_string( nxt_completion,
&tmp,
ACCEPT_INCOMPLETE |
EXECUTABLES_ONLY ) != EXPAND_ERROR )
{
for( i=0; i<al_get_count(&tmp); i++ )
@ -1293,7 +1293,7 @@ static void complete_cmd( const wchar_t *cmd,
al_push( comp, al_get( &tmp, i ) );
}
}
al_destroy( &tmp );
}
@ -1337,19 +1337,19 @@ static void complete_cmd( const wchar_t *cmd,
al_init( &tmp );
if( expand_string( nxt_completion,
if( expand_string( nxt_completion,
&tmp,
ACCEPT_INCOMPLETE | DIRECTORIES_ONLY ) != EXPAND_ERROR )
{
for( i=0; i<al_get_count(&tmp); i++ )
{
wchar_t *nxt = (wchar_t *)al_get( &tmp, i );
wchar_t *desc = wcsrchr( nxt, COMPLETE_SEP );
if( desc )
{
int is_valid = desc && (wcscmp(desc+1,
int is_valid = desc && (wcscmp(desc+1,
COMPLETE_DIRECTORY_DESC)==0);
if( is_valid )
{
@ -1376,7 +1376,7 @@ static void complete_cmd( const wchar_t *cmd,
copy_strings_with_prefix, meaning the completion may contain
wildcards. Logically, this is not always the right thing to do, but
I have yet to come up with a case where this matters.
\param str The string to complete.
\param args The list of option arguments to be evaluated.
\param desc Description of the completion
@ -1388,16 +1388,16 @@ static void complete_from_args( const wchar_t *str,
array_list_t *comp_out )
{
int was_interactive = is_interactive;
array_list_t possible_comp;
int i;
al_init( &possible_comp );
is_interactive=0;
eval_args( args, &possible_comp );
is_interactive=was_interactive;
/* We need to unescape these strings before matching them */
for( i=0; i< al_get_count( &possible_comp ); i++ )
{
@ -1502,15 +1502,15 @@ static int short_ok( wchar_t *arg,
return 1;
}
void complete_load( wchar_t *cmd,
void complete_load( wchar_t *cmd,
int reload )
{
const wchar_t *path_var;
const wchar_t *path_var;
array_list_t path_list;
int i;
string_buffer_t path;
time_t *tm;
/*
First check that the specified completion hasn't already been loaded
*/
@ -1534,7 +1534,7 @@ void complete_load( wchar_t *cmd,
*/
if( !reload && tm )
return;
/*
Do we know where to look for completions?
*/
@ -1545,7 +1545,7 @@ void complete_load( wchar_t *cmd,
al_init( &path_list );
sb_init( &path );
expand_variable_array( path_var, &path_list );
/*
@ -1553,18 +1553,18 @@ void complete_load( wchar_t *cmd,
*/
for( i=0; i<al_get_count( &path_list ); i++ )
{
struct stat buf;
wchar_t *next = (wchar_t *)al_get( &path_list, i );
struct stat buf;
wchar_t *next = (wchar_t *)al_get( &path_list, i );
sb_clear( &path );
sb_append2( &path, next, L"/", cmd, L".fish", (void *)0 );
if( (wstat( (wchar_t *)path.buff, &buf )== 0) &&
if( (wstat( (wchar_t *)path.buff, &buf )== 0) &&
(waccess( (wchar_t *)path.buff, R_OK ) == 0) )
{
if( !tm || (*tm != buf.st_mtime ) )
{
wchar_t *esc = expand_escape( (wchar_t *)path.buff, 1 );
wchar_t *src_cmd = wcsdupcat( L". ", esc );
if( !tm )
{
tm = malloc(sizeof(time_t));
@ -1572,15 +1572,15 @@ void complete_load( wchar_t *cmd,
die_mem();
}
*tm = buf.st_mtime;
*tm = buf.st_mtime;
hash_put( loaded_completions,
intern( cmd ),
tm );
free( esc );
complete_remove( cmd, COMMAND, 0, 0 );
/*
Source the completion file for the specified completion
*/
@ -1588,7 +1588,7 @@ void complete_load( wchar_t *cmd,
free(src_cmd);
break;
}
}
}
}
@ -1599,17 +1599,17 @@ void complete_load( wchar_t *cmd,
*/
if( !tm )
{
tm = malloc(sizeof(time_t));
tm = malloc(sizeof(time_t));
if( !tm )
die_mem();
*tm = 0;
hash_put( loaded_completions, intern( cmd ), tm );
}
sb_destroy( &path );
al_foreach( &path_list, (void (*)(const void *))&free );
al_destroy( &path_list );
}
@ -1634,7 +1634,7 @@ static int complete_param( wchar_t *cmd_orig,
parse_cmd_string( cmd_orig, &path, &cmd );
complete_load( cmd, 1 );
al_init( &matches );
@ -1657,7 +1657,7 @@ static int complete_param( wchar_t *cmd_orig,
wchar_t *arg;
if( (arg=param_match2( o, str ))!=0 && condition_test( o->condition ))
{
/* wprintf( L"Use option with desc %ls\n", o->desc ); */
use_common &= ((o->result_mode & NO_COMMON )==0);
use_files &= ((o->result_mode & NO_FILES )==0);
@ -1706,13 +1706,13 @@ static int complete_param( wchar_t *cmd_orig,
*/
if( !o->old_mode && wcslen(o->long_opt) && !(o->result_mode & NO_COMMON) )
continue;
if( param_match( o, popt ) && condition_test( o->condition ))
{
use_common &= ((o->result_mode & NO_COMMON )==0);
use_files &= ((o->result_mode & NO_FILES )==0);
complete_from_args( str, o->comp, o->desc, comp_out );
}
}
}
@ -1727,15 +1727,15 @@ static int complete_param( wchar_t *cmd_orig,
If this entry is for the base command,
check if any of the arguments match
*/
if( !condition_test( o->condition ))
continue;
if( (o->short_opt == L'\0' ) && (o->long_opt[0]==L'\0'))
{
use_files &= ((o->result_mode & NO_FILES )==0);
// debug( 0, L"Running argument command %ls", o->comp );
// debug( 0, L"Running argument command %ls", o->comp );
complete_from_args( str, o->comp, o->desc, comp_out );
}
@ -1751,10 +1751,10 @@ static int complete_param( wchar_t *cmd_orig,
malloc( sizeof(wchar_t)*(3 + wcslen(o->desc)));
if( !next_opt )
die_mem();
next_opt[0]=o->short_opt;
next_opt[1]=COMPLETE_SEP;
next_opt[2]=L'\0';
next_opt[1]=COMPLETE_SEP;
next_opt[2]=L'\0';
wcscat( next_opt, o->desc );
al_push( comp_out, next_opt );
}
@ -1767,9 +1767,9 @@ static int complete_param( wchar_t *cmd_orig,
string_buffer_t whole_opt;
sb_init( &whole_opt );
sb_append2( &whole_opt, o->old_mode?L"-":L"--", o->long_opt, (void *)0 );
if( wcsncmp( str, (wchar_t *)whole_opt.buff, wcslen(str) )==0)
{
{
/*
If the option requires arguments, add
option with an appended '=' . If the
@ -1784,14 +1784,14 @@ static int complete_param( wchar_t *cmd_orig,
wcsdupcat2(&((wchar_t *)whole_opt.buff)[wcslen(str)], COMPLETE_SEP_STR, o->desc, (void *)0) );
// fwprintf( stderr, L"Add without param %ls\n", o->long_opt );
}
if( !o->old_mode && ( wcslen(o->comp) || (o->result_mode & NO_COMMON ) ) )
{
al_push( comp_out,
wcsdupcat2(&((wchar_t *)whole_opt.buff)[wcslen(str)], L"=", COMPLETE_SEP_STR, o->desc, (void *)0) );
// fwprintf( stderr, L"Add with param %ls\n", o->long_opt );
}
// fwprintf( stderr, L"Matching long option %ls\n", o->long_opt );
}
sb_destroy( &whole_opt );
@ -1808,8 +1808,8 @@ static int complete_param( wchar_t *cmd_orig,
/**
Perform file completion on the specified string
*/
static void complete_param_expand( wchar_t *str,
array_list_t *comp_out,
static void complete_param_expand( wchar_t *str,
array_list_t *comp_out,
int do_file )
{
wchar_t *comp_str;
@ -1819,19 +1819,19 @@ static void complete_param_expand( wchar_t *str,
}
else
comp_str = str;
debug( 2,
L"expand_string( \"%ls\", comp_out, EXPAND_SKIP_SUBSHELL | ACCEPT_INCOMPLETE | %ls );",
comp_str,
debug( 2,
L"expand_string( \"%ls\", comp_out, EXPAND_SKIP_SUBSHELL | ACCEPT_INCOMPLETE | %ls );",
comp_str,
do_file?L"0":L"EXPAND_SKIP_WILDCARDS" );
expand_string( wcsdup(comp_str), comp_out, EXPAND_SKIP_SUBSHELL | ACCEPT_INCOMPLETE | (do_file?0:EXPAND_SKIP_WILDCARDS) );
}
/**
Complete the specified string as an environment variable
*/
static int complete_variable( const wchar_t *var,
static int complete_variable( const wchar_t *var,
array_list_t *comp )
{
int i;
@ -1877,7 +1877,7 @@ static int complete_variable( const wchar_t *var,
/**
Search the specified string for the \$ sign, try to complete as an environment variable
*/
static int try_complete_variable( const wchar_t *cmd,
static int try_complete_variable( const wchar_t *cmd,
array_list_t *comp )
{
int len = wcslen( cmd );
@ -1904,7 +1904,7 @@ static int try_complete_variable( const wchar_t *cmd,
Try to complete the specified string as a username. This is used by ~USER type expansion.
*/
static int try_complete_user( const wchar_t *cmd,
static int try_complete_user( const wchar_t *cmd,
array_list_t *comp )
{
const wchar_t *first_char=0;
@ -1983,8 +1983,8 @@ static int try_complete_user( const wchar_t *cmd,
{
if( wcsncmp( user_name, pw_name, name_len )==0 )
{
wchar_t *blarg = wcsdupcat2( &pw_name[name_len],
L"/",
wchar_t *blarg = wcsdupcat2( &pw_name[name_len],
L"/",
COMPLETE_SEP_STR,
COMPLETE_USER_DESC,
0 );
@ -2015,12 +2015,12 @@ void complete( const wchar_t *cmd,
int on_command=0;
int pos;
int old_error_max = error_max;
int done=0;
int cursor_pos = wcslen(cmd );
error_max=0;
/**
@ -2031,11 +2031,11 @@ void complete( const wchar_t *cmd,
if( try_complete_variable( cmd, comp ))
{
done=1;
}
else if( try_complete_user( cmd, comp ))
{
done=1;
done=1;
}
/*
@ -2051,10 +2051,10 @@ void complete( const wchar_t *cmd,
if( !begin )
done=1;
}
if( !done )
{
pos = cursor_pos-(begin-cmd);
buff = wcsndup( begin, end-begin );
@ -2062,14 +2062,14 @@ void complete( const wchar_t *cmd,
if( !buff )
done=1;
}
if( !done )
{
int had_cmd=0;
int end_loop=0;
tok_init( &tok, buff, TOK_ACCEPT_UNFINISHED );
while( tok_has_next( &tok) && !end_loop )
{
switch( tok_last_type( &tok ) )
@ -2079,31 +2079,31 @@ void complete( const wchar_t *cmd,
{
if( parser_is_subcommand( tok_last( &tok ) ) )
break;
current_command = wcsdup( tok_last( &tok ) );
on_command = (pos <= tok_get_pos( &tok) + wcslen( tok_last( &tok ) ) );
had_cmd=1;
}
break;
case TOK_END:
case TOK_PIPE:
case TOK_BACKGROUND:
had_cmd=0;
break;
case TOK_ERROR:
end_loop=1;
break;
}
if( tok_get_pos( &tok ) >= pos )
end_loop=1;
tok_next( &tok );
}
tok_destroy( &tok );
@ -2120,10 +2120,10 @@ void complete( const wchar_t *cmd,
prev_token = prev_begin ? wcsndup( prev_begin, prev_end - prev_begin ): wcsdup(L"");
// fwprintf( stderr, L"on_command: %d, %ls %ls\n", on_command, current_compmand, current_token );
if( current_token && current_command && prev_token )
{
if( on_command )
{
/* Complete command filename */
@ -2164,11 +2164,11 @@ void complete( const wchar_t *cmd,
non-null and longer than 0 characters.
*/
static void append_switch( string_buffer_t *out,
const wchar_t *opt,
const wchar_t *opt,
const wchar_t *argument )
{
wchar_t *esc;
if( !argument || argument==L"" )
return;
@ -2180,7 +2180,7 @@ static void append_switch( string_buffer_t *out,
void complete_print( string_buffer_t *out )
{
complete_entry *e;
for( e = first_entry; e; e=e->next )
{
complete_entry_opt *o;
@ -2198,11 +2198,11 @@ void complete_print( string_buffer_t *out )
sb_printf( out,
L"complete%ls",
modestr[o->result_mode] );
append_switch( out,
e->cmd_type?L"path":L"command",
e->cmd );
if( o->short_opt != 0 )
{
@ -2210,24 +2210,24 @@ void complete_print( string_buffer_t *out )
L" --short-option '%lc'",
o->short_opt );
}
append_switch( out,
o->old_mode?L"old-option":L"long-option",
o->long_opt );
append_switch( out,
L"description",
o->desc );
append_switch( out,
L"arguments",
o->comp );
append_switch( out,
L"condition",
o->condition );
sb_printf( out, L"\n" );
}
}

530
expand.c

File diff suppressed because it is too large Load Diff

638
parser.c

File diff suppressed because it is too large Load Diff

256
reader.c
View File

@ -321,14 +321,14 @@ static void term_donate()
break;
}
}
/**
Grab control of terminal
*/
static void term_steal()
{
{
while( 1 )
{
@ -345,7 +345,7 @@ static void term_steal()
break;
}
common_handle_winch(0 );
common_handle_winch(0 );
if( tcsetattr(0,TCSANOW,&old_modes))/* return to previous mode */
{
@ -431,7 +431,7 @@ static int check_size()
data->new_color == 0 )
{
die_mem();
}
}
return 1;
@ -510,7 +510,7 @@ static int calc_output()
{
data->output[0]=ellipsis_char;
data->output[1]=0;
}
wcsncat( data->output,
@ -520,7 +520,7 @@ static int calc_output()
if( offset_end<data->buff_len )
{
int l = wcslen(data->output);
data->output[l]=ellipsis_char;
data->output[l+1]=0;
@ -537,7 +537,7 @@ static int calc_output()
/**
Compare two completions, ignoring their description.
Compare two completions, ignoring their description.
*/
static int fldcmp( wchar_t *a, wchar_t *b )
{
@ -606,7 +606,7 @@ void reader_write_title()
wchar_t *title;
array_list_t l;
wchar_t *term = env_get( L"TERM" );
/*
This is a pretty lame heuristic for detecting terminals that do
not support setting the title. If we recognise the terminal name
@ -650,16 +650,16 @@ void reader_write_title()
static int try_sequence( char *seq, wchar_t *str )
{
int i;
for( i=0;; i++ )
{
if( !seq[i] )
return i;
if( seq[i] != str[i] )
return 0;
}
return 0;
}
@ -672,11 +672,11 @@ static int calc_prompt_width( array_list_t *arr )
{
int res = 0;
int i, j, k;
for( i=0; i<al_get_count( arr ); i++ )
{
wchar_t *next = (wchar_t *)al_get( arr, i );
for( j=0; next[j]; j++ )
{
if( next[j] == L'\e' )
@ -687,11 +687,11 @@ static int calc_prompt_width( array_list_t *arr )
int l;
int len=0;
int found = 0;
/*
Test these color escapes with parameter value 0..7
*/
char * esc[] =
char * esc[] =
{
set_a_foreground,
set_a_background,
@ -714,12 +714,12 @@ static int calc_prompt_width( array_list_t *arr )
flash_screen
}
;
for( l=0; l < (sizeof(esc)/sizeof(char *)) && !found; l++ )
{
if( !esc[l] )
continue;
for( k=0; k<8; k++ )
{
len = try_sequence( tparm(esc[l],k), &next[j] );
@ -729,9 +729,9 @@ static int calc_prompt_width( array_list_t *arr )
found = 1;
break;
}
}
}
}
for( l=0; l < (sizeof(esc2)/sizeof(char *)) && !found; l++ )
{
if( !esc2[l] )
@ -743,7 +743,7 @@ static int calc_prompt_width( array_list_t *arr )
*/
len = maxi( try_sequence( tparm(esc2[l]), &next[j] ),
try_sequence( esc2[l], &next[j] ));
if( len )
{
j += (len-1);
@ -751,14 +751,14 @@ static int calc_prompt_width( array_list_t *arr )
}
}
}
else
else
{
/*
Ordinary decent character. Just add width.
*/
res += wcwidth( next[j] );
}
}
}
return res;
@ -1152,10 +1152,10 @@ static int insert_str(wchar_t *str)
else
{
int old_len = data->buff_len;
data->buff_len += len;
check_size();
/* Insert space for extra characters at the right position */
if( data->buff_pos < old_len )
{
@ -1168,17 +1168,17 @@ static int insert_str(wchar_t *str)
data->buff[data->buff_len]='\0';
/* Syntax highlight */
reader_super_highlight_me_plenty( data->buff,
data->new_color,
data->buff_pos-1,
0 );
memcpy( data->color, data->new_color, sizeof(int) * data->buff_len );
/* repaint */
repaint();
}
return 1;
}
@ -1409,49 +1409,49 @@ static void run_pager( wchar_t *prefix, int is_quoted, array_list_t *comp )
prefix_esc = escape( prefix,1);
sb_init( &cmd );
sb_printf( &cmd,
L"fish_pager %d %ls",
is_quoted,
sb_printf( &cmd,
L"fish_pager %d %ls",
is_quoted,
prefix_esc );
free( prefix_esc );
for( i=0; i<al_get_count( comp); i++ )
{
wchar_t *el = escape( (wchar_t*)al_get( comp, i ),1);
wchar_t *el = escape( (wchar_t*)al_get( comp, i ),1);
sb_printf( &cmd, L" %ls", el );
free(el);
}
term_donate();
term_donate();
io_data_t *out = io_buffer_create();
eval( (wchar_t *)cmd.buff, out, TOP);
term_steal();
term_steal();
io_buffer_read( out );
sb_destroy( &cmd );
int nil=0;
sb_destroy( &cmd );
int nil=0;
b_append( out->param2.out_buffer, &nil, 1 );
wchar_t *tmp;
wchar_t *str = str2wcs((char *)out->param2.out_buffer->buff);
if( str )
{
for( tmp = str + wcslen(str)-1; tmp >= str; tmp-- )
{
input_unreadch( *tmp );
}
}
free( str );
}
io_buffer_destroy( out);
}
/**
@ -1527,7 +1527,7 @@ static int handle_completions( array_list_t *comp )
0 );
len = &data->buff[data->buff_pos]-prefix_start+1;
if( len <= PREFIX_MAX_LEN )
{
prefix = malloc( sizeof(wchar_t)*(len+1) );
@ -1542,11 +1542,11 @@ static int handle_completions( array_list_t *comp )
0
}
;
prefix = wcsdupcat( tmp,
prefix_start + (len - PREFIX_MAX_LEN) );
prefix[PREFIX_MAX_LEN] = 0;
}
{
@ -1559,7 +1559,7 @@ static int handle_completions( array_list_t *comp )
writech(L'\n');
run_pager( prefix, is_quoted, comp );
/*
Try to print a list of completions. First try with five
@ -1638,8 +1638,8 @@ static void reader_interactive_init()
history_init();
common_handle_winch(0);
common_handle_winch(0);
tcgetattr(0,&shell_modes); /* get the current terminal modes */
memcpy( &saved_modes,
&shell_modes,
@ -1744,7 +1744,7 @@ static void handle_history( const wchar_t *new_str )
Check if the specified string is contained in the list, using
wcscmp as a comparison function
*/
static int contains( const wchar_t *needle,
static int contains( const wchar_t *needle,
array_list_t *haystack )
{
int i;
@ -1754,7 +1754,7 @@ static int contains( const wchar_t *needle,
return 1;
}
return 0;
}
/**
@ -1771,7 +1771,7 @@ static void reset_token_history()
}
else
data->search_buff[0]=0;
data->token_history_pos = -1;
data->search_pos=0;
al_foreach( &data->search_prev, (void (*)(const void *))&free );
@ -1798,7 +1798,7 @@ static void handle_token_history( int forward, int reset )
Start a new token search using the current token
*/
reset_token_history();
}
@ -1851,13 +1851,13 @@ static void handle_token_history( int forward, int reset )
}
else
{
return;
}
return;
}
}
else
{
debug( 3, L"new '%ls'", data->token_history_buff );
debug( 3, L"new '%ls'", data->token_history_buff );
for( tok_init( &tok, data->token_history_buff, TOK_ACCEPT_UNFINISHED );
tok_has_next( &tok);
@ -1882,7 +1882,7 @@ static void handle_token_history( int forward, int reset )
data->token_history_pos = tok_get_pos( &tok );
str = wcsdup(tok_last( &tok ));
}
}
}
}
@ -1890,7 +1890,7 @@ static void handle_token_history( int forward, int reset )
tok_destroy( &tok );
}
if( str )
{
reader_replace_current_token( str );
@ -1912,10 +1912,10 @@ static void handle_token_history( int forward, int reset )
Move buffer position one word or erase one word. This function
updates both the internal buffer and the screen. It is used by
M-left, M-right and ^W to do block movement or block erase.
\param dir Direction to move/erase. 0 means move left, 1 means move right.
\param erase Whether to erase the characters along the way or only move past them.
*/
static void move_word( int dir, int erase )
{
@ -1952,7 +1952,7 @@ static void move_word( int dir, int erase )
if( !dir )
end_buff_pos -= step;
mode++;
}
}
break;
/*
case 2:
@ -1985,9 +1985,9 @@ static void move_word( int dir, int erase )
data->buff_len -= remove_count;
data->buff_pos = first_char;
data->buff[data->buff_len]=0;
reader_super_highlight_me_plenty( data->buff, data->color, data->buff_pos, 0 );
repaint();
}
else
@ -2063,7 +2063,7 @@ int reader_get_cursor_pos()
void reader_run_command( wchar_t *cmd )
{
wchar_t *ft;
ft= tok_first( cmd );
@ -2073,12 +2073,12 @@ void reader_run_command( wchar_t *cmd )
free(ft);
reader_write_title();
term_donate();
eval( cmd, 0, TOP );
job_reap( 1 );
term_steal();
env_set( L"_", L"fish", ENV_GLOBAL );
@ -2087,7 +2087,7 @@ void reader_run_command( wchar_t *cmd )
proc_update_jiffies();
#endif
}
@ -2161,11 +2161,11 @@ void reader_pop()
Clean up after history search
*/
al_foreach( &n->search_prev, (void (*)(const void *))&free );
al_destroy( &n->search_prev );
al_destroy( &n->search_prev );
free( (void *)n->token_history_buff);
free(n);
if( data == 0 )
{
reader_interactive_destroy();
@ -2271,9 +2271,9 @@ static int read_i()
that we can handle a call to reader_set_buffer
during evaluation.
*/
tmp = wcsdup( reader_readline() );
data->buff_pos=data->buff_len=0;
data->buff[data->buff_len]=L'\0';
reader_run_command( tmp );
@ -2308,7 +2308,7 @@ static int can_read( int fd )
{
struct timeval can_read_timeout = { 0, 0 };
fd_set fds;
FD_ZERO(&fds);
FD_SET(fd, &fds);
return select(fd + 1, &fds, 0, 0, &can_read_timeout) == 1;
@ -2378,13 +2378,13 @@ wchar_t *reader_readline()
wchar_t arr[READAHEAD_MAX+1];
int i;
memset( arr, 0, sizeof( arr ) );
arr[0] = c;
for( i=1; i<READAHEAD_MAX; i++ )
{
if( !can_read( 0 ) )
{
c = 0;
@ -2399,12 +2399,12 @@ wchar_t *reader_readline()
else
break;
}
insert_str( arr );
}
}
if( c != 0 )
break;
}
@ -2448,11 +2448,11 @@ wchar_t *reader_readline()
repaint();
break;
}
/* complete */
case R_COMPLETE:
{
// fwprintf( stderr, L"aaa\n" );
if( !data->complete_func )
break;
@ -2509,10 +2509,10 @@ wchar_t *reader_readline()
wchar_t *str = wcsndup( data->buff, data->buff_pos );
if( !str )
die_mem();
kill_add( str );
free( str );
data->buff_len = wcslen(data->buff +data->buff_pos);
memmove( data->buff, data->buff +data->buff_pos, sizeof(wchar_t)*data->buff_len );
data->buff[data->buff_len]=L'\0';
@ -2544,7 +2544,7 @@ wchar_t *reader_readline()
// wcscpy(data->search_buff,data->buff);
break;
}
/* rotate killring*/
case R_YANK_POP:
{
@ -2559,16 +2559,16 @@ wchar_t *reader_readline()
}
break;
}
/* Escape was pressed */
case L'\e':
{
if( *data->search_buff )
{
if( data->token_history_pos==-1 )
{
{
history_reset();
reader_set_buffer( data->search_buff,
reader_set_buffer( data->search_buff,
wcslen(data->search_buff ) );
}
else
@ -2577,26 +2577,26 @@ wchar_t *reader_readline()
}
*data->search_buff=0;
check_colors();
}
break;
}
/* delete backward*/
case R_BACKWARD_DELETE_CHAR:
{
remove_backward();
break;
}
/* delete forward*/
case R_DELETE_CHAR:
{
remove_forward();
break;
}
/* exit, but only if line is empty */
case R_EXIT:
{
@ -2607,7 +2607,7 @@ wchar_t *reader_readline()
}
break;
}
/* Newline, evaluate*/
case L'\n':
{
@ -2633,7 +2633,7 @@ wchar_t *reader_readline()
writech('\n');
repaint();
}
break;
}
@ -2650,7 +2650,7 @@ wchar_t *reader_readline()
handle_history(history_prev_match(data->search_buff));
break;
}
/* History down */
case R_HISTORY_SEARCH_FORWARD:
{
@ -2664,7 +2664,7 @@ wchar_t *reader_readline()
handle_history(history_next_match(data->search_buff));
break;
}
/* Token search for a earlier match */
case R_HISTORY_TOKEN_SEARCH_BACKWARD:
{
@ -2697,7 +2697,7 @@ wchar_t *reader_readline()
break;
}
/* Move left*/
case R_BACKWARD_CHAR:
if( data->buff_pos > 0 )
@ -2735,7 +2735,7 @@ wchar_t *reader_readline()
}
break;
}
case R_DELETE_LINE:
{
data->buff[0]=0;
@ -2744,35 +2744,35 @@ wchar_t *reader_readline()
repaint();
break;
}
/* kill one word left */
case R_BACKWARD_KILL_WORD:
{
move_word(0,1);
break;
}
/* kill one word right */
case R_KILL_WORD:
{
move_word(1,1);
break;
}
/* move one word left*/
case R_BACKWARD_WORD:
{
move_word(0,0);
break;
}
/* move one word right*/
case R_FORWARD_WORD:
{
move_word( 1,0);
break;
}
case R_CLEAR_SCREEN:
{
writembs( clear_screen );
@ -2813,7 +2813,7 @@ wchar_t *reader_readline()
data->search_buff[0]=0;
history_reset();
data->token_history_pos=-1;
}
@ -2845,21 +2845,21 @@ static int read_ni( int fd )
int des = fd == 0 ? dup(0) : fd;
int res=0;
if (des == -1)
{
wperror( L"dup" );
return 1;
}
b_init( &acc );
in_stream = fdopen( des, "r" );
if( in_stream != 0 )
{
wchar_t *str;
int acc_used;
while(!feof( in_stream ))
{
char buff[4096];
@ -2868,7 +2868,7 @@ static int read_ni( int fd )
c = fread(buff, 1, 4096, in_stream);
if( ferror( in_stream ) )
{
debug( 1,
debug( 1,
_( L"Error while reading commands" ) );
/*
@ -2877,7 +2877,7 @@ static int read_ni( int fd )
acc.used=0;
break;
}
b_append( &acc, buff, c );
}
b_append( &acc, "\0", 1 );
@ -2887,16 +2887,16 @@ static int read_ni( int fd )
if( fclose( in_stream ))
{
debug( 1,
debug( 1,
_( L"Error while closing input stream" ) );
wperror( L"fclose" );
res = 1;
}
// fwprintf( stderr, L"Woot is %d chars\n", wcslen( acc.buff ) );
if( str )
{
{
if( !parser_test( str, 1 ) )
{
//fwprintf( stderr, L"We parse it\n" );
@ -2916,21 +2916,21 @@ static int read_ni( int fd )
if( acc_used > 1 )
{
debug( 1,
_( L"Could not convert input. Read %d bytes." ),
_( L"Could not convert input. Read %d bytes." ),
acc_used-1 );
}
else
{
debug( 1,
debug( 1,
_( L"Could not read input stream" ) );
}
res=1;
}
res=1;
}
}
else
{
debug( 1,
debug( 1,
_( L"Error while opening input stream" ) );
wperror( L"fdopen" );
free( buff );
@ -2949,18 +2949,18 @@ int reader_read( int fd )
original state. We also update the signal handlers.
*/
int shell_was_interactive = is_interactive;
is_interactive = ((fd == 0) && isatty(STDIN_FILENO));
signal_set_handlers();
res= is_interactive?read_i():read_ni( fd );
/*
If the exit command was called in a script, only exit the
script, not the program
*/
end_loop = 0;
is_interactive = shell_was_interactive;
signal_set_handlers();
return res;

View File

@ -116,15 +116,15 @@ static void tok_error( tokenizer *tok, const wchar_t *err )
void tok_init( tokenizer *tok, const wchar_t *b, int flags )
{
// fwprintf( stderr, L"CREATE: \'%ls\'\n", b );
memset( tok, 0, sizeof( tokenizer) );
tok->accept_unfinished = flags & TOK_ACCEPT_UNFINISHED;
tok->show_comments = flags & TOK_SHOW_COMMENTS;
tok->has_next=1;
tok->has_next=1;
/*
/*
Before we copy the buffer we need to check that it is not
null. But before that, we need to init the tokenizer far enough
so that errors can be properly flagged
@ -137,7 +137,7 @@ void tok_init( tokenizer *tok, const wchar_t *b, int flags )
tok->has_next = (*b != L'\0');
tok->orig_buff = tok->buff = (wchar_t *)(b);
if( tok->accept_unfinished )
{
int l = wcslen( tok->orig_buff );
@ -149,7 +149,7 @@ void tok_init( tokenizer *tok, const wchar_t *b, int flags )
tok->orig_buff = tok->buff = wcsdup( tok->orig_buff );
if( !tok->orig_buff )
{
die_mem();
die_mem();
}
tok->orig_buff[l-1] = L'\0';
}
@ -223,7 +223,7 @@ static void read_string( tokenizer *tok )
while( 1 )
{
if( !myal( *tok->buff ) )
{
// debug(1, L"%lc", *tok->buff );
@ -260,7 +260,7 @@ static void read_string( tokenizer *tok )
mode = 1;
break;
}
case L'[':
{
if( tok->buff != start )
@ -271,7 +271,7 @@ static void read_string( tokenizer *tok )
case L'\'':
case L'"':
{
wchar_t *end = quote_end( tok->buff );
tok->last_quote = *tok->buff;
if( end )
@ -281,14 +281,14 @@ static void read_string( tokenizer *tok )
else
{
tok->buff += wcslen( tok->buff );
if( (!tok->accept_unfinished) )
{
tok_error( tok, EOL_ERROR );
return;
}
do_loop = 0;
}
break;
}
@ -303,7 +303,7 @@ static void read_string( tokenizer *tok )
}
break;
}
case 3:
case 1:
switch( *tok->buff )
@ -355,7 +355,7 @@ static void read_string( tokenizer *tok )
break;
}
}
if( !do_loop )
break;
@ -408,7 +408,7 @@ static void read_comment( tokenizer *tok )
static void read_redirect( tokenizer *tok, int fd )
{
int mode = -1;
if( (*tok->buff == L'>') ||
(*tok->buff == L'^') )
{
@ -430,7 +430,7 @@ static void read_redirect( tokenizer *tok, int fd )
tok_error( tok, PIPE_ERROR );
return;
}
check_size( tok, FD_STR_MAX_LEN );
check_size( tok, FD_STR_MAX_LEN );
tok->buff++;
swprintf( tok->last, FD_STR_MAX_LEN, L"%d", fd );
tok->last_type = TOK_PIPE;
@ -446,14 +446,14 @@ static void read_redirect( tokenizer *tok, int fd )
{
tok_error( tok, REDIRECT_ERROR);
}
if( !check_size( tok, 2 ))
{
return;
}
swprintf( tok->last, tok->last_len, L"%d", fd );
if( *tok->buff == L'&' )
{
tok->buff++;
@ -496,10 +496,10 @@ void tok_next( tokenizer *tok )
if( tok_last_type( tok ) == TOK_ERROR )
{
tok->has_next=0;
return;
tok->has_next=0;
return;
}
if( !tok->has_next )
{
/* wprintf( L"EOL\n" );*/
@ -551,9 +551,9 @@ void tok_next( tokenizer *tok )
case L'|':
check_size( tok, 2 );
tok->last[0]=L'1';
tok->last[1]=L'\0';
tok->last[1]=L'\0';
tok->last_type = TOK_PIPE;
tok->buff++;
break;
@ -567,9 +567,9 @@ void tok_next( tokenizer *tok )
default:
{
if( iswdigit( *tok->buff ) )
{
{
wchar_t *orig = tok->buff;
int fd = 0;
while( iswdigit( *tok->buff ) )
@ -583,11 +583,11 @@ void tok_next( tokenizer *tok )
read_redirect( tok, fd );
return;
}
tok->buff = orig;
tok->buff = orig;
}
read_string( tok );
}
}
}
@ -603,7 +603,7 @@ wchar_t *tok_first( const wchar_t *str )
wchar_t *res=0;
tok_init( &t, str, 0 );
switch( tok_last_type( &t ) )
{
case TOK_STRING: