diff options
author | Denys Vlasenko <vda.linux@googlemail.com> | 2013-08-19 16:45:04 +0200 |
---|---|---|
committer | Denys Vlasenko <vda.linux@googlemail.com> | 2013-08-19 16:45:04 +0200 |
commit | e66a56de23fd08907f324d79e61ed2930ea5c350 (patch) | |
tree | 8cca369a09ef4f638d79c0153c10da2ca8b22928 | |
parent | 7a18043a968ec6d4b8c4c8cac059ad977d14e47c (diff) | |
download | busybox-w32-e66a56de23fd08907f324d79e61ed2930ea5c350.tar.gz busybox-w32-e66a56de23fd08907f324d79e61ed2930ea5c350.tar.bz2 busybox-w32-e66a56de23fd08907f324d79e61ed2930ea5c350.zip |
lineedit: fix multi-line PS1 handling: calculate PS1 length from last \n
function old new delta
parse_and_put_prompt 755 774 +19
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
-rw-r--r-- | libbb/lineedit.c | 44 |
1 files changed, 30 insertions, 14 deletions
diff --git a/libbb/lineedit.c b/libbb/lineedit.c index ecf3066b1..b3f16cd9d 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" |
@@ -1759,34 +1767,36 @@ static void ask_terminal(void) | |||
1759 | #define ask_terminal() ((void)0) | 1767 | #define ask_terminal() ((void)0) |
1760 | #endif | 1768 | #endif |
1761 | 1769 | ||
1770 | /* Called just once at read_line_input() init time */ | ||
1762 | #if !ENABLE_FEATURE_EDITING_FANCY_PROMPT | 1771 | #if !ENABLE_FEATURE_EDITING_FANCY_PROMPT |
1763 | static void parse_and_put_prompt(const char *prmt_ptr) | 1772 | static void parse_and_put_prompt(const char *prmt_ptr) |
1764 | { | 1773 | { |
1774 | const char *p; | ||
1765 | cmdedit_prompt = prmt_ptr; | 1775 | cmdedit_prompt = prmt_ptr; |
1766 | cmdedit_prmt_len = unicode_strlen(prmt_ptr); | 1776 | p = strrchr(prmt_ptr, '\n'); |
1777 | cmdedit_prmt_len = unicode_strlen(p ? p+1 : prmt_ptr); | ||
1767 | put_prompt(); | 1778 | put_prompt(); |
1768 | } | 1779 | } |
1769 | #else | 1780 | #else |
1770 | static void parse_and_put_prompt(const char *prmt_ptr) | 1781 | static void parse_and_put_prompt(const char *prmt_ptr) |
1771 | { | 1782 | { |
1772 | int prmt_len = 0; | 1783 | int prmt_size = 0; |
1773 | size_t cur_prmt_len = 0; | ||
1774 | char flg_not_length = '['; | ||
1775 | char *prmt_mem_ptr = xzalloc(1); | 1784 | char *prmt_mem_ptr = xzalloc(1); |
1776 | # if ENABLE_USERNAME_OR_HOMEDIR | 1785 | # if ENABLE_USERNAME_OR_HOMEDIR |
1777 | char *cwd_buf = NULL; | 1786 | char *cwd_buf = NULL; |
1778 | # endif | 1787 | # endif |
1779 | char timebuf[sizeof("HH:MM:SS")]; | 1788 | char flg_not_length = '['; |
1780 | char cbuf[2]; | 1789 | char cbuf[2]; |
1781 | char c; | ||
1782 | char *pbuf; | ||
1783 | 1790 | ||
1784 | /*cmdedit_prmt_len = 0; - already is */ | 1791 | /*cmdedit_prmt_len = 0; - already is */ |
1785 | 1792 | ||
1786 | cbuf[1] = '\0'; /* never changes */ | 1793 | cbuf[1] = '\0'; /* never changes */ |
1787 | 1794 | ||
1788 | while (*prmt_ptr) { | 1795 | while (*prmt_ptr) { |
1796 | char timebuf[sizeof("HH:MM:SS")]; | ||
1789 | char *free_me = NULL; | 1797 | char *free_me = NULL; |
1798 | char *pbuf; | ||
1799 | char c; | ||
1790 | 1800 | ||
1791 | pbuf = cbuf; | 1801 | pbuf = cbuf; |
1792 | c = *prmt_ptr++; | 1802 | c = *prmt_ptr++; |
@@ -1924,16 +1934,22 @@ static void parse_and_put_prompt(const char *prmt_ptr) | |||
1924 | } /* if */ | 1934 | } /* if */ |
1925 | } /* if */ | 1935 | } /* if */ |
1926 | cbuf[0] = c; | 1936 | cbuf[0] = c; |
1927 | cur_prmt_len = strlen(pbuf); | 1937 | { |
1928 | prmt_len += cur_prmt_len; | 1938 | int n = strlen(pbuf); |
1929 | if (flg_not_length != ']') { | 1939 | prmt_size += n; |
1930 | #if 0 /*ENABLE_UNICODE_SUPPORT - won't work, pbuf is one BYTE string here. FIXME */ | 1940 | if (c == '\n') |
1931 | cmdedit_prmt_len += unicode_strlen(pbuf); | 1941 | cmdedit_prmt_len = 0; |
1942 | else if (flg_not_length != ']') { | ||
1943 | #if 0 /*ENABLE_UNICODE_SUPPORT*/ | ||
1944 | /* Won't work, pbuf is one BYTE string here instead of an one Unicode char string. */ | ||
1945 | /* FIXME */ | ||
1946 | cmdedit_prmt_len += unicode_strlen(pbuf); | ||
1932 | #else | 1947 | #else |
1933 | cmdedit_prmt_len += cur_prmt_len; | 1948 | cmdedit_prmt_len += n; |
1934 | #endif | 1949 | #endif |
1950 | } | ||
1935 | } | 1951 | } |
1936 | prmt_mem_ptr = strcat(xrealloc(prmt_mem_ptr, prmt_len+1), pbuf); | 1952 | prmt_mem_ptr = strcat(xrealloc(prmt_mem_ptr, prmt_size+1), pbuf); |
1937 | free(free_me); | 1953 | free(free_me); |
1938 | } /* while */ | 1954 | } /* while */ |
1939 | 1955 | ||