From 3368b5e9d143c3cf021ba6647bd15ee7cc312b27 Mon Sep 17 00:00:00 2001 From: kyak Date: Sat, 20 Aug 2011 00:22:47 +0400 Subject: [PATCH] busybox: backport reverse history search patch See https://dev.openwrt.org/ticket/9695 --- package/busybox/config/libbb/Config.in | 8 + .../busybox/patches/910-insmod-q-flag.patch | 6 +- ...mplement-optional-Ctrl-R-history-sea.patch | 255 ++++++++++++++++++ 3 files changed, 266 insertions(+), 3 deletions(-) create mode 100644 package/busybox/patches/911-libbb-lineedit-implement-optional-Ctrl-R-history-sea.patch diff --git a/package/busybox/config/libbb/Config.in b/package/busybox/config/libbb/Config.in index a3c9641c4..e3568eee6 100644 --- a/package/busybox/config/libbb/Config.in +++ b/package/busybox/config/libbb/Config.in @@ -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 diff --git a/package/busybox/patches/910-insmod-q-flag.patch b/package/busybox/patches/910-insmod-q-flag.patch index 596fe910d..716d4c2ba 100644 --- a/package/busybox/patches/910-insmod-q-flag.patch +++ b/package/busybox/patches/910-insmod-q-flag.patch @@ -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)); diff --git a/package/busybox/patches/911-libbb-lineedit-implement-optional-Ctrl-R-history-sea.patch b/package/busybox/patches/911-libbb-lineedit-implement-optional-Ctrl-R-history-sea.patch new file mode 100644 index 000000000..d14fdaf40 --- /dev/null +++ b/package/busybox/patches/911-libbb-lineedit-implement-optional-Ctrl-R-history-sea.patch @@ -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