mirror of
git://projects.qi-hardware.com/openwrt-xburst.git
synced 2024-11-30 17:40:16 +02:00
busybox: backport reverse history search patch
See https://dev.openwrt.org/ticket/9695
This commit is contained in:
parent
67e619ef6f
commit
f7181200a7
@ -91,6 +91,14 @@ config BUSYBOX_CONFIG_FEATURE_EDITING_SAVEHISTORY
|
||||
help
|
||||
Enable history saving in shells.
|
||||
|
||||
config BUSYBOX_CONFIG_FEATURE_REVERSE_SEARCH
|
||||
bool "Reverse history search"
|
||||
default n
|
||||
depends on BUSYBOX_CONFIG_FEATURE_EDITING_SAVEHISTORY
|
||||
help
|
||||
Enable readline-like Ctrl-R combination for reverse history search.
|
||||
Increases code by about 0.5k.
|
||||
|
||||
config BUSYBOX_CONFIG_FEATURE_TAB_COMPLETION
|
||||
bool "Tab completion"
|
||||
default y
|
||||
|
@ -1,6 +1,6 @@
|
||||
--- a/modutils/insmod.c
|
||||
+++ b/modutils/insmod.c
|
||||
@@ -133,7 +133,7 @@ int insmod_main(int argc, char **argv) M
|
||||
@@ -140,7 +140,7 @@ int insmod_main(int argc, char **argv) M
|
||||
int insmod_main(int argc UNUSED_PARAM, char **argv)
|
||||
{
|
||||
char *filename;
|
||||
@ -9,7 +9,7 @@
|
||||
|
||||
/* Compat note:
|
||||
* 2.6 style insmod has no options and required filename
|
||||
@@ -143,10 +143,8 @@ int insmod_main(int argc UNUSED_PARAM, c
|
||||
@@ -150,10 +150,8 @@ int insmod_main(int argc UNUSED_PARAM, c
|
||||
* or in $MODPATH.
|
||||
*/
|
||||
|
||||
@ -22,7 +22,7 @@
|
||||
|
||||
filename = *++argv;
|
||||
if (!filename)
|
||||
@@ -157,7 +155,7 @@ int insmod_main(int argc UNUSED_PARAM, c
|
||||
@@ -164,7 +162,7 @@ int insmod_main(int argc UNUSED_PARAM, c
|
||||
goto done;
|
||||
|
||||
rc = bb_init_module(g_filename, parse_cmdline_module_options(argv));
|
||||
|
@ -0,0 +1,255 @@
|
||||
--- a/libbb/lineedit.c
|
||||
+++ b/libbb/lineedit.c
|
||||
@@ -202,13 +202,23 @@ static void deinit_S(void)
|
||||
|
||||
|
||||
#if ENABLE_UNICODE_SUPPORT
|
||||
-static size_t load_string(const char *src, int maxsize)
|
||||
+static size_t load_string(const char *src)
|
||||
{
|
||||
- ssize_t len = mbstowcs(command_ps, src, maxsize - 1);
|
||||
- if (len < 0)
|
||||
- len = 0;
|
||||
- command_ps[len] = BB_NUL;
|
||||
- return len;
|
||||
+ if (unicode_status == UNICODE_ON) {
|
||||
+ ssize_t len = mbstowcs(command_ps, src, S.maxsize - 1);
|
||||
+ if (len < 0)
|
||||
+ len = 0;
|
||||
+ command_ps[len] = BB_NUL;
|
||||
+ return len;
|
||||
+ } else {
|
||||
+ unsigned i = 0;
|
||||
+ while (src[i] && i < S.maxsize - 1) {
|
||||
+ command_ps[i] = src[i];
|
||||
+ i++;
|
||||
+ }
|
||||
+ command_ps[i] = BB_NUL;
|
||||
+ return i;
|
||||
+ }
|
||||
}
|
||||
static unsigned save_string(char *dst, unsigned maxsize)
|
||||
{
|
||||
@@ -297,9 +307,9 @@ static wchar_t adjust_width_and_validate
|
||||
return wc;
|
||||
}
|
||||
#else /* !UNICODE */
|
||||
-static size_t load_string(const char *src, int maxsize)
|
||||
+static size_t load_string(const char *src)
|
||||
{
|
||||
- safe_strncpy(command_ps, src, maxsize);
|
||||
+ safe_strncpy(command_ps, src, S.maxsize);
|
||||
return strlen(command_ps);
|
||||
}
|
||||
# if ENABLE_FEATURE_TAB_COMPLETION
|
||||
@@ -1202,10 +1212,10 @@ static NOINLINE void input_tab(smallint
|
||||
strcpy(match_buf, &command[cursor_mb]);
|
||||
/* where do we want to have cursor after all? */
|
||||
strcpy(&command[cursor_mb], chosen_match + match_pfx_len);
|
||||
- len = load_string(command, S.maxsize);
|
||||
+ len = load_string(command);
|
||||
/* add match and tail */
|
||||
sprintf(&command[cursor_mb], "%s%s", chosen_match + match_pfx_len, match_buf);
|
||||
- command_len = load_string(command, S.maxsize);
|
||||
+ command_len = load_string(command);
|
||||
/* write out the matched command */
|
||||
/* paranoia: load_string can return 0 on conv error,
|
||||
* prevent passing pos = (0 - 12) to redraw */
|
||||
@@ -1911,6 +1921,140 @@ static int isrtl_str(void)
|
||||
#undef CTRL
|
||||
#define CTRL(a) ((a) & ~0x40)
|
||||
|
||||
+enum {
|
||||
+ VI_CMDMODE_BIT = 0x40000000,
|
||||
+ /* 0x80000000 bit flags KEYCODE_xxx */
|
||||
+};
|
||||
+
|
||||
+#if ENABLE_FEATURE_REVERSE_SEARCH
|
||||
+/* Mimic readline Ctrl-R reverse history search.
|
||||
+ * When invoked, it shows the following prompt:
|
||||
+ * (reverse-i-search)'': user_input [cursor pos unchanged by Ctrl-R]
|
||||
+ * and typing results in search being performed:
|
||||
+ * (reverse-i-search)'tmp': cd /tmp [cursor under t in /tmp]
|
||||
+ * Search is performed by looking at progressively older lines in history.
|
||||
+ * Ctrl-R again searches for the next match in history.
|
||||
+ * Backspace deletes last matched char.
|
||||
+ * Control keys exit search and return to normal editing (at current history line).
|
||||
+ */
|
||||
+static int32_t reverse_i_search(void)
|
||||
+{
|
||||
+ char match_buf[128]; /* for user input */
|
||||
+ char read_key_buffer[KEYCODE_BUFFER_SIZE];
|
||||
+ const char *matched_history_line;
|
||||
+ const char *saved_prompt;
|
||||
+ int32_t ic;
|
||||
+
|
||||
+ matched_history_line = NULL;
|
||||
+ read_key_buffer[0] = 0;
|
||||
+ match_buf[0] = '\0';
|
||||
+
|
||||
+ /* Save and replace the prompt */
|
||||
+ saved_prompt = cmdedit_prompt;
|
||||
+ goto set_prompt;
|
||||
+
|
||||
+ while (1) {
|
||||
+ int h;
|
||||
+ unsigned match_buf_len = strlen(match_buf);
|
||||
+
|
||||
+ fflush_all();
|
||||
+//FIXME: correct timeout?
|
||||
+ ic = lineedit_read_key(read_key_buffer);
|
||||
+
|
||||
+ switch (ic) {
|
||||
+ case CTRL('R'): /* searching for the next match */
|
||||
+ break;
|
||||
+
|
||||
+ case '\b':
|
||||
+ case '\x7f':
|
||||
+ /* Backspace */
|
||||
+ if (unicode_status == UNICODE_ON) {
|
||||
+ while (match_buf_len != 0) {
|
||||
+ uint8_t c = match_buf[--match_buf_len];
|
||||
+ if ((c & 0xc0) != 0x80) /* start of UTF-8 char? */
|
||||
+ break; /* yes */
|
||||
+ }
|
||||
+ } else {
|
||||
+ if (match_buf_len != 0)
|
||||
+ match_buf_len--;
|
||||
+ }
|
||||
+ match_buf[match_buf_len] = '\0';
|
||||
+ break;
|
||||
+
|
||||
+ default:
|
||||
+ if (ic < ' '
|
||||
+ || (!ENABLE_UNICODE_SUPPORT && ic >= 256)
|
||||
+ || (ENABLE_UNICODE_SUPPORT && ic >= VI_CMDMODE_BIT)
|
||||
+ ) {
|
||||
+ goto ret;
|
||||
+ }
|
||||
+
|
||||
+ /* Append this char */
|
||||
+#if ENABLE_UNICODE_SUPPORT
|
||||
+ if (unicode_status == UNICODE_ON) {
|
||||
+ mbstate_t mbstate = { 0 };
|
||||
+ char buf[MB_CUR_MAX + 1];
|
||||
+ int len = wcrtomb(buf, ic, &mbstate);
|
||||
+ if (len > 0) {
|
||||
+ buf[len] = '\0';
|
||||
+ if (match_buf_len + len < sizeof(match_buf))
|
||||
+ strcpy(match_buf + match_buf_len, buf);
|
||||
+ }
|
||||
+ } else
|
||||
+#endif
|
||||
+ if (match_buf_len < sizeof(match_buf) - 1) {
|
||||
+ match_buf[match_buf_len] = ic;
|
||||
+ match_buf[match_buf_len + 1] = '\0';
|
||||
+ }
|
||||
+ break;
|
||||
+ } /* switch (ic) */
|
||||
+
|
||||
+ /* Search in history for match_buf */
|
||||
+ h = state->cur_history;
|
||||
+ if (ic == CTRL('R'))
|
||||
+ h--;
|
||||
+ while (h >= 0) {
|
||||
+ if (state->history[h]) {
|
||||
+ char *match = strstr(state->history[h], match_buf);
|
||||
+ if (match) {
|
||||
+ state->cur_history = h;
|
||||
+ matched_history_line = state->history[h];
|
||||
+ command_len = load_string(matched_history_line);
|
||||
+ cursor = match - matched_history_line;
|
||||
+//FIXME: cursor position for Unicode case
|
||||
+
|
||||
+ free((char*)cmdedit_prompt);
|
||||
+ set_prompt:
|
||||
+ cmdedit_prompt = xasprintf("(reverse-i-search)'%s': ", match_buf);
|
||||
+ cmdedit_prmt_len = strlen(cmdedit_prompt);
|
||||
+ goto do_redraw;
|
||||
+ }
|
||||
+ }
|
||||
+ h--;
|
||||
+ }
|
||||
+
|
||||
+ /* Not found */
|
||||
+ match_buf[match_buf_len] = '\0';
|
||||
+ beep();
|
||||
+ continue;
|
||||
+
|
||||
+ do_redraw:
|
||||
+ redraw(cmdedit_y, command_len - cursor);
|
||||
+ } /* while (1) */
|
||||
+
|
||||
+ ret:
|
||||
+ if (matched_history_line)
|
||||
+ command_len = load_string(matched_history_line);
|
||||
+
|
||||
+ free((char*)cmdedit_prompt);
|
||||
+ cmdedit_prompt = saved_prompt;
|
||||
+ cmdedit_prmt_len = strlen(cmdedit_prompt);
|
||||
+ redraw(cmdedit_y, command_len - cursor);
|
||||
+
|
||||
+ return ic;
|
||||
+}
|
||||
+#endif
|
||||
+
|
||||
/* maxsize must be >= 2.
|
||||
* Returns:
|
||||
* -1 on read errors or EOF, or on bare Ctrl-D,
|
||||
@@ -2026,15 +2170,14 @@ int FAST_FUNC read_line_input(const char
|
||||
* clutters the big switch a bit, but keeps all the code
|
||||
* in one place.
|
||||
*/
|
||||
- enum {
|
||||
- VI_CMDMODE_BIT = 0x40000000,
|
||||
- /* 0x80000000 bit flags KEYCODE_xxx */
|
||||
- };
|
||||
int32_t ic, ic_raw;
|
||||
|
||||
fflush_all();
|
||||
ic = ic_raw = lineedit_read_key(read_key_buffer);
|
||||
|
||||
+#if ENABLE_FEATURE_REVERSE_SEARCH
|
||||
+ again:
|
||||
+#endif
|
||||
#if ENABLE_FEATURE_EDITING_VI
|
||||
newdelflag = 1;
|
||||
if (vi_cmdmode) {
|
||||
@@ -2138,6 +2281,11 @@ int FAST_FUNC read_line_input(const char
|
||||
while (cursor > 0 && !BB_isspace(command_ps[cursor-1]))
|
||||
input_backspace();
|
||||
break;
|
||||
+#if ENABLE_FEATURE_REVERSE_SEARCH
|
||||
+ case CTRL('R'):
|
||||
+ ic = ic_raw = reverse_i_search();
|
||||
+ goto again;
|
||||
+#endif
|
||||
|
||||
#if ENABLE_FEATURE_EDITING_VI
|
||||
case 'i'|VI_CMDMODE_BIT:
|
||||
@@ -2291,7 +2439,7 @@ int FAST_FUNC read_line_input(const char
|
||||
/* Rewrite the line with the selected history item */
|
||||
/* change command */
|
||||
command_len = load_string(state->history[state->cur_history] ?
|
||||
- state->history[state->cur_history] : "", maxsize);
|
||||
+ state->history[state->cur_history] : "");
|
||||
/* redraw and go to eol (bol, in vi) */
|
||||
redraw(cmdedit_y, (state->flags & VI_MODE) ? 9999 : 0);
|
||||
break;
|
||||
--- a/libbb/Config.src
|
||||
+++ b/libbb/Config.src
|
||||
@@ -93,6 +93,14 @@ config FEATURE_EDITING_SAVEHISTORY
|
||||
help
|
||||
Enable history saving in shells.
|
||||
|
||||
+config FEATURE_REVERSE_SEARCH
|
||||
+ bool "Reverse history search"
|
||||
+ default y
|
||||
+ depends on FEATURE_EDITING_SAVEHISTORY
|
||||
+ help
|
||||
+ Enable readline-like Ctrl-R combination for reverse history search.
|
||||
+ Increases code by about 0.5k.
|
||||
+
|
||||
config FEATURE_TAB_COMPLETION
|
||||
bool "Tab completion"
|
||||
default y
|
Loading…
Reference in New Issue
Block a user