[git commit] vi: improvements to character search within line

Denys Vlasenko vda.linux at googlemail.com
Mon Mar 29 10:16:21 UTC 2021


commit: https://git.busybox.net/busybox/commit/?id=15f4ac3ca99bca8811a334f9c7603969ab7ad362
branch: https://git.busybox.net/busybox/commit/?id=refs/heads/master

- 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 at pobox.com>
Signed-off-by: Denys Vlasenko <vda.linux at googlemail.com>
---
 editors/vi.c | 80 +++++++++++++++++++++++++++++-------------------------------
 1 file 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 {
 	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


More information about the busybox-cvs mailing list