aboutsummaryrefslogtreecommitdiff
path: root/libbb/lineedit.c
diff options
context:
space:
mode:
authorRon Yorston <rmy@pobox.com>2013-08-27 16:10:53 +0100
committerRon Yorston <rmy@pobox.com>2013-08-27 16:10:53 +0100
commit3fd34651ea72ea1c335d3170f234cb0517fd897f (patch)
tree36e8fc40cffd464ffda4759020777dd3ca23ca31 /libbb/lineedit.c
parente3ac39098326de084a805d0dd31db9666b734f20 (diff)
parentd6ae4fb446daedfe3073d67be655942e9fa7eb18 (diff)
downloadbusybox-w32-3fd34651ea72ea1c335d3170f234cb0517fd897f.tar.gz
busybox-w32-3fd34651ea72ea1c335d3170f234cb0517fd897f.tar.bz2
busybox-w32-3fd34651ea72ea1c335d3170f234cb0517fd897f.zip
Merge branch 'busybox' into merge
Diffstat (limited to 'libbb/lineedit.c')
-rw-r--r--libbb/lineedit.c82
1 files changed, 63 insertions, 19 deletions
diff --git a/libbb/lineedit.c b/libbb/lineedit.c
index 7f64a9691..20d75cf56 100644
--- a/libbb/lineedit.c
+++ b/libbb/lineedit.c
@@ -38,6 +38,14 @@
38 * and the \] escape to signal the end of such a sequence. Example: 38 * and the \] escape to signal the end of such a sequence. Example:
39 * 39 *
40 * PS1='\[\033[01;32m\]\u@\h\[\033[01;34m\] \w \$\[\033[00m\] ' 40 * PS1='\[\033[01;32m\]\u@\h\[\033[01;34m\] \w \$\[\033[00m\] '
41 *
42 * Unicode in PS1 is not fully supported: prompt length calulation is wrong,
43 * resulting in line wrap problems with long (multi-line) input.
44 *
45 * Multi-line PS1 (e.g. PS1="\n[\w]\n$ ") has problems with history
46 * browsing: up/down arrows result in scrolling.
47 * It stems from simplistic "cmdedit_y = cmdedit_prmt_len / cmdedit_termw"
48 * calculation of how many lines the prompt takes.
41 */ 49 */
42#include "libbb.h" 50#include "libbb.h"
43#include "unicode.h" 51#include "unicode.h"
@@ -1268,7 +1276,7 @@ line_input_t* FAST_FUNC new_line_input_t(int flags)
1268 1276
1269#if MAX_HISTORY > 0 1277#if MAX_HISTORY > 0
1270 1278
1271unsigned size_from_HISTFILESIZE(const char *hp) 1279unsigned FAST_FUNC size_from_HISTFILESIZE(const char *hp)
1272{ 1280{
1273 int size = MAX_HISTORY; 1281 int size = MAX_HISTORY;
1274 if (hp) { 1282 if (hp) {
@@ -1323,6 +1331,17 @@ static int get_next_history(void)
1323 return 0; 1331 return 0;
1324} 1332}
1325 1333
1334/* Lists command history. Used by shell 'history' builtins */
1335void FAST_FUNC show_history(const line_input_t *st)
1336{
1337 int i;
1338
1339 if (!st)
1340 return;
1341 for (i = 0; i < st->cnt_history; i++)
1342 printf("%4d %s\n", i, st->history[i]);
1343}
1344
1326# if ENABLE_FEATURE_EDITING_SAVEHISTORY 1345# if ENABLE_FEATURE_EDITING_SAVEHISTORY
1327/* We try to ensure that concurrent additions to the history 1346/* We try to ensure that concurrent additions to the history
1328 * do not overwrite each other. 1347 * do not overwrite each other.
@@ -1762,34 +1781,36 @@ static void ask_terminal(void)
1762#define ask_terminal() ((void)0) 1781#define ask_terminal() ((void)0)
1763#endif 1782#endif
1764 1783
1784/* Called just once at read_line_input() init time */
1765#if !ENABLE_FEATURE_EDITING_FANCY_PROMPT 1785#if !ENABLE_FEATURE_EDITING_FANCY_PROMPT
1766static void parse_and_put_prompt(const char *prmt_ptr) 1786static void parse_and_put_prompt(const char *prmt_ptr)
1767{ 1787{
1788 const char *p;
1768 cmdedit_prompt = prmt_ptr; 1789 cmdedit_prompt = prmt_ptr;
1769 cmdedit_prmt_len = strlen(prmt_ptr); 1790 p = strrchr(prmt_ptr, '\n');
1791 cmdedit_prmt_len = unicode_strwidth(p ? p+1 : prmt_ptr);
1770 put_prompt(); 1792 put_prompt();
1771} 1793}
1772#else 1794#else
1773static void parse_and_put_prompt(const char *prmt_ptr) 1795static void parse_and_put_prompt(const char *prmt_ptr)
1774{ 1796{
1775 int prmt_len = 0; 1797 int prmt_size = 0;
1776 size_t cur_prmt_len = 0;
1777 char flg_not_length = '[';
1778 char *prmt_mem_ptr = xzalloc(1); 1798 char *prmt_mem_ptr = xzalloc(1);
1779# if ENABLE_USERNAME_OR_HOMEDIR 1799# if ENABLE_USERNAME_OR_HOMEDIR
1780 char *cwd_buf = NULL; 1800 char *cwd_buf = NULL;
1781# endif 1801# endif
1782 char timebuf[sizeof("HH:MM:SS")]; 1802 char flg_not_length = '[';
1783 char cbuf[2]; 1803 char cbuf[2];
1784 char c;
1785 char *pbuf;
1786 1804
1787 cmdedit_prmt_len = 0; 1805 /*cmdedit_prmt_len = 0; - already is */
1788 1806
1789 cbuf[1] = '\0'; /* never changes */ 1807 cbuf[1] = '\0'; /* never changes */
1790 1808
1791 while (*prmt_ptr) { 1809 while (*prmt_ptr) {
1810 char timebuf[sizeof("HH:MM:SS")];
1792 char *free_me = NULL; 1811 char *free_me = NULL;
1812 char *pbuf;
1813 char c;
1793 1814
1794 pbuf = cbuf; 1815 pbuf = cbuf;
1795 c = *prmt_ptr++; 1816 c = *prmt_ptr++;
@@ -1922,7 +1943,8 @@ static void parse_and_put_prompt(const char *prmt_ptr)
1922 } 1943 }
1923 case '[': case ']': 1944 case '[': case ']':
1924 if (c == flg_not_length) { 1945 if (c == flg_not_length) {
1925 flg_not_length = (flg_not_length == '[' ? ']' : '['); 1946 /* Toggle '['/']' hex 5b/5d */
1947 flg_not_length ^= 6;
1926 continue; 1948 continue;
1927 } 1949 }
1928 break; 1950 break;
@@ -1930,11 +1952,22 @@ static void parse_and_put_prompt(const char *prmt_ptr)
1930 } /* if */ 1952 } /* if */
1931 } /* if */ 1953 } /* if */
1932 cbuf[0] = c; 1954 cbuf[0] = c;
1933 cur_prmt_len = strlen(pbuf); 1955 {
1934 prmt_len += cur_prmt_len; 1956 int n = strlen(pbuf);
1935 if (flg_not_length != ']') 1957 prmt_size += n;
1936 cmdedit_prmt_len += cur_prmt_len; 1958 if (c == '\n')
1937 prmt_mem_ptr = strcat(xrealloc(prmt_mem_ptr, prmt_len+1), pbuf); 1959 cmdedit_prmt_len = 0;
1960 else if (flg_not_length != ']') {
1961#if 0 /*ENABLE_UNICODE_SUPPORT*/
1962/* Won't work, pbuf is one BYTE string here instead of an one Unicode char string. */
1963/* FIXME */
1964 cmdedit_prmt_len += unicode_strwidth(pbuf);
1965#else
1966 cmdedit_prmt_len += n;
1967#endif
1968 }
1969 }
1970 prmt_mem_ptr = strcat(xrealloc(prmt_mem_ptr, prmt_size+1), pbuf);
1938 free(free_me); 1971 free(free_me);
1939 } /* while */ 1972 } /* while */
1940 1973
@@ -2003,7 +2036,15 @@ static int lineedit_read_key(char *read_key_buffer, int timeout)
2003 S.sent_ESC_br6n = 0; 2036 S.sent_ESC_br6n = 0;
2004 if (cursor == 0) { /* otherwise it may be bogus */ 2037 if (cursor == 0) { /* otherwise it may be bogus */
2005 int col = ((ic >> 32) & 0x7fff) - 1; 2038 int col = ((ic >> 32) & 0x7fff) - 1;
2006 if (col > cmdedit_prmt_len) { 2039 /*
2040 * Is col > cmdedit_prmt_len?
2041 * If yes (terminal says cursor is farther to the right
2042 * of where we think it should be),
2043 * the prompt wasn't printed starting at col 1,
2044 * there was additional text before it.
2045 */
2046 if ((int)(col - cmdedit_prmt_len) > 0) {
2047 /* Fix our understanding of current x position */
2007 cmdedit_x += (col - cmdedit_prmt_len); 2048 cmdedit_x += (col - cmdedit_prmt_len);
2008 while (cmdedit_x >= cmdedit_termw) { 2049 while (cmdedit_x >= cmdedit_termw) {
2009 cmdedit_x -= cmdedit_termw; 2050 cmdedit_x -= cmdedit_termw;
@@ -2094,6 +2135,7 @@ static int32_t reverse_i_search(void)
2094 char read_key_buffer[KEYCODE_BUFFER_SIZE]; 2135 char read_key_buffer[KEYCODE_BUFFER_SIZE];
2095 const char *matched_history_line; 2136 const char *matched_history_line;
2096 const char *saved_prompt; 2137 const char *saved_prompt;
2138 unsigned saved_prmt_len;
2097 int32_t ic; 2139 int32_t ic;
2098 2140
2099 matched_history_line = NULL; 2141 matched_history_line = NULL;
@@ -2102,6 +2144,7 @@ static int32_t reverse_i_search(void)
2102 2144
2103 /* Save and replace the prompt */ 2145 /* Save and replace the prompt */
2104 saved_prompt = cmdedit_prompt; 2146 saved_prompt = cmdedit_prompt;
2147 saved_prmt_len = cmdedit_prmt_len;
2105 goto set_prompt; 2148 goto set_prompt;
2106 2149
2107 while (1) { 2150 while (1) {
@@ -2177,7 +2220,7 @@ static int32_t reverse_i_search(void)
2177 free((char*)cmdedit_prompt); 2220 free((char*)cmdedit_prompt);
2178 set_prompt: 2221 set_prompt:
2179 cmdedit_prompt = xasprintf("(reverse-i-search)'%s': ", match_buf); 2222 cmdedit_prompt = xasprintf("(reverse-i-search)'%s': ", match_buf);
2180 cmdedit_prmt_len = strlen(cmdedit_prompt); 2223 cmdedit_prmt_len = unicode_strwidth(cmdedit_prompt);
2181 goto do_redraw; 2224 goto do_redraw;
2182 } 2225 }
2183 } 2226 }
@@ -2199,7 +2242,7 @@ static int32_t reverse_i_search(void)
2199 2242
2200 free((char*)cmdedit_prompt); 2243 free((char*)cmdedit_prompt);
2201 cmdedit_prompt = saved_prompt; 2244 cmdedit_prompt = saved_prompt;
2202 cmdedit_prmt_len = strlen(cmdedit_prompt); 2245 cmdedit_prmt_len = saved_prmt_len;
2203 redraw(cmdedit_y, command_len - cursor); 2246 redraw(cmdedit_y, command_len - cursor);
2204 2247
2205 return ic; 2248 return ic;
@@ -2774,8 +2817,9 @@ int FAST_FUNC read_line_input(line_input_t *st, const char *prompt, char *comman
2774 free(command_ps); 2817 free(command_ps);
2775#endif 2818#endif
2776 2819
2777 if (command_len > 0) 2820 if (command_len > 0) {
2778 remember_in_history(command); 2821 remember_in_history(command);
2822 }
2779 2823
2780 if (break_out > 0) { 2824 if (break_out > 0) {
2781 command[command_len++] = '\n'; 2825 command[command_len++] = '\n';