aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--autoload.cpp1
-rw-r--r--builtin.cpp14
-rw-r--r--builtin.h3
-rw-r--r--builtin_complete.cpp21
-rw-r--r--common.cpp22
-rw-r--r--common.h6
-rw-r--r--complete.cpp121
-rw-r--r--complete.h24
-rw-r--r--expand.cpp431
-rw-r--r--expand.h4
-rw-r--r--parser.cpp72
-rw-r--r--parser.h10
-rw-r--r--reader.cpp129
-rw-r--r--reader.h7
-rw-r--r--wildcard.cpp66
-rw-r--r--wildcard.h5
16 files changed, 666 insertions, 270 deletions
diff --git a/autoload.cpp b/autoload.cpp
index 01c89468..69461c09 100644
--- a/autoload.cpp
+++ b/autoload.cpp
@@ -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;
diff --git a/builtin.cpp b/builtin.cpp
index 3897e899..e2374f1d 100644
--- a/builtin.cpp
+++ b/builtin.cpp
@@ -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 );
diff --git a/builtin.h b/builtin.h
index fead6e25..e90d24c0 100644
--- a/builtin.h
+++ b/builtin.h
@@ -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.
*/
diff --git a/builtin_complete.cpp b/builtin_complete.cpp
index 18e953a0..15173958 100644
--- a/builtin_complete.cpp
+++ b/builtin_complete.cpp
@@ -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--;
}
diff --git a/common.cpp b/common.cpp
index 388f68cc..c5974d3e 100644
--- a/common.cpp
+++ b/common.cpp
@@ -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;
diff --git a/common.h b/common.h
index 4a52071f..0fdfc443 100644
--- a/common.h
+++ b/common.h
@@ -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
diff --git a/complete.cpp b/complete.cpp
index bca8f6fc..69ea413a 100644
--- a/complete.cpp
+++ b/complete.cpp
@@ -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
diff --git a/complete.h b/complete.h
index ba16e896..1cfeac28 100644
--- a/complete.h
+++ b/complete.h
@@ -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 );
diff --git a/expand.cpp b/expand.cpp
index ff62d540..7b347b5c 100644
--- a/expand.cpp
+++ b/expand.cpp
@@ -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;
}
+
diff --git a/expand.h b/expand.h
index c9c3f138..0d235ea5 100644
--- a/expand.h
+++ b/expand.h
@@ -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 );
/**
diff --git a/parser.cpp b/parser.cpp
index 6aa25ec5..1f744e4c 100644
--- a/parser.cpp
+++ b/parser.cpp
@@ -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 );
}
}
diff --git a/parser.h b/parser.h
index 5ecab5bd..8c111e1e 100644
--- a/parser.h
+++ b/parser.h
@@ -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
diff --git a/reader.cpp b/reader.cpp
index 6541396d..0381eae9 100644
--- a/reader.cpp
+++ b/reader.cpp
@@ -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;
diff --git a/reader.h b/reader.h
index 138ecbcc..6f99ba4f 100644
--- a/reader.h
+++ b/reader.h
@@ -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
diff --git a/wildcard.cpp b/wildcard.cpp
index 219a9c0d..1d250176 100644
--- a/wildcard.cpp
+++ b/wildcard.cpp
@@ -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;
}
diff --git a/wildcard.h b/wildcard.h
index c82ae1f2..891b0b5f 100644
--- a/wildcard.h
+++ b/wildcard.h
@@ -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