mirror of
https://github.com/fish-shell/fish-shell
synced 2024-12-26 12:53:13 +00:00
Make up/down cursor move up or down when in multiline mode, except if already in search mode or at the top/bottom line. Since part of this is done in script-space, this involves adding some functionality to the commandline builtin.
darcs-hash:20070921140549-75c98-ba9e83f5e6fdecae5df8f83dd863794c6af9770c.gz
This commit is contained in:
parent
607e970659
commit
d2d397d9eb
9 changed files with 308 additions and 29 deletions
|
@ -220,6 +220,8 @@ static int builtin_commandline( wchar_t **argv )
|
|||
int tokenize = 0;
|
||||
|
||||
int cursor_mode = 0;
|
||||
int line_mode = 0;
|
||||
int search_mode = 0;
|
||||
wchar_t *begin, *end;
|
||||
|
||||
current_buffer = (wchar_t *)builtin_complete_get_temporary_buffer();
|
||||
|
@ -312,6 +314,14 @@ static int builtin_commandline( wchar_t **argv )
|
|||
L"cursor", no_argument, 0, 'C'
|
||||
}
|
||||
,
|
||||
{
|
||||
L"line", no_argument, 0, 'L'
|
||||
}
|
||||
,
|
||||
{
|
||||
L"search-mode", no_argument, 0, 'S'
|
||||
}
|
||||
,
|
||||
{
|
||||
0, 0, 0, 0
|
||||
}
|
||||
|
@ -322,7 +332,7 @@ static int builtin_commandline( wchar_t **argv )
|
|||
|
||||
int opt = wgetopt_long( argc,
|
||||
argv,
|
||||
L"abijpctwforhI:C",
|
||||
L"abijpctwforhI:CLS",
|
||||
long_options,
|
||||
&opt_index );
|
||||
if( opt == -1 )
|
||||
|
@ -391,6 +401,14 @@ static int builtin_commandline( wchar_t **argv )
|
|||
cursor_mode = 1;
|
||||
break;
|
||||
|
||||
case 'L':
|
||||
line_mode = 1;
|
||||
break;
|
||||
|
||||
case 'S':
|
||||
search_mode = 1;
|
||||
break;
|
||||
|
||||
case 'h':
|
||||
builtin_print_help( argv[0], sb_out );
|
||||
return 0;
|
||||
|
@ -408,7 +426,7 @@ static int builtin_commandline( wchar_t **argv )
|
|||
/*
|
||||
Check for invalid switch combinations
|
||||
*/
|
||||
if( buffer_part || cut_at_cursor || append_mode || tokenize || cursor_mode )
|
||||
if( buffer_part || cut_at_cursor || append_mode || tokenize || cursor_mode || line_mode || search_mode )
|
||||
{
|
||||
sb_printf(sb_err,
|
||||
BUILTIN_ERR_COMBO,
|
||||
|
@ -457,7 +475,7 @@ static int builtin_commandline( wchar_t **argv )
|
|||
/*
|
||||
Check for invalid switch combinations
|
||||
*/
|
||||
if( cursor_mode && (argc-woptind > 1) )
|
||||
if( (search_mode || line_mode || cursor_mode) && (argc-woptind > 1) )
|
||||
{
|
||||
|
||||
sb_append2( sb_err,
|
||||
|
@ -468,7 +486,7 @@ static int builtin_commandline( wchar_t **argv )
|
|||
return 1;
|
||||
}
|
||||
|
||||
if( (buffer_part || tokenize || cut_at_cursor) && cursor_mode )
|
||||
if( (buffer_part || tokenize || cut_at_cursor) && (cursor_mode || line_mode || search_mode) )
|
||||
{
|
||||
sb_printf( sb_err,
|
||||
BUILTIN_ERR_COMBO,
|
||||
|
@ -527,9 +545,9 @@ static int builtin_commandline( wchar_t **argv )
|
|||
if( *endptr || errno )
|
||||
{
|
||||
sb_printf( sb_err,
|
||||
BUILTIN_ERR_NOT_NUMBER,
|
||||
argv[0],
|
||||
argv[woptind] );
|
||||
BUILTIN_ERR_NOT_NUMBER,
|
||||
argv[0],
|
||||
argv[woptind] );
|
||||
builtin_print_help( argv[0], sb_err );
|
||||
}
|
||||
|
||||
|
@ -546,6 +564,20 @@ static int builtin_commandline( wchar_t **argv )
|
|||
|
||||
}
|
||||
|
||||
if( line_mode )
|
||||
{
|
||||
int pos = reader_get_cursor_pos();
|
||||
wchar_t *buff = reader_get_buffer();
|
||||
sb_printf( sb_out, L"%d\n", parse_util_lineno( buff, pos ) );
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
if( search_mode )
|
||||
{
|
||||
return !reader_search_mode();
|
||||
}
|
||||
|
||||
|
||||
switch( buffer_part )
|
||||
{
|
||||
|
|
16
input.c
16
input.c
|
@ -134,7 +134,9 @@ static const wchar_t *name_arr[] =
|
|||
L"execute",
|
||||
L"beginning-of-buffer",
|
||||
L"end-of-buffer",
|
||||
L"repaint"
|
||||
L"repaint",
|
||||
L"up-line",
|
||||
L"down-line"
|
||||
}
|
||||
;
|
||||
|
||||
|
@ -215,7 +217,9 @@ static const wchar_t code_arr[] =
|
|||
R_EXECUTE,
|
||||
R_BEGINNING_OF_BUFFER,
|
||||
R_END_OF_BUFFER,
|
||||
R_REPAINT
|
||||
R_REPAINT,
|
||||
R_UP_LINE,
|
||||
R_DOWN_LINE
|
||||
}
|
||||
;
|
||||
|
||||
|
@ -1242,10 +1246,10 @@ static void add_common_bindings()
|
|||
terminfo sometimes specifies a different sequence than what
|
||||
keypresses actually generate
|
||||
*/
|
||||
add_mapping( name[i], L"\x1b[A", L"Up", L"history-search-backward" );
|
||||
add_mapping( name[i], L"\x1b[B", L"Down", L"history-search-forward" );
|
||||
add_terminfo_mapping( name[i], (key_up), L"Up", L"history-search-backward" );
|
||||
add_terminfo_mapping( name[i], (key_down), L"Down", L"history-search-forward" );
|
||||
add_mapping( name[i], L"\x1b[A", L"Up", L"up-or-search" );
|
||||
add_mapping( name[i], L"\x1b[B", L"Down", L"down-or-search" );
|
||||
add_terminfo_mapping( name[i], (key_up), L"Up", L"up-or-search" );
|
||||
add_terminfo_mapping( name[i], (key_down), L"Down", L"down-or-search" );
|
||||
|
||||
add_mapping( name[i], L"\x1b[C", L"Right", L"forward-char" );
|
||||
add_mapping( name[i], L"\x1b[D", L"Left", L"backward-char" );
|
||||
|
|
4
input.h
4
input.h
|
@ -49,7 +49,9 @@ enum
|
|||
R_EXECUTE,
|
||||
R_BEGINNING_OF_BUFFER,
|
||||
R_END_OF_BUFFER,
|
||||
R_REPAINT
|
||||
R_REPAINT,
|
||||
R_UP_LINE,
|
||||
R_DOWN_LINE,
|
||||
}
|
||||
;
|
||||
|
||||
|
|
91
parse_util.c
91
parse_util.c
|
@ -135,6 +135,97 @@ int parse_util_lineno( const wchar_t *str, int len )
|
|||
return res;
|
||||
}
|
||||
|
||||
|
||||
int parse_util_get_line_from_offset( wchar_t *buff, int pos )
|
||||
{
|
||||
// return parse_util_lineno( buff, pos );
|
||||
|
||||
int i;
|
||||
int count = 0;
|
||||
if( pos < 0 )
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
for( i=0; i<pos; i++ )
|
||||
{
|
||||
if( !buff[i] )
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
if( buff[i] == L'\n' )
|
||||
{
|
||||
count++;
|
||||
}
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
|
||||
int parse_util_get_offset_from_line( wchar_t *buff, int line )
|
||||
{
|
||||
int i;
|
||||
int count = 0;
|
||||
|
||||
if( line < 0 )
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
if( line == 0 )
|
||||
return 0;
|
||||
|
||||
for( i=0;; i++ )
|
||||
{
|
||||
if( !buff[i] )
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
if( buff[i] == L'\n' )
|
||||
{
|
||||
count++;
|
||||
if( count == line )
|
||||
{
|
||||
return i+1;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int parse_util_get_offset( wchar_t *buff, int line, int line_offset )
|
||||
{
|
||||
int off = parse_util_get_offset_from_line( buff, line );
|
||||
int off2 = parse_util_get_offset_from_line( buff, line+1 );
|
||||
int line_offset2 = line_offset;
|
||||
|
||||
if( off < 0 )
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
if( off2 < 0 )
|
||||
{
|
||||
off2 = wcslen( buff );
|
||||
}
|
||||
|
||||
if( line_offset2 < 0 )
|
||||
{
|
||||
line_offset2 = 0;
|
||||
}
|
||||
|
||||
if( line_offset2 >= off2-off-1 )
|
||||
{
|
||||
line_offset2 = off2-off-1;
|
||||
}
|
||||
|
||||
return off + line_offset2;
|
||||
|
||||
}
|
||||
|
||||
|
||||
int parse_util_locate_cmdsubst( const wchar_t *in,
|
||||
wchar_t **begin,
|
||||
wchar_t **end,
|
||||
|
|
17
parse_util.h
17
parse_util.h
|
@ -93,6 +93,23 @@ void parse_util_token_extent( const wchar_t *buff,
|
|||
*/
|
||||
int parse_util_lineno( const wchar_t *str, int len );
|
||||
|
||||
/**
|
||||
Calculate the line number of the specified cursor position
|
||||
*/
|
||||
int parse_util_get_line_from_offset( wchar_t *buff, int pos );
|
||||
|
||||
/**
|
||||
Get the offset of the first character on the specified line
|
||||
*/
|
||||
int parse_util_get_offset_from_line( wchar_t *buff, int line );
|
||||
|
||||
|
||||
/**
|
||||
Return the total offset of the buffer for the cursor position nearest to the specified poition
|
||||
*/
|
||||
int parse_util_get_offset( wchar_t *buff, int line, int line_offset );
|
||||
|
||||
|
||||
/**
|
||||
Autoload the specified file, if it exists in the specified path. Do
|
||||
not load it multiple times unless it's timestamp changes or
|
||||
|
|
109
reader.c
109
reader.c
|
@ -258,6 +258,12 @@ typedef struct reader_data
|
|||
Pointer to previous reader_data
|
||||
*/
|
||||
struct reader_data *next;
|
||||
|
||||
/**
|
||||
This variable keeps state on if we are in search mode, and
|
||||
if yes, what mode
|
||||
*/
|
||||
int search_mode;
|
||||
}
|
||||
reader_data_t;
|
||||
|
||||
|
@ -681,6 +687,7 @@ void repaint()
|
|||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Remove the previous character in the character buffer and on the
|
||||
screen using syntax highlighting, etc.
|
||||
|
@ -2304,11 +2311,11 @@ wchar_t *reader_readline()
|
|||
int comp_empty=1;
|
||||
int finished=0;
|
||||
struct termios old_modes;
|
||||
int search_mode = 0;
|
||||
|
||||
check_size();
|
||||
sb_clear( &data->search_buff );
|
||||
data->buff[data->buff_len]='\0';
|
||||
data->search_mode = NO_SEARCH;
|
||||
|
||||
s_reset( &data->screen );
|
||||
|
||||
|
@ -2621,9 +2628,9 @@ wchar_t *reader_readline()
|
|||
/* Escape was pressed */
|
||||
case L'\x1b':
|
||||
{
|
||||
if( search_mode )
|
||||
if( data->search_mode )
|
||||
{
|
||||
search_mode= 0;
|
||||
data->search_mode= NO_SEARCH;
|
||||
|
||||
if( data->token_history_pos==-1 )
|
||||
{
|
||||
|
@ -2745,23 +2752,23 @@ wchar_t *reader_readline()
|
|||
{
|
||||
int reset = 0;
|
||||
|
||||
if( search_mode == NO_SEARCH )
|
||||
if( data->search_mode == NO_SEARCH )
|
||||
{
|
||||
reset = 1;
|
||||
if( ( c == R_HISTORY_SEARCH_BACKWARD ) ||
|
||||
( c == R_HISTORY_SEARCH_FORWARD ) )
|
||||
( c == R_HISTORY_SEARCH_FORWARD ) )
|
||||
{
|
||||
search_mode = LINE_SEARCH;
|
||||
data->search_mode = LINE_SEARCH;
|
||||
}
|
||||
else
|
||||
{
|
||||
search_mode = TOKEN_SEARCH;
|
||||
data->search_mode = TOKEN_SEARCH;
|
||||
}
|
||||
|
||||
sb_append( &data->search_buff, data->buff );
|
||||
}
|
||||
|
||||
switch( search_mode )
|
||||
switch( data->search_mode )
|
||||
{
|
||||
|
||||
case LINE_SEARCH:
|
||||
|
@ -2874,6 +2881,72 @@ wchar_t *reader_readline()
|
|||
break;
|
||||
}
|
||||
|
||||
case R_UP_LINE:
|
||||
case R_DOWN_LINE:
|
||||
{
|
||||
int line = parse_util_get_line_from_offset( data->buff,
|
||||
data->buff_pos );
|
||||
int new_line;
|
||||
|
||||
if( c == R_UP_LINE )
|
||||
new_line = line-1;
|
||||
else
|
||||
new_line = line+1;
|
||||
|
||||
int line_count = parse_util_lineno( data->buff, data->buff_len )-1;
|
||||
|
||||
if( new_line >= 0 && new_line <= line_count)
|
||||
{
|
||||
int base_pos;
|
||||
|
||||
int indent_old;
|
||||
int indent_new;
|
||||
int old_line_offset;
|
||||
int new_total_offset;
|
||||
|
||||
// debug( 0, L"Move up one line to %d", new_line );
|
||||
|
||||
base_pos = parse_util_get_offset_from_line( data->buff,
|
||||
new_line );
|
||||
/* debug( 0, L"Old cursor offset is %d, new base offset is %d",
|
||||
data->buff_pos,
|
||||
base_pos );
|
||||
*/
|
||||
|
||||
if( data->buff_pos ==(data->buff_len) )
|
||||
{
|
||||
if( data->buff_pos == 0 )
|
||||
{
|
||||
indent_old = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
indent_old = data->indent[data->buff_pos-1];
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if( data->buff[data->buff_pos] == L'\n' )
|
||||
indent_old = data->indent[data->buff_pos-1];
|
||||
else
|
||||
indent_old = data->indent[data->buff_pos];
|
||||
}
|
||||
|
||||
indent_new = data->indent[base_pos];
|
||||
// debug( 0, L"Old indent %d, new indent %d", indent_old, indent_new );
|
||||
|
||||
old_line_offset = data->buff_pos - parse_util_get_offset_from_line( data->buff,
|
||||
line );
|
||||
new_total_offset = parse_util_get_offset( data->buff, new_line, old_line_offset - 4*(indent_new-indent_old));
|
||||
data->buff_pos = new_total_offset;
|
||||
repaint();
|
||||
}
|
||||
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
/* Other, if a normal character, we add it to the command */
|
||||
default:
|
||||
{
|
||||
|
@ -2898,11 +2971,12 @@ wchar_t *reader_readline()
|
|||
}
|
||||
|
||||
if( (c != R_HISTORY_SEARCH_BACKWARD) &&
|
||||
(c != R_HISTORY_SEARCH_FORWARD) &&
|
||||
(c != R_HISTORY_TOKEN_SEARCH_BACKWARD) &&
|
||||
(c != R_HISTORY_TOKEN_SEARCH_FORWARD) )
|
||||
(c != R_HISTORY_SEARCH_FORWARD) &&
|
||||
(c != R_HISTORY_TOKEN_SEARCH_BACKWARD) &&
|
||||
(c != R_HISTORY_TOKEN_SEARCH_FORWARD) &&
|
||||
(c != R_NULL) )
|
||||
{
|
||||
search_mode = 0;
|
||||
data->search_mode = NO_SEARCH;
|
||||
sb_clear( &data->search_buff );
|
||||
history_reset();
|
||||
data->token_history_pos=-1;
|
||||
|
@ -2929,6 +3003,17 @@ wchar_t *reader_readline()
|
|||
return finished ? data->buff : 0;
|
||||
}
|
||||
|
||||
int reader_search_mode()
|
||||
{
|
||||
if( !data )
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
return !!data->search_mode;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Read non-interactively. Read input from stdin without displaying
|
||||
the prompt, using syntax highlighting. This is used for reading
|
||||
|
|
8
reader.h
8
reader.h
|
@ -174,4 +174,12 @@ int reader_exit_forced();
|
|||
*/
|
||||
int reader_shell_test( wchar_t *b );
|
||||
|
||||
/**
|
||||
Test whether the interactive reader is in search mode.
|
||||
|
||||
\return o if not in search mode, 1 if in search mode and -1 if not in interactive mode
|
||||
*/
|
||||
int reader_search_mode();
|
||||
|
||||
|
||||
#endif
|
||||
|
|
23
share/functions/down-or-search.fish
Normal file
23
share/functions/down-or-search.fish
Normal file
|
@ -0,0 +1,23 @@
|
|||
function down-or-search
|
||||
# If we are already in search mode, continue
|
||||
if commandline --search-mode
|
||||
commandline -f history-search-forward
|
||||
return
|
||||
end
|
||||
|
||||
# We are not in search mode.
|
||||
# If we are on the bottom line, start search mode,
|
||||
# otherwise move down
|
||||
set lineno (commandline -L)
|
||||
set line_count (commandline|wc -l)
|
||||
|
||||
echo on line $lineno of $line_count >&2
|
||||
|
||||
switch $lineno
|
||||
case $line_count
|
||||
commandline -f history-search-forward
|
||||
|
||||
case '*'
|
||||
commandline -f down-line
|
||||
end
|
||||
end
|
17
share/functions/up-or-search.fish
Normal file
17
share/functions/up-or-search.fish
Normal file
|
@ -0,0 +1,17 @@
|
|||
function up-or-search
|
||||
# If we are already in search mode, continue
|
||||
if commandline --search-mode
|
||||
commandline -f history-search-backward
|
||||
return
|
||||
end
|
||||
|
||||
set lineno (commandline -L)
|
||||
|
||||
switch $lineno
|
||||
case 1
|
||||
commandline -f history-search-backward
|
||||
|
||||
case '*'
|
||||
commandline -f up-line
|
||||
end
|
||||
end
|
Loading…
Reference in a new issue