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:
liljencrantz 2007-09-22 00:05:49 +10:00
parent 607e970659
commit d2d397d9eb
9 changed files with 308 additions and 29 deletions

View file

@ -220,6 +220,8 @@ static int builtin_commandline( wchar_t **argv )
int tokenize = 0; int tokenize = 0;
int cursor_mode = 0; int cursor_mode = 0;
int line_mode = 0;
int search_mode = 0;
wchar_t *begin, *end; wchar_t *begin, *end;
current_buffer = (wchar_t *)builtin_complete_get_temporary_buffer(); 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"cursor", no_argument, 0, 'C'
} }
, ,
{
L"line", no_argument, 0, 'L'
}
,
{
L"search-mode", no_argument, 0, 'S'
}
,
{ {
0, 0, 0, 0 0, 0, 0, 0
} }
@ -322,7 +332,7 @@ static int builtin_commandline( wchar_t **argv )
int opt = wgetopt_long( argc, int opt = wgetopt_long( argc,
argv, argv,
L"abijpctwforhI:C", L"abijpctwforhI:CLS",
long_options, long_options,
&opt_index ); &opt_index );
if( opt == -1 ) if( opt == -1 )
@ -391,6 +401,14 @@ static int builtin_commandline( wchar_t **argv )
cursor_mode = 1; cursor_mode = 1;
break; break;
case 'L':
line_mode = 1;
break;
case 'S':
search_mode = 1;
break;
case 'h': case 'h':
builtin_print_help( argv[0], sb_out ); builtin_print_help( argv[0], sb_out );
return 0; return 0;
@ -408,7 +426,7 @@ static int builtin_commandline( wchar_t **argv )
/* /*
Check for invalid switch combinations 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, sb_printf(sb_err,
BUILTIN_ERR_COMBO, BUILTIN_ERR_COMBO,
@ -457,7 +475,7 @@ static int builtin_commandline( wchar_t **argv )
/* /*
Check for invalid switch combinations 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, sb_append2( sb_err,
@ -468,7 +486,7 @@ static int builtin_commandline( wchar_t **argv )
return 1; 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, sb_printf( sb_err,
BUILTIN_ERR_COMBO, BUILTIN_ERR_COMBO,
@ -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 ) switch( buffer_part )
{ {

16
input.c
View file

@ -134,7 +134,9 @@ static const wchar_t *name_arr[] =
L"execute", L"execute",
L"beginning-of-buffer", L"beginning-of-buffer",
L"end-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_EXECUTE,
R_BEGINNING_OF_BUFFER, R_BEGINNING_OF_BUFFER,
R_END_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 terminfo sometimes specifies a different sequence than what
keypresses actually generate keypresses actually generate
*/ */
add_mapping( name[i], L"\x1b[A", L"Up", L"history-search-backward" ); add_mapping( name[i], L"\x1b[A", L"Up", L"up-or-search" );
add_mapping( name[i], L"\x1b[B", L"Down", L"history-search-forward" ); add_mapping( name[i], L"\x1b[B", L"Down", L"down-or-search" );
add_terminfo_mapping( name[i], (key_up), L"Up", L"history-search-backward" ); add_terminfo_mapping( name[i], (key_up), L"Up", L"up-or-search" );
add_terminfo_mapping( name[i], (key_down), L"Down", L"history-search-forward" ); 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[C", L"Right", L"forward-char" );
add_mapping( name[i], L"\x1b[D", L"Left", L"backward-char" ); add_mapping( name[i], L"\x1b[D", L"Left", L"backward-char" );

View file

@ -49,7 +49,9 @@ enum
R_EXECUTE, R_EXECUTE,
R_BEGINNING_OF_BUFFER, R_BEGINNING_OF_BUFFER,
R_END_OF_BUFFER, R_END_OF_BUFFER,
R_REPAINT R_REPAINT,
R_UP_LINE,
R_DOWN_LINE,
} }
; ;

View file

@ -135,6 +135,97 @@ int parse_util_lineno( const wchar_t *str, int len )
return res; 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, int parse_util_locate_cmdsubst( const wchar_t *in,
wchar_t **begin, wchar_t **begin,
wchar_t **end, wchar_t **end,

View file

@ -93,6 +93,23 @@ void parse_util_token_extent( const wchar_t *buff,
*/ */
int parse_util_lineno( const wchar_t *str, int len ); 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 Autoload the specified file, if it exists in the specified path. Do
not load it multiple times unless it's timestamp changes or not load it multiple times unless it's timestamp changes or

103
reader.c
View file

@ -258,6 +258,12 @@ typedef struct reader_data
Pointer to previous reader_data Pointer to previous reader_data
*/ */
struct reader_data *next; 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; reader_data_t;
@ -681,6 +687,7 @@ void repaint()
} }
/** /**
Remove the previous character in the character buffer and on the Remove the previous character in the character buffer and on the
screen using syntax highlighting, etc. screen using syntax highlighting, etc.
@ -2304,11 +2311,11 @@ wchar_t *reader_readline()
int comp_empty=1; int comp_empty=1;
int finished=0; int finished=0;
struct termios old_modes; struct termios old_modes;
int search_mode = 0;
check_size(); check_size();
sb_clear( &data->search_buff ); sb_clear( &data->search_buff );
data->buff[data->buff_len]='\0'; data->buff[data->buff_len]='\0';
data->search_mode = NO_SEARCH;
s_reset( &data->screen ); s_reset( &data->screen );
@ -2621,9 +2628,9 @@ wchar_t *reader_readline()
/* Escape was pressed */ /* Escape was pressed */
case L'\x1b': case L'\x1b':
{ {
if( search_mode ) if( data->search_mode )
{ {
search_mode= 0; data->search_mode= NO_SEARCH;
if( data->token_history_pos==-1 ) if( data->token_history_pos==-1 )
{ {
@ -2745,23 +2752,23 @@ wchar_t *reader_readline()
{ {
int reset = 0; int reset = 0;
if( search_mode == NO_SEARCH ) if( data->search_mode == NO_SEARCH )
{ {
reset = 1; reset = 1;
if( ( c == R_HISTORY_SEARCH_BACKWARD ) || 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 else
{ {
search_mode = TOKEN_SEARCH; data->search_mode = TOKEN_SEARCH;
} }
sb_append( &data->search_buff, data->buff ); sb_append( &data->search_buff, data->buff );
} }
switch( search_mode ) switch( data->search_mode )
{ {
case LINE_SEARCH: case LINE_SEARCH:
@ -2874,6 +2881,72 @@ wchar_t *reader_readline()
break; 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 */ /* Other, if a normal character, we add it to the command */
default: default:
{ {
@ -2900,9 +2973,10 @@ wchar_t *reader_readline()
if( (c != R_HISTORY_SEARCH_BACKWARD) && if( (c != R_HISTORY_SEARCH_BACKWARD) &&
(c != R_HISTORY_SEARCH_FORWARD) && (c != R_HISTORY_SEARCH_FORWARD) &&
(c != R_HISTORY_TOKEN_SEARCH_BACKWARD) && (c != R_HISTORY_TOKEN_SEARCH_BACKWARD) &&
(c != R_HISTORY_TOKEN_SEARCH_FORWARD) ) (c != R_HISTORY_TOKEN_SEARCH_FORWARD) &&
(c != R_NULL) )
{ {
search_mode = 0; data->search_mode = NO_SEARCH;
sb_clear( &data->search_buff ); sb_clear( &data->search_buff );
history_reset(); history_reset();
data->token_history_pos=-1; data->token_history_pos=-1;
@ -2929,6 +3003,17 @@ wchar_t *reader_readline()
return finished ? data->buff : 0; 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 Read non-interactively. Read input from stdin without displaying
the prompt, using syntax highlighting. This is used for reading the prompt, using syntax highlighting. This is used for reading

View file

@ -174,4 +174,12 @@ int reader_exit_forced();
*/ */
int reader_shell_test( wchar_t *b ); 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 #endif

View 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

View 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