buggy-auto-complete is not so buggy now. Merged branch 'buggy-auto-complete' into CPlusPlus

This commit is contained in:
Siteshwar Vashisht 2012-01-29 14:11:39 +05:30
commit 1a5d866a91
16 changed files with 666 additions and 270 deletions

View file

@ -12,6 +12,7 @@ The classes responsible for autoloading functions and completions.
#include "builtin_scripts.h"
#include "exec.h"
#include <assert.h>
#include <algorithm>
/* The time before we'll recheck an autoloaded file */
static const int kAutoloadStalenessInterval = 1;

View file

@ -2184,7 +2184,7 @@ static int builtin_read( parser_t &parser, wchar_t **argv )
reader_set_prompt( prompt );
if( shell )
{
reader_set_complete_function( &complete );
reader_set_complete_function( &complete2 );
reader_set_highlight_function( &highlight_shell );
reader_set_test_function( &reader_shell_test );
}
@ -3885,6 +3885,18 @@ void builtin_get_names( array_list_t *list )
hash_get_keys( &builtin, list );
}
void builtin_get_names2(std::vector<completion_t> &list) {
for (int i=0;i<builtin.size ; ++i) {
completion_t data_to_push;
if (builtin.arr[i].key == 0)
continue;
data_to_push.completion = (wchar_t*)builtin.arr[i].key;
list.push_back( data_to_push );
}
}
const wchar_t *builtin_get_desc( const wchar_t *b )
{
CHECK( b, 0 );

View file

@ -9,6 +9,7 @@
#include "util.h"
#include "io.h"
#include "common.h"
class parser_t;
@ -143,6 +144,8 @@ int builtin_run( parser_t &parser, wchar_t **argv, io_data_t *io );
*/
void builtin_get_names( array_list_t *list );
void builtin_get_names2 (std::vector<completion_t>&);
/**
Pushes a new set of input/output to the stack. The new stdin is supplied, a new set of output string_buffer_ts is created.
*/

View file

@ -541,7 +541,7 @@ static int builtin_complete( parser_t &parser, wchar_t **argv )
{
if( do_complete )
{
array_list_t *comp;
std::vector<completion_t> comp;
int i;
const wchar_t *prev_temporary_buffer = temporary_buffer;
@ -556,16 +556,17 @@ static int builtin_complete( parser_t &parser, wchar_t **argv )
{
recursion_level++;
comp = al_halloc( 0 );
// comp = al_halloc( 0 );
complete( do_complete, comp );
complete2( do_complete, comp );
for( i=0; i<al_get_count( comp ); i++ )
for( i=0; i< comp.size() ; i++ )
{
completion_t *next = (completion_t *)al_get( comp, i );
const completion_t &next = comp.at( i );
const wchar_t *prepend;
if( next->flags & COMPLETE_NO_CASE )
if( next.flags & COMPLETE_NO_CASE )
{
prepend = L"";
}
@ -575,17 +576,17 @@ static int builtin_complete( parser_t &parser, wchar_t **argv )
}
if( next->description )
if( !(next.description).empty() )
{
sb_printf( sb_out, L"%ls%ls\t%ls\n", prepend, next->completion, next->description );
sb_printf( sb_out, L"%ls%ls\t%ls\n", prepend, next.completion.c_str(), next.description.c_str() );
}
else
{
sb_printf( sb_out, L"%ls%ls\n", prepend, next->completion );
sb_printf( sb_out, L"%ls%ls\n", prepend, next.completion.c_str() );
}
}
halloc_free( comp );
// halloc_free( comp );
recursion_level--;
}

View file

@ -83,6 +83,7 @@ parts of fish.
#include "proc.h"
#include "wildcard.h"
#include "parser.h"
#include "complete.h"
#include "util.cpp"
#include "halloc.cpp"
@ -155,6 +156,23 @@ wchar_t **list_to_char_arr( array_list_t *l )
return res;
}
wchar_t **completions_to_char_arr( std::vector<completion_t> &l )
{
wchar_t ** res = (wchar_t **)malloc( sizeof(wchar_t *)*( l.size() + 1) );
int i;
if( res == 0 )
{
DIE_MEM();
}
for( i=0; i< l.size(); i++ )
{
res[i] = const_cast<wchar_t*>(l.at(i).completion.c_str());
}
res[i]='\0';
return res;
}
int fgetws2( wchar_t **b, int *len, FILE *f )
{
int i=0;
@ -242,6 +260,10 @@ void sort_strings( std::vector<wcstring> &strings)
std::sort(strings.begin(), strings.end(), string_sort_predicate);
}
void sort_completions( std::vector<completion_t> &completions)
{
std::sort(completions.begin(), completions.end());
}
wchar_t *str2wcs( const char *in )
{
wchar_t *out;

View file

@ -22,6 +22,8 @@
#include <assert.h>
#include "util.h"
struct completion_t;
/* Common string type */
typedef std::wstring wcstring;
typedef std::vector<wcstring> wcstring_list_t;
@ -193,6 +195,8 @@ void show_stackframe();
*/
wchar_t **list_to_char_arr( array_list_t *l );
wchar_t **completions_to_char_arr( std::vector<completion_t> &l );
/**
Read a line from the stream f into the buffer buff of length len. If
buff is to small, it will be reallocated, and both buff and len will
@ -214,6 +218,8 @@ void sort_list( array_list_t *comp );
void sort_strings( std::vector<wcstring> &strings);
void sort_completions( std::vector<completion_t> &strings);
/**
Returns a newly allocated wide character string equivalent of the
specified multibyte character string

View file

@ -209,15 +209,17 @@ static void complete_free_entry( complete_entry_t *c );
Create a new completion entry
*/
void completion_allocate( array_list_t *context,
void completion_allocate( std::vector<completion_t> &context,
const wchar_t *comp,
const wchar_t *desc,
int flags )
{
completion_t *res = (completion_t *)halloc( context, sizeof( completion_t) );
res->completion = halloc_wcsdup( context, comp );
// completion_t *res = (completion_t *)halloc( context, sizeof( completion_t) );
completion_t res;
res.completion = comp;
if( desc )
res->description = halloc_wcsdup( context, desc );
res.description = desc;
if( flags & COMPLETE_AUTO_SPACE )
{
@ -230,8 +232,8 @@ void completion_allocate( array_list_t *context,
}
res->flags = flags;
al_push( context, res );
res.flags = flags;
context.push_back( res );
}
/**
@ -898,11 +900,11 @@ int complete_is_valid_argument( const wchar_t *str,
\param possible_comp the list of possible completions to iterate over
*/
static void complete_strings( array_list_t *comp_out,
static void complete_strings( std::vector<completion_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,
std::vector<completion_t> &possible_comp,
int flags )
{
int i;
@ -916,9 +918,10 @@ static void complete_strings( array_list_t *comp_out,
wc = parse_util_unescape_wildcards( tmp );
free(tmp);
for( i=0; i<al_get_count( possible_comp ); i++ )
for( i=0; i< possible_comp.size(); i++ )
{
wchar_t *next_str = (wchar_t *)al_get( possible_comp, i );
wcstring temp = possible_comp.at( i ).completion;
const wchar_t *next_str = temp.empty()?NULL:temp.c_str();
if( next_str )
{
@ -933,7 +936,7 @@ static void complete_strings( array_list_t *comp_out,
If command to complete is short enough, substitute
the description with the whatis information for the executable.
*/
static void complete_cmd_desc( const wchar_t *cmd, array_list_t *comp )
static void complete_cmd_desc( const wchar_t *cmd, std::vector<completion_t> &comp )
{
int i;
const wchar_t *cmd_start;
@ -971,11 +974,11 @@ static void complete_cmd_desc( const wchar_t *cmd, array_list_t *comp )
skip = 1;
for( i=0; i<al_get_count( comp ); i++ )
for( i=0; i< comp.size(); i++ )
{
completion_t *c = (completion_t *)al_get( comp, i );
const completion_t &c = comp.at ( i );
if( !wcslen( c->completion) || (c->completion[wcslen(c->completion)-1] != L'/' ))
if( c.completion.empty() || (c.completion[c.completion.size()-1] != L'/' ))
{
skip = 0;
break;
@ -1049,11 +1052,12 @@ static void complete_cmd_desc( const wchar_t *cmd, array_list_t *comp )
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++ )
for( i=0; i<comp.size(); i++ )
{
completion_t *c = (completion_t *)al_get( comp, i );
const wchar_t *el = c->completion;
completion_t &c = comp.at( i );
// const wchar_t *el = c.completion.empty()?NULL:c.completion.c_str();
const wchar_t *el = c.completion.c_str();
wchar_t *new_desc;
new_desc = (wchar_t *)hash_get( &lookup,
@ -1061,7 +1065,7 @@ static void complete_cmd_desc( const wchar_t *cmd, array_list_t *comp )
if( new_desc )
{
c->description = halloc_wcsdup( comp, new_desc );
c.description = new_desc;
}
}
}
@ -1097,7 +1101,7 @@ static const wchar_t *complete_function_desc( const wchar_t *fn )
\param comp the list to add all completions to
*/
static void complete_cmd( const wchar_t *cmd,
array_list_t *comp,
std::vector<completion_t> &comp,
int use_function,
int use_builtin,
int use_command )
@ -1105,7 +1109,7 @@ static void complete_cmd( const wchar_t *cmd,
wchar_t *path_cpy;
wchar_t *nxt_path;
wchar_t *state;
array_list_t possible_comp;
std::vector<completion_t> possible_comp;
wchar_t *nxt_completion;
const env_var_t cdpath = env_get_string(L"CDPATH");
@ -1118,8 +1122,7 @@ static void complete_cmd( const wchar_t *cmd,
if( use_command )
{
if( expand_string( 0,
wcsdup(cmd),
if( expand_string2( wcsdup(cmd),
comp,
ACCEPT_INCOMPLETE | EXECUTABLES_ONLY ) != EXPAND_ERROR )
{
@ -1151,7 +1154,7 @@ static void complete_cmd( const wchar_t *cmd,
{
continue;
}
add_slash = nxt_path[path_len-1]!=L'/';
nxt_completion = wcsdupcat( nxt_path,
add_slash?L"/":L"",
@ -1159,20 +1162,20 @@ static void complete_cmd( const wchar_t *cmd,
if( ! nxt_completion )
continue;
prev_count = al_get_count( comp );
prev_count = comp.size() ;
if( expand_string( 0,
if( expand_string2(
nxt_completion,
comp,
ACCEPT_INCOMPLETE |
EXECUTABLES_ONLY ) != EXPAND_ERROR )
{
for( i=prev_count; i<al_get_count( comp ); i++ )
for( i=prev_count; i< comp.size(); i++ )
{
completion_t *c = (completion_t *)al_get( comp, i );
if(c->flags & COMPLETE_NO_CASE )
completion_t &c = comp.at( i );
if(c.flags & COMPLETE_NO_CASE )
{
c->completion = halloc_wcsdup( comp, c->completion + path_len + add_slash );
c.completion += add_slash ;
}
}
}
@ -1186,27 +1189,29 @@ static void complete_cmd( const wchar_t *cmd,
These return the original strings - don't free them
*/
al_init( &possible_comp );
// al_init( &possible_comp );
if( use_function )
{
//function_get_names( &possible_comp, cmd[0] == L'_' );
wcstring_list_t names = function_get_names(cmd[0] == L'_' );
for (size_t i=0; i < names.size(); i++) {
al_push(&possible_comp, names.at(i).c_str());
completion_t data_to_push;
data_to_push.completion = names.at(i);
possible_comp.push_back( data_to_push );
}
complete_strings( comp, cmd, 0, &complete_function_desc, &possible_comp, 0 );
complete_strings( comp, cmd, 0, &complete_function_desc, possible_comp, 0 );
}
al_truncate( &possible_comp, 0 );
possible_comp.clear();
if( use_builtin )
{
builtin_get_names( &possible_comp );
complete_strings( comp, cmd, 0, &builtin_get_desc, &possible_comp, 0 );
builtin_get_names2( possible_comp );
complete_strings( comp, cmd, 0, &builtin_get_desc, possible_comp, 0 );
}
al_destroy( &possible_comp );
// al_destroy( &possible_comp );
}
@ -1230,8 +1235,7 @@ static void complete_cmd( const wchar_t *cmd,
continue;
}
if( expand_string( 0,
nxt_completion,
if( expand_string2( nxt_completion,
comp,
ACCEPT_INCOMPLETE | DIRECTORIES_ONLY ) != EXPAND_ERROR )
{
@ -1258,22 +1262,22 @@ static void complete_cmd( const wchar_t *cmd,
static void complete_from_args( const wchar_t *str,
const wchar_t *args,
const wchar_t *desc,
array_list_t *comp_out,
std::vector<completion_t> &comp_out,
int flags )
{
array_list_t possible_comp;
std::vector<completion_t> possible_comp;
al_init( &possible_comp );
parser_t parser(PARSER_TYPE_COMPLETIONS_ONLY);
proc_push_interactive(0);
parser.eval_args( args, &possible_comp );
parser.eval_args( args, possible_comp );
proc_pop_interactive();
complete_strings( comp_out, str, desc, 0, &possible_comp, flags );
complete_strings( comp_out, str, desc, 0, possible_comp, flags );
al_foreach( &possible_comp, &free );
al_destroy( &possible_comp );
// al_foreach( &possible_comp, &free );
// al_destroy( &possible_comp );
}
/**
@ -1381,7 +1385,7 @@ static int complete_param( const wchar_t *cmd_orig,
const wchar_t *popt,
const wchar_t *str,
int use_switches,
array_list_t *comp_out )
std::vector<completion_t> &comp_out )
{
complete_entry_t *i;
complete_entry_opt_t *o;
@ -1598,7 +1602,7 @@ static int complete_param( const wchar_t *cmd_orig,
Perform file completion on the specified string
*/
static void complete_param_expand( wchar_t *str,
array_list_t *comp_out,
std::vector<completion_t> &comp_out,
int do_file )
{
wchar_t *comp_str;
@ -1617,8 +1621,7 @@ static void complete_param_expand( wchar_t *str,
ACCEPT_INCOMPLETE |
(do_file?0:EXPAND_SKIP_WILDCARDS);
if( expand_string( 0,
wcsdup(comp_str),
if( expand_string2( wcsdup(comp_str),
comp_out,
flags ) == EXPAND_ERROR )
{
@ -1633,7 +1636,7 @@ static void complete_param_expand( wchar_t *str,
*/
static int complete_variable( const wchar_t *whole_var,
int start_offset,
array_list_t *comp_list )
std::vector<completion_t> &comp_list )
{
int i;
const wchar_t *var = &whole_var[start_offset];
@ -1711,7 +1714,7 @@ static int complete_variable( const wchar_t *whole_var,
\return 0 if unable to complete, 1 otherwise
*/
static int try_complete_variable( const wchar_t *cmd,
array_list_t *comp )
std::vector<completion_t> &comp )
{
int len = wcslen( cmd );
int i;
@ -1738,7 +1741,7 @@ static int try_complete_variable( const wchar_t *cmd,
\return 0 if unable to complete, 1 otherwise
*/
static int try_complete_user( const wchar_t *cmd,
array_list_t *comp )
std::vector<completion_t> &comp )
{
const wchar_t *first_char=cmd;
int res=0;
@ -1821,10 +1824,8 @@ static int try_complete_user( const wchar_t *cmd,
return res;
}
void complete( const wchar_t *cmd,
array_list_t *comp )
void complete2( const wchar_t *cmd,
std::vector<completion_t> &comp )
{
wchar_t *tok_begin, *tok_end, *cmdsubst_begin, *cmdsubst_end, *prev_begin, *prev_end;
wchar_t *buff;
@ -1840,7 +1841,7 @@ void complete( const wchar_t *cmd,
int had_ddash = 0;
CHECK( cmd, );
CHECK( comp, );
// CHECK( comp, );
complete_init();
@ -2066,7 +2067,7 @@ void complete( const wchar_t *cmd,
If we have found no command specific completions at
all, fall back to using file completions.
*/
if( !al_get_count( comp ) )
if( comp.empty() )
do_file = 1;
/*
@ -2087,6 +2088,8 @@ void complete( const wchar_t *cmd,
}
/**
Print the GNU longopt style switch \c opt, and the argument \c
argument to the specified stringbuffer, but only if arguemnt is

View file

@ -12,10 +12,11 @@
*/
#define FISH_COMPLETE_H
#include <wchar.h>
#include "util.h"
#include "common.h"
/**
Use all completions
*/
@ -101,18 +102,18 @@
typedef struct
struct completion_t
{
/**
The completion string
*/
const wchar_t *completion;
wcstring completion;
/**
The description for this completion
*/
const wchar_t *description;
wcstring description;
/**
Flags determining the completion behaviour.
@ -126,8 +127,15 @@ typedef struct
*/
int flags;
completion_t () {
flags = 0;
}
bool operator < (const completion_t& rhs) const { return this->completion < rhs.completion; }
bool operator == (const completion_t& rhs) const { return this->completion == rhs.completion; }
bool operator != (const completion_t& rhs) const { return this->completion != rhs.completion; }
}
completion_t;
;
/**
@ -209,7 +217,9 @@ void complete_remove( const wchar_t *cmd,
Values returned by this function should be freed by the caller.
*/
void complete( const wchar_t *cmd, array_list_t *out );
//void complete( const wchar_t *cmd, array_list_t *out );
void complete2( const wchar_t* cmd, std::vector<completion_t> &out);
/**
Print a list of all current completions into the string_buffer_t.
@ -254,7 +264,7 @@ void complete_load( const wchar_t *cmd, int reload );
\param desc The description of the completion
\param flags completion flags
*/
void completion_allocate( array_list_t *context,
void completion_allocate( std::vector<completion_t> &context,
const wchar_t *comp,
const wchar_t *desc,
int flags );

View file

@ -377,7 +377,7 @@ static int match_pid( const wchar_t *cmd,
static int find_process( const wchar_t *proc,
int flags,
array_list_t *out )
std::vector<completion_t> &out )
{
DIR *dir;
wchar_t *pdir_name;
@ -442,7 +442,9 @@ static int find_process( const wchar_t *proc,
{
result = (wchar_t *)malloc(sizeof(wchar_t)*16 );
swprintf( result, 16, L"%d", j->pgid );
al_push( out, result );
completion_t data_to_push;
data_to_push.completion = result;
out.push_back( data_to_push);
found = 1;
}
}
@ -472,7 +474,9 @@ static int find_process( const wchar_t *proc,
{
result = (wchar_t *)malloc(sizeof(wchar_t)*16 );
swprintf( result, 16, L"%d", j->pgid );
al_push( out, result );
completion_t data_to_push;
data_to_push.completion = result;
out.push_back( data_to_push);
found = 1;
}
}
@ -508,7 +512,9 @@ static int find_process( const wchar_t *proc,
{
result = (wchar_t *)malloc(sizeof(wchar_t)*16 );
swprintf( result, 16, L"%d", p->pid );
al_push( out, result );
completion_t data_to_push;
data_to_push.completion = result;
out.push_back( data_to_push );
found = 1;
}
}
@ -623,8 +629,11 @@ static int find_process( const wchar_t *proc,
else
{
wchar_t *res = wcsdup(name);
if( res )
al_push( out, res );
if( res ) {
completion_t data_to_push;
data_to_push.completion = res;
out.push_back( data_to_push );
}
}
}
}
@ -646,15 +655,17 @@ static int find_process( const wchar_t *proc,
*/
static int expand_pid( wchar_t *in,
int flags,
array_list_t *out )
std::vector<completion_t> &out )
{
CHECK( in, 0 );
CHECK( out, 0 );
// CHECK( out, 0 );
if( *in != PROCESS_EXPAND )
{
al_push( out, in );
completion_t data_to_push;
data_to_push.completion = in;
out.push_back( data_to_push );
return 1;
}
@ -682,7 +693,11 @@ static int expand_pid( wchar_t *in,
wchar_t *str= (wchar_t *)malloc( sizeof(wchar_t)*32);
free(in);
swprintf( str, 32, L"%d", getpid() );
al_push( out, str );
completion_t data_to_push;
data_to_push.completion = str;
out.push_back( data_to_push );
return 1;
}
@ -695,18 +710,21 @@ static int expand_pid( wchar_t *in,
str = (wchar_t *)malloc( sizeof(wchar_t)*32);
free(in);
swprintf( str, 32, L"%d", proc_last_bg_pid );
al_push( out, str );
completion_t data_to_push;
data_to_push.completion = str;
out.push_back( data_to_push);
}
return 1;
}
}
int prev = al_get_count( out );
int prev = out.size();
if( !find_process( in+1, flags, out ) )
return 0;
if( prev == al_get_count( out ) )
if( prev == out.size() )
{
if( flags & ACCEPT_INCOMPLETE )
free( in );
@ -723,13 +741,13 @@ static int expand_pid( wchar_t *in,
return 1;
}
static int expand_pid2( const wcstring &in, int flags, std::vector<wcstring> &outputs )
/*
static int expand_pid2( const wcstring &in, int flags, std::vector<completion_t> &outputs )
{
wcstring_adapter adapter(in, outputs);
return expand_pid(adapter.str, flags, &adapter.lst);
}
*/
void expand_variable_error( parser_t &parser, const wchar_t *token, int token_pos, int error_pos )
{
@ -1187,16 +1205,282 @@ static int expand_variables( parser_t &parser, wchar_t *in, array_list_t *out, i
return is_ok;
}
static int expand_variables2( parser_t &parser, const wcstring &in, std::vector<wcstring> &outputs, int last_idx )
static int expand_variables2( parser_t &parser, wchar_t * in, std::vector<completion_t> &out, int last_idx )
{
wcstring_adapter adapter(in, outputs);
return expand_variables(parser, adapter.str, &adapter.lst, last_idx);
wchar_t c;
wchar_t prev_char=0;
int i, j;
int is_ok= 1;
int empty=0;
static string_buffer_t *var_tmp = 0;
static array_list_t *var_idx_list = 0;
CHECK( in, 0 );
// CHECK( out, 0 );
if( !var_tmp )
{
var_tmp = sb_halloc( global_context );
if( !var_tmp )
DIE_MEM();
}
else
{
sb_clear(var_tmp );
}
if( !var_idx_list )
{
var_idx_list = al_halloc( global_context );
if( !var_idx_list )
DIE_MEM();
}
else
{
al_truncate( var_idx_list, 0 );
}
for( i=last_idx; (i>=0) && is_ok && !empty; i-- )
{
c = in[i];
if( ( c == VARIABLE_EXPAND ) || (c == VARIABLE_EXPAND_SINGLE ) )
{
int start_pos = i+1;
int stop_pos;
int var_len, new_len;
const wchar_t * var_val;
wchar_t * new_in;
int is_single = (c==VARIABLE_EXPAND_SINGLE);
int var_name_stop_pos;
stop_pos = start_pos;
while( 1 )
{
if( !(in[stop_pos ]) )
break;
if( !( iswalnum( in[stop_pos] ) ||
(wcschr(L"_", in[stop_pos])!= 0) ) )
break;
stop_pos++;
}
var_name_stop_pos = stop_pos;
/* printf( "Stop for '%c'\n", in[stop_pos]);*/
var_len = stop_pos - start_pos;
if( var_len == 0 )
{
expand_variable_error( parser_t::principal_parser(), in, stop_pos-1, -1 );
is_ok = 0;
break;
}
sb_append_substring( var_tmp, &in[start_pos], var_len );
var_val = expand_var( (wchar_t *)var_tmp->buff );
if( var_val )
{
int all_vars=1;
array_list_t var_item_list;
al_init( &var_item_list );
if( in[stop_pos] == L'[' )
{
wchar_t *slice_end;
all_vars=0;
if( parse_slice( &in[stop_pos], &slice_end, var_idx_list ) )
{
parser_t::principal_parser().error( SYNTAX_ERROR,
-1,
L"Invalid index value" );
is_ok = 0;
}
stop_pos = (slice_end-in);
}
if( is_ok )
{
tokenize_variable_array( var_val, &var_item_list );
if( !all_vars )
{
int j;
for( j=0; j<al_get_count( var_idx_list ); j++)
{
long tmp = al_get_long( var_idx_list, j );
if( tmp < 0 )
{
tmp = al_get_count( &var_item_list)+tmp+1;
}
/*
Check that we are within array
bounds. If not, truncate the list to
exit.
*/
if( tmp < 1 || tmp > al_get_count( &var_item_list ) )
{
parser_t::principal_parser().error( SYNTAX_ERROR,
-1,
ARRAY_BOUNDS_ERR );
is_ok=0;
al_truncate( var_idx_list, j );
break;
}
else
{
/* Replace each index in var_idx_list inplace with the string value at the specified index */
al_set( var_idx_list, j, wcsdup((const wchar_t *)al_get( &var_item_list, tmp-1 ) ) );
}
}
/* Free strings in list var_item_list and truncate it */
al_foreach( &var_item_list, &free );
al_truncate( &var_item_list, 0 );
/* Add items from list idx back to list l */
al_push_all( &var_item_list, var_idx_list );
}
}
if( is_ok )
{
if( is_single )
{
string_buffer_t res;
in[i]=0;
sb_init( &res );
sb_append( &res, in );
sb_append_char( &res, INTERNAL_SEPARATOR );
for( j=0; j<al_get_count( &var_item_list); j++ )
{
wchar_t *next = (wchar_t *)al_get( &var_item_list, j );
if( is_ok )
{
if( j != 0 )
sb_append( &res, L" " );
sb_append( &res, next );
}
free( next );
}
sb_append( &res, &in[stop_pos] );
is_ok &= expand_variables2( parser_t::principal_parser(), (wchar_t *)res.buff, out, i );
}
else
{
for( j=0; j<al_get_count( &var_item_list); j++ )
{
wchar_t *next = (wchar_t *)al_get( &var_item_list, j );
if( is_ok && (i == 0) && (!in[stop_pos]) )
{
completion_t data_to_push;
data_to_push.completion = next;
out.push_back( data_to_push );
}
else
{
if( is_ok )
{
new_len = wcslen(in) - (stop_pos-start_pos+1);
new_len += wcslen( next) +2;
if( !(new_in = (wchar_t *)malloc( sizeof(wchar_t)*new_len )))
{
DIE_MEM();
}
else
{
wcslcpy( new_in, in, start_pos );
if(start_pos>1 && new_in[start_pos-2]!=VARIABLE_EXPAND)
{
new_in[start_pos-1]=INTERNAL_SEPARATOR;
new_in[start_pos]=L'\0';
}
else
new_in[start_pos-1]=L'\0';
wcscat( new_in, next );
wcscat( new_in, &in[stop_pos] );
is_ok &= expand_variables2( parser_t::principal_parser(), new_in, out, i );
}
}
free( next );
}
}
}
}
free(in);
al_destroy( &var_item_list );
return is_ok;
}
else
{
/*
Expand a non-existing variable
*/
if( c == VARIABLE_EXPAND )
{
/*
Regular expansion, i.e. expand this argument to nothing
*/
empty = 1;
}
else
{
/*
Expansion to single argument.
*/
string_buffer_t res;
sb_init( &res );
in[i]=0;
sb_append( &res, in );
sb_append( &res, &in[stop_pos] );
is_ok &= expand_variables2( parser_t::principal_parser(), (wchar_t *)res.buff, out, i );
free(in);
return is_ok;
}
}
}
prev_char = c;
}
if( !empty )
{
completion_t data_to_push;
data_to_push.completion = in;
out.push_back( data_to_push );
}
else
{
free( in );
}
return is_ok;
}
/**
Perform bracket expansion
*/
static int expand_brackets( parser_t &parser, wchar_t *in, int flags, array_list_t *out )
static int expand_brackets(parser_t &parser, wchar_t *in, int flags, std::vector<completion_t> &out )
{
wchar_t *pos;
int syntax_error=0;
@ -1209,7 +1493,7 @@ static int expand_brackets( parser_t &parser, wchar_t *in, int flags, array_list
int len1, len2, tot_len;
CHECK( in, 0 );
CHECK( out, 0 );
// CHECK( out, 0 );
for( pos=in;
(*pos) && !syntax_error;
@ -1284,7 +1568,9 @@ static int expand_brackets( parser_t &parser, wchar_t *in, int flags, array_list
if( bracket_begin == 0 )
{
al_push( out, in );
completion_t data_to_push;
data_to_push.completion = in;
out.push_back( data_to_push );
return 1;
}
@ -1328,12 +1614,13 @@ static int expand_brackets( parser_t &parser, wchar_t *in, int flags, array_list
return 1;
}
static int expand_brackets2( parser_t &parser, const wcstring &in, int flags, std::vector<wcstring> outputs )
/*
static int expand_brackets2( parser_t &parser, const wcstring &in, int flags, std::vector<wcstring> &outputs )
{
wcstring_adapter adapter(in, outputs);
return expand_brackets(parser, adapter.str, flags, &adapter.lst);
}
*/
/**
Perform cmdsubst expansion
*/
@ -1487,7 +1774,7 @@ static int expand_cmdsubst( parser_t &parser, wchar_t *in, array_list_t *out )
/**
Perform cmdsubst expansion
*/
static int expand_cmdsubst2( parser_t &parser, const wcstring &input, std::vector<wcstring> &outList )
static int expand_cmdsubst2( parser_t &parser, const wcstring &input, std::vector<completion_t> &outList )
{
wchar_t *paran_begin=0, *paran_end=0;
int len1;
@ -1499,7 +1786,9 @@ static int expand_cmdsubst2( parser_t &parser, const wcstring &input, std::vecto
const wchar_t * const in = input.c_str();
switch( parse_util_locate_cmdsubst(in,
completion_t data_to_push;
int parse_ret;
switch( parse_ret = parse_util_locate_cmdsubst(in,
&paran_begin,
&paran_end,
0 ) )
@ -1510,7 +1799,8 @@ static int expand_cmdsubst2( parser_t &parser, const wcstring &input, std::vecto
L"Mismatched parans" );
return 0;
case 0:
outList.push_back(input);
data_to_push.completion = input;
outList.push_back(data_to_push);
return 1;
case 1:
@ -1574,7 +1864,7 @@ static int expand_cmdsubst2( parser_t &parser, const wcstring &input, std::vecto
substitutions. The result of this recursive call using the tail
of the string is inserted into the tail_expand array list
*/
std::vector<wcstring> tail_expand;
std::vector<completion_t> tail_expand;
expand_cmdsubst2( parser, tail_begin, tail_expand );
/*
@ -1591,7 +1881,7 @@ static int expand_cmdsubst2( parser_t &parser, const wcstring &input, std::vecto
wcstring whole_item;
wcstring tail_item = tail_expand.at(j);
wcstring tail_item = tail_expand.at(j).completion;
//sb_append_substring( &whole_item, in, len1 );
whole_item.append(in, len1);
@ -1609,7 +1899,9 @@ static int expand_cmdsubst2( parser_t &parser, const wcstring &input, std::vecto
whole_item.append(tail_item);
//al_push( out, whole_item.buff );
outList.push_back(whole_item);
completion_t data_to_push;
data_to_push.completion = whole_item;
outList.push_back(data_to_push);
}
}
@ -1766,11 +2058,11 @@ static void remove_internal_separator2( wcstring &s, int conv )
}
int expand_string2( const wcstring &input, std::vector<wcstring> &output, int flags )
int expand_string2( const wcstring &input, std::vector<completion_t> &output, int flags )
{
parser_t &parser = parser_t::principal_parser();
std::vector<wcstring> list1, list2;
std::vector<wcstring> *in, *out;
std::vector<completion_t> list1, list2;
std::vector<completion_t> *in, *out;
size_t i;
int cmdsubst_ok = 1;
@ -1778,7 +2070,9 @@ int expand_string2( const wcstring &input, std::vector<wcstring> &output, int fl
if( (!(flags & ACCEPT_INCOMPLETE)) && expand_is_clean( input.c_str() ) )
{
output.push_back(input);
completion_t data_to_push;
data_to_push.completion = input;
output.push_back(data_to_push);
return EXPAND_OK;
}
@ -1794,7 +2088,9 @@ int expand_string2( const wcstring &input, std::vector<wcstring> &output, int fl
parser.error( CMDSUBST_ERROR, -1, L"Command substitutions not allowed" );
return EXPAND_ERROR;
}
list1.push_back(input);
completion_t data_to_push;
data_to_push.completion = input;
list1.push_back(data_to_push);
}
else
{
@ -1818,7 +2114,7 @@ int expand_string2( const wcstring &input, std::vector<wcstring> &output, int fl
commandline.
*/
int unescape_flags = UNESCAPE_SPECIAL | UNESCAPE_INCOMPLETE;
wcstring next = expand_unescape_string( in->at(i), unescape_flags );
wcstring next = expand_unescape_string( in->at(i).completion, unescape_flags );
if( EXPAND_SKIP_VARIABLES & flags )
{
@ -1827,11 +2123,13 @@ int expand_string2( const wcstring &input, std::vector<wcstring> &output, int fl
next[i] = L'$';
}
}
out->push_back(next);
completion_t data_to_push;
data_to_push.completion = next;
out->push_back(data_to_push);
}
else
{
if(!expand_variables2( parser, next, *out, next.size() - 1 ))
if(!expand_variables2( parser, wcsdup(next.c_str()), *out, next.size() - 1 ))
{
return EXPAND_ERROR;
}
@ -1845,9 +2143,9 @@ int expand_string2( const wcstring &input, std::vector<wcstring> &output, int fl
for( i=0; i < in->size(); i++ )
{
wcstring next = in->at(i);
wcstring next = in->at(i).completion;
if( !expand_brackets2( parser, next, flags, *out ))
if( !expand_brackets( parser, wcsdup(next.c_str()), flags, *out ))
{
return EXPAND_ERROR;
}
@ -1859,7 +2157,7 @@ int expand_string2( const wcstring &input, std::vector<wcstring> &output, int fl
for( i=0; i < in->size(); i++ )
{
wcstring next = in->at(i);
wcstring next = in->at(i).completion;
expand_tilde_internal(next);
@ -1873,17 +2171,19 @@ int expand_string2( const wcstring &input, std::vector<wcstring> &output, int fl
interested in other completions, so we
short-circut and return
*/
expand_pid2( next, flags, output );
expand_pid( wcsdup(next.c_str()), flags, output );
return EXPAND_OK;
}
else
{
out->push_back(next);
completion_t data_to_push;
data_to_push.completion = next;
out->push_back(data_to_push);
}
}
else
{
if( !expand_pid2( next, flags, *out ) )
if( !expand_pid( wcsdup(next.c_str()), flags, *out ) )
{
return EXPAND_ERROR;
}
@ -1897,7 +2197,7 @@ int expand_string2( const wcstring &input, std::vector<wcstring> &output, int fl
for( i=0; i < in->size(); i++ )
{
wcstring next_str = in->at(i);
wcstring next_str = in->at(i).completion;
int wc_res;
remove_internal_separator2( next_str, EXPAND_SKIP_WILDCARDS & flags );
@ -1907,7 +2207,7 @@ int expand_string2( const wcstring &input, std::vector<wcstring> &output, int fl
wildcard_has( next, 1 ) )
{
const wchar_t *start, *rest;
std::vector<wcstring> *list = out;
std::vector<completion_t> *list = out;
if( next[0] == '/' )
{
@ -1925,7 +2225,7 @@ int expand_string2( const wcstring &input, std::vector<wcstring> &output, int fl
list = &output;
}
wc_res = wildcard_expand_string(rest, start, flags, *list);
wc_res = wildcard_expand_string(rest, start, flags, *list);
if( !(flags & ACCEPT_INCOMPLETE) )
{
@ -1946,12 +2246,11 @@ int expand_string2( const wcstring &input, std::vector<wcstring> &output, int fl
{
size_t j;
res = EXPAND_WILDCARD_MATCH;
sort_strings( *out );
sort_completions( *out );
for( j=0; j< out->size(); j++ )
{
wcstring next = out->at(j);
output.push_back(next);
output.push_back( out->at(j) );
}
out->clear();
break;
@ -1973,7 +2272,9 @@ int expand_string2( const wcstring &input, std::vector<wcstring> &output, int fl
}
else
{
output.push_back(next);
completion_t data_to_push;
data_to_push.completion = next;
output.push_back(data_to_push);
}
}
@ -1986,6 +2287,7 @@ int expand_string2( const wcstring &input, std::vector<wcstring> &output, int fl
/**
The real expansion function. expand_one is just a wrapper around this one.
*/
/*
int expand_string( void *context,
wchar_t *str,
array_list_t *end_out,
@ -2048,13 +2350,13 @@ int expand_string( void *context,
for( i=0; i<al_get_count( in ); i++ )
{
wchar_t *next;
*/
/*
We accept incomplete strings here, since complete uses
expand_string to expand incomplete strings from the
commandline.
*/
int unescape_flags = UNESCAPE_SPECIAL | UNESCAPE_INCOMPLETE;
/* int unescape_flags = UNESCAPE_SPECIAL | UNESCAPE_INCOMPLETE;
next = expand_unescape( parser, (wchar_t *)al_get( in, i ), unescape_flags );
@ -2132,13 +2434,13 @@ int expand_string( void *context,
if( flags & ACCEPT_INCOMPLETE )
{
if( *next == PROCESS_EXPAND )
{
{*/
/*
If process expansion matches, we are not
interested in other completions, so we
short-circut and return
*/
expand_pid( next, flags, end_out );
/* expand_pid( next, flags, end_out );
al_destroy( in );
al_destroy( out );
return EXPAND_OK;
@ -2278,11 +2580,11 @@ int expand_string( void *context,
return res;
}
*/
wchar_t *expand_one( void *context, wchar_t *string, int flags )
{
array_list_t l;
std::vector<completion_t> l;
int res;
wchar_t *one;
@ -2294,29 +2596,30 @@ wchar_t *expand_one( void *context, wchar_t *string, int flags )
return string;
}
al_init( &l );
res = expand_string( 0, string, &l, flags );
// al_init( &l );
res = expand_string2( string, l, flags );
if( !res )
{
one = 0;
}
else
{
if( al_get_count( &l ) != 1 )
if( l.size() != 1 )
{
one=0;
}
else
{
one = (wchar_t *)al_get( &l, 0 );
al_set( &l, 0, 0 );
one = wcsdup( l.at(0).completion.c_str() );
// al_set( &l, 0, 0 );
}
}
al_foreach( &l, &free );
al_destroy( &l );
// al_foreach( &l, &free );
// al_destroy( &l );
halloc_register( context, one );
return one;
}

View file

@ -65,6 +65,8 @@
*/
#define EXPAND_RESERVED_END 0xf000f
struct completion_t;
enum
{
/** Character represeting a home directory */
@ -147,7 +149,7 @@ class parser_t;
\return One of EXPAND_OK, EXPAND_ERROR, EXPAND_WILDCARD_MATCH and EXPAND_WILDCARD_NO_MATCH. EXPAND_WILDCARD_NO_MATCH and EXPAND_WILDCARD_MATCH are normal exit conditions used only on strings containing wildcards to tell if the wildcard produced any matches.
*/
__warn_unused int expand_string( void *context, wchar_t *in, array_list_t *out, int flag );
__warn_unused int expand_string2( const wcstring &input, std::list<wcstring> &output, int flag );
__warn_unused int expand_string2( const wcstring &input, std::vector<completion_t> &output, int flag );
/**

View file

@ -44,6 +44,7 @@ The fish parser. Contains functions for parsing and evaluating code.
#include "halloc_util.h"
#include "path.h"
#include "signal.h"
#include "complete.h"
/**
Maximum number of block levels in code. This is not the same as
@ -775,7 +776,7 @@ void parser_t::print_errors_stderr()
}
int parser_t::eval_args( const wchar_t *line, array_list_t *args )
int parser_t::eval_args( const wchar_t *line, std::vector<completion_t> &args )
{
tokenizer tok;
/*
@ -787,7 +788,7 @@ int parser_t::eval_args( const wchar_t *line, array_list_t *args )
int do_loop=1;
CHECK( line, 1 );
CHECK( args, 1 );
// CHECK( args, 1 );
proc_push_interactive(0);
current_tokenizer = &tok;
@ -810,7 +811,7 @@ int parser_t::eval_args( const wchar_t *line, array_list_t *args )
DIE_MEM();
}
if( expand_string( 0, tmp, args, 0 ) == EXPAND_ERROR )
if( expand_string2( tmp, args, 0 ) == EXPAND_ERROR )
{
err_pos=tok_get_pos( &tok );
do_loop=0;
@ -1226,7 +1227,7 @@ int parser_t::is_help( wchar_t *s, int min_match ) const
void parser_t::parse_job_argument_list( process_t *p,
job_t *j,
tokenizer *tok,
array_list_t *args )
std::vector<completion_t> &args )
{
int is_finished=0;
@ -1244,7 +1245,7 @@ void parser_t::parse_job_argument_list( process_t *p,
workaround and a huge hack, but as near as I can tell, the
alternatives are worse.
*/
proc_is_count = (wcscmp( (wchar_t *)al_get( args, 0 ), L"count" )==0);
proc_is_count = ( args.at(0).completion == L"count" );
while( 1 )
{
@ -1275,7 +1276,7 @@ void parser_t::parse_job_argument_list( process_t *p,
}
if( !p->argv )
halloc_register( j, p->argv = list_to_char_arr( args ) );
halloc_register( j, p->argv = completions_to_char_arr( args ) );
p->next = (process_t *)halloc( j, sizeof( process_t ) );
tok_next( tok );
@ -1298,7 +1299,7 @@ void parser_t::parse_job_argument_list( process_t *p,
case TOK_END:
{
if( !p->argv )
halloc_register( j, p->argv = list_to_char_arr( args ) );
halloc_register( j, p->argv = completions_to_char_arr( args ) );
if( tok_has_next(tok))
tok_next(tok);
@ -1326,9 +1327,7 @@ void parser_t::parse_job_argument_list( process_t *p,
But if this is in fact a case statement, then it should be evaluated
*/
if( (current_block->type == SWITCH) &&
(wcscmp( (const wchar_t *)al_get( args, 0), L"case" )==0) &&
p->type == INTERNAL_BUILTIN )
if( (current_block->type == SWITCH) && args.at(0).completion == L"case" && p->type == INTERNAL_BUILTIN )
{
skip=0;
}
@ -1337,7 +1336,7 @@ void parser_t::parse_job_argument_list( process_t *p,
if( !skip )
{
if( ( proc_is_count ) &&
( al_get_count( args) == 1) &&
( args.size() == 1) &&
( parser_t::is_help( tok_last(tok), 0) ) &&
( p->type == INTERNAL_BUILTIN ) )
{
@ -1347,7 +1346,7 @@ void parser_t::parse_job_argument_list( process_t *p,
p->count_help_magic = 1;
}
switch( expand_string( j, wcsdup(tok_last( tok )), args, 0 ) )
switch( expand_string2( wcsdup(tok_last( tok )), args, 0 ) )
{
case EXPAND_ERROR:
{
@ -1622,7 +1621,8 @@ int parser_t::parse_job( process_t *p,
job_t *j,
tokenizer *tok )
{
array_list_t *args = al_halloc( j ); // The list that will become the argc array for the program
// array_list_t *args = al_halloc( j ); // The list that will become the argc array for the program
std::vector<completion_t> *args = new std::vector<completion_t>();
int use_function = 1; // May functions be considered when checking what action this command represents
int use_builtin = 1; // May builtins be considered when checking what action this command represents
int use_command = 1; // May commands be considered when checking what action this command represents
@ -1633,7 +1633,7 @@ int parser_t::parse_job( process_t *p,
current_tokenizer_pos = tok_get_pos( tok );
while( al_get_count( args ) == 0 )
while( args->size() == 0 )
{
wchar_t *nxt=0;
int consumed = 0; // Set to one if the command requires a second command, like e.g. while does
@ -1880,7 +1880,9 @@ int parser_t::parse_job( process_t *p,
}
}
}
al_push( args, nxt );
completion_t data_to_push;
data_to_push.completion = nxt;
args->push_back( data_to_push );
}
if( error_code == 0 )
@ -1888,10 +1890,10 @@ int parser_t::parse_job( process_t *p,
if( !p->type )
{
if( use_builtin &&
builtin_exists( (wchar_t *)al_get( args, 0 ) ) )
builtin_exists( const_cast<wchar_t*>(args->at(0).completion.c_str()) ) )
{
p->type = INTERNAL_BUILTIN;
is_new_block |= parser_keywords_is_block( (wchar_t *)al_get( args, 0 ) );
is_new_block |= parser_keywords_is_block( args->at( 0 ).completion.c_str() );
}
}
@ -1909,7 +1911,7 @@ int parser_t::parse_job( process_t *p,
{
int err;
p->actual_cmd = path_get_path( j, (wchar_t *)al_get( args, 0 ) );
p->actual_cmd = path_get_path( j, args->at(0).completion.c_str() );
err = errno;
/*
@ -1924,15 +1926,23 @@ int parser_t::parse_job( process_t *p,
implicit command.
*/
wchar_t *pp =
path_get_cdpath( j, (wchar_t *)al_get( args, 0 ) );
path_get_cdpath( j, args->at(0).completion.c_str() );
if( pp )
{
wchar_t *tmp;
tmp = (wchar_t *)al_get( args, 0 );
al_truncate( args, 0 );
al_push( args, halloc_wcsdup( j, L"cd" ) );
al_push( args, tmp );
tmp = (wchar_t *)wcsdup(args->at( 0 ).completion.c_str());
// al_truncate( args, 0 );
args->clear();
// al_push( args, halloc_wcsdup( j, L"cd" ) );
completion_t comp;
comp.completion = L"cd";
args->push_back(comp);
completion_t comp2;
comp2.completion = tmp;
args->push_back( comp2 );
// free(tmp);
/*
If we have defined a wrapper around cd, use it,
otherwise use the cd builtin
@ -1945,7 +1955,7 @@ int parser_t::parse_job( process_t *p,
else
{
int tmp;
wchar_t *cmd = (wchar_t *)al_get( args, 0 );
wchar_t *cmd = (wchar_t *)args->at( 0 ).completion.c_str();
/*
We couldn't find the specified command.
@ -2025,7 +2035,7 @@ int parser_t::parse_job( process_t *p,
current_tokenizer_pos=tmp;
job_set_flag( j, JOB_SKIP, 1 );
event_fire_generic(L"fish_command_not_found", (wchar_t *)al_get( args, 0 ) );
event_fire_generic(L"fish_command_not_found", (wchar_t *)( args->at( 0 ).completion.c_str() ) );
proc_set_last_status( err==ENOENT?STATUS_UNKNOWN_COMMAND:STATUS_NOT_EXECUTABLE );
}
}
@ -2037,7 +2047,7 @@ int parser_t::parse_job( process_t *p,
error( SYNTAX_ERROR,
tok_get_pos( tok ),
UNKNOWN_BUILTIN_ERR_MSG,
al_get( args, al_get_count( args ) -1 ) );
args->at( args->size() -1 ) );
}
}
@ -2114,7 +2124,9 @@ int parser_t::parse_job( process_t *p,
end_pos - current_tokenizer_pos);
p->type = INTERNAL_BLOCK;
al_set( args, 0, sub_block );
completion_t data_to_push;
data_to_push.completion = sub_block;
args->at( 0 ) = data_to_push;
tok_set_pos( tok,
end_pos );
@ -2133,14 +2145,14 @@ int parser_t::parse_job( process_t *p,
if( !error_code )
{
if( p->type == INTERNAL_BUILTIN && parser_keywords_skip_arguments( (wchar_t *)al_get(args, 0) ) )
if( p->type == INTERNAL_BUILTIN && parser_keywords_skip_arguments( (wchar_t *)args->at( 0 ).completion.c_str() ) )
{
if( !p->argv )
halloc_register( j, p->argv = list_to_char_arr( args ) );
halloc_register( j, p->argv = completions_to_char_arr( *args ) );
}
else
{
parse_job_argument_list( p, j, tok, args );
parse_job_argument_list( p, j, tok, *args );
}
}

View file

@ -260,7 +260,7 @@ class parser_t {
*/
const wchar_t *is_function() const;
void parse_job_argument_list( process_t *p, job_t *j, tokenizer *tok, array_list_t *args );
void parse_job_argument_list( process_t *p, job_t *j, tokenizer *tok, std::vector<completion_t>& );
int parse_job( process_t *p, job_t *j, tokenizer *tok );
void skipped_exec( job_t * j );
void eval_job( tokenizer *tok );
@ -304,8 +304,12 @@ class parser_t {
\param line Line to evaluate
\param output List to insert output to
*/
int eval_args( const wchar_t *line, array_list_t *output );
/**
\param line Line to evaluate
\param output List to insert output to
*/
int eval_args( const wchar_t *line, std::vector<completion_t> &output );
/**
Sets the current evaluation error. This function should only be used by libraries that are called by

View file

@ -20,6 +20,7 @@ commence.
*/
#include "config.h"
#include <algorithm>
#include <stdlib.h>
#include <stdio.h>
@ -260,7 +261,7 @@ class reader_data_t
Function for tab completion
*/
void (*complete_func)( const wchar_t *,
array_list_t * );
std::vector<completion_t>& );
/**
Function for syntax highlighting
@ -547,6 +548,7 @@ static int check_size()
/**
Compare two completion entrys
*/
/*
static int completion_cmp( const void *a, const void *b )
{
completion_t *c= *((completion_t **)a);
@ -555,10 +557,11 @@ static int completion_cmp( const void *a, const void *b )
return wcsfilecmp( c->completion, d->completion );
}
*/
/**
Sort an array_list_t containing compltion_t structs.
*/
/*
static void sort_completion_list( array_list_t *comp )
{
qsort( comp->arr,
@ -566,11 +569,16 @@ static void sort_completion_list( array_list_t *comp )
sizeof( void*),
&completion_cmp );
}
*/
static void sort_completion_list( std::vector<completion_t> &comp ) {
sort(comp.begin(), comp.end());
}
/**
Remove any duplicate completions in the list. This relies on the
list first beeing sorted.
*/
/*
static void remove_duplicates( array_list_t *l )
{
int in, out;
@ -595,7 +603,12 @@ static void remove_duplicates( array_list_t *l )
}
al_truncate( l, out );
}
*/
static void remove_duplicates(std::vector<completion_t> &l) {
l.erase(std::unique( l.begin(), l.end()), l.end());
}
int reader_interrupted()
{
@ -1142,7 +1155,7 @@ static void completion_insert( const wchar_t *val, int flags )
\param comp the list of completions to display
*/
static void run_pager( wchar_t *prefix, int is_quoted, array_list_t *comp )
static void run_pager( wchar_t *prefix, int is_quoted, const std::vector<completion_t> &comp )
{
int i;
string_buffer_t cmd;
@ -1177,49 +1190,54 @@ static void run_pager( wchar_t *prefix, int is_quoted, array_list_t *comp )
escaped_separator = escape( COMPLETE_SEP_STR, 1);
for( i=0; i<al_get_count( comp ); i++ )
for( i=0; i< comp.size(); i++ )
{
completion_t *el = (completion_t *)al_get( comp, i );
has_case_sensitive |= !(el->flags & COMPLETE_NO_CASE );
const completion_t &el = comp.at( i );
has_case_sensitive |= !(el.flags & COMPLETE_NO_CASE );
}
for( i=0; i<al_get_count( comp ); i++ )
for( i=0; i< comp.size(); i++ )
{
int base_len=-1;
completion_t *el = (completion_t *)al_get( comp, i );
const completion_t &el = comp.at( i );
wchar_t *foo=0;
wchar_t *baz=0;
if( has_case_sensitive && (el->flags & COMPLETE_NO_CASE ))
if( has_case_sensitive && (el.flags & COMPLETE_NO_CASE ))
{
continue;
}
if( el && el->completion )
{
if( el->flags & COMPLETE_NO_CASE )
{
if( base_len == -1 )
{
wchar_t *begin;
parse_util_token_extent( data->buff, data->buff_pos, &begin, 0, 0, 0 );
base_len = data->buff_pos - (begin-data->buff);
}
foo = escape( el->completion + base_len, ESCAPE_ALL | ESCAPE_NO_QUOTED );
}
else
{
foo = escape( el->completion, ESCAPE_ALL | ESCAPE_NO_QUOTED );
}
if( el.completion.empty() ){
continue;
}
if( el && el->description )
if( el.flags & COMPLETE_NO_CASE )
{
if( base_len == -1 )
{
wchar_t *begin;
parse_util_token_extent( data->buff, data->buff_pos, &begin, 0, 0, 0 );
base_len = data->buff_pos - (begin-data->buff);
}
wcstring foo_wstr = escape_string( el.completion.c_str() + base_len, ESCAPE_ALL | ESCAPE_NO_QUOTED );
foo = wcsdup(foo_wstr.c_str());
}
else
{
wcstring foo_wstr = escape_string( el.completion, ESCAPE_ALL | ESCAPE_NO_QUOTED );
foo = wcsdup(foo_wstr.c_str());
}
if( !el.description.empty() )
{
baz = escape( el->description, 1 );
wcstring baz_wstr = escape_string( el.description, 1 );
baz = wcsdup(baz_wstr.c_str());
}
if( !foo )
@ -1369,7 +1387,7 @@ int reader_can_replace( const wchar_t *in, int flags )
*/
static int handle_completions( array_list_t *comp )
static int handle_completions( std::vector<completion_t> &comp )
{
int i;
void *context = 0;
@ -1390,7 +1408,7 @@ static int handle_completions( array_list_t *comp )
/*
Check trivial cases
*/
switch( al_get_count( comp ) )
switch( comp.size() )
{
/*
No suitable completions found, flash screen and retur
@ -1408,7 +1426,7 @@ static int handle_completions( array_list_t *comp )
case 1:
{
completion_t *c = (completion_t *)al_get( comp, 0 );
const completion_t &c = comp.at( 0 );
/*
If this is a replacement completion, check
@ -1416,10 +1434,10 @@ static int handle_completions( array_list_t *comp )
the token doesn't contain evil operators
like {}
*/
if( !(c->flags & COMPLETE_NO_CASE) || reader_can_replace( tok, c->flags ) )
if( !(c.flags & COMPLETE_NO_CASE) || reader_can_replace( tok, c.flags ) )
{
completion_insert( c->completion,
c->flags );
completion_insert( c.completion.c_str(),
c.flags );
}
done = 1;
len = 1;
@ -1433,29 +1451,29 @@ static int handle_completions( array_list_t *comp )
/*
Try to find something to insert whith the correct case
*/
for( i=0; i<al_get_count( comp ); i++ )
for( i=0; i< comp.size() ; i++ )
{
completion_t *c = (completion_t *)al_get( comp, i );
const completion_t &c = comp.at( i );
int new_len;
/*
Ignore case insensitive completions for now
*/
if( c->flags & COMPLETE_NO_CASE )
if( c.flags & COMPLETE_NO_CASE )
continue;
count++;
if( base )
{
new_len = comp_len( base, c->completion );
new_len = comp_len( base, c.completion.c_str() );
len = new_len < len ? new_len: len;
}
else
{
base = wcsdup( c->completion );
base = wcsdup( c.completion.c_str() );
len = wcslen( base );
flags = c->flags;
flags = c.flags;
}
}
@ -1488,16 +1506,16 @@ static int handle_completions( array_list_t *comp )
count = 0;
for( i=0; i<al_get_count( comp ); i++ )
for( i=0; i< comp.size(); i++ )
{
completion_t *c = (completion_t *)al_get( comp, i );
const completion_t &c = comp.at( i );
int new_len;
if( !(c->flags & COMPLETE_NO_CASE) )
if( !(c.flags & COMPLETE_NO_CASE) )
continue;
if( !reader_can_replace( tok, c->flags ) )
if( !reader_can_replace( tok, c.flags ) )
{
len=0;
break;
@ -1507,14 +1525,14 @@ static int handle_completions( array_list_t *comp )
if( base )
{
new_len = offset + comp_ilen( base+offset, c->completion+offset );
new_len = offset + comp_ilen( base+offset, c.completion.c_str()+offset );
len = new_len < len ? new_len: len;
}
else
{
base = wcsdup( c->completion );
base = wcsdup( c.completion.c_str() );
len = wcslen( base );
flags = c->flags;
flags = c.flags;
}
}
@ -2343,7 +2361,7 @@ void reader_set_prompt( const wchar_t *new_prompt )
}
void reader_set_complete_function( void (*f)( const wchar_t *,
array_list_t * ) )
std::vector<completion_t>& ) )
{
data->complete_func = f;
}
@ -2578,7 +2596,7 @@ static int read_i()
event_fire_generic(L"fish_prompt");
reader_push(L"fish");
reader_set_complete_function( &complete );
reader_set_complete_function( &complete2 );
reader_set_highlight_function( &highlight_shell );
reader_set_test_function( &reader_shell_test );
parser_t &parser = parser_t::principal_parser();
@ -2683,7 +2701,7 @@ wchar_t *reader_readline()
int i;
int last_char=0, yank=0;
const wchar_t *yank_str;
array_list_t *comp=0;
std::vector<completion_t> comp;
int comp_empty=1;
int finished=0;
struct termios old_modes;
@ -2876,19 +2894,18 @@ wchar_t *reader_readline()
len = data->buff_pos - (begin-data->buff);
buffcpy = wcsndup( begin, len );
comp = al_halloc( 0 );
// comp = al_halloc( 0 );
data->complete_func( buffcpy, comp );
sort_completion_list( comp );
remove_duplicates( comp );
free( buffcpy );
comp_empty = handle_completions( comp );
halloc_free( comp );
comp = 0;
comp.clear();
// halloc_free( comp );
// comp = 0;
}
break;

View file

@ -9,12 +9,14 @@
#ifndef FISH_READER_H
#define FISH_READER_H
#include <vector>
#include <wchar.h>
#include "util.h"
#include "io.h"
class parser_t;
struct completion_t;
/**
Read commands from \c fd until encountering EOF
@ -125,18 +127,15 @@ void reader_pop();
- The command to be completed as a null terminated array of wchar_t
- An array_list_t in which completions will be inserted.
*/
void reader_set_complete_function( void (*f)( const wchar_t *, array_list_t * ) );
void reader_set_complete_function( void (*f)( const wchar_t *, std::vector<completion_t> & ) );
/**
<<<<<<< upstream
=======
The type of a highlight function.
*/
class env_vars;
typedef void (*highlight_function_t)( const wchar_t *, int *, int, array_list_t *, const env_vars &vars );
/**
>>>>>>> HEAD~2
Specify function for syntax highlighting. The function must take these arguments:
- The command to be highlighted as a null terminated array of wchar_t

View file

@ -7,7 +7,7 @@ wildcards using **.
*/
#include "config.h"
#include <algorithm>
#include <stdlib.h>
#include <stdio.h>
#include <limits.h>
@ -236,7 +236,7 @@ static int wildcard_complete_internal( const wchar_t *orig,
int is_first,
const wchar_t *desc,
const wchar_t *(*desc_func)(const wchar_t *),
array_list_t *out,
std::vector<completion_t> &out,
int flags )
{
if( !wc || !str || !orig)
@ -250,12 +250,7 @@ static int wildcard_complete_internal( const wchar_t *orig,
{
wchar_t *out_completion = 0;
const wchar_t *out_desc = desc;
if( !out )
{
return 1;
}
if( flags & COMPLETE_NO_CASE )
{
out_completion = wcsdup( orig );
@ -319,7 +314,7 @@ static int wildcard_complete_internal( const wchar_t *orig,
do
{
res |= wildcard_complete_internal( orig, str, wc+1, 0, desc, desc_func, out, flags );
if( res && !out )
if( res )
break;
}
while( *str++ != 0 );
@ -345,7 +340,7 @@ int wildcard_complete( const wchar_t *str,
const wchar_t *wc,
const wchar_t *desc,
const wchar_t *(*desc_func)(const wchar_t *),
array_list_t *out,
std::vector<completion_t> &out,
int flags )
{
int res;
@ -645,7 +640,7 @@ static const wchar_t *file_get_desc( const wchar_t *filename,
\param wc the wildcard to match against
\param is_cmd whether we are performing command completion
*/
static void wildcard_completion_allocate( array_list_t *list,
static void wildcard_completion_allocate( std::vector<completion_t> &list,
const wchar_t *fullname,
const wchar_t *completion,
const wchar_t *wc,
@ -778,7 +773,7 @@ static int test_flags( const wchar_t *filename,
static int wildcard_expand_internal( const wchar_t *wc,
const wchar_t *base_dir,
int flags,
array_list_t *out )
std::vector<completion_t> &out )
{
/* Points to the end of the current wildcard segment */
@ -810,7 +805,7 @@ static int wildcard_expand_internal( const wchar_t *wc,
return -1;
}
if( !wc || !base_dir || !out)
if( !wc || !base_dir )
{
debug( 2, L"Got null string on line %d of file %s", __LINE__, __FILE__ );
return 0;
@ -897,7 +892,11 @@ static int wildcard_expand_internal( const wchar_t *wc,
else
{
res = 1;
al_push_check( out, wcsdup( base_dir ) );
completion_t data_to_push;
data_to_push.completion = base_dir;
if ( std::find( out.begin(), out.end(), data_to_push ) != out.end() ){
out.push_back( data_to_push);
}
}
}
else
@ -918,11 +917,12 @@ static int wildcard_expand_internal( const wchar_t *wc,
/*
Test for matches before stating file, so as to minimize the number of calls to the much slower stat function
*/
std::vector<completion_t> test;
if( wildcard_complete( name,
wc,
L"",
0,
0,
test,
0 ) )
{
if( test_flags( long_name, flags ) )
@ -966,7 +966,9 @@ static int wildcard_expand_internal( const wchar_t *wc,
}
else
{
al_push_check( out, long_name );
completion_t data_to_push;
data_to_push.completion = long_name;
out.push_back( data_to_push );
}
res = 1;
}
@ -1053,7 +1055,7 @@ static int wildcard_expand_internal( const wchar_t *wc,
if( is_recursive )
{
const wchar_t *end = wcschr( wc, ANY_STRING_RECURSIVE );
wchar_t *wc_sub = const_cast<wchar_t*>(wcsndup( wc, end-wc+1));
wchar_t *wc_sub = wcsndup( wc, end-wc+1);
partial_match = wildcard_match2( name, wc_sub, 1 );
free( wc_sub );
}
@ -1156,9 +1158,9 @@ static int wildcard_expand_internal( const wchar_t *wc,
int wildcard_expand( const wchar_t *wc,
const wchar_t *base_dir,
int flags,
array_list_t *out )
std::vector<completion_t> &out )
{
int c = al_get_count( out );
int c = out.size();
int res = wildcard_expand_internal( wc, base_dir, flags, out );
int i;
@ -1176,16 +1178,16 @@ int wildcard_expand( const wchar_t *wc,
sb_init( &sb );
for( i=c; i<al_get_count( out ); i++ )
for( i=c; i<out.size(); i++ )
{
completion_t *c = (completion_t *)al_get( out, i );
completion_t &c = out.at( i );
if( c->flags & COMPLETE_NO_CASE )
if( c.flags & COMPLETE_NO_CASE )
{
sb_clear( &sb );
sb_printf( &sb, L"%ls%ls%ls", base_dir, wc_base, c->completion );
sb_printf( &sb, L"%ls%ls%ls", base_dir, wc_base, c.completion.c_str() );
c->completion = halloc_wcsdup( out, (wchar_t *)sb.buff );
c.completion = (wchar_t *)sb.buff;
}
}
@ -1200,19 +1202,17 @@ int wildcard_expand( const wchar_t *wc,
return res;
}
int wildcard_expand_string(const wcstring &wc, const wcstring &base_dir, int flags, wcstring_list_t &outputs )
int wildcard_expand_string(const wcstring &wc, const wcstring &base_dir, int flags, std::vector<completion_t> &outputs )
{
array_list_t lst;
al_init(&lst);
std::vector<completion_t> lst;
// al_init(&lst);
int res = wildcard_expand(wc.c_str(), base_dir.c_str(), flags, &lst);
int res = wildcard_expand(wc.c_str(), base_dir.c_str(), flags, lst);
int i, max = al_get_count(&lst);
int i, max = lst.size();
for (i=0; i < max; i++) {
wchar_t *tmp = (wchar_t *)al_get(&lst, i);
outputs.push_back(tmp);
free(tmp);
outputs.push_back( lst.at(i));
}
al_destroy(&lst);
// al_destroy(&lst);
return res;
}

View file

@ -24,6 +24,7 @@
#define WILDCARD_RESERVED 0xf400
struct completion_t;
/**
Enumeration of all wildcard types
*/
@ -70,7 +71,7 @@ int wildcard_expand( const wchar_t *wc,
int flags,
array_list_t *out );
int wildcard_expand_string(const wcstring &wc, const wcstring &base_dir, int flags, wcstring_list_t &out );
int wildcard_expand_string(const wcstring &wc, const wcstring &base_dir, int flags, std::vector<completion_t> &out );
/**
Test whether the given wildcard matches the string
@ -94,7 +95,7 @@ int wildcard_complete( const wchar_t *str,
const wchar_t *wc,
const wchar_t *desc,
const wchar_t *(*desc_func)(const wchar_t *),
array_list_t *out,
std::vector<completion_t> &out,
int flags );
#endif