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 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
View file

@ -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" );

View file

@ -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,
}
;

View file

@ -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,

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 );
/**
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
View file

@ -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

View file

@ -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

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