mirror of
https://github.com/fish-shell/fish-shell
synced 2024-12-26 12:53:13 +00:00
Add variable expand ranges
echo $PATH[-1..1] #now works Add tests for ranges
This commit is contained in:
parent
c0e996acf8
commit
5f05756e65
6 changed files with 61 additions and 35 deletions
64
expand.cpp
64
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
|
Parse an array slicing specification
|
||||||
*/
|
*/
|
||||||
static int parse_slice( const wchar_t *in, wchar_t **end_ptr, std::vector<long> &idx, int size=-1 )
|
static int parse_slice( const wchar_t *in, wchar_t **end_ptr, std::vector<long> &idx, int size )
|
||||||
{
|
{
|
||||||
wchar_t *end;
|
wchar_t *end;
|
||||||
|
|
||||||
|
@ -757,6 +757,7 @@ static int parse_slice( const wchar_t *in, wchar_t **end_ptr, std::vector<long>
|
||||||
}
|
}
|
||||||
// debug( 0, L"Push idx %d", tmp );
|
// debug( 0, L"Push idx %d", tmp );
|
||||||
|
|
||||||
|
long i1 = tmp>-1 ? tmp : size+tmp+1;
|
||||||
pos = end-in;
|
pos = end-in;
|
||||||
if ( in[pos]==L'.' && in[pos+1]==L'.' ){
|
if ( in[pos]==L'.' && in[pos+1]==L'.' ){
|
||||||
pos+=2;
|
pos+=2;
|
||||||
|
@ -767,23 +768,19 @@ static int parse_slice( const wchar_t *in, wchar_t **end_ptr, std::vector<long>
|
||||||
}
|
}
|
||||||
pos = end-in;
|
pos = end-in;
|
||||||
|
|
||||||
if ( size>-1 ) {
|
// debug( 0, L"Push range %d %d", tmp, tmp1 );
|
||||||
// debug( 0, L"Push range idx %d %d", tmp, tmp1 );
|
long i2 = tmp1>-1 ? tmp1 : size+tmp1+1;
|
||||||
long i1 = tmp>-1 ? tmp : size+tmp+1;
|
// debug( 0, L"Push range idx %d %d", i1, i2 );
|
||||||
long i2 = tmp1>-1 ? tmp1 : size+tmp1+1;
|
short direction = i2<i1 ? -1 : 1 ;
|
||||||
// debug( 0, L"Push range idx %d %d", i1, i2 );
|
for (long jjj = i1; jjj*direction <= i2*direction; jjj+=direction) {
|
||||||
short direction = i2<i1 ? -1 : 1 ;
|
// debug(0, L"Expand range [subst]: %i\n", jjj);
|
||||||
for (long jjj = i1; jjj*direction <= i2*direction; jjj+=direction) {
|
idx.push_back( jjj );
|
||||||
// debug(0, L"Expand range [subst]: %i\n", jjj);
|
|
||||||
idx.push_back( jjj );
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
// debug( 0, L"Push idx %d", tmp );
|
// debug( 0, L"Push idx %d", tmp );
|
||||||
idx.push_back(tmp);
|
idx.push_back( i1 );
|
||||||
// idx.push_back(tmp2);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if( end_ptr )
|
if( end_ptr )
|
||||||
|
@ -875,25 +872,26 @@ static int expand_variables_internal( parser_t &parser, wchar_t * const in, std:
|
||||||
int all_vars=1;
|
int all_vars=1;
|
||||||
wcstring_list_t var_item_list;
|
wcstring_list_t 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.error( SYNTAX_ERROR,
|
|
||||||
-1,
|
|
||||||
L"Invalid index value" );
|
|
||||||
is_ok = 0;
|
|
||||||
}
|
|
||||||
stop_pos = (slice_end-in);
|
|
||||||
}
|
|
||||||
|
|
||||||
if( is_ok )
|
if( is_ok )
|
||||||
{
|
{
|
||||||
tokenize_variable_array( var_val.c_str(), var_item_list );
|
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 )
|
if( !all_vars )
|
||||||
{
|
{
|
||||||
wcstring_list_t string_values(var_idx_list.size());
|
wcstring_list_t string_values(var_idx_list.size());
|
||||||
|
@ -901,11 +899,6 @@ static int expand_variables_internal( parser_t &parser, wchar_t * const in, std:
|
||||||
for( size_t j=0; j<var_idx_list.size(); j++)
|
for( size_t j=0; j<var_idx_list.size(); j++)
|
||||||
{
|
{
|
||||||
long tmp = var_idx_list.at(j);
|
long tmp = var_idx_list.at(j);
|
||||||
if( tmp < 0 )
|
|
||||||
{
|
|
||||||
tmp = ((long)var_item_list.size())+tmp+1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Check that we are within array
|
Check that we are within array
|
||||||
bounds. If not, truncate the list to
|
bounds. If not, truncate the list to
|
||||||
|
@ -1224,10 +1217,11 @@ static int expand_cmdsubst( parser_t &parser, const wcstring &input, std::vector
|
||||||
long idx = slice_idx.at(i);
|
long idx = slice_idx.at(i);
|
||||||
if( idx < 1 || (size_t)idx > sub_res.size() )
|
if( idx < 1 || (size_t)idx > sub_res.size() )
|
||||||
{
|
{
|
||||||
parser.error( SYNTAX_ERROR, -1, L"Invalid index value" );
|
parser.error( SYNTAX_ERROR,
|
||||||
|
-1,
|
||||||
|
ARRAY_BOUNDS_ERR );
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
idx = idx-1;
|
idx = idx-1;
|
||||||
|
|
||||||
sub_res2.push_back(sub_res.at(idx));
|
sub_res2.push_back(sub_res.at(idx));
|
||||||
|
|
0
tests/test8.err
Normal file
0
tests/test8.err
Normal file
21
tests/test8.in
Normal file
21
tests/test8.in
Normal file
|
@ -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]
|
||||||
|
|
9
tests/test8.out
Normal file
9
tests/test8.out
Normal file
|
@ -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
|
1
tests/test8.status
Normal file
1
tests/test8.status
Normal file
|
@ -0,0 +1 @@
|
||||||
|
0
|
|
@ -6,3 +6,4 @@ File test4.in tested ok
|
||||||
File test5.in tested ok
|
File test5.in tested ok
|
||||||
File test6.in tested ok
|
File test6.in tested ok
|
||||||
File test7.in tested ok
|
File test7.in tested ok
|
||||||
|
File test8.in tested ok
|
||||||
|
|
Loading…
Reference in a new issue