diff options
author | Paul Fox <pgf@brightstareng.com> | 2008-03-06 01:34:23 +0000 |
---|---|---|
committer | Paul Fox <pgf@brightstareng.com> | 2008-03-06 01:34:23 +0000 |
commit | c51fc7bed6d6555997fdfb3879f42c6b1191465c (patch) | |
tree | f4819ba9be3b4ad6a8744775dc69631f0477312a | |
parent | b4a5087ee006bfee20c7272e92322f9f6377d042 (diff) | |
download | busybox-w32-c51fc7bed6d6555997fdfb3879f42c6b1191465c.tar.gz busybox-w32-c51fc7bed6d6555997fdfb3879f42c6b1191465c.tar.bz2 busybox-w32-c51fc7bed6d6555997fdfb3879f42c6b1191465c.zip |
fixed the "dot" (i.e. '.') command, to properly re-init its
buffer between commands, not recalculate its length all the time,
and to not reallocate its fixed-length buffer frequently.
fixed the 'c', 'd', and 'y' commands to properly handle both motions
that are just part of a line, and those that are multiline. for
instance, now "c%" and "2cw" work correctly, whether the motions span
lines or not.
added some permissble motions for 'c', 'd', and 'y': namely 'h',
'l', SPACE, BS, and DEL
-rw-r--r-- | editors/vi.c | 123 |
1 files changed, 65 insertions, 58 deletions
diff --git a/editors/vi.c b/editors/vi.c index 31ad96c02..d9db94322 100644 --- a/editors/vi.c +++ b/editors/vi.c | |||
@@ -170,6 +170,7 @@ static smallint readonly_mode = 0; | |||
170 | #if ENABLE_FEATURE_VI_DOT_CMD | 170 | #if ENABLE_FEATURE_VI_DOT_CMD |
171 | static smallint adding2q; // are we currently adding user input to q | 171 | static smallint adding2q; // are we currently adding user input to q |
172 | static char *last_modifying_cmd; // [MAX_INPUT_LEN] last modifying cmd for "." | 172 | static char *last_modifying_cmd; // [MAX_INPUT_LEN] last modifying cmd for "." |
173 | static smallint lmc_len; // length of last_modifying_cmd | ||
173 | static char *ioq, *ioq_start; // pointer to string for get_one_char to "read" | 174 | static char *ioq, *ioq_start; // pointer to string for get_one_char to "read" |
174 | #endif | 175 | #endif |
175 | #if ENABLE_FEATURE_VI_OPTIMIZE_CURSOR | 176 | #if ENABLE_FEATURE_VI_OPTIMIZE_CURSOR |
@@ -262,7 +263,7 @@ static char *bound_dot(char *); // make sure text[0] <= P < "end" | |||
262 | static char *new_screen(int, int); // malloc virtual screen memory | 263 | static char *new_screen(int, int); // malloc virtual screen memory |
263 | static char *char_insert(char *, char); // insert the char c at 'p' | 264 | static char *char_insert(char *, char); // insert the char c at 'p' |
264 | static char *stupid_insert(char *, char); // stupidly insert the char c at 'p' | 265 | static char *stupid_insert(char *, char); // stupidly insert the char c at 'p' |
265 | static char find_range(char **, char **, char); // return pointers for an object | 266 | static int find_range(char **, char **, char); // return pointers for an object |
266 | static int st_test(char *, int, int, char *); // helper for skip_thing() | 267 | static int st_test(char *, int, int, char *); // helper for skip_thing() |
267 | static char *skip_thing(char *, int, int, int); // skip some object | 268 | static char *skip_thing(char *, int, int, int); // skip some object |
268 | static char *find_pair(char *, char); // find matching pair () [] {} | 269 | static char *find_pair(char *, char); // find matching pair () [] {} |
@@ -526,9 +527,9 @@ static void edit_file(char *fn) | |||
526 | offset = 0; // no horizontal offset | 527 | offset = 0; // no horizontal offset |
527 | c = '\0'; | 528 | c = '\0'; |
528 | #if ENABLE_FEATURE_VI_DOT_CMD | 529 | #if ENABLE_FEATURE_VI_DOT_CMD |
529 | free(last_modifying_cmd); | ||
530 | free(ioq_start); | 530 | free(ioq_start); |
531 | ioq = ioq_start = last_modifying_cmd = NULL; | 531 | ioq = ioq_start = NULL; |
532 | lmc_len = 0; | ||
532 | adding2q = 0; | 533 | adding2q = 0; |
533 | #endif | 534 | #endif |
534 | redraw(FALSE); // dont force every col re-draw | 535 | redraw(FALSE); // dont force every col re-draw |
@@ -1662,10 +1663,10 @@ static char *stupid_insert(char * p, char c) // stupidly insert the char c at 'p | |||
1662 | return p; | 1663 | return p; |
1663 | } | 1664 | } |
1664 | 1665 | ||
1665 | static char find_range(char ** start, char ** stop, char c) | 1666 | static int find_range(char ** start, char ** stop, char c) |
1666 | { | 1667 | { |
1667 | char *save_dot, *p, *q; | 1668 | char *save_dot, *p, *q, *t; |
1668 | int cnt; | 1669 | int cnt, multiline = 0; |
1669 | 1670 | ||
1670 | save_dot = dot; | 1671 | save_dot = dot; |
1671 | p = q = dot; | 1672 | p = q = dot; |
@@ -1677,7 +1678,7 @@ static char find_range(char ** start, char ** stop, char c) | |||
1677 | q = next_line(q); | 1678 | q = next_line(q); |
1678 | } | 1679 | } |
1679 | q = end_line(q); | 1680 | q = end_line(q); |
1680 | } else if (strchr("^%$0bBeEft", c)) { | 1681 | } else if (strchr("^%$0bBeEfth\b\177", c)) { |
1681 | // These cmds operate on char positions | 1682 | // These cmds operate on char positions |
1682 | do_cmd(c); // execute movement cmd | 1683 | do_cmd(c); // execute movement cmd |
1683 | q = dot; | 1684 | q = dot; |
@@ -1706,17 +1707,33 @@ static char find_range(char ** start, char ** stop, char c) | |||
1706 | dot_end(); // find NL | 1707 | dot_end(); // find NL |
1707 | q = dot; | 1708 | q = dot; |
1708 | } else { | 1709 | } else { |
1709 | c = 27; // error- return an ESC char | 1710 | // nothing -- this causes any other values of c to |
1710 | //break; | 1711 | // represent the one-character range under the |
1712 | // cursor. this is correct for ' ' and 'l', but | ||
1713 | // perhaps no others. | ||
1714 | // | ||
1711 | } | 1715 | } |
1712 | *start = p; | ||
1713 | *stop = q; | ||
1714 | if (q < p) { | 1716 | if (q < p) { |
1715 | *start = q; | 1717 | t = q; |
1716 | *stop = p; | 1718 | q = p; |
1719 | p = t; | ||
1717 | } | 1720 | } |
1721 | |||
1722 | // backward char movements don't include start position | ||
1723 | if (q > p && strchr("^0bBh\b\177", c)) q--; | ||
1724 | |||
1725 | multiline = 0; | ||
1726 | for (t = p; t <= q; t++) { | ||
1727 | if (*t == '\n') { | ||
1728 | multiline = 1; | ||
1729 | break; | ||
1730 | } | ||
1731 | } | ||
1732 | |||
1733 | *start = p; | ||
1734 | *stop = q; | ||
1718 | dot = save_dot; | 1735 | dot = save_dot; |
1719 | return c; | 1736 | return multiline; |
1720 | } | 1737 | } |
1721 | 1738 | ||
1722 | static int st_test(char * p, int type, int dir, char * tested) | 1739 | static int st_test(char * p, int type, int dir, char * tested) |
@@ -1780,27 +1797,12 @@ static char *find_pair(char * p, const char c) | |||
1780 | level = 1; | 1797 | level = 1; |
1781 | dir = 1; // assume forward | 1798 | dir = 1; // assume forward |
1782 | switch (c) { | 1799 | switch (c) { |
1783 | case '(': | 1800 | case '(': match = ')'; break; |
1784 | match = ')'; | 1801 | case '[': match = ']'; break; |
1785 | break; | 1802 | case '{': match = '}'; break; |
1786 | case '[': | 1803 | case ')': match = '('; dir = -1; break; |
1787 | match = ']'; | 1804 | case ']': match = '['; dir = -1; break; |
1788 | break; | 1805 | case '}': match = '{'; dir = -1; break; |
1789 | case '{': | ||
1790 | match = '}'; | ||
1791 | break; | ||
1792 | case ')': | ||
1793 | match = '('; | ||
1794 | dir = -1; | ||
1795 | break; | ||
1796 | case ']': | ||
1797 | match = '['; | ||
1798 | dir = -1; | ||
1799 | break; | ||
1800 | case '}': | ||
1801 | match = '{'; | ||
1802 | dir = -1; | ||
1803 | break; | ||
1804 | } | 1806 | } |
1805 | for (q = p + dir; text <= q && q < end; q += dir) { | 1807 | for (q = p + dir; text <= q && q < end; q += dir) { |
1806 | // look for match, count levels of pairs (( )) | 1808 | // look for match, count levels of pairs (( )) |
@@ -1976,10 +1978,10 @@ static void start_new_cmd_q(char c) | |||
1976 | last_modifying_cmd = xzalloc(MAX_INPUT_LEN); | 1978 | last_modifying_cmd = xzalloc(MAX_INPUT_LEN); |
1977 | // if there is a current cmd count put it in the buffer first | 1979 | // if there is a current cmd count put it in the buffer first |
1978 | if (cmdcnt > 0) | 1980 | if (cmdcnt > 0) |
1979 | sprintf(last_modifying_cmd, "%d%c", cmdcnt, c); | 1981 | lmc_len = sprintf(last_modifying_cmd, "%d%c", cmdcnt, c); |
1980 | else { // just save char c onto queue | 1982 | else { // just save char c onto queue |
1981 | last_modifying_cmd[0] = c; | 1983 | last_modifying_cmd[0] = c; |
1982 | last_modifying_cmd[1] = '\0'; | 1984 | lmc_len = 1; |
1983 | } | 1985 | } |
1984 | adding2q = 1; | 1986 | adding2q = 1; |
1985 | } | 1987 | } |
@@ -2280,9 +2282,6 @@ static char get_one_char(void) | |||
2280 | char c; | 2282 | char c; |
2281 | 2283 | ||
2282 | #if ENABLE_FEATURE_VI_DOT_CMD | 2284 | #if ENABLE_FEATURE_VI_DOT_CMD |
2283 | // ! adding2q && ioq == 0 read() | ||
2284 | // ! adding2q && ioq != 0 *ioq | ||
2285 | // adding2q *last_modifying_cmd= read() | ||
2286 | if (!adding2q) { | 2285 | if (!adding2q) { |
2287 | // we are not adding to the q. | 2286 | // we are not adding to the q. |
2288 | // but, we may be reading from a q | 2287 | // but, we may be reading from a q |
@@ -2303,12 +2302,11 @@ static char get_one_char(void) | |||
2303 | // adding STDIN chars to q | 2302 | // adding STDIN chars to q |
2304 | c = readit(); // get the users input | 2303 | c = readit(); // get the users input |
2305 | if (last_modifying_cmd != NULL) { | 2304 | if (last_modifying_cmd != NULL) { |
2306 | int len = strlen(last_modifying_cmd); | 2305 | if (lmc_len >= MAX_INPUT_LEN - 1) { |
2307 | if (len >= MAX_INPUT_LEN - 1) { | ||
2308 | status_line_bold("last_modifying_cmd overrun"); | 2306 | status_line_bold("last_modifying_cmd overrun"); |
2309 | } else { | 2307 | } else { |
2310 | // add new char to q | 2308 | // add new char to q |
2311 | last_modifying_cmd[len] = c; | 2309 | last_modifying_cmd[lmc_len++] = c; |
2312 | } | 2310 | } |
2313 | } | 2311 | } |
2314 | } | 2312 | } |
@@ -2947,7 +2945,7 @@ static void do_cmd(char c) | |||
2947 | char c1, *p, *q, *save_dot; | 2945 | char c1, *p, *q, *save_dot; |
2948 | char buf[12]; | 2946 | char buf[12]; |
2949 | int dir = dir; // for compiler | 2947 | int dir = dir; // for compiler |
2950 | int cnt, i, j, yf; | 2948 | int cnt, i, j; |
2951 | 2949 | ||
2952 | // c1 = c; // quiet the compiler | 2950 | // c1 = c; // quiet the compiler |
2953 | // cnt = yf = 0; // quiet the compiler | 2951 | // cnt = yf = 0; // quiet the compiler |
@@ -3282,7 +3280,8 @@ static void do_cmd(char c) | |||
3282 | case '.': // .- repeat the last modifying command | 3280 | case '.': // .- repeat the last modifying command |
3283 | // Stuff the last_modifying_cmd back into stdin | 3281 | // Stuff the last_modifying_cmd back into stdin |
3284 | // and let it be re-executed. | 3282 | // and let it be re-executed. |
3285 | if (last_modifying_cmd != NULL) { | 3283 | if (last_modifying_cmd != NULL && lmc_len > 0) { |
3284 | last_modifying_cmd[lmc_len] = 0; | ||
3286 | ioq = ioq_start = xstrdup(last_modifying_cmd); | 3285 | ioq = ioq_start = xstrdup(last_modifying_cmd); |
3287 | } | 3286 | } |
3288 | break; | 3287 | break; |
@@ -3668,6 +3667,8 @@ static void do_cmd(char c) | |||
3668 | case 'y': // y- yank something | 3667 | case 'y': // y- yank something |
3669 | case 'Y': // Y- Yank a line | 3668 | case 'Y': // Y- Yank a line |
3670 | #endif | 3669 | #endif |
3670 | { | ||
3671 | int yf, ml, whole = 0; | ||
3671 | yf = YANKDEL; // assume either "c" or "d" | 3672 | yf = YANKDEL; // assume either "c" or "d" |
3672 | #if ENABLE_FEATURE_VI_YANKMARK | 3673 | #if ENABLE_FEATURE_VI_YANKMARK |
3673 | if (c == 'y' || c == 'Y') | 3674 | if (c == 'y' || c == 'Y') |
@@ -3676,7 +3677,8 @@ static void do_cmd(char c) | |||
3676 | c1 = 'y'; | 3677 | c1 = 'y'; |
3677 | if (c != 'Y') | 3678 | if (c != 'Y') |
3678 | c1 = get_one_char(); // get the type of thing to delete | 3679 | c1 = get_one_char(); // get the type of thing to delete |
3679 | find_range(&p, &q, c1); | 3680 | // determine range, and whether it spans lines |
3681 | ml = find_range(&p, &q, c1); | ||
3680 | if (c1 == 27) { // ESC- user changed mind and wants out | 3682 | if (c1 == 27) { // ESC- user changed mind and wants out |
3681 | c = c1 = 27; // Escape- do nothing | 3683 | c = c1 = 27; // Escape- do nothing |
3682 | } else if (strchr("wW", c1)) { | 3684 | } else if (strchr("wW", c1)) { |
@@ -3688,27 +3690,31 @@ static void do_cmd(char c) | |||
3688 | q--; | 3690 | q--; |
3689 | } | 3691 | } |
3690 | } | 3692 | } |
3691 | dot = yank_delete(p, q, 0, yf); // delete word | 3693 | dot = yank_delete(p, q, ml, yf); // delete word |
3692 | } else if (strchr("^0bBeEft$", c1)) { | 3694 | } else if (strchr("^0bBeEft%$ lh\b\177", c1)) { |
3693 | // single line copy text into a register and delete | 3695 | // partial line copy text into a register and delete |
3694 | dot = yank_delete(p, q, 0, yf); // delete word | 3696 | dot = yank_delete(p, q, ml, yf); // delete word |
3695 | } else if (strchr("cdykjHL%+-{}\r\n", c1)) { | 3697 | } else if (strchr("cdykjHL+-{}\r\n", c1)) { |
3696 | // multiple line copy text into a register and delete | 3698 | // whole line copy text into a register and delete |
3697 | dot = yank_delete(p, q, 1, yf); // delete lines | 3699 | dot = yank_delete(p, q, ml, yf); // delete lines |
3700 | whole = 1; | ||
3701 | } else { | ||
3702 | // could not recognize object | ||
3703 | c = c1 = 27; // error- | ||
3704 | ml = 0; | ||
3705 | indicate_error(c); | ||
3706 | } | ||
3707 | if (ml && whole) { | ||
3698 | if (c == 'c') { | 3708 | if (c == 'c') { |
3699 | dot = char_insert(dot, '\n'); | 3709 | dot = char_insert(dot, '\n'); |
3700 | // on the last line of file don't move to prev line | 3710 | // on the last line of file don't move to prev line |
3701 | if (dot != (end-1)) { | 3711 | if (whole && dot != (end-1)) { |
3702 | dot_prev(); | 3712 | dot_prev(); |
3703 | } | 3713 | } |
3704 | } else if (c == 'd') { | 3714 | } else if (c == 'd') { |
3705 | dot_begin(); | 3715 | dot_begin(); |
3706 | dot_skip_over_ws(); | 3716 | dot_skip_over_ws(); |
3707 | } | 3717 | } |
3708 | } else { | ||
3709 | // could not recognize object | ||
3710 | c = c1 = 27; // error- | ||
3711 | indicate_error(c); | ||
3712 | } | 3718 | } |
3713 | if (c1 != 27) { | 3719 | if (c1 != 27) { |
3714 | // if CHANGING, not deleting, start inserting after the delete | 3720 | // if CHANGING, not deleting, start inserting after the delete |
@@ -3734,6 +3740,7 @@ static void do_cmd(char c) | |||
3734 | #endif | 3740 | #endif |
3735 | end_cmd_q(); // stop adding to q | 3741 | end_cmd_q(); // stop adding to q |
3736 | } | 3742 | } |
3743 | } | ||
3737 | break; | 3744 | break; |
3738 | case 'k': // k- goto prev line, same col | 3745 | case 'k': // k- goto prev line, same col |
3739 | case VI_K_UP: // cursor key Up | 3746 | case VI_K_UP: // cursor key Up |