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
get_column                                             -      57     +57
char_insert                                          699     720     +21
------------------------------------------------------------------------------
(add/remove: 1/0 grow/shrink: 1/0 up/down: 78/0)               Total: 78 bytes
---
 editors/vi.c | 29 ++++++++++++++++++++++-------
 1 file changed, 22 insertions(+), 7 deletions(-)

diff --git a/editors/vi.c b/editors/vi.c
index 261a5c075..7b974a255 100644
--- a/editors/vi.c
+++ b/editors/vi.c
@@ -763,6 +763,11 @@ static int next_tabstop(int col)
 }
 
 #if ENABLE_FEATURE_VI_SETOPTS
+static int prev_tabstop(int col)
+{
+       return col - ((col % tabstop) ?: tabstop);
+}
+
 static int get_column(char *p)
 {
        const char *r;
@@ -2116,14 +2121,24 @@ 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);
                }
+               return p;
+#if ENABLE_FEATURE_VI_SETOPTS
        } else if (c == '\t' && expandtab) {    // expand tab
                int col = get_column(p);
                int next = next_tabstop(col);
-- 
2.30.2

_______________________________________________
busybox mailing list
busybox@busybox.net
http://lists.busybox.net/mailman/listinfo/busybox

Reply via email to