lineedit: use read_key to recognize ESC sequence.
This fixes several vi mode bugs and prepares for further fixes. function old new delta read_line_input 3287 5511 +2224 remember_in_history - 499 +499 lineedit_read_key - 70 +70 read_key 321 332 +11 input_tab 2823 - -2823 ------------------------------------------------------------------------------ (add/remove: 2/1 grow/shrink: 2/0 up/down: 2804/-2823) Total: -19 bytes Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
This commit is contained in:
parent
1b0a93edb9
commit
c15f40c3e7
@ -1198,23 +1198,23 @@ unsigned long long bb_makedev(unsigned int major, unsigned int minor) FAST_FUNC;
|
|||||||
|
|
||||||
#if ENABLE_FEATURE_EDITING
|
#if ENABLE_FEATURE_EDITING
|
||||||
/* It's NOT just ENABLEd or disabled. It's a number: */
|
/* It's NOT just ENABLEd or disabled. It's a number: */
|
||||||
#ifdef CONFIG_FEATURE_EDITING_HISTORY
|
# ifdef CONFIG_FEATURE_EDITING_HISTORY
|
||||||
# define MAX_HISTORY (CONFIG_FEATURE_EDITING_HISTORY + 0)
|
# define MAX_HISTORY (CONFIG_FEATURE_EDITING_HISTORY + 0)
|
||||||
#else
|
# else
|
||||||
# define MAX_HISTORY 0
|
# define MAX_HISTORY 0
|
||||||
#endif
|
# endif
|
||||||
typedef struct line_input_t {
|
typedef struct line_input_t {
|
||||||
int flags;
|
int flags;
|
||||||
const char *path_lookup;
|
const char *path_lookup;
|
||||||
#if MAX_HISTORY
|
# if MAX_HISTORY
|
||||||
int cnt_history;
|
int cnt_history;
|
||||||
int cur_history;
|
int cur_history;
|
||||||
#if ENABLE_FEATURE_EDITING_SAVEHISTORY
|
# if ENABLE_FEATURE_EDITING_SAVEHISTORY
|
||||||
unsigned cnt_history_in_file;
|
unsigned cnt_history_in_file;
|
||||||
const char *hist_file;
|
const char *hist_file;
|
||||||
#endif
|
# endif
|
||||||
char *history[MAX_HISTORY + 1];
|
char *history[MAX_HISTORY + 1];
|
||||||
#endif
|
# endif
|
||||||
} line_input_t;
|
} line_input_t;
|
||||||
enum {
|
enum {
|
||||||
DO_HISTORY = 1 * (MAX_HISTORY > 0),
|
DO_HISTORY = 1 * (MAX_HISTORY > 0),
|
||||||
@ -1241,12 +1241,12 @@ int read_line_input(const char* prompt, char* command, int maxsize) FAST_FUNC;
|
|||||||
|
|
||||||
|
|
||||||
#ifndef COMM_LEN
|
#ifndef COMM_LEN
|
||||||
#ifdef TASK_COMM_LEN
|
# ifdef TASK_COMM_LEN
|
||||||
enum { COMM_LEN = TASK_COMM_LEN };
|
enum { COMM_LEN = TASK_COMM_LEN };
|
||||||
#else
|
# else
|
||||||
/* synchronize with sizeof(task_struct.comm) in /usr/include/linux/sched.h */
|
/* synchronize with sizeof(task_struct.comm) in /usr/include/linux/sched.h */
|
||||||
enum { COMM_LEN = 16 };
|
enum { COMM_LEN = 16 };
|
||||||
#endif
|
# endif
|
||||||
#endif
|
#endif
|
||||||
typedef struct procps_status_t {
|
typedef struct procps_status_t {
|
||||||
DIR *dir;
|
DIR *dir;
|
||||||
|
275
libbb/lineedit.c
275
libbb/lineedit.c
@ -1430,6 +1430,22 @@ static void win_changed(int nsig)
|
|||||||
signal(SIGWINCH, win_changed); /* rearm ourself */
|
signal(SIGWINCH, win_changed); /* rearm ourself */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int lineedit_read_key(smalluint *read_key_bufsize, char *read_key_buffer)
|
||||||
|
{
|
||||||
|
int ic;
|
||||||
|
struct pollfd pfd;
|
||||||
|
pfd.fd = STDIN_FILENO;
|
||||||
|
pfd.events = POLLIN;
|
||||||
|
do {
|
||||||
|
/* Wait for input. Can't just call read_key, it will return
|
||||||
|
* at once if stdin is in non-blocking mode. */
|
||||||
|
safe_poll(&pfd, 1, -1);
|
||||||
|
/* note: read_key sets errno to 0 on success: */
|
||||||
|
ic = read_key(STDIN_FILENO, read_key_bufsize, read_key_buffer);
|
||||||
|
} while (errno == EAGAIN);
|
||||||
|
return ic;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* The emacs and vi modes share much of the code in the big
|
* The emacs and vi modes share much of the code in the big
|
||||||
* command loop. Commands entered when in vi's command mode (aka
|
* command loop. Commands entered when in vi's command mode (aka
|
||||||
@ -1438,7 +1454,7 @@ static void win_changed(int nsig)
|
|||||||
* big switch a bit, but keeps all the code in one place.
|
* big switch a bit, but keeps all the code in one place.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#define vbit 0x100
|
#define VI_CMDMODE_BIT 0x100
|
||||||
|
|
||||||
/* leave out the "vi-mode"-only case labels if vi editing isn't
|
/* leave out the "vi-mode"-only case labels if vi editing isn't
|
||||||
* configured. */
|
* configured. */
|
||||||
@ -1459,15 +1475,15 @@ int FAST_FUNC read_line_input(const char *prompt, char *command, int maxsize, li
|
|||||||
#if ENABLE_FEATURE_TAB_COMPLETION
|
#if ENABLE_FEATURE_TAB_COMPLETION
|
||||||
smallint lastWasTab = FALSE;
|
smallint lastWasTab = FALSE;
|
||||||
#endif
|
#endif
|
||||||
unsigned ic;
|
int ic;
|
||||||
unsigned char c;
|
|
||||||
smallint break_out = 0;
|
smallint break_out = 0;
|
||||||
#if ENABLE_FEATURE_EDITING_VI
|
#if ENABLE_FEATURE_EDITING_VI
|
||||||
smallint vi_cmdmode = 0;
|
smallint vi_cmdmode = 0;
|
||||||
smalluint prevc;
|
|
||||||
#endif
|
#endif
|
||||||
struct termios initial_settings;
|
struct termios initial_settings;
|
||||||
struct termios new_settings;
|
struct termios new_settings;
|
||||||
|
smalluint read_key_bufsize;
|
||||||
|
char read_key_buffer[KEYCODE_BUFFER_SIZE];
|
||||||
|
|
||||||
INIT_S();
|
INIT_S();
|
||||||
|
|
||||||
@ -1545,42 +1561,40 @@ int FAST_FUNC read_line_input(const char *prompt, char *command, int maxsize, li
|
|||||||
|
|
||||||
while (1) {
|
while (1) {
|
||||||
fflush(NULL);
|
fflush(NULL);
|
||||||
|
ic = lineedit_read_key(&read_key_bufsize, read_key_buffer);
|
||||||
if (nonblock_safe_read(STDIN_FILENO, &c, 1) < 1) {
|
|
||||||
/* if we can't read input then exit */
|
|
||||||
goto prepare_to_die;
|
|
||||||
}
|
|
||||||
|
|
||||||
ic = c;
|
|
||||||
|
|
||||||
#if ENABLE_FEATURE_EDITING_VI
|
#if ENABLE_FEATURE_EDITING_VI
|
||||||
newdelflag = 1;
|
newdelflag = 1;
|
||||||
if (vi_cmdmode)
|
if (vi_cmdmode) {
|
||||||
ic |= vbit;
|
/* btw, since KEYCODE_xxx are all < 0, this doesn't
|
||||||
|
* change ic if it contains one of them: */
|
||||||
|
ic |= VI_CMDMODE_BIT;
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
switch (ic) {
|
switch (ic) {
|
||||||
case '\n':
|
case '\n':
|
||||||
case '\r':
|
case '\r':
|
||||||
vi_case('\n'|vbit:)
|
vi_case('\n'|VI_CMDMODE_BIT:)
|
||||||
vi_case('\r'|vbit:)
|
vi_case('\r'|VI_CMDMODE_BIT:)
|
||||||
/* Enter */
|
/* Enter */
|
||||||
goto_new_line();
|
goto_new_line();
|
||||||
break_out = 1;
|
break_out = 1;
|
||||||
break;
|
break;
|
||||||
case CTRL('A'):
|
case CTRL('A'):
|
||||||
vi_case('0'|vbit:)
|
vi_case('0'|VI_CMDMODE_BIT:)
|
||||||
/* Control-a -- Beginning of line */
|
/* Control-a -- Beginning of line */
|
||||||
input_backward(cursor);
|
input_backward(cursor);
|
||||||
break;
|
break;
|
||||||
case CTRL('B'):
|
case CTRL('B'):
|
||||||
vi_case('h'|vbit:)
|
vi_case('h'|VI_CMDMODE_BIT:)
|
||||||
vi_case('\b'|vbit:)
|
vi_case('\b'|VI_CMDMODE_BIT:)
|
||||||
vi_case('\x7f'|vbit:) /* DEL */
|
vi_case('\x7f'|VI_CMDMODE_BIT:) /* DEL */
|
||||||
/* Control-b -- Move back one character */
|
/* Control-b -- Move back one character */
|
||||||
input_backward(1);
|
input_backward(1);
|
||||||
break;
|
break;
|
||||||
case CTRL('C'):
|
case CTRL('C'):
|
||||||
vi_case(CTRL('C')|vbit:)
|
vi_case(CTRL('C')|VI_CMDMODE_BIT:)
|
||||||
/* Control-c -- stop gathering input */
|
/* Control-c -- stop gathering input */
|
||||||
goto_new_line();
|
goto_new_line();
|
||||||
command_len = 0;
|
command_len = 0;
|
||||||
@ -1598,31 +1612,27 @@ int FAST_FUNC read_line_input(const char *prompt, char *command, int maxsize, li
|
|||||||
}
|
}
|
||||||
input_delete(0);
|
input_delete(0);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case CTRL('E'):
|
case CTRL('E'):
|
||||||
vi_case('$'|vbit:)
|
vi_case('$'|VI_CMDMODE_BIT:)
|
||||||
/* Control-e -- End of line */
|
/* Control-e -- End of line */
|
||||||
input_end();
|
input_end();
|
||||||
break;
|
break;
|
||||||
case CTRL('F'):
|
case CTRL('F'):
|
||||||
vi_case('l'|vbit:)
|
vi_case('l'|VI_CMDMODE_BIT:)
|
||||||
vi_case(' '|vbit:)
|
vi_case(' '|VI_CMDMODE_BIT:)
|
||||||
/* Control-f -- Move forward one character */
|
/* Control-f -- Move forward one character */
|
||||||
input_forward();
|
input_forward();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case '\b':
|
case '\b':
|
||||||
case '\x7f': /* DEL */
|
case '\x7f': /* DEL */
|
||||||
/* Control-h and DEL */
|
/* Control-h and DEL */
|
||||||
input_backspace();
|
input_backspace();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
#if ENABLE_FEATURE_TAB_COMPLETION
|
#if ENABLE_FEATURE_TAB_COMPLETION
|
||||||
case '\t':
|
case '\t':
|
||||||
input_tab(&lastWasTab);
|
input_tab(&lastWasTab);
|
||||||
break;
|
break;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
case CTRL('K'):
|
case CTRL('K'):
|
||||||
/* Control-k -- clear to end of line */
|
/* Control-k -- clear to end of line */
|
||||||
command[cursor] = 0;
|
command[cursor] = 0;
|
||||||
@ -1630,31 +1640,29 @@ int FAST_FUNC read_line_input(const char *prompt, char *command, int maxsize, li
|
|||||||
printf("\033[J");
|
printf("\033[J");
|
||||||
break;
|
break;
|
||||||
case CTRL('L'):
|
case CTRL('L'):
|
||||||
vi_case(CTRL('L')|vbit:)
|
vi_case(CTRL('L')|VI_CMDMODE_BIT:)
|
||||||
/* Control-l -- clear screen */
|
/* Control-l -- clear screen */
|
||||||
printf("\033[H");
|
printf("\033[H");
|
||||||
redraw(0, command_len - cursor);
|
redraw(0, command_len - cursor);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
#if MAX_HISTORY > 0
|
#if MAX_HISTORY > 0
|
||||||
case CTRL('N'):
|
case CTRL('N'):
|
||||||
vi_case(CTRL('N')|vbit:)
|
vi_case(CTRL('N')|VI_CMDMODE_BIT:)
|
||||||
vi_case('j'|vbit:)
|
vi_case('j'|VI_CMDMODE_BIT:)
|
||||||
/* Control-n -- Get next command in history */
|
/* Control-n -- Get next command in history */
|
||||||
if (get_next_history())
|
if (get_next_history())
|
||||||
goto rewrite_line;
|
goto rewrite_line;
|
||||||
break;
|
break;
|
||||||
case CTRL('P'):
|
case CTRL('P'):
|
||||||
vi_case(CTRL('P')|vbit:)
|
vi_case(CTRL('P')|VI_CMDMODE_BIT:)
|
||||||
vi_case('k'|vbit:)
|
vi_case('k'|VI_CMDMODE_BIT:)
|
||||||
/* Control-p -- Get previous command from history */
|
/* Control-p -- Get previous command from history */
|
||||||
if (get_previous_history())
|
if (get_previous_history())
|
||||||
goto rewrite_line;
|
goto rewrite_line;
|
||||||
break;
|
break;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
case CTRL('U'):
|
case CTRL('U'):
|
||||||
vi_case(CTRL('U')|vbit:)
|
vi_case(CTRL('U')|VI_CMDMODE_BIT:)
|
||||||
/* Control-U -- Clear line before cursor */
|
/* Control-U -- Clear line before cursor */
|
||||||
if (cursor) {
|
if (cursor) {
|
||||||
overlapping_strcpy(command, command + cursor);
|
overlapping_strcpy(command, command + cursor);
|
||||||
@ -1663,7 +1671,7 @@ int FAST_FUNC read_line_input(const char *prompt, char *command, int maxsize, li
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case CTRL('W'):
|
case CTRL('W'):
|
||||||
vi_case(CTRL('W')|vbit:)
|
vi_case(CTRL('W')|VI_CMDMODE_BIT:)
|
||||||
/* Control-W -- Remove the last word */
|
/* Control-W -- Remove the last word */
|
||||||
while (cursor > 0 && isspace(command[cursor-1]))
|
while (cursor > 0 && isspace(command[cursor-1]))
|
||||||
input_backspace();
|
input_backspace();
|
||||||
@ -1672,75 +1680,80 @@ int FAST_FUNC read_line_input(const char *prompt, char *command, int maxsize, li
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
#if ENABLE_FEATURE_EDITING_VI
|
#if ENABLE_FEATURE_EDITING_VI
|
||||||
case 'i'|vbit:
|
case 'i'|VI_CMDMODE_BIT:
|
||||||
vi_cmdmode = 0;
|
vi_cmdmode = 0;
|
||||||
break;
|
break;
|
||||||
case 'I'|vbit:
|
case 'I'|VI_CMDMODE_BIT:
|
||||||
input_backward(cursor);
|
input_backward(cursor);
|
||||||
vi_cmdmode = 0;
|
vi_cmdmode = 0;
|
||||||
break;
|
break;
|
||||||
case 'a'|vbit:
|
case 'a'|VI_CMDMODE_BIT:
|
||||||
input_forward();
|
input_forward();
|
||||||
vi_cmdmode = 0;
|
vi_cmdmode = 0;
|
||||||
break;
|
break;
|
||||||
case 'A'|vbit:
|
case 'A'|VI_CMDMODE_BIT:
|
||||||
input_end();
|
input_end();
|
||||||
vi_cmdmode = 0;
|
vi_cmdmode = 0;
|
||||||
break;
|
break;
|
||||||
case 'x'|vbit:
|
case 'x'|VI_CMDMODE_BIT:
|
||||||
input_delete(1);
|
input_delete(1);
|
||||||
break;
|
break;
|
||||||
case 'X'|vbit:
|
case 'X'|VI_CMDMODE_BIT:
|
||||||
if (cursor > 0) {
|
if (cursor > 0) {
|
||||||
input_backward(1);
|
input_backward(1);
|
||||||
input_delete(1);
|
input_delete(1);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 'W'|vbit:
|
case 'W'|VI_CMDMODE_BIT:
|
||||||
vi_Word_motion(command, 1);
|
vi_Word_motion(command, 1);
|
||||||
break;
|
break;
|
||||||
case 'w'|vbit:
|
case 'w'|VI_CMDMODE_BIT:
|
||||||
vi_word_motion(command, 1);
|
vi_word_motion(command, 1);
|
||||||
break;
|
break;
|
||||||
case 'E'|vbit:
|
case 'E'|VI_CMDMODE_BIT:
|
||||||
vi_End_motion(command);
|
vi_End_motion(command);
|
||||||
break;
|
break;
|
||||||
case 'e'|vbit:
|
case 'e'|VI_CMDMODE_BIT:
|
||||||
vi_end_motion(command);
|
vi_end_motion(command);
|
||||||
break;
|
break;
|
||||||
case 'B'|vbit:
|
case 'B'|VI_CMDMODE_BIT:
|
||||||
vi_Back_motion(command);
|
vi_Back_motion(command);
|
||||||
break;
|
break;
|
||||||
case 'b'|vbit:
|
case 'b'|VI_CMDMODE_BIT:
|
||||||
vi_back_motion(command);
|
vi_back_motion(command);
|
||||||
break;
|
break;
|
||||||
case 'C'|vbit:
|
case 'C'|VI_CMDMODE_BIT:
|
||||||
vi_cmdmode = 0;
|
vi_cmdmode = 0;
|
||||||
/* fall through */
|
/* fall through */
|
||||||
case 'D'|vbit:
|
case 'D'|VI_CMDMODE_BIT:
|
||||||
goto clear_to_eol;
|
goto clear_to_eol;
|
||||||
|
|
||||||
case 'c'|vbit:
|
case 'c'|VI_CMDMODE_BIT:
|
||||||
vi_cmdmode = 0;
|
vi_cmdmode = 0;
|
||||||
/* fall through */
|
/* fall through */
|
||||||
case 'd'|vbit: {
|
case 'd'|VI_CMDMODE_BIT: {
|
||||||
int nc, sc;
|
int nc, sc;
|
||||||
|
int prev_ic;
|
||||||
|
|
||||||
sc = cursor;
|
sc = cursor;
|
||||||
prevc = ic;
|
prev_ic = ic;
|
||||||
if (safe_read(STDIN_FILENO, &c, 1) < 1)
|
|
||||||
|
ic = lineedit_read_key(&read_key_bufsize, read_key_buffer);
|
||||||
|
if (errno) /* error */
|
||||||
goto prepare_to_die;
|
goto prepare_to_die;
|
||||||
if (c == (prevc & 0xff)) {
|
|
||||||
|
if ((ic | VI_CMDMODE_BIT) == prev_ic) {
|
||||||
/* "cc", "dd" */
|
/* "cc", "dd" */
|
||||||
input_backward(cursor);
|
input_backward(cursor);
|
||||||
goto clear_to_eol;
|
goto clear_to_eol;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
switch (c) {
|
switch (ic) {
|
||||||
case 'w':
|
case 'w':
|
||||||
case 'W':
|
case 'W':
|
||||||
case 'e':
|
case 'e':
|
||||||
case 'E':
|
case 'E':
|
||||||
switch (c) {
|
switch (ic) {
|
||||||
case 'w': /* "dw", "cw" */
|
case 'w': /* "dw", "cw" */
|
||||||
vi_word_motion(command, vi_cmdmode);
|
vi_word_motion(command, vi_cmdmode);
|
||||||
break;
|
break;
|
||||||
@ -1763,7 +1776,7 @@ int FAST_FUNC read_line_input(const char *prompt, char *command, int maxsize, li
|
|||||||
break;
|
break;
|
||||||
case 'b': /* "db", "cb" */
|
case 'b': /* "db", "cb" */
|
||||||
case 'B': /* implemented as B */
|
case 'B': /* implemented as B */
|
||||||
if (c == 'b')
|
if (ic == 'b')
|
||||||
vi_back_motion(command);
|
vi_back_motion(command);
|
||||||
else
|
else
|
||||||
vi_Back_motion(command);
|
vi_Back_motion(command);
|
||||||
@ -1781,136 +1794,102 @@ int FAST_FUNC read_line_input(const char *prompt, char *command, int maxsize, li
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 'p'|vbit:
|
case 'p'|VI_CMDMODE_BIT:
|
||||||
input_forward();
|
input_forward();
|
||||||
/* fallthrough */
|
/* fallthrough */
|
||||||
case 'P'|vbit:
|
case 'P'|VI_CMDMODE_BIT:
|
||||||
put();
|
put();
|
||||||
break;
|
break;
|
||||||
case 'r'|vbit:
|
case 'r'|VI_CMDMODE_BIT:
|
||||||
if (safe_read(STDIN_FILENO, &c, 1) < 1)
|
ic = lineedit_read_key(&read_key_bufsize, read_key_buffer);
|
||||||
|
if (errno) /* error */
|
||||||
goto prepare_to_die;
|
goto prepare_to_die;
|
||||||
if (c == 0)
|
if (ic < ' ' || ic > 255) {
|
||||||
beep();
|
beep();
|
||||||
else {
|
} else {
|
||||||
*(command + cursor) = c;
|
command[cursor] = ic;
|
||||||
bb_putchar(c);
|
bb_putchar(ic);
|
||||||
bb_putchar('\b');
|
bb_putchar('\b');
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case '\x1b': /* ESC */
|
||||||
|
if (state->flags & VI_MODE) {
|
||||||
|
/* insert mode --> command mode */
|
||||||
|
vi_cmdmode = 1;
|
||||||
|
input_backward(1);
|
||||||
|
}
|
||||||
|
break;
|
||||||
#endif /* FEATURE_COMMAND_EDITING_VI */
|
#endif /* FEATURE_COMMAND_EDITING_VI */
|
||||||
|
|
||||||
case '\x1b': /* ESC */
|
|
||||||
|
|
||||||
#if ENABLE_FEATURE_EDITING_VI
|
|
||||||
if (state->flags & VI_MODE) {
|
|
||||||
/* ESC: insert mode --> command mode */
|
|
||||||
vi_cmdmode = 1;
|
|
||||||
input_backward(1);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
/* escape sequence follows */
|
|
||||||
if (safe_read(STDIN_FILENO, &c, 1) < 1)
|
|
||||||
goto prepare_to_die;
|
|
||||||
/* different vt100 emulations */
|
|
||||||
if (c == '[' || c == 'O') {
|
|
||||||
vi_case('['|vbit:)
|
|
||||||
vi_case('O'|vbit:)
|
|
||||||
if (safe_read(STDIN_FILENO, &c, 1) < 1)
|
|
||||||
goto prepare_to_die;
|
|
||||||
}
|
|
||||||
if (c >= '1' && c <= '9') {
|
|
||||||
unsigned char dummy;
|
|
||||||
|
|
||||||
if (safe_read(STDIN_FILENO, &dummy, 1) < 1)
|
|
||||||
goto prepare_to_die;
|
|
||||||
if (dummy != '~')
|
|
||||||
c = '\0';
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (c) {
|
|
||||||
#if ENABLE_FEATURE_TAB_COMPLETION
|
|
||||||
case '\t': /* Alt-Tab */
|
|
||||||
input_tab(&lastWasTab);
|
|
||||||
break;
|
|
||||||
#endif
|
|
||||||
#if MAX_HISTORY > 0
|
#if MAX_HISTORY > 0
|
||||||
case 'A':
|
case KEYCODE_UP:
|
||||||
/* Up Arrow -- Get previous command from history */
|
|
||||||
if (get_previous_history())
|
if (get_previous_history())
|
||||||
goto rewrite_line;
|
goto rewrite_line;
|
||||||
beep();
|
beep();
|
||||||
break;
|
break;
|
||||||
case 'B':
|
case KEYCODE_DOWN:
|
||||||
/* Down Arrow -- Get next command in history */
|
|
||||||
if (!get_next_history())
|
if (!get_next_history())
|
||||||
break;
|
break;
|
||||||
rewrite_line:
|
rewrite_line:
|
||||||
/* Rewrite the line with the selected history item */
|
/* Rewrite the line with the selected history item */
|
||||||
/* change command */
|
/* change command */
|
||||||
command_len = strlen(strcpy(command, state->history[state->cur_history] ? : ""));
|
command_len = strlen(strcpy(command, state->history[state->cur_history] ? : ""));
|
||||||
/* redraw and go to eol (bol, in vi */
|
/* redraw and go to eol (bol, in vi) */
|
||||||
redraw(cmdedit_y, (state->flags & VI_MODE) ? 9999 : 0);
|
redraw(cmdedit_y, (state->flags & VI_MODE) ? 9999 : 0);
|
||||||
break;
|
break;
|
||||||
#endif
|
#endif
|
||||||
case 'C':
|
case KEYCODE_RIGHT:
|
||||||
/* Right Arrow -- Move forward one character */
|
|
||||||
input_forward();
|
input_forward();
|
||||||
break;
|
break;
|
||||||
case 'D':
|
case KEYCODE_LEFT:
|
||||||
/* Left Arrow -- Move back one character */
|
|
||||||
input_backward(1);
|
input_backward(1);
|
||||||
break;
|
break;
|
||||||
case '3':
|
case KEYCODE_DELETE:
|
||||||
/* Delete */
|
|
||||||
input_delete(0);
|
input_delete(0);
|
||||||
break;
|
break;
|
||||||
case '1': // vt100? linux vt? or what?
|
case KEYCODE_HOME:
|
||||||
case '7': // vt100? linux vt? or what?
|
|
||||||
case 'H': /* xterm's <Home> */
|
|
||||||
input_backward(cursor);
|
input_backward(cursor);
|
||||||
break;
|
break;
|
||||||
case '4': // vt100? linux vt? or what?
|
case KEYCODE_END:
|
||||||
case '8': // vt100? linux vt? or what?
|
|
||||||
case 'F': /* xterm's <End> */
|
|
||||||
input_end();
|
input_end();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
c = '\0';
|
// /* Control-V -- force insert of next char */
|
||||||
beep();
|
// if (c == CTRL('V')) {
|
||||||
}
|
// if (safe_read(STDIN_FILENO, &c, 1) < 1)
|
||||||
break;
|
// goto prepare_to_die;
|
||||||
|
// if (c == 0) {
|
||||||
default: /* If it's regular input, do the normal thing */
|
// beep();
|
||||||
|
// break;
|
||||||
/* Control-V -- force insert of next char */
|
// }
|
||||||
if (c == CTRL('V')) {
|
// }
|
||||||
if (safe_read(STDIN_FILENO, &c, 1) < 1)
|
if (ic < ' ' || ic > 255) {
|
||||||
goto prepare_to_die;
|
/* If VI_CMDMODE_BIT is set, ic is >= 256
|
||||||
if (c == 0) {
|
* and command mode ignores unexpected chars.
|
||||||
beep();
|
* Otherwise, we are here if ic is a
|
||||||
|
* control char or an unhandled ESC sequence,
|
||||||
|
* which is also ignored.
|
||||||
|
*/
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
if ((int)command_len >= (maxsize - 2)) {
|
||||||
|
/* Not enough space for the char and EOL */
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if ENABLE_FEATURE_EDITING_VI
|
|
||||||
if (vi_cmdmode) /* Don't self-insert */
|
|
||||||
break;
|
|
||||||
#endif
|
|
||||||
if ((int)command_len >= (maxsize - 2)) /* Need to leave space for enter */
|
|
||||||
break;
|
|
||||||
|
|
||||||
command_len++;
|
command_len++;
|
||||||
if (cursor == (command_len - 1)) { /* Append if at the end of the line */
|
if (cursor == (command_len - 1)) {
|
||||||
command[cursor] = c;
|
/* We are at the end, append */
|
||||||
command[cursor+1] = '\0';
|
command[cursor] = ic;
|
||||||
|
command[cursor + 1] = '\0';
|
||||||
cmdedit_set_out_char(' ');
|
cmdedit_set_out_char(' ');
|
||||||
} else { /* Insert otherwise */
|
} else {
|
||||||
|
/* In the middle, insert */
|
||||||
int sc = cursor;
|
int sc = cursor;
|
||||||
|
|
||||||
memmove(command + sc + 1, command + sc, command_len - sc);
|
memmove(command + sc + 1, command + sc, command_len - sc);
|
||||||
command[sc] = c;
|
command[sc] = ic;
|
||||||
sc++;
|
sc++;
|
||||||
/* rewrite from cursor */
|
/* rewrite from cursor */
|
||||||
input_end();
|
input_end();
|
||||||
@ -1918,15 +1897,17 @@ int FAST_FUNC read_line_input(const char *prompt, char *command, int maxsize, li
|
|||||||
input_backward(cursor - sc);
|
input_backward(cursor - sc);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
} /* switch (input_key) */
|
||||||
if (break_out) /* Enter is the command terminator, no more input. */
|
|
||||||
|
if (break_out)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
#if ENABLE_FEATURE_TAB_COMPLETION
|
#if ENABLE_FEATURE_TAB_COMPLETION
|
||||||
if (c != '\t')
|
ic &= ~VI_CMDMODE_BIT;
|
||||||
|
if (ic != '\t')
|
||||||
lastWasTab = FALSE;
|
lastWasTab = FALSE;
|
||||||
#endif
|
#endif
|
||||||
}
|
} /* while (1) */
|
||||||
|
|
||||||
if (command_len > 0)
|
if (command_len > 0)
|
||||||
remember_in_history(command);
|
remember_in_history(command);
|
||||||
|
@ -66,6 +66,7 @@ int FAST_FUNC read_key(int fd, smalluint *nbuffered, char *buffer)
|
|||||||
0
|
0
|
||||||
};
|
};
|
||||||
|
|
||||||
|
errno = 0;
|
||||||
n = 0;
|
n = 0;
|
||||||
if (nbuffered)
|
if (nbuffered)
|
||||||
n = *nbuffered;
|
n = *nbuffered;
|
||||||
|
Loading…
Reference in New Issue
Block a user