From 15f4ac3ca99bca8811a334f9c7603969ab7ad362 Mon Sep 17 00:00:00 2001 From: Ron Yorston Date: Sun, 28 Mar 2021 17:15:30 +0100 Subject: 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 Signed-off-by: Denys Vlasenko --- editors/vi.c | 80 +++++++++++++++++++++++++++++------------------------------- 1 file changed, 39 insertions(+), 41 deletions(-) (limited to 'editors') diff --git a/editors/vi.c b/editors/vi.c index 2c724a4..ec2d64d 100644 --- a/editors/vi.c +++ b/editors/vi.c @@ -322,7 +322,8 @@ struct globals { char *screen; // pointer to the virtual screen buffer int screensize; // and its size int tabstop; - int last_forward_char; // last char searched for with 'f' (int because of Unicode) + int last_search_char; // last char searched for (int because of Unicode) + smallint last_search_cmd; // command used to invoke last char search #if ENABLE_FEATURE_VI_CRASHME char last_input_char; // last char read from user #endif @@ -439,7 +440,8 @@ struct globals { #define screensize (G.screensize ) #define screenbegin (G.screenbegin ) #define tabstop (G.tabstop ) -#define last_forward_char (G.last_forward_char ) +#define last_search_char (G.last_search_char ) +#define last_search_cmd (G.last_search_cmd ) #if ENABLE_FEATURE_VI_CRASHME #define last_input_char (G.last_input_char ) #endif @@ -1772,6 +1774,31 @@ static void dot_skip_over_ws(void) dot++; } +static void dot_to_char(int cmd) +{ + char *q = dot; + int dir = islower(cmd) ? FORWARD : BACK; + + if (last_search_char == 0) + return; + + do { + do { + q += dir; + if ((dir == FORWARD ? q > end - 1 : q < text) || *q == '\n') + return; + } while (*q != last_search_char); + } while (--cmdcnt > 0); + + dot = q; + + // place cursor before/after char as required + if (cmd == 't') + dot_left(); + else if (cmd == 'T') + dot_right(); +} + static void dot_scroll(int cnt, int dir) { char *q; @@ -3181,11 +3208,9 @@ static void do_cmd(int c) //case '*': // *- //case '=': // =- //case '@': // @- - //case 'F': // F- //case 'K': // K- //case 'Q': // Q- //case 'S': // S- - //case 'T': // T- //case 'V': // V- //case '[': // [- //case '\\': // \- @@ -3379,36 +3404,16 @@ static void do_cmd(int c) indicate_error(); break; case 'f': // f- forward to a user specified char - last_forward_char = get_one_char(); // get the search char - // - // dont separate these two commands. 'f' depends on ';' - // - //**** fall through to ... ';' - case ';': // ;- look at rest of line for last forward char - do { - if (last_forward_char == 0) - break; - q = dot + 1; - while (q < end - 1 && *q != '\n' && *q != last_forward_char) { - q++; - } - if (*q == last_forward_char) - dot = q; - } while (--cmdcnt > 0); - break; - case ',': // repeat latest 'f' in opposite direction - if (last_forward_char == 0) - break; - do { - q = dot - 1; - while (q >= text && *q != '\n' && *q != last_forward_char) { - q--; - } - if (q >= text && *q == last_forward_char) - dot = q; - } while (--cmdcnt > 0); + case 'F': // F- backward to a user specified char + case 't': // t- move to char prior to next x + case 'T': // T- move to char after previous x + last_search_char = get_one_char(); // get the search char + last_search_cmd = c; + // fall through + case ';': // ;- look at rest of line for last search char + case ',': // ,- repeat latest search in opposite direction + dot_to_char(c != ',' ? last_search_cmd : last_search_cmd ^ 0x20); break; - case '-': // -- goto prev line do { dot_prev(); @@ -3854,13 +3859,6 @@ static void do_cmd(int c) } end_cmd_q(); // stop adding to q break; - case 't': // t- move to char prior to next x - last_forward_char = get_one_char(); - do_cmd(';'); - if (*dot == last_forward_char) - dot_left(); - last_forward_char = 0; - break; case 'w': // w- forward a word do { if (isalnum(*dot) || *dot == '_') { // we are on ALNUM @@ -4204,7 +4202,7 @@ static void edit_file(char *fn) mark[26] = mark[27] = text; // init "previous context" #endif - last_forward_char = '\0'; + last_search_char = '\0'; #if ENABLE_FEATURE_VI_CRASHME last_input_char = '\0'; #endif -- cgit v1.1