[git commit] vi: position cursor on last column of tab

Denys Vlasenko vda.linux at googlemail.com
Thu Apr 15 11:09:12 UTC 2021


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

Vi places the cursor on the last column of a tab character whereas
BusyBox vi puts it on the first.  This is disconcerting for
experienced vi users and makes it impossible to distinguish
visually between an empty line and one containing just a tab.

It wasn't always this way.  Prior to commit e3cbfb91d (vi: introduce
FEATURE_VI_8BIT) BusyBox vi also put the cursor on the last column.
However there were problems with cursor positioning when text was
inserted before a tab.  Commit eaabf0675 (vi: multiple fixes by
Natanael Copa) includes a partial attempt to fix this.  (The code is
still present but it's never executed.  Clever compilers optimise it
away.)

Revert the changes of commit e3cbfb91d and fix the insert problem
for all tabs, not just the first.

To quote Natanael:  "Costs a few bytes but its worth it imho".

function                                             old     new   delta
refresh                                              974    1000     +26
move_to_col                                           81      83      +2
------------------------------------------------------------------------------
(add/remove: 0/0 grow/shrink: 2/0 up/down: 28/0)               Total: 28 bytes

Signed-off-by: Ron Yorston <rmy at pobox.com>
Signed-off-by: Denys Vlasenko <vda.linux at googlemail.com>
---
 editors/vi.c | 21 +++++++++------------
 1 file changed, 9 insertions(+), 12 deletions(-)

diff --git a/editors/vi.c b/editors/vi.c
index fef328117..f71897253 100644
--- a/editors/vi.c
+++ b/editors/vi.c
@@ -826,21 +826,20 @@ static void sync_cursor(char *d, int *row, int *col)
 
 	// find out what col "d" is on
 	co = 0;
-	while (tp < d) { // drive "co" to correct column
+	do { // drive "co" to correct column
 		if (*tp == '\n') //vda || *tp == '\0')
 			break;
 		if (*tp == '\t') {
-			// handle tabs like real vi
-			if (d == tp && cmd_mode) {
-				break;
-			}
 			co = next_tabstop(co);
 		} else if ((unsigned char)*tp < ' ' || *tp == 0x7f) {
 			co++; // display as ^X, use 2 columns
 		}
-		co++;
-		tp++;
-	}
+		// inserting text before a tab, don't include its position
+		if (cmd_mode && tp == d - 1 && *d == '\t') {
+			co++;
+			break;
+		}
+	} while (tp++ < d && ++co);
 
 	// "co" is the column where "dot" is.
 	// The screen has "columns" columns.
@@ -1801,7 +1800,7 @@ static char *move_to_col(char *p, int l)
 
 	p = begin_line(p);
 	co = 0;
-	while (co < l && p < end) {
+	do {
 		if (*p == '\n') //vda || *p == '\0')
 			break;
 		if (*p == '\t') {
@@ -1809,9 +1808,7 @@ static char *move_to_col(char *p, int l)
 		} else if (*p < ' ' || *p == 127) {
 			co++; // display as ^X, use 2 columns
 		}
-		co++;
-		p++;
-	}
+	} while (++co <= l && p++ < end);
 	return p;
 }
 


More information about the busybox-cvs mailing list