From a17eeb847e66824c4d389751cc90415d3fc1c5a3 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Sun, 25 Oct 2009 23:50:56 +0100 Subject: lineedit: handle Ctrl-arrows function old new delta read_line_input 4629 4824 +195 BB_isalnum - 39 +39 BB_ispunct - 35 +35 BB_isspace - 31 +31 static.esccmds 69 93 +24 vi_word_motion 165 162 -3 vi_back_motion 204 198 -6 vi_end_motion 172 163 -9 bb_iswspace 28 - -28 bb_iswpunct 32 - -32 bb_iswalnum 37 - -37 ------------------------------------------------------------------------------ (add/remove: 3/3 grow/shrink: 5/8 up/down: 334/-129) Total: 205 bytes Signed-off-by: Denys Vlasenko --- include/libbb.h | 5 +++ libbb/lineedit.c | 97 ++++++++++++++++++++++++++++++++++++++++---------------- libbb/read_key.c | 16 +++++++++- 3 files changed, 90 insertions(+), 28 deletions(-) diff --git a/include/libbb.h b/include/libbb.h index a1744ecc3..6274ea2e8 100644 --- a/include/libbb.h +++ b/include/libbb.h @@ -1203,6 +1203,11 @@ enum { KEYCODE_DELETE = -9, KEYCODE_PAGEUP = -10, KEYCODE_PAGEDOWN = -11, + + KEYCODE_CTRL_UP = KEYCODE_UP & ~0x40, + KEYCODE_CTRL_DOWN = KEYCODE_DOWN & ~0x40, + KEYCODE_CTRL_RIGHT = KEYCODE_RIGHT & ~0x40, + KEYCODE_CTRL_LEFT = KEYCODE_LEFT & ~0x40, #if 0 KEYCODE_FUN1 = -12, KEYCODE_FUN2 = -13, diff --git a/libbb/lineedit.c b/libbb/lineedit.c index 5f5beb17c..bfd0e3346 100644 --- a/libbb/lineedit.c +++ b/libbb/lineedit.c @@ -16,12 +16,18 @@ /* * Usage and known bugs: - * Terminal key codes are not extensive, and more will probably - * need to be added. This version was created on Debian GNU/Linux 2.x. + * Terminal key codes are not extensive, more needs to be added. + * This version was created on Debian GNU/Linux 2.x. * Delete, Backspace, Home, End, and the arrow keys were tested * to work in an Xterm and console. Ctrl-A also works as Home. * Ctrl-E also works as End. * + * The following readline-like commands are not implemented: + * ESC-b -- Move back one word + * ESC-f -- Move forward one word + * ESC-d -- Delete forward one word + * CTL-t -- Transpose two characters + * * lineedit does not know that the terminal escape sequences do not * take up space on the screen. The redisplay code assumes, unless * told otherwise, that each character in the prompt is a printable @@ -64,11 +70,9 @@ #if ENABLE_FEATURE_ASSUME_UNICODE # define BB_NUL L'\0' # define CHAR_T wchar_t -# define BB_isspace(c) iswspace(c) -# define BB_isalnum(c) iswalnum(c) -# define BB_ispunct(c) iswpunct(c) -# define BB_isprint(c) iswprint(c) -/* this catches bugs */ +static bool BB_isspace(CHAR_T c) { return ((unsigned)c < 256 && isspace(c)); } +static bool BB_isalnum(CHAR_T c) { return ((unsigned)c < 256 && isalnum(c)); } +static bool BB_ispunct(CHAR_T c) { return ((unsigned)c < 256 && ispunct(c)); } # undef isspace # undef isalnum # undef ispunct @@ -83,11 +87,6 @@ # define BB_isspace(c) isspace(c) # define BB_isalnum(c) isalnum(c) # define BB_ispunct(c) ispunct(c) -# if ENABLE_LOCALE_SUPPORT -# define BB_isprint(c) isprint(c) -# else -# define BB_isprint(c) ((c) >= ' ' && (c) != ((unsigned char)'\233')) -# endif #endif @@ -1302,24 +1301,10 @@ static void remember_in_history(char *str) #endif /* MAX_HISTORY */ +#if ENABLE_FEATURE_EDITING_VI /* - * This function is used to grab a character buffer - * from the input file descriptor and allows you to - * a string with full command editing (sort of like - * a mini readline). - * - * The following standard commands are not implemented: - * ESC-b -- Move back one word - * ESC-f -- Move forward one word - * ESC-d -- Delete back one word - * ESC-h -- Delete forward one word - * CTL-t -- Transpose two characters - * - * Minimalist vi-style command line editing available if configured. * vi mode implemented 2005 by Paul Fox */ - -#if ENABLE_FEATURE_EDITING_VI static void vi_Word_motion(int eat) { @@ -1428,6 +1413,58 @@ vi_back_motion(void) } #endif +/* Modelled after bash 4.0 behavior of Ctrl- */ +static void ctrl_left(void) +{ + CHAR_T *command = command_ps; + + while (1) { + CHAR_T c; + + input_backward(1); + if (cursor == 0) + break; + c = command[cursor]; + if (c != ' ' && !BB_ispunct(c)) { + /* we reached a "word" delimited by spaces/punct. + * go to its beginning */ + while (1) { + c = command[cursor - 1]; + if (c == ' ' || BB_ispunct(c)) + break; + input_backward(1); + if (cursor == 0) + break; + } + break; + } + } +} +static void ctrl_right(void) +{ + CHAR_T *command = command_ps; + + while (1) { + CHAR_T c; + + c = command[cursor]; + if (c == BB_NUL) + break; + if (c != ' ' && !BB_ispunct(c)) { + /* we reached a "word" delimited by spaces/punct. + * go to its end + 1 */ + while (1) { + input_forward(); + c = command[cursor]; + if (c == BB_NUL || c == ' ' || BB_ispunct(c)) + break; + } + break; + } + input_forward(); + } +} + /* * read_line_input and its helpers @@ -2028,6 +2065,12 @@ int FAST_FUNC read_line_input(const char *prompt, char *command, int maxsize, li case KEYCODE_LEFT: input_backward(1); break; + case KEYCODE_CTRL_LEFT: + ctrl_left(); + break; + case KEYCODE_CTRL_RIGHT: + ctrl_right(); + break; case KEYCODE_DELETE: input_delete(0); break; diff --git a/libbb/read_key.c b/libbb/read_key.c index d3832fa6c..410a99995 100644 --- a/libbb/read_key.c +++ b/libbb/read_key.c @@ -22,7 +22,6 @@ int64_t FAST_FUNC read_key(int fd, char *buffer) 'O','B' |0x80,KEYCODE_DOWN , 'O','C' |0x80,KEYCODE_RIGHT , 'O','D' |0x80,KEYCODE_LEFT , - /* Ctrl-: ESC [ 1 ; 5 x, where x = A/B/C/D */ 'O','H' |0x80,KEYCODE_HOME , 'O','F' |0x80,KEYCODE_END , #if 0 @@ -37,15 +36,26 @@ int64_t FAST_FUNC read_key(int fd, char *buffer) '[','B' |0x80,KEYCODE_DOWN , '[','C' |0x80,KEYCODE_RIGHT , '[','D' |0x80,KEYCODE_LEFT , + /* ESC [ 1 ; 2 x, where x = A/B/C/D: Shift- */ + /* ESC [ 1 ; 3 x, where x = A/B/C/D: Alt- */ + /* ESC [ 1 ; 4 x, where x = A/B/C/D: Alt-Shift- */ + /* ESC [ 1 ; 5 x, where x = A/B/C/D: Ctrl- - implemented below */ + /* ESC [ 1 ; 6 x, where x = A/B/C/D: Ctrl-Shift- */ '[','H' |0x80,KEYCODE_HOME , /* xterm */ /* [ESC] ESC [ [2] H - [Alt-][Shift-]Home */ '[','F' |0x80,KEYCODE_END , /* xterm */ '[','1','~' |0x80,KEYCODE_HOME , /* vt100? linux vt? or what? */ '[','2','~' |0x80,KEYCODE_INSERT , + /* ESC [ 2 ; 3 ~ - Alt-Insert */ '[','3','~' |0x80,KEYCODE_DELETE , /* [ESC] ESC [ 3 [;2] ~ - [Alt-][Shift-]Delete */ + /* ESC [ 3 ; 3 ~ - Alt-Delete */ + /* ESC [ 3 ; 5 ~ - Ctrl-Delete */ '[','4','~' |0x80,KEYCODE_END , /* vt100? linux vt? or what? */ '[','5','~' |0x80,KEYCODE_PAGEUP , + /* ESC [ 5 ; 3 ~ - Alt-PgUp */ + /* ESC [ 5 ; 5 ~ - Ctrl-PgUp */ + /* ESC [ 5 ; 7 ~ - Ctrl-Alt-PgUp */ '[','6','~' |0x80,KEYCODE_PAGEDOWN, '[','7','~' |0x80,KEYCODE_HOME , /* vt100? linux vt? or what? */ '[','8','~' |0x80,KEYCODE_END , /* vt100? linux vt? or what? */ @@ -64,6 +74,10 @@ int64_t FAST_FUNC read_key(int fd, char *buffer) '[','2','3','~'|0x80,KEYCODE_FUN11 , '[','2','4','~'|0x80,KEYCODE_FUN12 , #endif + '[','1',';','5','A' |0x80,KEYCODE_CTRL_UP , + '[','1',';','5','B' |0x80,KEYCODE_CTRL_DOWN , + '[','1',';','5','C' |0x80,KEYCODE_CTRL_RIGHT, + '[','1',';','5','D' |0x80,KEYCODE_CTRL_LEFT , 0 }; -- cgit v1.2.3