[git commit master] lineedit: handle Ctrl-arrows

Denys Vlasenko vda.linux at googlemail.com
Sun Oct 25 22:50:56 UTC 2009


commit: http://git.busybox.net/busybox/commit/?id=a17eeb847e66824c4d389751cc90415d3fc1c5a3
branch: http://git.busybox.net/busybox/commit/?id=refs/heads/master

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 at googlemail.com>
---
 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 a1744ec..6274ea2 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 5f5beb1..bfd0e33 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 <pgf at 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;
diff --git a/libbb/read_key.c b/libbb/read_key.c
index d3832fa..410a999 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-<arrow>: 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-<arrow> */
+		/* ESC [ 1 ; 3 x, where x = A/B/C/D: Alt-<arrow> */
+		/* ESC [ 1 ; 4 x, where x = A/B/C/D: Alt-Shift-<arrow> */
+		/* ESC [ 1 ; 5 x, where x = A/B/C/D: Ctrl-<arrow> - implemented below */
+		/* ESC [ 1 ; 6 x, where x = A/B/C/D: Ctrl-Shift-<arrow> */
 		'[','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
 	};
 
-- 
1.6.3.3



More information about the busybox-cvs mailing list