mirror of
https://github.com/fish-shell/fish-shell
synced 2025-01-12 21:18:53 +00:00
Add support for calculating completions for arbitrary commands through the 'complete' builtin
darcs-hash:20060130165150-ac50b-5e2ef3bb0298dd5e1a5d6fbdade314cc73ef36f3.gz
This commit is contained in:
parent
3efb0bf5cf
commit
521d09b6d0
22 changed files with 693 additions and 488 deletions
|
@ -61,7 +61,7 @@ COMMON_OBJS := function.o builtin.o common.o complete.o env.o exec.o \
|
|||
expand.o highlight.o history.o kill.o parser.o proc.o reader.o \
|
||||
sanity.o tokenizer.o util.o wildcard.o wgetopt.o wutil.o input.o \
|
||||
output.o intern.o env_universal.o env_universal_common.o \
|
||||
input_common.o event.o signal.o io.o translate.o
|
||||
input_common.o event.o signal.o io.o translate.o parse_util.o
|
||||
|
||||
# builtin_help.h exists, but builtin_help.c is autogenerated
|
||||
COMMON_OBJS_WITH_HEADER := builtin_help.o
|
||||
|
|
|
@ -1733,8 +1733,8 @@ static int builtin_status( wchar_t **argv )
|
|||
|
||||
case 'h':
|
||||
builtin_print_help( argv[0], sb_err );
|
||||
break;
|
||||
|
||||
return 0;
|
||||
|
||||
case 'i':
|
||||
mode = INTERACTIVE;
|
||||
break;
|
||||
|
|
|
@ -159,6 +159,8 @@ int builtin_ulimit(wchar_t **argv);
|
|||
*/
|
||||
int builtin_complete(wchar_t **argv);
|
||||
|
||||
const wchar_t *builtin_complete_get_temporary_buffer();
|
||||
|
||||
/**
|
||||
This function works like wperror, but it prints its result into
|
||||
the sb_err string_buffer_t instead of to stderr. Used by the builtin
|
||||
|
|
|
@ -24,6 +24,7 @@ Functions used for implementing the commandline builtin.
|
|||
#include "input_common.h"
|
||||
#include "input.h"
|
||||
#include "translate.h"
|
||||
#include "parse_util.h"
|
||||
|
||||
/**
|
||||
Which part of the comandbuffer are we operating on
|
||||
|
@ -48,6 +49,26 @@ enum
|
|||
}
|
||||
;
|
||||
|
||||
/**
|
||||
Returns the current commandline buffer.
|
||||
*/
|
||||
static const wchar_t *get_buffer()
|
||||
{
|
||||
const wchar_t *buff = builtin_complete_get_temporary_buffer();
|
||||
if( !buff )
|
||||
buff = reader_get_buffer();
|
||||
return buff;
|
||||
}
|
||||
|
||||
static int get_cursor_pos()
|
||||
{
|
||||
const wchar_t *buff = builtin_complete_get_temporary_buffer();
|
||||
if( buff )
|
||||
return wcslen( buff );
|
||||
else
|
||||
return reader_get_cursor_pos();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Replace/append/insert the selection with/at/after the specified string.
|
||||
|
@ -57,14 +78,14 @@ enum
|
|||
\param insert the string to insert
|
||||
\param append_mode can be one of REPLACE_MODE, INSERT_MODE or APPEND_MODE, affects the way the test update is performed
|
||||
*/
|
||||
static void replace_part( wchar_t *begin,
|
||||
wchar_t *end,
|
||||
static void replace_part( const wchar_t *begin,
|
||||
const wchar_t *end,
|
||||
wchar_t *insert,
|
||||
int append_mode )
|
||||
{
|
||||
wchar_t *buff = reader_get_buffer();
|
||||
const wchar_t *buff = get_buffer();
|
||||
string_buffer_t out;
|
||||
int out_pos=reader_get_cursor_pos();
|
||||
int out_pos=get_cursor_pos();
|
||||
|
||||
sb_init( &out );
|
||||
|
||||
|
@ -88,7 +109,7 @@ static void replace_part( wchar_t *begin,
|
|||
}
|
||||
case INSERT_MODE:
|
||||
{
|
||||
int cursor = reader_get_cursor_pos() -(begin-buff);
|
||||
int cursor = get_cursor_pos() -(begin-buff);
|
||||
sb_append_substring( &out, begin, cursor );
|
||||
sb_append( &out, insert );
|
||||
sb_append_substring( &out, begin+cursor, end-begin-cursor );
|
||||
|
@ -109,8 +130,8 @@ static void replace_part( wchar_t *begin,
|
|||
\param cut_at_cursor whether printing should stop at the surrent cursor position
|
||||
\param tokenize whether the string should be tokenized, printing one string token on every line and skipping non-string tokens
|
||||
*/
|
||||
static void write_part( wchar_t *begin,
|
||||
wchar_t *end,
|
||||
static void write_part( const wchar_t *begin,
|
||||
const wchar_t *end,
|
||||
int cut_at_cursor,
|
||||
int tokenize )
|
||||
{
|
||||
|
@ -119,7 +140,7 @@ static void write_part( wchar_t *begin,
|
|||
wchar_t *buff;
|
||||
int pos;
|
||||
|
||||
pos = reader_get_cursor_pos()-(begin-reader_get_buffer());
|
||||
pos = get_cursor_pos()-(begin-get_buffer());
|
||||
|
||||
if( tokenize )
|
||||
{
|
||||
|
@ -184,7 +205,7 @@ int builtin_commandline( wchar_t **argv )
|
|||
|
||||
int tokenize = 0;
|
||||
|
||||
if( !reader_get_buffer() )
|
||||
if( !get_buffer() )
|
||||
{
|
||||
sb_append2( sb_err,
|
||||
argv[0],
|
||||
|
@ -429,32 +450,42 @@ int builtin_commandline( wchar_t **argv )
|
|||
buffer_part = STRING_MODE;
|
||||
}
|
||||
|
||||
wchar_t *begin, *end;
|
||||
const wchar_t *begin, *end;
|
||||
|
||||
switch( buffer_part )
|
||||
{
|
||||
case STRING_MODE:
|
||||
{
|
||||
begin = reader_get_buffer();
|
||||
begin = get_buffer();
|
||||
end = begin+wcslen(begin);
|
||||
break;
|
||||
}
|
||||
|
||||
case PROCESS_MODE:
|
||||
{
|
||||
reader_current_process_extent( &begin, &end );
|
||||
parse_util_process_extent( get_buffer(),
|
||||
get_cursor_pos(),
|
||||
&begin,
|
||||
&end );
|
||||
break;
|
||||
}
|
||||
|
||||
case JOB_MODE:
|
||||
{
|
||||
reader_current_job_extent( &begin, &end );
|
||||
parse_util_job_extent( get_buffer(),
|
||||
get_cursor_pos(),
|
||||
&begin,
|
||||
&end );
|
||||
break;
|
||||
}
|
||||
|
||||
case TOKEN_MODE:
|
||||
{
|
||||
reader_current_token_extent( &begin, &end, 0, 0 );
|
||||
parse_util_token_extent( get_buffer(),
|
||||
get_cursor_pos(),
|
||||
&begin,
|
||||
&end,
|
||||
0, 0 );
|
||||
break;
|
||||
}
|
||||
|
||||
|
|
|
@ -19,8 +19,11 @@ Functions used for implementing the complete builtin.
|
|||
#include "complete.h"
|
||||
#include "wgetopt.h"
|
||||
#include "parser.h"
|
||||
#include "reader.h"
|
||||
#include "translate.h"
|
||||
|
||||
const static wchar_t *temporary_buffer;
|
||||
|
||||
/*
|
||||
builtin_complete_* are a set of rather silly looping functions that
|
||||
make sure that all the proper combinations of complete_add or
|
||||
|
@ -235,6 +238,11 @@ static void builtin_complete_remove( array_list_t *cmd,
|
|||
}
|
||||
|
||||
|
||||
const wchar_t *builtin_complete_get_temporary_buffer()
|
||||
{
|
||||
return temporary_buffer;
|
||||
}
|
||||
|
||||
int builtin_complete( wchar_t **argv )
|
||||
{
|
||||
int res=0;
|
||||
|
@ -247,9 +255,18 @@ int builtin_complete( wchar_t **argv )
|
|||
array_list_t gnu_opt, old_opt;
|
||||
wchar_t *comp=L"", *desc=L"", *condition=L"", *load=0;
|
||||
|
||||
wchar_t *do_complete = 0;
|
||||
|
||||
array_list_t cmd;
|
||||
array_list_t path;
|
||||
|
||||
static int recursion_level=0;
|
||||
|
||||
if( !is_interactive_session )
|
||||
{
|
||||
debug( 1, _(L"%ls: Command only available in interactive sessions"), argv[0] );
|
||||
}
|
||||
|
||||
al_init( &cmd );
|
||||
al_init( &path );
|
||||
sb_init( &short_opt );
|
||||
|
@ -320,6 +337,10 @@ int builtin_complete( wchar_t **argv )
|
|||
L"load", required_argument, 0, 'y'
|
||||
}
|
||||
,
|
||||
{
|
||||
L"do-complete", required_argument, 0, 'C'
|
||||
}
|
||||
,
|
||||
{
|
||||
0, 0, 0, 0
|
||||
}
|
||||
|
@ -330,7 +351,7 @@ int builtin_complete( wchar_t **argv )
|
|||
|
||||
int opt = wgetopt_long( argc,
|
||||
argv,
|
||||
L"a:c:p:s:l:o:d:frxeun:y:",
|
||||
L"a:c:p:s:l:o:d:frxeun:y:C:",
|
||||
long_options,
|
||||
&opt_index );
|
||||
if( opt == -1 )
|
||||
|
@ -410,8 +431,11 @@ int builtin_complete( wchar_t **argv )
|
|||
case 'y':
|
||||
load = woptarg;
|
||||
break;
|
||||
|
||||
|
||||
case 'C':
|
||||
do_complete = woptarg?woptarg:reader_get_buffer();
|
||||
break;
|
||||
|
||||
case '?':
|
||||
// builtin_print_help( argv[0], sb_err );
|
||||
|
||||
|
@ -424,6 +448,40 @@ int builtin_complete( wchar_t **argv )
|
|||
|
||||
if( res != 0 )
|
||||
{
|
||||
}
|
||||
else if( do_complete )
|
||||
{
|
||||
array_list_t comp;
|
||||
int i;
|
||||
|
||||
const wchar_t *prev_temporary_buffer = temporary_buffer;
|
||||
temporary_buffer = do_complete;
|
||||
|
||||
if( recursion_level < 1 )
|
||||
{
|
||||
recursion_level++;
|
||||
|
||||
|
||||
al_init( &comp );
|
||||
|
||||
complete( do_complete, &comp );
|
||||
|
||||
for( i=0; i<al_get_count( &comp ); i++ )
|
||||
{
|
||||
wchar_t *next = (wchar_t *)al_get( &comp, i );
|
||||
wchar_t *sep = wcschr( next, COMPLETE_SEP );
|
||||
if( sep )
|
||||
*sep = L'\t';
|
||||
sb_printf( sb_out, L"%ls\n", next );
|
||||
}
|
||||
|
||||
al_foreach( &comp, (void (*)(const void *))&free );
|
||||
al_destroy( &comp );
|
||||
recursion_level--;
|
||||
}
|
||||
|
||||
temporary_buffer = prev_temporary_buffer;
|
||||
|
||||
}
|
||||
else if( woptind != argc )
|
||||
{
|
||||
|
|
16
complete.c
16
complete.c
|
@ -36,6 +36,7 @@
|
|||
#include "history.h"
|
||||
#include "intern.h"
|
||||
#include "translate.h"
|
||||
#include "parse_util.h"
|
||||
|
||||
#include "wutil.h"
|
||||
|
||||
|
@ -2007,7 +2008,8 @@ 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, *buff;
|
||||
const wchar_t *begin, *end, *prev_begin, *prev_end;
|
||||
wchar_t *buff;
|
||||
tokenizer tok;
|
||||
wchar_t *current_token=0, *current_command=0, *prev_token=0;
|
||||
|
||||
|
@ -2016,7 +2018,9 @@ void complete( const wchar_t *cmd,
|
|||
|
||||
int old_error_max = error_max;
|
||||
int done=0;
|
||||
|
||||
|
||||
int cursor_pos = wcslen(cmd );
|
||||
|
||||
error_max=0;
|
||||
|
||||
/**
|
||||
|
@ -2042,7 +2046,7 @@ void complete( const wchar_t *cmd,
|
|||
|
||||
if( !done )
|
||||
{
|
||||
reader_current_subshell_extent( &begin, &end );
|
||||
parse_util_cmdsubst_extent( cmd, cursor_pos, &begin, &end );
|
||||
|
||||
if( !begin )
|
||||
done=1;
|
||||
|
@ -2051,7 +2055,7 @@ void complete( const wchar_t *cmd,
|
|||
if( !done )
|
||||
{
|
||||
|
||||
pos = reader_get_cursor_pos()-(begin-reader_get_buffer());
|
||||
pos = cursor_pos-(begin-cmd);
|
||||
|
||||
buff = wcsndup( begin, end-begin );
|
||||
|
||||
|
@ -2109,9 +2113,9 @@ void complete( const wchar_t *cmd,
|
|||
Get the string to complete
|
||||
*/
|
||||
|
||||
reader_current_token_extent( &begin, &end, &prev_begin, &prev_end );
|
||||
parse_util_token_extent( cmd, cursor_pos, &begin, &end, &prev_begin, &prev_end );
|
||||
|
||||
current_token = wcsndup( begin, reader_get_cursor_pos()-(begin-reader_get_buffer()) );
|
||||
current_token = wcsndup( begin, cursor_pos-(begin-cmd) );
|
||||
|
||||
prev_token = prev_begin ? wcsndup( prev_begin, prev_end - prev_begin ): wcsdup(L"");
|
||||
|
||||
|
|
1
exec.c
1
exec.c
|
@ -1077,7 +1077,6 @@ void exec( job_t *j )
|
|||
p->completed = 1;
|
||||
}
|
||||
|
||||
|
||||
io_buffer_destroy( io_buffer );
|
||||
|
||||
io_buffer=0;
|
||||
|
|
95
expand.c
95
expand.c
|
@ -39,6 +39,7 @@ parameter expansion.
|
|||
#include "tokenizer.h"
|
||||
#include "complete.h"
|
||||
#include "translate.h"
|
||||
#include "parse_util.h"
|
||||
|
||||
/**
|
||||
Description for child process
|
||||
|
@ -1154,105 +1155,23 @@ static int expand_brackets( wchar_t *in, int flags, array_list_t *out )
|
|||
return 1;
|
||||
}
|
||||
|
||||
int expand_locate_subshell( wchar_t *in,
|
||||
wchar_t **begin,
|
||||
wchar_t **end,
|
||||
int allow_incomplete )
|
||||
{
|
||||
wchar_t *pos;
|
||||
wchar_t prev=0;
|
||||
int syntax_error=0;
|
||||
int paran_count=0;
|
||||
|
||||
wchar_t *paran_begin=0, *paran_end=0;
|
||||
|
||||
for( pos=in; *pos; pos++ )
|
||||
{
|
||||
if( prev != '\\' )
|
||||
{
|
||||
if( wcschr( L"\'\"", *pos ) )
|
||||
{
|
||||
wchar_t *end = quote_end( pos );
|
||||
if( end && *end)
|
||||
{
|
||||
pos=end;
|
||||
}
|
||||
else
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
if( *pos == '(' )
|
||||
{
|
||||
if(( paran_count == 0)&&(paran_begin==0))
|
||||
paran_begin = pos;
|
||||
|
||||
paran_count++;
|
||||
}
|
||||
else if( *pos == ')' )
|
||||
{
|
||||
paran_count--;
|
||||
if( (paran_count == 0) && (paran_end == 0) )
|
||||
{
|
||||
paran_end = pos;
|
||||
break;
|
||||
}
|
||||
|
||||
if( paran_count < 0 )
|
||||
{
|
||||
syntax_error = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
prev = *pos;
|
||||
}
|
||||
|
||||
syntax_error |= (paran_count < 0 );
|
||||
syntax_error |= ((paran_count>0)&&(!allow_incomplete));
|
||||
|
||||
if( syntax_error )
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
if( paran_begin == 0 )
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
*begin = paran_begin;
|
||||
*end = paran_count?in+wcslen(in):paran_end;
|
||||
|
||||
/* assert( *begin >= in );
|
||||
assert( *begin < (in+wcslen(in) ) );
|
||||
assert( *end >= *begin );
|
||||
assert( *end < (in+wcslen(in) ) );
|
||||
*/
|
||||
return 1;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
Perform subshell expansion
|
||||
*/
|
||||
static int expand_subshell( wchar_t *in, array_list_t *out )
|
||||
{
|
||||
wchar_t *paran_begin=0, *paran_end=0;
|
||||
const wchar_t *paran_begin=0, *paran_end=0;
|
||||
int len1, len2;
|
||||
wchar_t prev=0;
|
||||
wchar_t *subcmd;
|
||||
array_list_t sub_res, tail_expand;
|
||||
int i, j;
|
||||
wchar_t *item_begin;
|
||||
const wchar_t *item_begin;
|
||||
|
||||
switch( expand_locate_subshell(in,
|
||||
¶n_begin,
|
||||
¶n_end,
|
||||
0 ) )
|
||||
switch( parse_util_locate_cmdsubst(in,
|
||||
¶n_begin,
|
||||
¶n_end,
|
||||
0 ) )
|
||||
{
|
||||
case -1:
|
||||
error( SYNTAX_ERROR,
|
||||
|
|
14
expand.h
14
expand.h
|
@ -182,20 +182,6 @@ wchar_t *expand_escape_variable( const wchar_t *in );
|
|||
*/
|
||||
wchar_t *expand_tilde(wchar_t *in);
|
||||
|
||||
/**
|
||||
Locate the first subshell in the specified string.
|
||||
|
||||
\param in the string to search for subshells
|
||||
\param begin the starting paranthesis of the subshell
|
||||
\param end the ending paranthesis of the subshell
|
||||
\param flags set this variable to ACCEPT_INCOMPLETE if in tab_completion mode
|
||||
\return -1 on syntax error, 0 if no subshells exist and 1 on sucess
|
||||
*/
|
||||
int expand_locate_subshell( wchar_t *in,
|
||||
wchar_t **begin,
|
||||
wchar_t **end,
|
||||
int flags );
|
||||
|
||||
|
||||
/**
|
||||
Tokenize the specified string into the specified array_list_t.
|
||||
|
|
90
fish_pager.c
90
fish_pager.c
|
@ -424,54 +424,54 @@ static void printed_length( wchar_t *str,
|
|||
else
|
||||
{
|
||||
|
||||
switch( *str )
|
||||
{
|
||||
case L'\n':
|
||||
case L'\b':
|
||||
case L'\r':
|
||||
case L'\e':
|
||||
case L'\t':
|
||||
case L'\\':
|
||||
case L'&':
|
||||
case L'$':
|
||||
case L' ':
|
||||
case L'#':
|
||||
case L'^':
|
||||
case L'<':
|
||||
case L'>':
|
||||
case L'(':
|
||||
case L')':
|
||||
case L'[':
|
||||
case L']':
|
||||
case L'{':
|
||||
case L'}':
|
||||
case L'?':
|
||||
case L'*':
|
||||
case L'|':
|
||||
case L';':
|
||||
case L':':
|
||||
case L'\'':
|
||||
case L'"':
|
||||
case L'%':
|
||||
case L'~':
|
||||
switch( *str )
|
||||
{
|
||||
case L'\n':
|
||||
case L'\b':
|
||||
case L'\r':
|
||||
case L'\e':
|
||||
case L'\t':
|
||||
case L'\\':
|
||||
case L'&':
|
||||
case L'$':
|
||||
case L' ':
|
||||
case L'#':
|
||||
case L'^':
|
||||
case L'<':
|
||||
case L'>':
|
||||
case L'(':
|
||||
case L')':
|
||||
case L'[':
|
||||
case L']':
|
||||
case L'{':
|
||||
case L'}':
|
||||
case L'?':
|
||||
case L'*':
|
||||
case L'|':
|
||||
case L';':
|
||||
case L':':
|
||||
case L'\'':
|
||||
case L'"':
|
||||
case L'%':
|
||||
case L'~':
|
||||
|
||||
if( has_description )
|
||||
desc_len++;
|
||||
else
|
||||
comp_len+=2;
|
||||
break;
|
||||
if( has_description )
|
||||
desc_len++;
|
||||
else
|
||||
comp_len+=2;
|
||||
break;
|
||||
|
||||
case COMPLETE_SEP:
|
||||
has_description = 1;
|
||||
break;
|
||||
case COMPLETE_SEP:
|
||||
has_description = 1;
|
||||
break;
|
||||
|
||||
default:
|
||||
if( has_description )
|
||||
desc_len+= wcwidth(*str);
|
||||
else
|
||||
comp_len+= wcwidth(*str);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
if( has_description )
|
||||
desc_len+= wcwidth(*str);
|
||||
else
|
||||
comp_len+= wcwidth(*str);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
str++;
|
||||
|
|
10
function.c
10
function.c
|
@ -86,16 +86,15 @@ void function_add( const wchar_t *name,
|
|||
{
|
||||
int i;
|
||||
wchar_t *cmd_end;
|
||||
function_data_t *d;
|
||||
|
||||
|
||||
if( function_exists( name ) )
|
||||
function_remove( name );
|
||||
|
||||
|
||||
|
||||
function_data_t *d = malloc( sizeof( function_data_t ) );
|
||||
d = malloc( sizeof( function_data_t ) );
|
||||
d->definition_offset = count_lineno( parser_get_buffer(), current_block->tok_pos );
|
||||
d->cmd = wcsdup( val );
|
||||
|
||||
cmd_end = d->cmd + wcslen(d->cmd)-1;
|
||||
while( (cmd_end>d->cmd) && wcschr( L"\n\r\t ", *cmd_end ) )
|
||||
{
|
||||
|
@ -105,6 +104,7 @@ void function_add( const wchar_t *name,
|
|||
d->desc = desc?wcsdup( desc ):0;
|
||||
d->is_binding = is_binding;
|
||||
d->definition_file = reader_current_filename()?intern(reader_current_filename()):0;
|
||||
|
||||
hash_put( &function, intern(name), d );
|
||||
|
||||
for( i=0; i<al_get_count( events ); i++ )
|
||||
|
@ -123,8 +123,8 @@ void function_remove( const wchar_t *name )
|
|||
{
|
||||
void *key;
|
||||
function_data_t *d;
|
||||
|
||||
event_t ev;
|
||||
|
||||
ev.type=EVENT_ANY;
|
||||
ev.function_name=name;
|
||||
event_remove( &ev );
|
||||
|
|
11
highlight.c
11
highlight.c
|
@ -18,6 +18,7 @@
|
|||
#include "tokenizer.h"
|
||||
#include "proc.h"
|
||||
#include "parser.h"
|
||||
#include "parse_util.h"
|
||||
#include "builtin.h"
|
||||
#include "function.h"
|
||||
#include "env.h"
|
||||
|
@ -365,11 +366,11 @@ void highlight_shell( wchar_t * buff,
|
|||
while( 1 )
|
||||
{
|
||||
wchar_t *begin, *end;
|
||||
|
||||
if( expand_locate_subshell( subpos,
|
||||
&begin,
|
||||
&end,
|
||||
1) <= 0)
|
||||
|
||||
if( parse_util_locate_cmdsubst( subpos,
|
||||
(const wchar_t **)&begin,
|
||||
(const wchar_t **)&end,
|
||||
1) <= 0)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -11,3 +11,4 @@ complete -c complete -s d -l description -d (_ "Description of this completions"
|
|||
complete -c complete -s u -l unauthorative -d (_ "Option list is not complete")
|
||||
complete -c complete -s e -l erase -d (_ "Remove completion")
|
||||
complete -c complete -s h -l help -d (_ "Display help and exit")
|
||||
complete -c complete -s C -l do-complete -d (_ "Print all completions for the specified commandline")
|
||||
|
|
|
@ -1,10 +1,8 @@
|
|||
#
|
||||
# Completion for sudo
|
||||
#
|
||||
# Generate a list of commands
|
||||
#
|
||||
|
||||
complete -c sudo -d (_ "Command to run") -x -a "(__fish_complete_command)"
|
||||
complete -c sudo -d (_ "Command to run") -x -a "(__fish_complete_subcommand)"
|
||||
|
||||
complete -c sudo -s h -d (_ "Display help and exit")
|
||||
complete -c sudo -s v -d (_ "Validate")
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
|
||||
complete -c time -a "(__fish_complete_command)" -d (_ "Command")
|
||||
complete -c time -a "(__fish_complete_subcommand -- -o --output -f --format)" -d (_ "Command")
|
||||
|
||||
complete -c time -s f -l format -d (_ "Specify output format") -x
|
||||
complete -c time -s p -l portable -d (_ "Use the portable output format")
|
||||
|
|
|
@ -96,9 +96,46 @@ function __fish_complete_pids -d "Print a list of process identifiers along with
|
|||
end
|
||||
|
||||
function __fish_complete_command -d "Complete using all available commands"
|
||||
for i in $PATH; command ls $i; end
|
||||
printf "%s\n" (commandline -ct)(complete -C (commandline -ct))
|
||||
end
|
||||
|
||||
function __fish_complete_subcommand -d "Complete subcommand"
|
||||
set -l res ""
|
||||
set -l had_cmd 0
|
||||
set -l cmd (commandline -cop) (commandline -ct)
|
||||
set -l skip_next 1
|
||||
|
||||
for i in $cmd
|
||||
|
||||
if test "$skip_next" = 1
|
||||
set skip_next 0
|
||||
continue
|
||||
end
|
||||
|
||||
if test "$had_cmd" = 1
|
||||
set res "$res $i"
|
||||
else
|
||||
|
||||
if contains $i $argv
|
||||
set skip_next 1
|
||||
continue
|
||||
end
|
||||
|
||||
switch $i
|
||||
case '-*'
|
||||
|
||||
case '*'
|
||||
set had_cmd 1
|
||||
set res $i
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
printf "%s\n" (commandline -ct)(complete -C $res)
|
||||
|
||||
end
|
||||
|
||||
|
||||
|
||||
function __fish_print_hostnames -d "Print a list of known hostnames"
|
||||
|
||||
|
|
377
parse_util.c
Normal file
377
parse_util.c
Normal file
|
@ -0,0 +1,377 @@
|
|||
/** \file parse_util.c
|
||||
|
||||
Various utility functions for parsing a command
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <sys/types.h>
|
||||
#include <unistd.h>
|
||||
#include <wctype.h>
|
||||
|
||||
#include <wchar.h>
|
||||
|
||||
#include <assert.h>
|
||||
|
||||
#include "util.h"
|
||||
#include "wutil.h"
|
||||
#include "common.h"
|
||||
#include "tokenizer.h"
|
||||
#include "parse_util.h"
|
||||
|
||||
int parse_util_locate_cmdsubst( const wchar_t *in,
|
||||
const wchar_t **begin,
|
||||
const wchar_t **end,
|
||||
int allow_incomplete )
|
||||
{
|
||||
const wchar_t *pos;
|
||||
wchar_t prev=0;
|
||||
int syntax_error=0;
|
||||
int paran_count=0;
|
||||
|
||||
const wchar_t *paran_begin=0, *paran_end=0;
|
||||
|
||||
for( pos=in; *pos; pos++ )
|
||||
{
|
||||
if( prev != '\\' )
|
||||
{
|
||||
if( wcschr( L"\'\"", *pos ) )
|
||||
{
|
||||
wchar_t *end = quote_end( pos );
|
||||
if( end && *end)
|
||||
{
|
||||
pos=end;
|
||||
}
|
||||
else
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
if( *pos == '(' )
|
||||
{
|
||||
if(( paran_count == 0)&&(paran_begin==0))
|
||||
paran_begin = pos;
|
||||
|
||||
paran_count++;
|
||||
}
|
||||
else if( *pos == ')' )
|
||||
{
|
||||
paran_count--;
|
||||
if( (paran_count == 0) && (paran_end == 0) )
|
||||
{
|
||||
paran_end = pos;
|
||||
break;
|
||||
}
|
||||
|
||||
if( paran_count < 0 )
|
||||
{
|
||||
syntax_error = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
prev = *pos;
|
||||
}
|
||||
|
||||
syntax_error |= (paran_count < 0 );
|
||||
syntax_error |= ((paran_count>0)&&(!allow_incomplete));
|
||||
|
||||
if( syntax_error )
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
if( paran_begin == 0 )
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
*begin = paran_begin;
|
||||
*end = paran_count?in+wcslen(in):paran_end;
|
||||
|
||||
/* assert( *begin >= in );
|
||||
assert( *begin < (in+wcslen(in) ) );
|
||||
assert( *end >= *begin );
|
||||
assert( *end < (in+wcslen(in) ) );
|
||||
*/
|
||||
return 1;
|
||||
|
||||
}
|
||||
|
||||
|
||||
void parse_util_cmdsubst_extent( const wchar_t *buff,
|
||||
int cursor_pos,
|
||||
const wchar_t **a,
|
||||
const wchar_t **b )
|
||||
{
|
||||
const wchar_t *begin, *end;
|
||||
const wchar_t *pos;
|
||||
|
||||
if( a )
|
||||
*a=0;
|
||||
if( b )
|
||||
*b = 0;
|
||||
|
||||
if( !buff )
|
||||
return;
|
||||
|
||||
pos = buff;
|
||||
|
||||
while( 1 )
|
||||
{
|
||||
int bc, ec;
|
||||
|
||||
if( parse_util_locate_cmdsubst( pos,
|
||||
&begin,
|
||||
&end,
|
||||
1 ) <= 0)
|
||||
{
|
||||
begin=buff;
|
||||
end = buff + wcslen(buff);
|
||||
break;
|
||||
}
|
||||
|
||||
if( !end )
|
||||
{
|
||||
end = buff + wcslen(buff);
|
||||
}
|
||||
|
||||
bc = begin-buff;
|
||||
ec = end-buff;
|
||||
|
||||
if(( bc < cursor_pos ) && (ec >= cursor_pos) )
|
||||
{
|
||||
begin++;
|
||||
break;
|
||||
}
|
||||
pos = end+1;
|
||||
}
|
||||
if( a )
|
||||
*a = begin;
|
||||
if( b )
|
||||
*b = end;
|
||||
}
|
||||
|
||||
/**
|
||||
Get the beginning and end of the job or process definition under the cursor
|
||||
*/
|
||||
static void job_or_process_extent( const wchar_t *buff,
|
||||
int cursor_pos,
|
||||
const wchar_t **a,
|
||||
const wchar_t **b,
|
||||
int process )
|
||||
{
|
||||
const wchar_t *begin, *end;
|
||||
int pos;
|
||||
wchar_t *buffcpy;
|
||||
int finished=0;
|
||||
|
||||
tokenizer tok;
|
||||
|
||||
if( a )
|
||||
*a=0;
|
||||
if( b )
|
||||
*b = 0;
|
||||
|
||||
parse_util_cmdsubst_extent( buff, cursor_pos, &begin, &end );
|
||||
if( !end || !begin )
|
||||
return;
|
||||
|
||||
pos = cursor_pos - (begin - buff);
|
||||
// fwprintf( stderr, L"Subshell extent: %d %d %d\n", begin-buff, end-buff, pos );
|
||||
|
||||
if( a )
|
||||
{
|
||||
*a = begin;
|
||||
}
|
||||
|
||||
if( b )
|
||||
{
|
||||
*b = end;
|
||||
}
|
||||
|
||||
buffcpy = wcsndup( begin, end-begin );
|
||||
|
||||
if( !buffcpy )
|
||||
{
|
||||
die_mem();
|
||||
}
|
||||
// fwprintf( stderr, L"Strlen: %d\n", wcslen(buffcpy ) );
|
||||
|
||||
for( tok_init( &tok, buffcpy, TOK_ACCEPT_UNFINISHED );
|
||||
tok_has_next( &tok ) && !finished;
|
||||
tok_next( &tok ) )
|
||||
{
|
||||
int tok_begin = tok_get_pos( &tok );
|
||||
// fwprintf( stderr, L".");
|
||||
|
||||
switch( tok_last_type( &tok ) )
|
||||
{
|
||||
case TOK_PIPE:
|
||||
if( !process )
|
||||
break;
|
||||
|
||||
case TOK_END:
|
||||
case TOK_BACKGROUND:
|
||||
{
|
||||
|
||||
// fwprintf( stderr, L"New cmd at %d\n", tok_begin );
|
||||
|
||||
if( tok_begin >= pos )
|
||||
{
|
||||
finished=1;
|
||||
if( b )
|
||||
*b = buff + tok_begin;
|
||||
}
|
||||
else
|
||||
{
|
||||
if( a )
|
||||
*a = buff + tok_begin+1;
|
||||
}
|
||||
break;
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// fwprintf( stderr, L"Res: %d %d\n", *a-buff, *b-buff );
|
||||
free( buffcpy);
|
||||
|
||||
tok_destroy( &tok );
|
||||
|
||||
}
|
||||
|
||||
void parse_util_process_extent( const wchar_t *buff,
|
||||
int pos,
|
||||
const wchar_t **a,
|
||||
const wchar_t **b )
|
||||
{
|
||||
job_or_process_extent( buff, pos, a, b, 1 );
|
||||
}
|
||||
|
||||
void parse_util_job_extent( const wchar_t *buff,
|
||||
int pos,
|
||||
const wchar_t **a,
|
||||
const wchar_t **b )
|
||||
{
|
||||
job_or_process_extent( buff,pos,a, b, 0 );
|
||||
}
|
||||
|
||||
|
||||
void parse_util_token_extent( const wchar_t *buff,
|
||||
int cursor_pos,
|
||||
const wchar_t **tok_begin,
|
||||
const wchar_t **tok_end,
|
||||
const wchar_t **prev_begin,
|
||||
const wchar_t **prev_end )
|
||||
{
|
||||
const wchar_t *begin, *end;
|
||||
int pos;
|
||||
wchar_t *buffcpy;
|
||||
|
||||
tokenizer tok;
|
||||
|
||||
const wchar_t *a, *b, *pa, *pb;
|
||||
|
||||
|
||||
a = b = pa = pb = 0;
|
||||
|
||||
parse_util_cmdsubst_extent( buff, cursor_pos, &begin, &end );
|
||||
|
||||
if( !end || !begin )
|
||||
return;
|
||||
|
||||
pos = cursor_pos - (begin - buff);
|
||||
|
||||
a = buff + pos;
|
||||
b = a;
|
||||
pa = buff + pos;
|
||||
pb = pa;
|
||||
|
||||
assert( begin >= buff );
|
||||
assert( begin <= (buff+wcslen(buff) ) );
|
||||
assert( end >= begin );
|
||||
assert( end <= (buff+wcslen(buff) ) );
|
||||
|
||||
buffcpy = wcsndup( begin, end-begin );
|
||||
|
||||
if( !buffcpy )
|
||||
{
|
||||
die_mem();
|
||||
}
|
||||
|
||||
for( tok_init( &tok, buffcpy, TOK_ACCEPT_UNFINISHED );
|
||||
tok_has_next( &tok );
|
||||
tok_next( &tok ) )
|
||||
{
|
||||
int tok_begin = tok_get_pos( &tok );
|
||||
int tok_end=tok_begin;
|
||||
|
||||
/*
|
||||
Calculate end of token
|
||||
*/
|
||||
if( tok_last_type( &tok ) == TOK_STRING )
|
||||
tok_end +=wcslen(tok_last(&tok));
|
||||
|
||||
/*
|
||||
Cursor was before beginning of this token, means that the
|
||||
cursor is between two tokens, so we set it to a zero element
|
||||
string and break
|
||||
*/
|
||||
if( tok_begin > pos )
|
||||
{
|
||||
a = b = buff + pos;
|
||||
break;
|
||||
}
|
||||
|
||||
/*
|
||||
If cursor is inside the token, this is the token we are
|
||||
looking for. If so, set a and b and break
|
||||
*/
|
||||
if( tok_end >= pos )
|
||||
{
|
||||
a = begin + tok_get_pos( &tok );
|
||||
b = a + wcslen(tok_last(&tok));
|
||||
|
||||
// fwprintf( stderr, L"Whee %ls\n", *a );
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
/*
|
||||
Remember previous string token
|
||||
*/
|
||||
if( tok_last_type( &tok ) == TOK_STRING )
|
||||
{
|
||||
pa = begin + tok_get_pos( &tok );
|
||||
pb = pa + wcslen(tok_last(&tok));
|
||||
}
|
||||
}
|
||||
|
||||
free( buffcpy);
|
||||
|
||||
tok_destroy( &tok );
|
||||
|
||||
if( tok_begin )
|
||||
*tok_begin = a;
|
||||
if( tok_end )
|
||||
*tok_end = b;
|
||||
if( prev_begin )
|
||||
*prev_begin = pa;
|
||||
if( prev_end )
|
||||
*prev_end = pb;
|
||||
|
||||
assert( pa >= buff );
|
||||
assert( pa <= (buff+wcslen(buff) ) );
|
||||
assert( pb >= pa );
|
||||
assert( pb <= (buff+wcslen(buff) ) );
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
50
parse_util.h
Normal file
50
parse_util.h
Normal file
|
@ -0,0 +1,50 @@
|
|||
/** \file parse_util.h
|
||||
|
||||
Various utility functions for parsing a command
|
||||
*/
|
||||
|
||||
#ifndef FISH_PARSE_UTIL_H
|
||||
#define FISH_PARSE_UTIL_H
|
||||
|
||||
#include <wchar.h>
|
||||
|
||||
/**
|
||||
Locate the first subshell in the specified string.
|
||||
|
||||
\param in the string to search for subshells
|
||||
\param begin the starting paranthesis of the subshell
|
||||
\param end the ending paranthesis of the subshell
|
||||
\param flags set this variable to ACCEPT_INCOMPLETE if in tab_completion mode
|
||||
\return -1 on syntax error, 0 if no subshells exist and 1 on sucess
|
||||
*/
|
||||
|
||||
int parse_util_locate_cmdsubst( const wchar_t *in,
|
||||
const wchar_t **begin,
|
||||
const wchar_t **end,
|
||||
int allow_incomplete );
|
||||
|
||||
|
||||
void parse_util_cmdsubst_extent( const wchar_t *buff,
|
||||
int cursor_pos,
|
||||
const wchar_t **a,
|
||||
const wchar_t **b );
|
||||
|
||||
void parse_util_process_extent( const wchar_t *buff,
|
||||
int pos,
|
||||
const wchar_t **a,
|
||||
const wchar_t **b );
|
||||
|
||||
|
||||
void parse_util_job_extent( const wchar_t *buff,
|
||||
int pos,
|
||||
const wchar_t **a,
|
||||
const wchar_t **b );
|
||||
|
||||
void parse_util_token_extent( const wchar_t *buff,
|
||||
int cursor_pos,
|
||||
const wchar_t **tok_begin,
|
||||
const wchar_t **tok_end,
|
||||
const wchar_t **prev_begin,
|
||||
const wchar_t **prev_end );
|
||||
|
||||
#endif
|
49
parser.c
49
parser.c
|
@ -265,7 +265,7 @@ static int current_tokenizer_pos;
|
|||
block_t *current_block=0;
|
||||
|
||||
/** List of called functions, used to help prevent infinite recursion */
|
||||
static array_list_t forbidden_function;
|
||||
static array_list_t *forbidden_function;
|
||||
|
||||
/**
|
||||
String index where the current job started.
|
||||
|
@ -726,7 +726,7 @@ void parser_forbid_function( wchar_t *function )
|
|||
if( function )
|
||||
debug( 2, L"Forbid %ls\n", function );
|
||||
*/
|
||||
al_push( &forbidden_function, function?wcsdup(function):0 );
|
||||
al_push( forbidden_function, function?wcsdup(function):0 );
|
||||
}
|
||||
|
||||
void parser_allow_function()
|
||||
|
@ -735,7 +735,7 @@ void parser_allow_function()
|
|||
if( al_peek( &forbidden_function) )
|
||||
debug( 2, L"Allow %ls\n", al_peek( &forbidden_function) );
|
||||
*/
|
||||
free( (void *) al_pop( &forbidden_function ) );
|
||||
free( (void *) al_pop( forbidden_function ) );
|
||||
}
|
||||
|
||||
void error( int ec, int p, const wchar_t *str, ... )
|
||||
|
@ -848,7 +848,8 @@ void parser_init()
|
|||
{
|
||||
al_init( &profile_data);
|
||||
}
|
||||
al_init( &forbidden_function );
|
||||
forbidden_function = al_new();
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -924,14 +925,15 @@ void parser_destroy()
|
|||
al_destroy( &profile_data );
|
||||
}
|
||||
|
||||
al_destroy( &forbidden_function );
|
||||
|
||||
if( lineinfo )
|
||||
{
|
||||
sb_destroy( lineinfo );
|
||||
free(lineinfo );
|
||||
lineinfo = 0;
|
||||
}
|
||||
|
||||
al_destroy( forbidden_function );
|
||||
free( forbidden_function );
|
||||
|
||||
}
|
||||
|
||||
|
@ -1236,7 +1238,7 @@ wchar_t *parser_current_line()
|
|||
*/
|
||||
if( !is_interactive || is_function() || (current_line_width!=0) )
|
||||
{
|
||||
// Workaround since it seems impossible to print 0 copies of a character using printf
|
||||
// Workaround since it seems impossible to print 0 copies of a character using %*lc
|
||||
if( offset+current_line_width )
|
||||
{
|
||||
sb_printf( lineinfo,
|
||||
|
@ -1875,7 +1877,7 @@ static int parse_job( process_t *p,
|
|||
int nxt_forbidden;
|
||||
wchar_t *forbid;
|
||||
|
||||
forbid = (wchar_t *)(al_get_count( &forbidden_function)?al_peek( &forbidden_function ):0);
|
||||
forbid = (wchar_t *)(al_get_count( forbidden_function)?al_peek( forbidden_function ):0);
|
||||
nxt_forbidden = forbid && (wcscmp( forbid, nxt) == 0 );
|
||||
|
||||
/*
|
||||
|
@ -1887,7 +1889,7 @@ static int parse_job( process_t *p,
|
|||
/*
|
||||
Check if we have reached the maximum recursion depth
|
||||
*/
|
||||
if( al_get_count( &forbidden_function ) > MAX_RECURSION_DEPTH )
|
||||
if( al_get_count( forbidden_function ) > MAX_RECURSION_DEPTH )
|
||||
{
|
||||
error( SYNTAX_ERROR,
|
||||
tok_get_pos( tok ),
|
||||
|
@ -2351,6 +2353,15 @@ int eval( const wchar_t *cmd, io_data_t *io, int block_type )
|
|||
tokenizer *previous_tokenizer=current_tokenizer;
|
||||
block_t *start_current_block = current_block;
|
||||
io_data_t *prev_io = block_io;
|
||||
array_list_t *prev_forbidden = forbidden_function;
|
||||
|
||||
if( block_type == SUBST )
|
||||
{
|
||||
forbidden_function = al_new();
|
||||
}
|
||||
|
||||
forbid_count = al_get_count( forbidden_function );
|
||||
|
||||
block_io = io;
|
||||
|
||||
job_reap( 0 );
|
||||
|
@ -2387,7 +2398,6 @@ int eval( const wchar_t *cmd, io_data_t *io, int block_type )
|
|||
|
||||
parser_push_block( block_type );
|
||||
|
||||
forbid_count = al_get_count( &forbidden_function );
|
||||
|
||||
tok_init( current_tokenizer, cmd, 0 );
|
||||
error_code = 0;
|
||||
|
@ -2447,19 +2457,28 @@ int eval( const wchar_t *cmd, io_data_t *io, int block_type )
|
|||
tok_destroy( current_tokenizer );
|
||||
free( current_tokenizer );
|
||||
|
||||
while( forbid_count < al_get_count( &forbidden_function ))
|
||||
while( al_get_count( forbidden_function ) > forbid_count )
|
||||
parser_allow_function();
|
||||
|
||||
if( block_type == SUBST )
|
||||
{
|
||||
al_destroy( forbidden_function );
|
||||
free( forbidden_function );
|
||||
}
|
||||
|
||||
/*
|
||||
Restore previous eval state
|
||||
*/
|
||||
forbidden_function = prev_forbidden;
|
||||
current_tokenizer=previous_tokenizer;
|
||||
block_io = prev_io;
|
||||
eval_level--;
|
||||
|
||||
code=error_code;
|
||||
error_code=0;
|
||||
|
||||
block_io = prev_io;
|
||||
|
||||
eval_level--;
|
||||
|
||||
job_reap( 0 );
|
||||
|
||||
return code;
|
||||
}
|
||||
|
||||
|
|
2
proc.c
2
proc.c
|
@ -388,7 +388,7 @@ static void handle_child_status( pid_t pid, int status )
|
|||
"Process %d is %ls from job %ls\n",
|
||||
(int) pid, p->actual_cmd, j->command );
|
||||
write( 2, mess, strlen(mess ));
|
||||
*/
|
||||
*/
|
||||
|
||||
mark_process_status ( j, p, status);
|
||||
if( p->completed && prev != 0 )
|
||||
|
|
270
reader.c
270
reader.c
|
@ -80,6 +80,7 @@ commence.
|
|||
#include "output.h"
|
||||
#include "signal.h"
|
||||
#include "translate.h"
|
||||
#include "parse_util.h"
|
||||
|
||||
/**
|
||||
Maximum length of prefix string when printing completion
|
||||
|
@ -1691,274 +1692,17 @@ void reader_sanity_check()
|
|||
}
|
||||
}
|
||||
|
||||
void reader_current_subshell_extent( wchar_t **a, wchar_t **b )
|
||||
{
|
||||
wchar_t *begin, *end;
|
||||
wchar_t *pos;
|
||||
|
||||
if( a )
|
||||
*a=0;
|
||||
if( b )
|
||||
*b = 0;
|
||||
|
||||
if( !data )
|
||||
return;
|
||||
|
||||
pos = data->buff;
|
||||
|
||||
while( 1 )
|
||||
{
|
||||
int bc, ec;
|
||||
|
||||
if( expand_locate_subshell( pos,
|
||||
&begin,
|
||||
&end,
|
||||
1 ) <= 0)
|
||||
{
|
||||
begin=data->buff;
|
||||
end = data->buff + wcslen(data->buff);
|
||||
break;
|
||||
}
|
||||
|
||||
if( !end )
|
||||
{
|
||||
end = data->buff + wcslen(data->buff);
|
||||
}
|
||||
|
||||
bc = begin-data->buff;
|
||||
ec = end-data->buff;
|
||||
|
||||
if(( bc < data->buff_pos ) && (ec >= data->buff_pos) )
|
||||
{
|
||||
begin++;
|
||||
break;
|
||||
}
|
||||
pos = end+1;
|
||||
}
|
||||
if( a )
|
||||
*a = begin;
|
||||
if( b )
|
||||
*b = end;
|
||||
}
|
||||
|
||||
/**
|
||||
Get the beginning and dend of the job or process definition under the cursor
|
||||
*/
|
||||
static void reader_current_job_or_process_extent( wchar_t **a,
|
||||
wchar_t **b,
|
||||
int process )
|
||||
{
|
||||
wchar_t *begin, *end;
|
||||
int pos;
|
||||
wchar_t *buffcpy;
|
||||
int finished=0;
|
||||
|
||||
tokenizer tok;
|
||||
|
||||
if( a )
|
||||
*a=0;
|
||||
if( b )
|
||||
*b = 0;
|
||||
|
||||
reader_current_subshell_extent( &begin, &end );
|
||||
if( !end || !begin )
|
||||
return;
|
||||
|
||||
pos = data->buff_pos - (begin - data->buff);
|
||||
// fwprintf( stderr, L"Subshell extent: %d %d %d\n", begin-data->buff, end-data->buff, pos );
|
||||
|
||||
if( a )
|
||||
{
|
||||
*a = begin;
|
||||
}
|
||||
|
||||
if( b )
|
||||
{
|
||||
*b = end;
|
||||
}
|
||||
|
||||
buffcpy = wcsndup( begin, end-begin );
|
||||
|
||||
if( !buffcpy )
|
||||
{
|
||||
die_mem();
|
||||
}
|
||||
// fwprintf( stderr, L"Strlen: %d\n", wcslen(buffcpy ) );
|
||||
|
||||
for( tok_init( &tok, buffcpy, TOK_ACCEPT_UNFINISHED );
|
||||
tok_has_next( &tok ) && !finished;
|
||||
tok_next( &tok ) )
|
||||
{
|
||||
int tok_begin = tok_get_pos( &tok );
|
||||
// fwprintf( stderr, L".");
|
||||
|
||||
switch( tok_last_type( &tok ) )
|
||||
{
|
||||
case TOK_PIPE:
|
||||
if( !process )
|
||||
break;
|
||||
|
||||
case TOK_END:
|
||||
case TOK_BACKGROUND:
|
||||
{
|
||||
|
||||
// fwprintf( stderr, L"New cmd at %d\n", tok_begin );
|
||||
|
||||
if( tok_begin >= pos )
|
||||
{
|
||||
finished=1;
|
||||
if( b )
|
||||
*b = data->buff + tok_begin;
|
||||
}
|
||||
else
|
||||
{
|
||||
if( a )
|
||||
*a = data->buff + tok_begin+1;
|
||||
}
|
||||
break;
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// fwprintf( stderr, L"Res: %d %d\n", *a-data->buff, *b-data->buff );
|
||||
free( buffcpy);
|
||||
|
||||
tok_destroy( &tok );
|
||||
|
||||
}
|
||||
|
||||
void reader_current_process_extent( wchar_t **a, wchar_t **b )
|
||||
{
|
||||
reader_current_job_or_process_extent( a, b, 1 );
|
||||
}
|
||||
|
||||
void reader_current_job_extent( wchar_t **a, wchar_t **b )
|
||||
{
|
||||
reader_current_job_or_process_extent( a, b, 0 );
|
||||
}
|
||||
|
||||
|
||||
void reader_current_token_extent( wchar_t **tok_begin,
|
||||
wchar_t **tok_end,
|
||||
wchar_t **prev_begin,
|
||||
wchar_t **prev_end )
|
||||
{
|
||||
wchar_t *begin, *end;
|
||||
int pos;
|
||||
wchar_t *buffcpy;
|
||||
|
||||
tokenizer tok;
|
||||
|
||||
wchar_t *a, *b, *pa, *pb;
|
||||
|
||||
|
||||
a = b = pa = pb = 0;
|
||||
|
||||
reader_current_subshell_extent( &begin, &end );
|
||||
|
||||
if( !end || !begin )
|
||||
return;
|
||||
|
||||
pos = data->buff_pos - (begin - data->buff);
|
||||
|
||||
a = data->buff + pos;
|
||||
b = a;
|
||||
pa = data->buff + pos;
|
||||
pb = pa;
|
||||
|
||||
assert( begin >= data->buff );
|
||||
assert( begin <= (data->buff+wcslen(data->buff) ) );
|
||||
assert( end >= begin );
|
||||
assert( end <= (data->buff+wcslen(data->buff) ) );
|
||||
|
||||
buffcpy = wcsndup( begin, end-begin );
|
||||
|
||||
if( !buffcpy )
|
||||
{
|
||||
die_mem();
|
||||
}
|
||||
|
||||
for( tok_init( &tok, buffcpy, TOK_ACCEPT_UNFINISHED );
|
||||
tok_has_next( &tok );
|
||||
tok_next( &tok ) )
|
||||
{
|
||||
int tok_begin = tok_get_pos( &tok );
|
||||
int tok_end=tok_begin;
|
||||
|
||||
/*
|
||||
Calculate end of token
|
||||
*/
|
||||
if( tok_last_type( &tok ) == TOK_STRING )
|
||||
tok_end +=wcslen(tok_last(&tok));
|
||||
|
||||
/*
|
||||
Cursor was before beginning of this token, means that the
|
||||
cursor is between two tokens, so we set it to a zero element
|
||||
string and break
|
||||
*/
|
||||
if( tok_begin > pos )
|
||||
{
|
||||
a = b = data->buff + pos;
|
||||
break;
|
||||
}
|
||||
|
||||
/*
|
||||
If cursor is inside the token, this is the token we are
|
||||
looking for. If so, set a and b and break
|
||||
*/
|
||||
if( tok_end >= pos )
|
||||
{
|
||||
a = begin + tok_get_pos( &tok );
|
||||
b = a + wcslen(tok_last(&tok));
|
||||
|
||||
// fwprintf( stderr, L"Whee %ls\n", *a );
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
/*
|
||||
Remember previous string token
|
||||
*/
|
||||
if( tok_last_type( &tok ) == TOK_STRING )
|
||||
{
|
||||
pa = begin + tok_get_pos( &tok );
|
||||
pb = pa + wcslen(tok_last(&tok));
|
||||
}
|
||||
}
|
||||
|
||||
free( buffcpy);
|
||||
|
||||
tok_destroy( &tok );
|
||||
|
||||
if( tok_begin )
|
||||
*tok_begin = a;
|
||||
if( tok_end )
|
||||
*tok_end = b;
|
||||
if( prev_begin )
|
||||
*prev_begin = pa;
|
||||
if( prev_end )
|
||||
*prev_end = pb;
|
||||
|
||||
assert( pa >= data->buff );
|
||||
assert( pa <= (data->buff+wcslen(data->buff) ) );
|
||||
assert( pb >= pa );
|
||||
assert( pb <= (data->buff+wcslen(data->buff) ) );
|
||||
|
||||
}
|
||||
|
||||
|
||||
void reader_replace_current_token( wchar_t *new_token )
|
||||
{
|
||||
|
||||
wchar_t *begin, *end;
|
||||
const wchar_t *begin, *end;
|
||||
string_buffer_t sb;
|
||||
int new_pos;
|
||||
|
||||
/*
|
||||
Find current token
|
||||
*/
|
||||
reader_current_token_extent( &begin, &end, 0, 0 );
|
||||
parse_util_token_extent( data->buff, data->buff_pos, &begin, &end, 0, 0 );
|
||||
|
||||
if( !begin || !end )
|
||||
return;
|
||||
|
@ -2018,9 +1762,9 @@ static int contains( const wchar_t *needle,
|
|||
*/
|
||||
static void reset_token_history()
|
||||
{
|
||||
wchar_t *begin, *end;
|
||||
const wchar_t *begin, *end;
|
||||
|
||||
reader_current_token_extent( &begin, &end, 0, 0 );
|
||||
parse_util_token_extent( data->buff, data->buff_pos, &begin, &end, 0, 0 );
|
||||
if( begin )
|
||||
{
|
||||
wcslcpy(data->search_buff, begin, end-begin+1);
|
||||
|
@ -2718,10 +2462,10 @@ wchar_t *reader_readline()
|
|||
|
||||
if( comp_empty )
|
||||
{
|
||||
wchar_t *begin, *end;
|
||||
const wchar_t *begin, *end;
|
||||
wchar_t *buffcpy;
|
||||
|
||||
reader_current_subshell_extent( &begin, &end );
|
||||
parse_util_cmdsubst_extent( data->buff, data->buff_pos, &begin, &end );
|
||||
|
||||
int len = data->buff_pos - (data->buff - begin);
|
||||
buffcpy = wcsndup( begin, len );
|
||||
|
|
21
reader.h
21
reader.h
|
@ -152,27 +152,6 @@ void reader_set_prompt( wchar_t *prompt );
|
|||
*/
|
||||
int exit_status();
|
||||
|
||||
/**
|
||||
Find the beginning and the end of the current subshell
|
||||
*/
|
||||
void reader_current_subshell_extent( wchar_t **a, wchar_t **b );
|
||||
|
||||
/**
|
||||
Find the beginning and the end of the job under the cursor
|
||||
*/
|
||||
void reader_current_job_extent( wchar_t **a, wchar_t **b );
|
||||
|
||||
/**
|
||||
Find the beginning and the end of the process under the cursor
|
||||
*/
|
||||
void reader_current_process_extent( wchar_t **a, wchar_t **b );
|
||||
|
||||
/**
|
||||
Find the beginning and the end of the token under the curor and the token before the cursor
|
||||
*/
|
||||
|
||||
void reader_current_token_extent( wchar_t **a, wchar_t **b, wchar_t **pa, wchar_t **pb );
|
||||
|
||||
/**
|
||||
Replace the current token with the specified string
|
||||
*/
|
||||
|
|
Loading…
Reference in a new issue