Date:2011-08-19 22:22:47 (8 years 3 months ago)
Author:kyak
Commit:3368b5e9d143c3cf021ba6647bd15ee7cc312b27
Message:busybox: backport reverse history search patch

See https://dev.openwrt.org/ticket/9695
Files: package/busybox/config/libbb/Config.in (1 diff)
package/busybox/patches/910-insmod-q-flag.patch (3 diffs)
package/busybox/patches/911-libbb-lineedit-implement-optional-Ctrl-R-history-sea.patch (1 diff)

Change Details

package/busybox/config/libbb/Config.in
9191    help
9292      Enable history saving in shells.
9393
94config BUSYBOX_CONFIG_FEATURE_REVERSE_SEARCH
95    bool "Reverse history search"
96    default n
97    depends on BUSYBOX_CONFIG_FEATURE_EDITING_SAVEHISTORY
98    help
99      Enable readline-like Ctrl-R combination for reverse history search.
100      Increases code by about 0.5k.
101
94102config BUSYBOX_CONFIG_FEATURE_TAB_COMPLETION
95103    bool "Tab completion"
96104    default y
package/busybox/patches/910-insmod-q-flag.patch
11--- a/modutils/insmod.c
22+++ b/modutils/insmod.c
3@@ -133,7 +133,7 @@ int insmod_main(int argc, char **argv) M
3@@ -140,7 +140,7 @@ int insmod_main(int argc, char **argv) M
44 int insmod_main(int argc UNUSED_PARAM, char **argv)
55 {
66     char *filename;
...... 
99
1010     /* Compat note:
1111      * 2.6 style insmod has no options and required filename
12@@ -143,10 +143,8 @@ int insmod_main(int argc UNUSED_PARAM, c
12@@ -150,10 +150,8 @@ int insmod_main(int argc UNUSED_PARAM, c
1313      * or in $MODPATH.
1414      */
1515
...... 
2222
2323     filename = *++argv;
2424     if (!filename)
25@@ -157,7 +155,7 @@ int insmod_main(int argc UNUSED_PARAM, c
25@@ -164,7 +162,7 @@ int insmod_main(int argc UNUSED_PARAM, c
2626             goto done;
2727
2828     rc = bb_init_module(g_filename, parse_cmdline_module_options(argv));
package/busybox/patches/911-libbb-lineedit-implement-optional-Ctrl-R-history-sea.patch
1--- a/libbb/lineedit.c
2@@ -202,13 +202,23 @@ static void deinit_S(void)
3
4
5 #if ENABLE_UNICODE_SUPPORT
6-static size_t load_string(const char *src, int maxsize)
7+static size_t load_string(const char *src)
8 {
9- ssize_t len = mbstowcs(command_ps, src, maxsize - 1);
10- if (len < 0)
11- len = 0;
12- command_ps[len] = BB_NUL;
13- return len;
14+ if (unicode_status == UNICODE_ON) {
15+ ssize_t len = mbstowcs(command_ps, src, S.maxsize - 1);
16+ if (len < 0)
17+ len = 0;
18+ command_ps[len] = BB_NUL;
19+ return len;
20+ } else {
21+ unsigned i = 0;
22+ while (src[i] && i < S.maxsize - 1) {
23+ command_ps[i] = src[i];
24+ i++;
25+ }
26+ command_ps[i] = BB_NUL;
27+ return i;
28+ }
29 }
30 static unsigned save_string(char *dst, unsigned maxsize)
31 {
32@@ -297,9 +307,9 @@ static wchar_t adjust_width_and_validate
33     return wc;
34 }
35 #else /* !UNICODE */
36-static size_t load_string(const char *src, int maxsize)
37+static size_t load_string(const char *src)
38 {
39- safe_strncpy(command_ps, src, maxsize);
40+ safe_strncpy(command_ps, src, S.maxsize);
41     return strlen(command_ps);
42 }
43 # if ENABLE_FEATURE_TAB_COMPLETION
44@@ -1202,10 +1212,10 @@ static NOINLINE void input_tab(smallint
45             strcpy(match_buf, &command[cursor_mb]);
46             /* where do we want to have cursor after all? */
47             strcpy(&command[cursor_mb], chosen_match + match_pfx_len);
48- len = load_string(command, S.maxsize);
49+ len = load_string(command);
50             /* add match and tail */
51             sprintf(&command[cursor_mb], "%s%s", chosen_match + match_pfx_len, match_buf);
52- command_len = load_string(command, S.maxsize);
53+ command_len = load_string(command);
54             /* write out the matched command */
55             /* paranoia: load_string can return 0 on conv error,
56              * prevent passing pos = (0 - 12) to redraw */
57@@ -1911,6 +1921,140 @@ static int isrtl_str(void)
58 #undef CTRL
59 #define CTRL(a) ((a) & ~0x40)
60
61+enum {
62+ VI_CMDMODE_BIT = 0x40000000,
63+ /* 0x80000000 bit flags KEYCODE_xxx */
64+};
65+
66+#if ENABLE_FEATURE_REVERSE_SEARCH
67+/* Mimic readline Ctrl-R reverse history search.
68+ * When invoked, it shows the following prompt:
69+ * (reverse-i-search)'': user_input [cursor pos unchanged by Ctrl-R]
70+ * and typing results in search being performed:
71+ * (reverse-i-search)'tmp': cd /tmp [cursor under t in /tmp]
72+ * Search is performed by looking at progressively older lines in history.
73+ * Ctrl-R again searches for the next match in history.
74+ * Backspace deletes last matched char.
75+ * Control keys exit search and return to normal editing (at current history line).
76+ */
77+static int32_t reverse_i_search(void)
78+{
79+ char match_buf[128]; /* for user input */
80+ char read_key_buffer[KEYCODE_BUFFER_SIZE];
81+ const char *matched_history_line;
82+ const char *saved_prompt;
83+ int32_t ic;
84+
85+ matched_history_line = NULL;
86+ read_key_buffer[0] = 0;
87+ match_buf[0] = '\0';
88+
89+ /* Save and replace the prompt */
90+ saved_prompt = cmdedit_prompt;
91+ goto set_prompt;
92+
93+ while (1) {
94+ int h;
95+ unsigned match_buf_len = strlen(match_buf);
96+
97+ fflush_all();
98+//FIXME: correct timeout?
99+ ic = lineedit_read_key(read_key_buffer);
100+
101+ switch (ic) {
102+ case CTRL('R'): /* searching for the next match */
103+ break;
104+
105+ case '\b':
106+ case '\x7f':
107+ /* Backspace */
108+ if (unicode_status == UNICODE_ON) {
109+ while (match_buf_len != 0) {
110+ uint8_t c = match_buf[--match_buf_len];
111+ if ((c & 0xc0) != 0x80) /* start of UTF-8 char? */
112+ break; /* yes */
113+ }
114+ } else {
115+ if (match_buf_len != 0)
116+ match_buf_len--;
117+ }
118+ match_buf[match_buf_len] = '\0';
119+ break;
120+
121+ default:
122+ if (ic < ' '
123+ || (!ENABLE_UNICODE_SUPPORT && ic >= 256)
124+ || (ENABLE_UNICODE_SUPPORT && ic >= VI_CMDMODE_BIT)
125+ ) {
126+ goto ret;
127+ }
128+
129+ /* Append this char */
130+#if ENABLE_UNICODE_SUPPORT
131+ if (unicode_status == UNICODE_ON) {
132+ mbstate_t mbstate = { 0 };
133+ char buf[MB_CUR_MAX + 1];
134+ int len = wcrtomb(buf, ic, &mbstate);
135+ if (len > 0) {
136+ buf[len] = '\0';
137+ if (match_buf_len + len < sizeof(match_buf))
138+ strcpy(match_buf + match_buf_len, buf);
139+ }
140+ } else
141+#endif
142+ if (match_buf_len < sizeof(match_buf) - 1) {
143+ match_buf[match_buf_len] = ic;
144+ match_buf[match_buf_len + 1] = '\0';
145+ }
146+ break;
147+ } /* switch (ic) */
148+
149+ /* Search in history for match_buf */
150+ h = state->cur_history;
151+ if (ic == CTRL('R'))
152+ h--;
153+ while (h >= 0) {
154+ if (state->history[h]) {
155+ char *match = strstr(state->history[h], match_buf);
156+ if (match) {
157+ state->cur_history = h;
158+ matched_history_line = state->history[h];
159+ command_len = load_string(matched_history_line);
160+ cursor = match - matched_history_line;
161+//FIXME: cursor position for Unicode case
162+
163+ free((char*)cmdedit_prompt);
164+ set_prompt:
165+ cmdedit_prompt = xasprintf("(reverse-i-search)'%s': ", match_buf);
166+ cmdedit_prmt_len = strlen(cmdedit_prompt);
167+ goto do_redraw;
168+ }
169+ }
170+ h--;
171+ }
172+
173+ /* Not found */
174+ match_buf[match_buf_len] = '\0';
175+ beep();
176+ continue;
177+
178+ do_redraw:
179+ redraw(cmdedit_y, command_len - cursor);
180+ } /* while (1) */
181+
182+ ret:
183+ if (matched_history_line)
184+ command_len = load_string(matched_history_line);
185+
186+ free((char*)cmdedit_prompt);
187+ cmdedit_prompt = saved_prompt;
188+ cmdedit_prmt_len = strlen(cmdedit_prompt);
189+ redraw(cmdedit_y, command_len - cursor);
190+
191+ return ic;
192+}
193+#endif
194+
195 /* maxsize must be >= 2.
196  * Returns:
197  * -1 on read errors or EOF, or on bare Ctrl-D,
198@@ -2026,15 +2170,14 @@ int FAST_FUNC read_line_input(const char
199          * clutters the big switch a bit, but keeps all the code
200          * in one place.
201          */
202- enum {
203- VI_CMDMODE_BIT = 0x40000000,
204- /* 0x80000000 bit flags KEYCODE_xxx */
205- };
206         int32_t ic, ic_raw;
207
208         fflush_all();
209         ic = ic_raw = lineedit_read_key(read_key_buffer);
210
211+#if ENABLE_FEATURE_REVERSE_SEARCH
212+ again:
213+#endif
214 #if ENABLE_FEATURE_EDITING_VI
215         newdelflag = 1;
216         if (vi_cmdmode) {
217@@ -2138,6 +2281,11 @@ int FAST_FUNC read_line_input(const char
218             while (cursor > 0 && !BB_isspace(command_ps[cursor-1]))
219                 input_backspace();
220             break;
221+#if ENABLE_FEATURE_REVERSE_SEARCH
222+ case CTRL('R'):
223+ ic = ic_raw = reverse_i_search();
224+ goto again;
225+#endif
226
227 #if ENABLE_FEATURE_EDITING_VI
228         case 'i'|VI_CMDMODE_BIT:
229@@ -2291,7 +2439,7 @@ int FAST_FUNC read_line_input(const char
230             /* Rewrite the line with the selected history item */
231             /* change command */
232             command_len = load_string(state->history[state->cur_history] ?
233- state->history[state->cur_history] : "", maxsize);
234+ state->history[state->cur_history] : "");
235             /* redraw and go to eol (bol, in vi) */
236             redraw(cmdedit_y, (state->flags & VI_MODE) ? 9999 : 0);
237             break;
238--- a/libbb/Config.src
239@@ -93,6 +93,14 @@ config FEATURE_EDITING_SAVEHISTORY
240     help
241       Enable history saving in shells.
242
243+config FEATURE_REVERSE_SEARCH
244+ bool "Reverse history search"
245+ default y
246+ depends on FEATURE_EDITING_SAVEHISTORY
247+ help
248+ Enable readline-like Ctrl-R combination for reverse history search.
249+ Increases code by about 0.5k.
250+
251 config FEATURE_TAB_COMPLETION
252     bool "Tab completion"
253     default y

Archive Download the corresponding diff file



interactive