lineedit: fix handling of repeating Alt-b, Alt-f, Alt-d, Alt-Backspace

These key combinations should repeat correctly when the keys are
pressed and held.

Before this change, they do this erratically - many repeats are "eaten"
because they are treated as unrecognized ESC seqs:
ESC 0x7f is treated by Alt+baskspace, but ESC 0x7f ESC 0x7f ESC 0x7f
is unrecognized.

Escape sequences corresponding to these key combinations are moved from
read_line_input to lineedit_read_key.

Also, these key sequences are now enabled regardless of whether
FEATURE_EDITING_VI is set, since Vim does not actually support these key
combinations, but they are present in readline library.

function                                             old     new   delta
static.esccmds                                        93     103     +10
read_line_input                                     3737    3687     -50

Signed-off-by: Rostislav Skudnov <rostislav@tuxera.com>
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
This commit is contained in:
Rostislav Skudnov 2016-11-24 15:04:00 +01:00 committed by Denys Vlasenko
parent cb810c48c0
commit 2e4ef38743
3 changed files with 67 additions and 79 deletions

View File

@ -1473,36 +1473,36 @@ enum {
KEYCODE_DELETE = -9, KEYCODE_DELETE = -9,
KEYCODE_PAGEUP = -10, KEYCODE_PAGEUP = -10,
KEYCODE_PAGEDOWN = -11, KEYCODE_PAGEDOWN = -11,
// -12 is reserved for Alt/Ctrl/Shift-TAB KEYCODE_BACKSPACE = -12, /* Used only if Alt/Ctrl/Shifted */
KEYCODE_D = -13, /* Used only if Alted */
#if 0 #if 0
KEYCODE_FUN1 = -13, KEYCODE_FUN1 = ,
KEYCODE_FUN2 = -14, KEYCODE_FUN2 = ,
KEYCODE_FUN3 = -15, KEYCODE_FUN3 = ,
KEYCODE_FUN4 = -16, KEYCODE_FUN4 = ,
KEYCODE_FUN5 = -17, KEYCODE_FUN5 = ,
KEYCODE_FUN6 = -18, KEYCODE_FUN6 = ,
KEYCODE_FUN7 = -19, KEYCODE_FUN7 = ,
KEYCODE_FUN8 = -20, KEYCODE_FUN8 = ,
KEYCODE_FUN9 = -21, KEYCODE_FUN9 = ,
KEYCODE_FUN10 = -22, KEYCODE_FUN10 = ,
KEYCODE_FUN11 = -23, KEYCODE_FUN11 = ,
KEYCODE_FUN12 = -24, KEYCODE_FUN12 = ,
#endif #endif
/* Be sure that last defined value is small enough /* ^^^^^ Be sure that last defined value is small enough.
* to not interfere with Alt/Ctrl/Shift bits. * Current read_key() code allows going up to -32 (0xfff..fffe0).
* So far we do not exceed -31 (0xfff..fffe1), * This gives three upper bits in LSB to play with:
* which gives us three upper bits in LSB to play with. * KEYCODE_foo values are 0xfff..fffXX, lowest XX bits are: scavvvvv,
* s=0 if SHIFT, c=0 if CTRL, a=0 if ALT,
* vvvvv bits are the same for same key regardless of "shift bits".
*/ */
//KEYCODE_SHIFT_TAB = (-12) & ~0x80,
//KEYCODE_SHIFT_... = KEYCODE_... & ~0x80, //KEYCODE_SHIFT_... = KEYCODE_... & ~0x80,
//KEYCODE_CTRL_UP = KEYCODE_UP & ~0x40,
//KEYCODE_CTRL_DOWN = KEYCODE_DOWN & ~0x40,
KEYCODE_CTRL_RIGHT = KEYCODE_RIGHT & ~0x40, KEYCODE_CTRL_RIGHT = KEYCODE_RIGHT & ~0x40,
KEYCODE_CTRL_LEFT = KEYCODE_LEFT & ~0x40, KEYCODE_CTRL_LEFT = KEYCODE_LEFT & ~0x40,
//KEYCODE_ALT_UP = KEYCODE_UP & ~0x20,
//KEYCODE_ALT_DOWN = KEYCODE_DOWN & ~0x20,
KEYCODE_ALT_RIGHT = KEYCODE_RIGHT & ~0x20, KEYCODE_ALT_RIGHT = KEYCODE_RIGHT & ~0x20,
KEYCODE_ALT_LEFT = KEYCODE_LEFT & ~0x20, KEYCODE_ALT_LEFT = KEYCODE_LEFT & ~0x20,
KEYCODE_ALT_BACKSPACE = KEYCODE_BACKSPACE & ~0x20,
KEYCODE_ALT_D = KEYCODE_D & ~0x20,
KEYCODE_CURSOR_POS = -0x100, /* 0xfff..fff00 */ KEYCODE_CURSOR_POS = -0x100, /* 0xfff..fff00 */
/* How long is the longest ESC sequence we know? /* How long is the longest ESC sequence we know?

View File

@ -13,7 +13,6 @@
* *
* This code is 'as is' with no warranty. * This code is 'as is' with no warranty.
*/ */
/* /*
* Usage and known bugs: * Usage and known bugs:
* Terminal key codes are not extensive, more needs to be added. * Terminal key codes are not extensive, more needs to be added.
@ -23,9 +22,6 @@
* Ctrl-E also works as End. * Ctrl-E also works as End.
* *
* The following readline-like commands are not implemented: * 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 * CTL-t -- Transpose two characters
* *
* lineedit does not know that the terminal escape sequences do not * lineedit does not know that the terminal escape sequences do not
@ -2483,6 +2479,24 @@ int FAST_FUNC read_line_input(line_input_t *st, const char *prompt, char *comman
while (cursor > 0 && !BB_isspace(command_ps[cursor-1])) while (cursor > 0 && !BB_isspace(command_ps[cursor-1]))
input_backspace(); input_backspace();
break; break;
case KEYCODE_ALT_D: {
/* Delete word forward */
int nc, sc = cursor;
ctrl_right();
nc = cursor - sc;
input_backward(nc);
while (--nc >= 0)
input_delete(1);
break;
}
case KEYCODE_ALT_BACKSPACE: {
/* Delete word backward */
int sc = cursor;
ctrl_left();
while (sc-- > cursor)
input_delete(1);
break;
}
#if ENABLE_FEATURE_REVERSE_SEARCH #if ENABLE_FEATURE_REVERSE_SEARCH
case CTRL('R'): case CTRL('R'):
ic = ic_raw = reverse_i_search(); ic = ic_raw = reverse_i_search();
@ -2625,44 +2639,6 @@ int FAST_FUNC read_line_input(line_input_t *st, const char *prompt, char *comman
vi_cmdmode = 1; vi_cmdmode = 1;
input_backward(1); input_backward(1);
} }
/* Handle a few ESC-<key> combinations the same way
* standard readline bindings (IOW: bash) do.
* Often, Alt-<key> generates ESC-<key>.
*/
ic = lineedit_read_key(read_key_buffer, 50);
switch (ic) {
//case KEYCODE_LEFT: - bash doesn't do this
case 'b':
ctrl_left();
break;
//case KEYCODE_RIGHT: - bash doesn't do this
case 'f':
ctrl_right();
break;
//case KEYCODE_DELETE: - bash doesn't do this
case 'd': /* Alt-D */
{
/* Delete word forward */
int nc, sc = cursor;
ctrl_right();
nc = cursor - sc;
input_backward(nc);
while (--nc >= 0)
input_delete(1);
break;
}
case '\b': /* Alt-Backspace(?) */
case '\x7f': /* Alt-Backspace(?) */
//case 'w': - bash doesn't do this
{
/* Delete word backward */
int sc = cursor;
ctrl_left();
while (sc-- > cursor)
input_delete(1);
break;
}
}
break; break;
#endif /* FEATURE_COMMAND_EDITING_VI */ #endif /* FEATURE_COMMAND_EDITING_VI */

View File

@ -18,8 +18,20 @@ int64_t FAST_FUNC read_key(int fd, char *buffer, int timeout)
/* Known escape sequences for cursor and function keys. /* Known escape sequences for cursor and function keys.
* See "Xterm Control Sequences" * See "Xterm Control Sequences"
* http://invisible-island.net/xterm/ctlseqs/ctlseqs.html * http://invisible-island.net/xterm/ctlseqs/ctlseqs.html
* Array should be sorted from shortest to longest.
*/ */
static const char esccmds[] ALIGN1 = { static const char esccmds[] ALIGN1 = {
'\x7f' |0x80,KEYCODE_ALT_BACKSPACE,
'\b' |0x80,KEYCODE_ALT_BACKSPACE,
'd' |0x80,KEYCODE_ALT_D ,
/* lineedit mimics bash: Alt-f and Alt-b are forward/backward
* word jumps. We cheat here and make them return ALT_LEFT/RIGHT
* keycodes. This way, lineedit need no special code to handle them.
* If we'll need to distinguish them, introduce new ALT_F/B keycodes,
* and update lineedit to react to them.
*/
'f' |0x80,KEYCODE_ALT_RIGHT,
'b' |0x80,KEYCODE_ALT_LEFT,
'O','A' |0x80,KEYCODE_UP , 'O','A' |0x80,KEYCODE_UP ,
'O','B' |0x80,KEYCODE_DOWN , 'O','B' |0x80,KEYCODE_DOWN ,
'O','C' |0x80,KEYCODE_RIGHT , 'O','C' |0x80,KEYCODE_RIGHT ,