From b23d65b0144e61afee0b0fdd841c6c746b2e885d Mon Sep 17 00:00:00 2001 From: maxfl Date: Sat, 7 Jul 2012 10:17:24 +0800 Subject: [PATCH 1/8] Set single-line default prompt Fish now doesn't join the fish_prompt output. This breaks the default fish_prompt. Make default fish_prompt single-line. Fixes #203. Add -l flag to 'read' documentation. Remove ambiguous '-x' description. Fixes #157. --- doc_src/read.txt | 2 +- reader.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/doc_src/read.txt b/doc_src/read.txt index b85b5fd8f..d69d715b7 100644 --- a/doc_src/read.txt +++ b/doc_src/read.txt @@ -9,8 +9,8 @@ The read builtin causes fish to read one line from standard input and store the result in one or more environment variables. - -c CMD or --command=CMD specifies that the initial string in the interactive mode command buffer should be CMD. -- -e or --export specifies that the variables will be exported to subshells. - -g or --global specifies that the variables will be made global. +- -l or --local specifies that the variables will be made local. - -m NAME or --mode-name=NAME specifies that the name NAME should be used to save/load the history file. If NAME is fish, the regular fish history will be available. - -p PROMPT_CMD or --prompt=PROMPT_CMD specifies that the output of the shell command PROMPT_CMD should be used as the prompt for the interactive mode prompt. The default prompt command is set_color green; echo read; set_color normal; echo "> ". - -s or --shell Use syntax highlighting, tab completions and command termination suitable for entering shellscript code diff --git a/reader.cpp b/reader.cpp index 29645d74b..ba275f54d 100644 --- a/reader.cpp +++ b/reader.cpp @@ -118,7 +118,7 @@ commence. fish specific commands, meaning it will work even if fish is not installed. This is used by read_i. */ -#define DEFAULT_PROMPT L"echo \"$USER@\"; hostname|cut -d . -f 1; echo \" \"; pwd; printf '> ';" +#define DEFAULT_PROMPT L"echo -n \"$USER@\"(hostname|cut -d . -f 1)' '(pwd)'> '" /** The name of the function that prints the fish prompt From 0a5e7be129644e9f53deb7051e812098c1f4e518 Mon Sep 17 00:00:00 2001 From: maxfl Date: Sat, 7 Jul 2012 10:57:28 +0800 Subject: [PATCH 2/8] Add index ranges Builtin 'set' now can set variable index ranges: set test[1..3] a b c #works set test[-1..-3] a b c #works if variable have enough elements set test[2..-2] a b c #works set test[1..3 -1..-2] a b c b b #works Expand now can parse index ranges. But not handle for now. TODO: * Add variable substitution index ranges: echo $PATH[-1..1] * Add command substitution index range: echo (seq 10)[-1..-4] * Add process substitution indexes and ranges: echo %vim[-1] --- builtin_set.cpp | 30 ++++++++++++++++++++++++++---- expand.cpp | 19 ++++++++++++++++++- 2 files changed, 44 insertions(+), 5 deletions(-) diff --git a/builtin_set.cpp b/builtin_set.cpp index c1bb65ccc..11fe2ab98 100644 --- a/builtin_set.cpp +++ b/builtin_set.cpp @@ -236,11 +236,33 @@ static int parse_index( std::vector &indexes, l_ind = var_count+l_ind+1; } - indexes.push_back( l_ind ); src = end; - count++; - while (iswspace(*src)) src++; - } + if ( *src==L'.' && *(src+1)==L'.' ){ + src+=2; + long l_ind2 = wcstol( src, &end, 10 ); + if( end==src || errno ) + { + return 1; + } + src = end; + + if( l_ind2 < 0 ) + { + l_ind2 = var_count+l_ind2+1; + } + int direction = l_ind2 } // debug( 0, L"Push idx %d", tmp ); - idx.push_back(tmp); pos = end-in; + if ( in[pos]==L'.' && in[pos+1]==L'.' ){ + pos+=2; + long tmp1 = wcstol( &in[pos], &end, 10 ); + if( ( errno ) || ( end == &in[pos] ) ) + { + return 1; + } + pos = end-in; + + debug( 0, L"Push range idx %d %d", tmp, tmp1 ); + idx.push_back(tmp); + // idx.push_back(tmp2); + continue; + } + + debug( 0, L"Push idx %d", tmp ); + idx.push_back(tmp); + // idx.push_back(tmp2); } if( end_ptr ) From 41ec58a5244603004a98c243b8612b8b2887a66e Mon Sep 17 00:00:00 2001 From: maxfl Date: Sat, 7 Jul 2012 11:04:29 +0800 Subject: [PATCH 3/8] misc --- expand.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/expand.cpp b/expand.cpp index 054859516..7212d7952 100644 --- a/expand.cpp +++ b/expand.cpp @@ -769,13 +769,13 @@ static int parse_slice( const wchar_t *in, wchar_t **end_ptr, std::vector } pos = end-in; - debug( 0, L"Push range idx %d %d", tmp, tmp1 ); + // debug( 0, L"Push range idx %d %d", tmp, tmp1 ); idx.push_back(tmp); // idx.push_back(tmp2); continue; } - debug( 0, L"Push idx %d", tmp ); + // debug( 0, L"Push idx %d", tmp ); idx.push_back(tmp); // idx.push_back(tmp2); } From c0e996acf8226e44da995d0e91dc26c4903e4427 Mon Sep 17 00:00:00 2001 From: maxfl Date: Sat, 7 Jul 2012 22:01:28 +0800 Subject: [PATCH 4/8] Implemented index ranges for command substitution Now the following code works: > echo (seq 10)[-1..1] With output: 10 9 8 7 6 5 4 3 2 1 --- expand.cpp | 25 +++++++++++++------------ 1 file changed, 13 insertions(+), 12 deletions(-) diff --git a/expand.cpp b/expand.cpp index 7212d7952..ab75a40ab 100644 --- a/expand.cpp +++ b/expand.cpp @@ -727,10 +727,8 @@ void expand_variable_error( parser_t &parser, const wchar_t *token, int token_po /** Parse an array slicing specification */ -static int parse_slice( const wchar_t *in, wchar_t **end_ptr, std::vector &idx ) +static int parse_slice( const wchar_t *in, wchar_t **end_ptr, std::vector &idx, int size=-1 ) { - - wchar_t *end; int pos = 1; @@ -769,9 +767,17 @@ static int parse_slice( const wchar_t *in, wchar_t **end_ptr, std::vector } pos = end-in; - // debug( 0, L"Push range idx %d %d", tmp, tmp1 ); - idx.push_back(tmp); - // idx.push_back(tmp2); + if ( size>-1 ) { + // debug( 0, L"Push range idx %d %d", tmp, tmp1 ); + long i1 = tmp>-1 ? tmp : size+tmp+1; + long i2 = tmp1>-1 ? tmp1 : size+tmp1+1; + // debug( 0, L"Push range idx %d %d", i1, i2 ); + short direction = i2 slice_idx; wchar_t *slice_end; - if( parse_slice( tail_begin, &slice_end, slice_idx ) ) + if( parse_slice( tail_begin, &slice_end, slice_idx, sub_res.size() ) ) { parser.error( SYNTAX_ERROR, -1, L"Invalid index value" ); return 0; @@ -1216,11 +1222,6 @@ static int expand_cmdsubst( parser_t &parser, const wcstring &input, std::vector for( i=0; i < slice_idx.size(); i++ ) { long idx = slice_idx.at(i); - if( idx < 0 ) - { - idx = sub_res.size() + idx + 1; - } - if( idx < 1 || (size_t)idx > sub_res.size() ) { parser.error( SYNTAX_ERROR, -1, L"Invalid index value" ); From 5f05756e657d85026026d95d4ada0b6677861900 Mon Sep 17 00:00:00 2001 From: maxfl Date: Sun, 8 Jul 2012 09:19:11 +0800 Subject: [PATCH 5/8] Add variable expand ranges echo $PATH[-1..1] #now works Add tests for ranges --- expand.cpp | 64 +++++++++++++++++++++------------------------- tests/test8.err | 0 tests/test8.in | 21 +++++++++++++++ tests/test8.out | 9 +++++++ tests/test8.status | 1 + tests/top.out | 1 + 6 files changed, 61 insertions(+), 35 deletions(-) create mode 100644 tests/test8.err create mode 100644 tests/test8.in create mode 100644 tests/test8.out create mode 100644 tests/test8.status diff --git a/expand.cpp b/expand.cpp index ab75a40ab..c370725a3 100644 --- a/expand.cpp +++ b/expand.cpp @@ -727,7 +727,7 @@ void expand_variable_error( parser_t &parser, const wchar_t *token, int token_po /** Parse an array slicing specification */ -static int parse_slice( const wchar_t *in, wchar_t **end_ptr, std::vector &idx, int size=-1 ) +static int parse_slice( const wchar_t *in, wchar_t **end_ptr, std::vector &idx, int size ) { wchar_t *end; @@ -757,6 +757,7 @@ static int parse_slice( const wchar_t *in, wchar_t **end_ptr, std::vector } // debug( 0, L"Push idx %d", tmp ); + long i1 = tmp>-1 ? tmp : size+tmp+1; pos = end-in; if ( in[pos]==L'.' && in[pos+1]==L'.' ){ pos+=2; @@ -767,23 +768,19 @@ static int parse_slice( const wchar_t *in, wchar_t **end_ptr, std::vector } pos = end-in; - if ( size>-1 ) { - // debug( 0, L"Push range idx %d %d", tmp, tmp1 ); - long i1 = tmp>-1 ? tmp : size+tmp+1; - long i2 = tmp1>-1 ? tmp1 : size+tmp1+1; - // debug( 0, L"Push range idx %d %d", i1, i2 ); - short direction = i2-1 ? tmp1 : size+tmp1+1; + // debug( 0, L"Push range idx %d %d", i1, i2 ); + short direction = i2 sub_res.size() ) { - parser.error( SYNTAX_ERROR, -1, L"Invalid index value" ); + parser.error( SYNTAX_ERROR, + -1, + ARRAY_BOUNDS_ERR ); return 0; } - idx = idx-1; sub_res2.push_back(sub_res.at(idx)); diff --git a/tests/test8.err b/tests/test8.err new file mode 100644 index 000000000..e69de29bb diff --git a/tests/test8.in b/tests/test8.in new file mode 100644 index 000000000..e03d9d05b --- /dev/null +++ b/tests/test8.in @@ -0,0 +1,21 @@ +# Test index ranges + +# Test variable expand +set test (seq 10) +echo $test[1..10] # normal range +echo $test[10..1] # inverted range +echo $test[2..5 8..6] # several ranges +echo $test[-1..-2] # range with negative limits +echo $test[-1..1] # range with mixed limits + +# Test variable set +set test1 $test +set test1[-1..1] $test # reverse variable +echo $echo $test1 +set test1[2..4 -2..-4] $test1[4..2 -4..-2] +echo $test1 + +# Test command substitution +echo (seq 5)[-1..1] +echo (seq 10)[3..5 -2..2] + diff --git a/tests/test8.out b/tests/test8.out new file mode 100644 index 000000000..e118e572b --- /dev/null +++ b/tests/test8.out @@ -0,0 +1,9 @@ +1 2 3 4 5 6 7 8 9 10 +10 9 8 7 6 5 4 3 2 1 +2 3 4 5 8 7 6 +10 9 +10 9 8 7 6 5 4 3 2 1 +10 9 8 7 6 5 4 3 2 1 +10 7 8 9 6 5 2 3 4 1 +5 4 3 2 1 +3 4 5 9 8 7 6 5 4 3 2 diff --git a/tests/test8.status b/tests/test8.status new file mode 100644 index 000000000..573541ac9 --- /dev/null +++ b/tests/test8.status @@ -0,0 +1 @@ +0 diff --git a/tests/top.out b/tests/top.out index 5614a6619..0c7b1103a 100644 --- a/tests/top.out +++ b/tests/top.out @@ -6,3 +6,4 @@ File test4.in tested ok File test5.in tested ok File test6.in tested ok File test7.in tested ok +File test8.in tested ok From e1b8c425da571b7f002103805520a1d496ebb087 Mon Sep 17 00:00:00 2001 From: maxfl Date: Sun, 8 Jul 2012 09:39:39 +0800 Subject: [PATCH 6/8] Fix case when second limit is a variable: echo $PATH[1..$n] --- expand.cpp | 3 ++- tests/test8.in | 24 ++++++++++++------------ tests/test8.out | 5 +++++ 3 files changed, 19 insertions(+), 13 deletions(-) diff --git a/expand.cpp b/expand.cpp index c370725a3..4a3eaf015 100644 --- a/expand.cpp +++ b/expand.cpp @@ -735,7 +735,6 @@ static int parse_slice( const wchar_t *in, wchar_t **end_ptr, std::vector // debug( 0, L"parse_slice on '%ls'", in ); - while( 1 ) { long tmp; @@ -761,6 +760,8 @@ static int parse_slice( const wchar_t *in, wchar_t **end_ptr, std::vector pos = end-in; if ( in[pos]==L'.' && in[pos+1]==L'.' ){ pos+=2; + while( in[pos]==INTERNAL_SEPARATOR ) + pos++; long tmp1 = wcstol( &in[pos], &end, 10 ); if( ( errno ) || ( end == &in[pos] ) ) { diff --git a/tests/test8.in b/tests/test8.in index e03d9d05b..3a76e8bf8 100644 --- a/tests/test8.in +++ b/tests/test8.in @@ -1,21 +1,21 @@ # Test index ranges -# Test variable expand -set test (seq 10) -echo $test[1..10] # normal range -echo $test[10..1] # inverted range +echo Test variable expand +set n 10 +set test (seq $n) +echo $test[1..$n] # normal range +echo $test[$n..1] # inverted range echo $test[2..5 8..6] # several ranges echo $test[-1..-2] # range with negative limits echo $test[-1..1] # range with mixed limits -# Test variable set +echo Test variable set set test1 $test -set test1[-1..1] $test # reverse variable -echo $echo $test1 -set test1[2..4 -2..-4] $test1[4..2 -4..-2] -echo $test1 +set test1[-1..1] $test; echo $test1 +set test1[1..$n] $test; echo $test1 +set test1[$n..1] $test; echo $test1 +set test1[2..4 -2..-4] $test1[4..2 -4..-2]; echo $test1 -# Test command substitution +echo Test command substitution echo (seq 5)[-1..1] -echo (seq 10)[3..5 -2..2] - +echo (seq $n)[3..5 -2..2] diff --git a/tests/test8.out b/tests/test8.out index e118e572b..82bf40942 100644 --- a/tests/test8.out +++ b/tests/test8.out @@ -1,9 +1,14 @@ +Test variable expand 1 2 3 4 5 6 7 8 9 10 10 9 8 7 6 5 4 3 2 1 2 3 4 5 8 7 6 10 9 10 9 8 7 6 5 4 3 2 1 +Test variable set +10 9 8 7 6 5 4 3 2 1 +1 2 3 4 5 6 7 8 9 10 10 9 8 7 6 5 4 3 2 1 10 7 8 9 6 5 2 3 4 1 +Test command substitution 5 4 3 2 1 3 4 5 9 8 7 6 5 4 3 2 From 079f17761c7392ee6369c67809db99a647237bfe Mon Sep 17 00:00:00 2001 From: maxfl Date: Sun, 8 Jul 2012 09:45:34 +0800 Subject: [PATCH 7/8] Fix case when first index is command substitution --- expand.cpp | 4 +++- tests/test8.in | 4 ++++ tests/test8.out | 3 +++ 3 files changed, 10 insertions(+), 1 deletion(-) diff --git a/expand.cpp b/expand.cpp index 4a3eaf015..76b16ae55 100644 --- a/expand.cpp +++ b/expand.cpp @@ -733,7 +733,7 @@ static int parse_slice( const wchar_t *in, wchar_t **end_ptr, std::vector int pos = 1; - // debug( 0, L"parse_slice on '%ls'", in ); + // debug( 0, L"parse_slice on '%ls'", in ); while( 1 ) { @@ -758,6 +758,8 @@ static int parse_slice( const wchar_t *in, wchar_t **end_ptr, std::vector long i1 = tmp>-1 ? tmp : size+tmp+1; pos = end-in; + while( in[pos]==INTERNAL_SEPARATOR ) + pos++; if ( in[pos]==L'.' && in[pos+1]==L'.' ){ pos+=2; while( in[pos]==INTERNAL_SEPARATOR ) diff --git a/tests/test8.in b/tests/test8.in index 3a76e8bf8..c3c733848 100644 --- a/tests/test8.in +++ b/tests/test8.in @@ -19,3 +19,7 @@ set test1[2..4 -2..-4] $test1[4..2 -4..-2]; echo $test1 echo Test command substitution echo (seq 5)[-1..1] echo (seq $n)[3..5 -2..2] + +echo Test more +echo $test[(count $test)..1] +echo $test[1..(count $test)] diff --git a/tests/test8.out b/tests/test8.out index 82bf40942..72af9bb81 100644 --- a/tests/test8.out +++ b/tests/test8.out @@ -12,3 +12,6 @@ Test variable set Test command substitution 5 4 3 2 1 3 4 5 9 8 7 6 5 4 3 2 +Test more +10 9 8 7 6 5 4 3 2 1 +1 2 3 4 5 6 7 8 9 10 From b25b5bf5f6b2bb6b06ab3d4a460e65a973c3b7a9 Mon Sep 17 00:00:00 2001 From: maxfl Date: Sun, 8 Jul 2012 10:55:48 +0800 Subject: [PATCH 8/8] restore tabs instead of spaces --- builtin_set.cpp | 130 ++++---- expand.cpp | 842 ++++++++++++++++++++++++------------------------ 2 files changed, 486 insertions(+), 486 deletions(-) diff --git a/builtin_set.cpp b/builtin_set.cpp index 11fe2ab98..4af0169ec 100644 --- a/builtin_set.cpp +++ b/builtin_set.cpp @@ -89,7 +89,7 @@ static int my_env_set( const wchar_t *key, wcstring_list_t &val, int scope ) if( error ) { const wchar_t *colon; - append_format(stderr_buffer, _(BUILTIN_SET_PATH_ERROR), L"set", dir, key); + append_format(stderr_buffer, _(BUILTIN_SET_PATH_ERROR), L"set", dir, key); colon = wcschr( dir, L':' ); if( colon && *(colon+1) ) @@ -106,7 +106,7 @@ static int my_env_set( const wchar_t *key, wcstring_list_t &val, int scope ) if( show_hint ) { - append_format(stderr_buffer, _(BUILTIN_SET_PATH_HINT), L"set", key, key, wcschr( dir, L':' )+1); + append_format(stderr_buffer, _(BUILTIN_SET_PATH_HINT), L"set", key, key, wcschr( dir, L':' )+1); } if( error ) @@ -128,7 +128,7 @@ static int my_env_set( const wchar_t *key, wcstring_list_t &val, int scope ) { for( i=0; i< val.size() ; i++ ) { - sb.append(val[i]); + sb.append(val[i]); if( i &indexes, } src = end; - if ( *src==L'.' && *(src+1)==L'.' ){ - src+=2; - long l_ind2 = wcstol( src, &end, 10 ); - if( end==src || errno ) - { - return 1; - } - src = end; + if ( *src==L'.' && *(src+1)==L'.' ){ + src+=2; + long l_ind2 = wcstol( src, &end, 10 ); + if( end==src || errno ) + { + return 1; + } + src = end; - if( l_ind2 < 0 ) - { - l_ind2 = var_count+l_ind2+1; - } - int direction = l_ind2= list.size() ) - { - list.resize( ind+1 ); - } + if ( ind >= list.size() ) + { + list.resize( ind+1 ); + } // free((void *) al_get(list, ind)); list[ ind ] = newv; @@ -303,19 +303,19 @@ static int update_values( wcstring_list_t &list, */ static void erase_values(wcstring_list_t &list, const std::vector &indexes) { - // Make a set of indexes. - // This both sorts them into ascending order and removes duplicates. - const std::set indexes_set(indexes.begin(), indexes.end()); - - // Now walk the set backwards, so we encounter larger indexes first, and remove elements at the given (1-based) indexes. - std::set::const_reverse_iterator iter; - for (iter = indexes_set.rbegin(); iter != indexes_set.rend(); iter++) { - long val = *iter; - if (val > 0 && val <= list.size()) { - // One-based indexing! - list.erase(list.begin() + val - 1); - } - } + // Make a set of indexes. + // This both sorts them into ascending order and removes duplicates. + const std::set indexes_set(indexes.begin(), indexes.end()); + + // Now walk the set backwards, so we encounter larger indexes first, and remove elements at the given (1-based) indexes. + std::set::const_reverse_iterator iter; + for (iter = indexes_set.rbegin(); iter != indexes_set.rend(); iter++) { + long val = *iter; + if (val > 0 && val <= list.size()) { + // One-based indexing! + list.erase(list.begin() + val - 1); + } + } } @@ -325,13 +325,13 @@ static void erase_values(wcstring_list_t &list, const std::vector &indexes */ static void print_variables(int include_values, int esc, bool shorten_ok, int scope) { - wcstring_list_t names = env_get_names(scope); - sort(names.begin(), names.end()); + wcstring_list_t names = env_get_names(scope); + sort(names.begin(), names.end()); for( size_t i = 0; i < names.size(); i++ ) { const wcstring key = names.at(i); - const wcstring e_key = escape_string(key, 0); + const wcstring e_key = escape_string(key, 0); stdout_buffer.append(e_key); @@ -350,8 +350,8 @@ static void print_variables(int include_values, int esc, bool shorten_ok, int sc wcstring e_value = esc ? expand_escape_variable(value) : value; - stdout_buffer.append(L" "); - stdout_buffer.append(e_value); + stdout_buffer.append(L" "); + stdout_buffer.append(e_value); if( shorten ) { @@ -407,7 +407,7 @@ static int builtin_set( parser_t &parser, wchar_t **argv ) { L"universal", no_argument, 0, 'U' } - , + , { L"long", no_argument, 0, 'L' } @@ -460,7 +460,7 @@ static int builtin_set( parser_t &parser, wchar_t **argv ) { break; } - + switch(c) { case 0: @@ -493,10 +493,10 @@ static int builtin_set( parser_t &parser, wchar_t **argv ) case 'U': universal = 1; break; - - case 'L': - shorten_ok = false; - break; + + case 'L': + shorten_ok = false; + break; case 'q': query = 1; @@ -604,9 +604,9 @@ static int builtin_set( parser_t &parser, wchar_t **argv ) wcstring_list_t result; size_t j; - env_var_t dest_str = env_get_string(dest); - if (! dest_str.missing()) - tokenize_variable_array( dest_str, result ); + env_var_t dest_str = env_get_string(dest); + if (! dest_str.missing()) + tokenize_variable_array( dest_str, result ); if( !parse_index( indexes, arg, dest, result.size() ) ) { @@ -718,9 +718,9 @@ static int builtin_set( parser_t &parser, wchar_t **argv ) std::vector indexes; wcstring_list_t result; - const env_var_t dest_str = env_get_string(dest); - if (! dest_str.missing()) - tokenize_variable_array( dest_str, result ); + const env_var_t dest_str = env_get_string(dest); + if (! dest_str.missing()) + tokenize_variable_array( dest_str, result ); for( ; woptindcommand_is_empty() ) @@ -355,7 +355,7 @@ static int find_process( const wchar_t *proc, if( wcsncmp( proc, jid, wcslen(proc ) )==0 ) { - wcstring desc_buff = format_string(COMPLETE_JOB_DESC_VAL, j->command_wcstr()); + wcstring desc_buff = format_string(COMPLETE_JOB_DESC_VAL, j->command_wcstr()); completion_allocate( out, jid+wcslen(proc), desc_buff, @@ -379,7 +379,7 @@ static int find_process( const wchar_t *proc, { { - wcstring result = to_string((long)j->pgid); + wcstring result = to_string((long)j->pgid); out.push_back(completion_t(result)); found = 1; } @@ -390,8 +390,8 @@ static int find_process( const wchar_t *proc, if( found ) return 1; - job_iterator_t jobs; - while ((j = jobs.next())) + job_iterator_t jobs; + while ((j = jobs.next())) { int offset; @@ -409,8 +409,8 @@ static int find_process( const wchar_t *proc, } else { - wcstring result = to_string((long)j->pgid); - out.push_back(completion_t(result)); + wcstring result = to_string((long)j->pgid); + out.push_back(completion_t(result)); found = 1; } } @@ -421,8 +421,8 @@ static int find_process( const wchar_t *proc, return 1; } - jobs.reset(); - while ((j = jobs.next())) + jobs.reset(); + while ((j = jobs.next())) { process_t *p; if( j->command_is_empty() ) @@ -445,7 +445,7 @@ static int find_process( const wchar_t *proc, } else { - wcstring result = to_string(p->pid); + wcstring result = to_string(p->pid); out.push_back(completion_t(result)); found = 1; } @@ -470,8 +470,8 @@ static int find_process( const wchar_t *proc, pfile_name = (wchar_t *)malloc( sizeof(wchar_t)*64 ); wcscpy( pdir_name, L"/proc/" ); - wcstring nameStr; - while (wreaddir(dir, nameStr)) + wcstring nameStr; + while (wreaddir(dir, nameStr)) { const wchar_t *name = nameStr.c_str(); struct stat buf; @@ -560,8 +560,8 @@ static int find_process( const wchar_t *proc, } else { - if (name) - out.push_back(completion_t(name)); + if (name) + out.push_back(completion_t(name)); } } } @@ -591,8 +591,8 @@ static int expand_pid( const wcstring &instr, out.push_back(completion_t(instr)); return 1; } - - const wchar_t * const in = instr.c_str(); + + const wchar_t * const in = instr.c_str(); if( flags & ACCEPT_INCOMPLETE ) { @@ -625,7 +625,7 @@ static int expand_pid( const wcstring &instr, { if( proc_last_bg_pid > 0 ) { - const wcstring pid_str = to_string(proc_last_bg_pid); + const wcstring pid_str = to_string(proc_last_bg_pid); out.push_back( completion_t(pid_str)); } @@ -732,8 +732,8 @@ static int parse_slice( const wchar_t *in, wchar_t **end_ptr, std::vector wchar_t *end; int pos = 1; - - // debug( 0, L"parse_slice on '%ls'", in ); + + // debug( 0, L"parse_slice on '%ls'", in ); while( 1 ) { @@ -754,45 +754,45 @@ static int parse_slice( const wchar_t *in, wchar_t **end_ptr, std::vector { return 1; } - // debug( 0, L"Push idx %d", tmp ); + // debug( 0, L"Push idx %d", tmp ); - long i1 = tmp>-1 ? tmp : size+tmp+1; + long i1 = tmp>-1 ? tmp : size+tmp+1; pos = end-in; - while( in[pos]==INTERNAL_SEPARATOR ) - pos++; - if ( in[pos]==L'.' && in[pos+1]==L'.' ){ - pos+=2; - while( in[pos]==INTERNAL_SEPARATOR ) - pos++; - long tmp1 = wcstol( &in[pos], &end, 10 ); - if( ( errno ) || ( end == &in[pos] ) ) - { - return 1; - } - pos = end-in; + while( in[pos]==INTERNAL_SEPARATOR ) + pos++; + if ( in[pos]==L'.' && in[pos+1]==L'.' ){ + pos+=2; + while( in[pos]==INTERNAL_SEPARATOR ) + pos++; + long tmp1 = wcstol( &in[pos], &end, 10 ); + if( ( errno ) || ( end == &in[pos] ) ) + { + return 1; + } + pos = end-in; - // debug( 0, L"Push range %d %d", tmp, tmp1 ); - long i2 = tmp1>-1 ? tmp1 : size+tmp1+1; - // debug( 0, L"Push range idx %d %d", i1, i2 ); - short direction = i2-1 ? tmp1 : size+tmp1+1; + // debug( 0, L"Push range idx %d %d", i1, i2 ); + short direction = i2 static int expand_variables_internal( parser_t &parser, wchar_t * const in, std::vector &out, int last_idx ); static int expand_variables2( parser_t &parser, const wcstring &instr, std::vector &out, int last_idx ) { - wchar_t *in = wcsdup(instr.c_str()); - int result = expand_variables_internal(parser, in, out, last_idx); - free(in); - return result; + wchar_t *in = wcsdup(instr.c_str()); + int result = expand_variables_internal(parser, in, out, last_idx); + free(in); + return result; } static int expand_variables_internal( parser_t &parser, wchar_t * const in, std::vector &out, int last_idx ) @@ -827,10 +827,10 @@ static int expand_variables_internal( parser_t &parser, wchar_t * const in, std: int is_ok= 1; int empty=0; - wcstring var_tmp; - std::vector var_idx_list; - - // CHECK( out, 0 ); + wcstring var_tmp; + std::vector var_idx_list; + + // CHECK( out, 0 ); for( int i=last_idx; (i>=0) && is_ok && !empty; i-- ) { @@ -843,22 +843,22 @@ static int expand_variables_internal( parser_t &parser, wchar_t * const in, std: int is_single = (c==VARIABLE_EXPAND_SINGLE); stop_pos = start_pos; - + while( 1 ) { if( !(in[stop_pos ]) ) break; if( !( iswalnum( in[stop_pos] ) || - (wcschr(L"_", in[stop_pos])!= 0) ) ) + (wcschr(L"_", in[stop_pos])!= 0) ) ) break; - + stop_pos++; } - /* printf( "Stop for '%c'\n", in[stop_pos]);*/ - + /* printf( "Stop for '%c'\n", in[stop_pos]);*/ + var_len = stop_pos - start_pos; - + if( var_len == 0 ) { expand_variable_error( parser, in, stop_pos-1, -1 ); @@ -866,52 +866,52 @@ static int expand_variables_internal( parser_t &parser, wchar_t * const in, std: is_ok = 0; break; } - - var_tmp.append(in + start_pos, var_len); + + var_tmp.append(in + start_pos, var_len); env_var_t var_val = expand_var(var_tmp.c_str() ); - + if( ! var_val.missing() ) { int all_vars=1; - wcstring_list_t var_item_list; - + wcstring_list_t var_item_list; + if( is_ok ) { - tokenize_variable_array( var_val.c_str(), 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, var_item_list.size() ) ) - { - parser.error( SYNTAX_ERROR, - -1, - L"Invalid index value" ); - is_ok = 0; - break; - } - stop_pos = (slice_end-in); - } - + tokenize_variable_array( var_val.c_str(), 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, var_item_list.size() ) ) + { + parser.error( SYNTAX_ERROR, + -1, + L"Invalid index value" ); + is_ok = 0; + break; + } + stop_pos = (slice_end-in); + } + if( !all_vars ) { - wcstring_list_t string_values(var_idx_list.size()); - + wcstring_list_t string_values(var_idx_list.size()); + for( size_t j=0; j var_item_list.size() ) { parser.error( SYNTAX_ERROR, - -1, - ARRAY_BOUNDS_ERR ); + -1, + ARRAY_BOUNDS_ERR ); is_ok=0; var_idx_list.resize(j); break; @@ -920,27 +920,27 @@ static int expand_variables_internal( parser_t &parser, wchar_t * const in, std: { /* 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 ) ) ); - string_values.at(j) = var_item_list.at(tmp-1); + string_values.at(j) = var_item_list.at(tmp-1); } } - - // string_values is the new var_item_list - var_item_list.swap(string_values); + + // string_values is the new var_item_list + var_item_list.swap(string_values); } } - + if( is_ok ) { if( is_single ) { - in[i]=0; - wcstring res = in; - res.push_back(INTERNAL_SEPARATOR); - + in[i]=0; + wcstring res = in; + res.push_back(INTERNAL_SEPARATOR); + for( size_t j=0; j 0) - new_in.append(in, start_pos - 1); - - // at this point new_in.size() is start_pos - 1 - if(start_pos>1 && new_in[start_pos-2]!=VARIABLE_EXPAND) - { - new_in.push_back(INTERNAL_SEPARATOR); - } - new_in.append(next); - new_in.append(in + stop_pos); - is_ok &= expand_variables2( parser, new_in, out, i ); + wcstring new_in; + + if (start_pos > 0) + new_in.append(in, start_pos - 1); + + // at this point new_in.size() is start_pos - 1 + if(start_pos>1 && new_in[start_pos-2]!=VARIABLE_EXPAND) + { + new_in.push_back(INTERNAL_SEPARATOR); + } + new_in.append(next); + new_in.append(in + stop_pos); + is_ok &= expand_variables2( parser, new_in, out, i ); } } @@ -990,39 +990,39 @@ static int expand_variables_internal( parser_t &parser, wchar_t * const in, std: else { /* - Expand a non-existing variable - */ + Expand a non-existing variable + */ if( c == VARIABLE_EXPAND ) { /* - Regular expansion, i.e. expand this argument to nothing - */ + Regular expansion, i.e. expand this argument to nothing + */ empty = 1; } else { /* - Expansion to single argument. - */ + Expansion to single argument. + */ wcstring res; - in[i] = 0; - res.append(in); - res.append(in + stop_pos); - + in[i] = 0; + res.append(in); + res.append(in + stop_pos); + is_ok &= expand_variables2( parser, res, out, i ); return is_ok; } } - - + + } } - + if( !empty ) { out.push_back(completion_t(in)); } - + return is_ok; } @@ -1088,7 +1088,7 @@ static int expand_brackets(parser_t &parser, const wchar_t *in, int flags, std:: } else { - wcstring mod; + wcstring mod; if( last_sep ) { mod.append( in, bracket_begin-in+1 ); @@ -1097,8 +1097,8 @@ static int expand_brackets(parser_t &parser, const wchar_t *in, int flags, std:: } else { - mod.append(in); - mod.push_back(BRACKET_END); + mod.append(in); + mod.push_back(BRACKET_END); } return expand_brackets( parser, mod.c_str(), 1, out ); @@ -1165,45 +1165,45 @@ static int expand_cmdsubst( parser_t &parser, const wcstring &input, std::vector { wchar_t *paran_begin=0, *paran_end=0; int len1; - std::vector sub_res; + std::vector sub_res; size_t i, j; wchar_t *tail_begin = 0; - - const wchar_t * const in = input.c_str(); - + + const wchar_t * const in = input.c_str(); + int parse_ret; switch( parse_ret = parse_util_locate_cmdsubst(in, - ¶n_begin, - ¶n_end, - 0 ) ) + ¶n_begin, + ¶n_end, + 0 ) ) { case -1: parser.error( SYNTAX_ERROR, - -1, - L"Mismatched parans" ); + -1, + L"Mismatched parans" ); return 0; case 0: - outList.push_back(completion_t(input)); + outList.push_back(completion_t(input)); return 1; case 1: - + break; } - + len1 = (paran_begin-in); - - const wcstring subcmd(paran_begin + 1, paran_end-paran_begin - 1); - + + const wcstring subcmd(paran_begin + 1, paran_end-paran_begin - 1); + if( exec_subshell( subcmd, sub_res) == -1 ) { parser.error( CMDSUBST_ERROR, -1, L"Unknown error while evaulating command substitution" ); return 0; } - + tail_begin = paran_end + 1; if( *tail_begin == L'[' ) { - std::vector slice_idx; + std::vector slice_idx; wchar_t *slice_end; if( parse_slice( tail_begin, &slice_end, slice_idx, sub_res.size() ) ) @@ -1213,73 +1213,73 @@ static int expand_cmdsubst( parser_t &parser, const wcstring &input, std::vector } else { - std::vector sub_res2; + std::vector sub_res2; tail_begin = slice_end; for( i=0; i < slice_idx.size(); i++ ) { long idx = slice_idx.at(i); if( idx < 1 || (size_t)idx > sub_res.size() ) { - parser.error( SYNTAX_ERROR, - -1, - ARRAY_BOUNDS_ERR ); + parser.error( SYNTAX_ERROR, + -1, + ARRAY_BOUNDS_ERR ); return 0; } idx = idx-1; - sub_res2.push_back(sub_res.at(idx)); - // debug( 0, L"Pushing item '%ls' with index %d onto sliced result", al_get( sub_res, idx ), idx ); + sub_res2.push_back(sub_res.at(idx)); + // debug( 0, L"Pushing item '%ls' with index %d onto sliced result", al_get( sub_res, idx ), idx ); //sub_res[idx] = 0; // ?? } sub_res = sub_res2; } } - - + + /* - Recursively call ourselves to expand any remaining command - substitutions. The result of this recursive call using the tail - of the string is inserted into the tail_expand array list - */ - std::vector tail_expand; + Recursively call ourselves to expand any remaining command + substitutions. The result of this recursive call using the tail + of the string is inserted into the tail_expand array list + */ + std::vector tail_expand; expand_cmdsubst( parser, tail_begin, tail_expand ); - + /* - Combine the result of the current command substitution with the - result of the recursive tail expansion - */ - for( i=0; i &output, exp parser_t parser(PARSER_TYPE_ERRORS_ONLY, true /* show errors */); std::vector list1, list2; std::vector *in, *out; - + size_t i; int res = EXPAND_OK; - + if( (!(flags & ACCEPT_INCOMPLETE)) && expand_is_clean( input.c_str() ) ) { output.push_back(completion_t(input)); return EXPAND_OK; } - + if( EXPAND_SKIP_CMDSUBST & flags ) { wchar_t *begin, *end; if( parse_util_locate_cmdsubst( input.c_str(), - &begin, - &end, - 1 ) != 0 ) + &begin, + &end, + 1 ) != 0 ) { parser.error( CMDSUBST_ERROR, -1, L"Command substitutions not allowed" ); return EXPAND_ERROR; @@ -1446,183 +1446,183 @@ int expand_string( const wcstring &input, std::vector &output, exp } else { - int cmdsubst_ok = expand_cmdsubst(parser, input, list1); - if (! cmdsubst_ok) - return EXPAND_ERROR; + int cmdsubst_ok = expand_cmdsubst(parser, input, list1); + if (! cmdsubst_ok) + return EXPAND_ERROR; } - in = &list1; - out = &list2; - - for( i=0; i < in->size(); i++ ) - { - /* - We accept incomplete strings here, since complete uses - expand_string to expand incomplete strings from the - commandline. - */ - int unescape_flags = UNESCAPE_SPECIAL | UNESCAPE_INCOMPLETE; - wcstring next = expand_unescape_string( in->at(i).completion, unescape_flags ); - - if( EXPAND_SKIP_VARIABLES & flags ) - { - for (size_t i=0; i < next.size(); i++) { - if (next.at(i) == VARIABLE_EXPAND) { - next[i] = L'$'; - } - } - out->push_back(completion_t(next)); - } - else - { - if(!expand_variables2( parser, next, *out, next.size() - 1 )) - { - return EXPAND_ERROR; - } - } - } - - in->clear(); - - in = &list2; - out = &list1; - - for( i=0; i < in->size(); i++ ) - { - wcstring next = in->at(i).completion; - - if( !expand_brackets( parser, next.c_str(), flags, *out )) - { - return EXPAND_ERROR; - } - } - in->clear(); - - in = &list1; - out = &list2; - - for( i=0; i < in->size(); i++ ) - { - wcstring next = in->at(i).completion; - - expand_tilde_internal(next); - - - if( flags & ACCEPT_INCOMPLETE ) - { - if( next[0] == PROCESS_EXPAND ) - { - /* - If process expansion matches, we are not - interested in other completions, so we - short-circut and return - */ - if (! (flags & EXPAND_SKIP_PROCESS )) - expand_pid( next, flags, output ); - return EXPAND_OK; - } - else - { - out->push_back(completion_t(next)); - } - } - else - { - if( ! (flags & EXPAND_SKIP_PROCESS ) && ! expand_pid( next, flags, *out ) ) - { - return EXPAND_ERROR; - } - } - } - - in->clear(); - - in = &list2; - out = &list1; - - for( i=0; i < in->size(); i++ ) - { - wcstring next_str = in->at(i).completion; - int wc_res; - - remove_internal_separator2( next_str, EXPAND_SKIP_WILDCARDS & flags ); - const wchar_t *next = next_str.c_str(); - - if( ((flags & ACCEPT_INCOMPLETE) && (!(flags & EXPAND_SKIP_WILDCARDS))) || - wildcard_has( next, 1 ) ) - { - const wchar_t *start, *rest; - std::vector *list = out; - - if( next[0] == '/' ) - { - start = L"/"; - rest = &next[1]; - } - else - { - start = L""; - rest = next; - } - - if( flags & ACCEPT_INCOMPLETE ) - { - list = &output; - } - - wc_res = wildcard_expand_string(rest, start, flags, *list); - - if( !(flags & ACCEPT_INCOMPLETE) ) - { - - switch( wc_res ) - { - case 0: - { - if( !(flags & ACCEPT_INCOMPLETE) ) - { - if( res == EXPAND_OK ) - res = EXPAND_WILDCARD_NO_MATCH; - break; - } - } - - case 1: - { - size_t j; - res = EXPAND_WILDCARD_MATCH; - sort_completions( *out ); - - for( j=0; j< out->size(); j++ ) - { - output.push_back( out->at(j) ); - } - out->clear(); - break; - } - - case -1: - { - return EXPAND_ERROR; - } - - } - } - - } - else - { - if( flags & ACCEPT_INCOMPLETE) - { - } - else - { - output.push_back(completion_t(next)); - } - } - - } - + in = &list1; + out = &list2; + + for( i=0; i < in->size(); i++ ) + { + /* + We accept incomplete strings here, since complete uses + expand_string to expand incomplete strings from the + commandline. + */ + int unescape_flags = UNESCAPE_SPECIAL | UNESCAPE_INCOMPLETE; + wcstring next = expand_unescape_string( in->at(i).completion, unescape_flags ); + + if( EXPAND_SKIP_VARIABLES & flags ) + { + for (size_t i=0; i < next.size(); i++) { + if (next.at(i) == VARIABLE_EXPAND) { + next[i] = L'$'; + } + } + out->push_back(completion_t(next)); + } + else + { + if(!expand_variables2( parser, next, *out, next.size() - 1 )) + { + return EXPAND_ERROR; + } + } + } + + in->clear(); + + in = &list2; + out = &list1; + + for( i=0; i < in->size(); i++ ) + { + wcstring next = in->at(i).completion; + + if( !expand_brackets( parser, next.c_str(), flags, *out )) + { + return EXPAND_ERROR; + } + } + in->clear(); + + in = &list1; + out = &list2; + + for( i=0; i < in->size(); i++ ) + { + wcstring next = in->at(i).completion; + + expand_tilde_internal(next); + + + if( flags & ACCEPT_INCOMPLETE ) + { + if( next[0] == PROCESS_EXPAND ) + { + /* + If process expansion matches, we are not + interested in other completions, so we + short-circut and return + */ + if (! (flags & EXPAND_SKIP_PROCESS )) + expand_pid( next, flags, output ); + return EXPAND_OK; + } + else + { + out->push_back(completion_t(next)); + } + } + else + { + if( ! (flags & EXPAND_SKIP_PROCESS ) && ! expand_pid( next, flags, *out ) ) + { + return EXPAND_ERROR; + } + } + } + + in->clear(); + + in = &list2; + out = &list1; + + for( i=0; i < in->size(); i++ ) + { + wcstring next_str = in->at(i).completion; + int wc_res; + + remove_internal_separator2( next_str, EXPAND_SKIP_WILDCARDS & flags ); + const wchar_t *next = next_str.c_str(); + + if( ((flags & ACCEPT_INCOMPLETE) && (!(flags & EXPAND_SKIP_WILDCARDS))) || + wildcard_has( next, 1 ) ) + { + const wchar_t *start, *rest; + std::vector *list = out; + + if( next[0] == '/' ) + { + start = L"/"; + rest = &next[1]; + } + else + { + start = L""; + rest = next; + } + + if( flags & ACCEPT_INCOMPLETE ) + { + list = &output; + } + + wc_res = wildcard_expand_string(rest, start, flags, *list); + + if( !(flags & ACCEPT_INCOMPLETE) ) + { + + switch( wc_res ) + { + case 0: + { + if( !(flags & ACCEPT_INCOMPLETE) ) + { + if( res == EXPAND_OK ) + res = EXPAND_WILDCARD_NO_MATCH; + break; + } + } + + case 1: + { + size_t j; + res = EXPAND_WILDCARD_MATCH; + sort_completions( *out ); + + for( j=0; j< out->size(); j++ ) + { + output.push_back( out->at(j) ); + } + out->clear(); + break; + } + + case -1: + { + return EXPAND_ERROR; + } + + } + } + + } + else + { + if( flags & ACCEPT_INCOMPLETE) + { + } + else + { + output.push_back(completion_t(next)); + } + } + + } + return res; } @@ -1632,14 +1632,14 @@ bool expand_one(wcstring &string, expand_flags_t flags) { if( (!(flags & ACCEPT_INCOMPLETE)) && expand_is_clean( string.c_str() ) ) { - return true; + return true; } - if (expand_string(string, completions, flags)) { - if (completions.size() == 1) { - string = completions.at(0).completion; - result = true; - } - } + if (expand_string(string, completions, flags)) { + if (completions.size() == 1) { + string = completions.at(0).completion; + result = true; + } + } return result; }