From f277c9eebb91a46cbd795c34aa64ee8b6a2e448c Mon Sep 17 00:00:00 2001 From: Ron Yorston Date: Sat, 17 Apr 2021 09:25:47 +0100 Subject: vi: make de-indentation with ctrl-D more like vim 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 Signed-off-by: Denys Vlasenko --- editors/vi.c | 30 +++++++++++++++++++++--------- 1 file changed, 21 insertions(+), 9 deletions(-) (limited to 'editors/vi.c') diff --git a/editors/vi.c b/editors/vi.c index de7a433..caf01ac 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; -- cgit v1.1