diff options
author | Ron Yorston <rmy@pobox.com> | 2021-03-28 17:15:30 +0100 |
---|---|---|
committer | Denys Vlasenko <vda.linux@googlemail.com> | 2021-03-29 12:16:21 +0200 |
commit | 15f4ac3ca99bca8811a334f9c7603969ab7ad362 (patch) | |
tree | 36d2dc12f4174725a709a491f47d6c3b07a58891 | |
parent | 50a2db7dff696c0196fcc9a27db6154983bae149 (diff) | |
download | busybox-w32-15f4ac3ca99bca8811a334f9c7603969ab7ad362.tar.gz busybox-w32-15f4ac3ca99bca8811a334f9c7603969ab7ad362.tar.bz2 busybox-w32-15f4ac3ca99bca8811a334f9c7603969ab7ad362.zip |
vi: improvements to character search within line
- Use a common routine to handle all commands to search for a
character in a line.
- When searching for the nth occurrence of a character don't move
the cursor if fewer than n occurrences are present.
- Add support for the 'T' command, search backwards for character
after next occurrence of given character.
function old new delta
do_cmd 4861 4805 -56
------------------------------------------------------------------------------
(add/remove: 0/0 grow/shrink: 0/1 up/down: 0/-56) Total: -56 bytes
v2: Add parentheses to avoid searches continuing past end of line.
Signed-off-by: Ron Yorston <rmy@pobox.com>
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
-rw-r--r-- | editors/vi.c | 80 |
1 files changed, 39 insertions, 41 deletions
diff --git a/editors/vi.c b/editors/vi.c index 2c724a448..ec2d64dfb 100644 --- a/editors/vi.c +++ b/editors/vi.c | |||
@@ -322,7 +322,8 @@ struct globals { | |||
322 | char *screen; // pointer to the virtual screen buffer | 322 | char *screen; // pointer to the virtual screen buffer |
323 | int screensize; // and its size | 323 | int screensize; // and its size |
324 | int tabstop; | 324 | int tabstop; |
325 | int last_forward_char; // last char searched for with 'f' (int because of Unicode) | 325 | int last_search_char; // last char searched for (int because of Unicode) |
326 | smallint last_search_cmd; // command used to invoke last char search | ||
326 | #if ENABLE_FEATURE_VI_CRASHME | 327 | #if ENABLE_FEATURE_VI_CRASHME |
327 | char last_input_char; // last char read from user | 328 | char last_input_char; // last char read from user |
328 | #endif | 329 | #endif |
@@ -439,7 +440,8 @@ struct globals { | |||
439 | #define screensize (G.screensize ) | 440 | #define screensize (G.screensize ) |
440 | #define screenbegin (G.screenbegin ) | 441 | #define screenbegin (G.screenbegin ) |
441 | #define tabstop (G.tabstop ) | 442 | #define tabstop (G.tabstop ) |
442 | #define last_forward_char (G.last_forward_char ) | 443 | #define last_search_char (G.last_search_char ) |
444 | #define last_search_cmd (G.last_search_cmd ) | ||
443 | #if ENABLE_FEATURE_VI_CRASHME | 445 | #if ENABLE_FEATURE_VI_CRASHME |
444 | #define last_input_char (G.last_input_char ) | 446 | #define last_input_char (G.last_input_char ) |
445 | #endif | 447 | #endif |
@@ -1772,6 +1774,31 @@ static void dot_skip_over_ws(void) | |||
1772 | dot++; | 1774 | dot++; |
1773 | } | 1775 | } |
1774 | 1776 | ||
1777 | static void dot_to_char(int cmd) | ||
1778 | { | ||
1779 | char *q = dot; | ||
1780 | int dir = islower(cmd) ? FORWARD : BACK; | ||
1781 | |||
1782 | if (last_search_char == 0) | ||
1783 | return; | ||
1784 | |||
1785 | do { | ||
1786 | do { | ||
1787 | q += dir; | ||
1788 | if ((dir == FORWARD ? q > end - 1 : q < text) || *q == '\n') | ||
1789 | return; | ||
1790 | } while (*q != last_search_char); | ||
1791 | } while (--cmdcnt > 0); | ||
1792 | |||
1793 | dot = q; | ||
1794 | |||
1795 | // place cursor before/after char as required | ||
1796 | if (cmd == 't') | ||
1797 | dot_left(); | ||
1798 | else if (cmd == 'T') | ||
1799 | dot_right(); | ||
1800 | } | ||
1801 | |||
1775 | static void dot_scroll(int cnt, int dir) | 1802 | static void dot_scroll(int cnt, int dir) |
1776 | { | 1803 | { |
1777 | char *q; | 1804 | char *q; |
@@ -3181,11 +3208,9 @@ static void do_cmd(int c) | |||
3181 | //case '*': // *- | 3208 | //case '*': // *- |
3182 | //case '=': // =- | 3209 | //case '=': // =- |
3183 | //case '@': // @- | 3210 | //case '@': // @- |
3184 | //case 'F': // F- | ||
3185 | //case 'K': // K- | 3211 | //case 'K': // K- |
3186 | //case 'Q': // Q- | 3212 | //case 'Q': // Q- |
3187 | //case 'S': // S- | 3213 | //case 'S': // S- |
3188 | //case 'T': // T- | ||
3189 | //case 'V': // V- | 3214 | //case 'V': // V- |
3190 | //case '[': // [- | 3215 | //case '[': // [- |
3191 | //case '\\': // \- | 3216 | //case '\\': // \- |
@@ -3379,36 +3404,16 @@ static void do_cmd(int c) | |||
3379 | indicate_error(); | 3404 | indicate_error(); |
3380 | break; | 3405 | break; |
3381 | case 'f': // f- forward to a user specified char | 3406 | case 'f': // f- forward to a user specified char |
3382 | last_forward_char = get_one_char(); // get the search char | 3407 | case 'F': // F- backward to a user specified char |
3383 | // | 3408 | case 't': // t- move to char prior to next x |
3384 | // dont separate these two commands. 'f' depends on ';' | 3409 | case 'T': // T- move to char after previous x |
3385 | // | 3410 | last_search_char = get_one_char(); // get the search char |
3386 | //**** fall through to ... ';' | 3411 | last_search_cmd = c; |
3387 | case ';': // ;- look at rest of line for last forward char | 3412 | // fall through |
3388 | do { | 3413 | case ';': // ;- look at rest of line for last search char |
3389 | if (last_forward_char == 0) | 3414 | case ',': // ,- repeat latest search in opposite direction |
3390 | break; | 3415 | dot_to_char(c != ',' ? last_search_cmd : last_search_cmd ^ 0x20); |
3391 | q = dot + 1; | ||
3392 | while (q < end - 1 && *q != '\n' && *q != last_forward_char) { | ||
3393 | q++; | ||
3394 | } | ||
3395 | if (*q == last_forward_char) | ||
3396 | dot = q; | ||
3397 | } while (--cmdcnt > 0); | ||
3398 | break; | ||
3399 | case ',': // repeat latest 'f' in opposite direction | ||
3400 | if (last_forward_char == 0) | ||
3401 | break; | ||
3402 | do { | ||
3403 | q = dot - 1; | ||
3404 | while (q >= text && *q != '\n' && *q != last_forward_char) { | ||
3405 | q--; | ||
3406 | } | ||
3407 | if (q >= text && *q == last_forward_char) | ||
3408 | dot = q; | ||
3409 | } while (--cmdcnt > 0); | ||
3410 | break; | 3416 | break; |
3411 | |||
3412 | case '-': // -- goto prev line | 3417 | case '-': // -- goto prev line |
3413 | do { | 3418 | do { |
3414 | dot_prev(); | 3419 | dot_prev(); |
@@ -3854,13 +3859,6 @@ static void do_cmd(int c) | |||
3854 | } | 3859 | } |
3855 | end_cmd_q(); // stop adding to q | 3860 | end_cmd_q(); // stop adding to q |
3856 | break; | 3861 | break; |
3857 | case 't': // t- move to char prior to next x | ||
3858 | last_forward_char = get_one_char(); | ||
3859 | do_cmd(';'); | ||
3860 | if (*dot == last_forward_char) | ||
3861 | dot_left(); | ||
3862 | last_forward_char = 0; | ||
3863 | break; | ||
3864 | case 'w': // w- forward a word | 3862 | case 'w': // w- forward a word |
3865 | do { | 3863 | do { |
3866 | if (isalnum(*dot) || *dot == '_') { // we are on ALNUM | 3864 | if (isalnum(*dot) || *dot == '_') { // we are on ALNUM |
@@ -4204,7 +4202,7 @@ static void edit_file(char *fn) | |||
4204 | mark[26] = mark[27] = text; // init "previous context" | 4202 | mark[26] = mark[27] = text; // init "previous context" |
4205 | #endif | 4203 | #endif |
4206 | 4204 | ||
4207 | last_forward_char = '\0'; | 4205 | last_search_char = '\0'; |
4208 | #if ENABLE_FEATURE_VI_CRASHME | 4206 | #if ENABLE_FEATURE_VI_CRASHME |
4209 | last_input_char = '\0'; | 4207 | last_input_char = '\0'; |
4210 | #endif | 4208 | #endif |