[git commit] vi: make de-indentation with ctrl-D more like vim

Denys Vlasenko vda.linux at googlemail.com
Tue Apr 20 09:21:43 UTC 2021


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

Commit ac6495f6f (vi: allow ctrl-D to reduce indentation) treated
ctrl-D during autoindent as a backspace.  This was adequate for
indentation using tabs but doesn't work well with the expandtab
option.  In the latter case it's necessary to backspace over all
the spaces.

Make ctrl-D work correctly when spaces are present in the indent.

Also, make it behave more like vim:

- ctrl-D is independent of autoindent;
- indentation is reduced even when the cursor isn't positioned at
  the end of the indent.

function                                             old     new   delta
char_insert                                          679     717     +38
get_column                                             -      37     +37
------------------------------------------------------------------------------
(add/remove: 1/0 grow/shrink: 1/0 up/down: 75/0)               Total: 75 bytes

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

diff --git a/editors/vi.c b/editors/vi.c
index de7a43325..caf01acd3 100644
--- a/editors/vi.c
+++ b/editors/vi.c
@@ -763,6 +763,11 @@ static int next_tabstop(int col)
 	return col + ((tabstop - 1) - (col % tabstop));
 }
 
+static int prev_tabstop(int col)
+{
+	return col - ((col % tabstop) ?: tabstop);
+}
+
 static int next_column(char c, int co)
 {
 	if (c == '\t')
@@ -772,7 +777,6 @@ static int next_column(char c, int co)
 	return co + 1;
 }
 
-#if ENABLE_FEATURE_VI_SETOPTS
 static int get_column(char *p)
 {
 	const char *r;
@@ -782,7 +786,6 @@ static int get_column(char *p)
 		co = next_column(*r, co);
 	return co;
 }
-#endif
 
 //----- Erase the Screen[] memory ------------------------------
 static void screen_erase(void)
@@ -2113,14 +2116,23 @@ static char *char_insert(char *p, char c, int undo) // insert the char c at 'p'
 		if ((p[-1] != '\n') && (dot > text)) {
 			p--;
 		}
-#if ENABLE_FEATURE_VI_SETOPTS
-	} else if (c == 4 && autoindent) {	// ctrl-D reduces indentation
-		q = begin_line(p);
-		len = strspn(q, " \t");
-		if (len && q + len == p) {
-			p--;
-			p = text_hole_delete(p, p, ALLOW_UNDO_QUEUED);
+	} else if (c == 4) {	// ctrl-D reduces indentation
+		int prev;
+		char *r, *bol;
+		bol = begin_line(p);
+		for (r = bol; r < end_line(p); ++r) {
+			if (!isblank(*r))
+				break;
 		}
+
+		prev = prev_tabstop(get_column(r));
+		while (r > bol && get_column(r) > prev) {
+			if (p > bol)
+				p--;
+			r--;
+			r = text_hole_delete(r, r, ALLOW_UNDO_QUEUED);
+		}
+#if ENABLE_FEATURE_VI_SETOPTS
 	} else if (c == '\t' && expandtab) {	// expand tab
 		int col = get_column(p);
 		col = next_tabstop(col) - col + 1;


More information about the busybox-cvs mailing list