vi: make autoindent respect expandtab setting

Autoindent took a copy of the indent from a neighbouring line, which
may not have respected the expandtab setting.

Determine the target column and construct a suitable indent.  This
will consist entirely of spaces if expandtab is enabled or an
efficient combination of tabs and spaces otherwise.

function                                             old     new   delta
char_insert                                          719     741     +22
------------------------------------------------------------------------------
(add/remove: 0/0 grow/shrink: 1/0 up/down: 22/0)               Total: 22 bytes

Signed-off-by: Ron Yorston <rmy@pobox.com>
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
This commit is contained in:
Ron Yorston 2021-05-20 08:27:19 +01:00 committed by Denys Vlasenko
parent d95f89ec57
commit 16e2fa9049

View File

@ -2111,6 +2111,7 @@ static char *char_insert(char *p, char c, int undo) // insert the char c at 'p'
#if ENABLE_FEATURE_VI_SETOPTS #if ENABLE_FEATURE_VI_SETOPTS
char *q; char *q;
size_t len; size_t len;
int col, ntab, nspc;
#endif #endif
if (c == 22) { // Is this an ctrl-V? if (c == 22) { // Is this an ctrl-V?
@ -2151,7 +2152,7 @@ static char *char_insert(char *p, char c, int undo) // insert the char c at 'p'
} }
#if ENABLE_FEATURE_VI_SETOPTS #if ENABLE_FEATURE_VI_SETOPTS
} else if (c == '\t' && expandtab) { // expand tab } else if (c == '\t' && expandtab) { // expand tab
int col = get_column(p); col = get_column(p);
col = next_tabstop(col) - col + 1; col = next_tabstop(col) - col + 1;
while (col--) { while (col--) {
# if ENABLE_FEATURE_VI_UNDO # if ENABLE_FEATURE_VI_UNDO
@ -2186,23 +2187,28 @@ static char *char_insert(char *p, char c, int undo) // insert the char c at 'p'
showmatching(p - 1); showmatching(p - 1);
} }
if (autoindent && c == '\n') { // auto indent the new line if (autoindent && c == '\n') { // auto indent the new line
// use current/previous line as template // use indent of current/previous line
q = openabove ? p : prev_line(p); q = openabove ? p : prev_line(p);
len = strspn(q, " \t"); // space or tab len = strspn(q, " \t"); // space or tab
if (openabove) { if (openabove)
p--; // this replaces dot_prev() in do_cmd() p--; // indent goes before newly inserted NL
q += len; // template will be shifted by text_hole_make()
}
if (len) { if (len) {
uintptr_t bias; col = get_column(q + len);
bias = text_hole_make(p, len); if (expandtab) {
p += bias; ntab = 0;
q += bias; nspc = col;
} else {
ntab = col / tabstop;
nspc = col % tabstop;
}
p += text_hole_make(p, ntab + nspc);
# if ENABLE_FEATURE_VI_UNDO # if ENABLE_FEATURE_VI_UNDO
undo_push_insert(p, len, undo); undo_push_insert(p, ntab + nspc, undo);
# endif # endif
memcpy(p, q, len); memset(p, '\t', ntab);
p += len; p += ntab;
memset(p, ' ', nspc);
p += nspc;
} }
} }
#endif #endif