diff options
author | Ron Yorston <rmy@pobox.com> | 2013-08-27 16:10:53 +0100 |
---|---|---|
committer | Ron Yorston <rmy@pobox.com> | 2013-08-27 16:10:53 +0100 |
commit | 3fd34651ea72ea1c335d3170f234cb0517fd897f (patch) | |
tree | 36e8fc40cffd464ffda4759020777dd3ca23ca31 /libbb/lineedit.c | |
parent | e3ac39098326de084a805d0dd31db9666b734f20 (diff) | |
parent | d6ae4fb446daedfe3073d67be655942e9fa7eb18 (diff) | |
download | busybox-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.c | 82 |
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 | ||
1271 | unsigned size_from_HISTFILESIZE(const char *hp) | 1279 | unsigned 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 */ | ||
1335 | void 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 |
1766 | static void parse_and_put_prompt(const char *prmt_ptr) | 1786 | static 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 |
1773 | static void parse_and_put_prompt(const char *prmt_ptr) | 1795 | static 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'; |