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 <vda.linux@googlemail.com>
This commit is contained in:
Denys Vlasenko
2009-10-25 23:50:56 +01:00
parent 77c066ea5c
commit a17eeb847e
3 changed files with 90 additions and 28 deletions

View File

@ -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 <pgf@foxharp.boston.ma.us>
*/
#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-<arrow> */
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;