[prev in list] [next in list] [prev in thread] [next in thread]
List: busybox
Subject: [RFC 1/2] vi: add expandtab option
From: Ron Yorston <rmy () pobox ! com>
Date: 2021-04-16 12:47:03
Message-ID: 60798747.OVfU2EuCvM8P5mZ+%rmy () pobox ! com
[Download RAW message or body]
This implements the vim option expandtab in BusyBox vi. From
vim help:
In Insert mode: Use the appropriate number of spaces to insert a
<Tab>. Spaces are used in indents with the '>' and '<' commands and
when 'autoindent' is on. To insert a real tab when 'expandtab' is
on, use CTRL-V<Tab>.
This implementation doesn't change how BusyBox vi handles autoindent:
it continues to copy the indentation from a neighbouring line. If
that line has tabs in its indentation so too will the new line.
function old new delta
char_insert 563 699 +136
do_cmd 4668 4716 +48
next_tabstop - 26 +26
.rodata 105211 105236 +25
colon 3844 3855 +11
refresh 1000 995 -5
move_to_col 83 74 -9
------------------------------------------------------------------------------
(add/remove: 1/0 grow/shrink: 4/2 up/down: 246/-14) Total: 232 bytes
---
editors/vi.c | 57 +++++++++++++++++++++++++++++++++++++++++++++-------
1 file changed, 50 insertions(+), 7 deletions(-)
diff --git a/editors/vi.c b/editors/vi.c
index 6dd951421..261a5c075 100644
--- a/editors/vi.c
+++ b/editors/vi.c
@@ -289,11 +289,13 @@ struct globals {
#if ENABLE_FEATURE_VI_SETOPTS
smallint vi_setops; // set by setops()
#define VI_AUTOINDENT (1 << 0)
-#define VI_ERR_METHOD (1 << 1)
-#define VI_IGNORECASE (1 << 2)
-#define VI_SHOWMATCH (1 << 3)
-#define VI_TABSTOP (1 << 4)
+#define VI_EXPANDTAB (1 << 1)
+#define VI_ERR_METHOD (1 << 2)
+#define VI_IGNORECASE (1 << 3)
+#define VI_SHOWMATCH (1 << 4)
+#define VI_TABSTOP (1 << 5)
#define autoindent (vi_setops & VI_AUTOINDENT)
+#define expandtab (vi_setops & VI_EXPANDTAB )
#define err_method (vi_setops & VI_ERR_METHOD) // indicate error with beep or flash
#define ignorecase (vi_setops & VI_IGNORECASE)
#define showmatch (vi_setops & VI_SHOWMATCH )
@@ -301,6 +303,7 @@ struct globals {
// order of constants and strings must match
#define OPTS_STR \
"ai\0""autoindent\0" \
+ "et\0""expandtab\0" \
"fl\0""flash\0" \
"ic\0""ignorecase\0" \
"sm\0""showmatch\0" \
@@ -309,6 +312,7 @@ struct globals {
#define clear_openabove() (vi_setops &= ~VI_TABSTOP)
#else
#define autoindent (0)
+#define expandtab (0)
#define err_method (0)
#define openabove (0)
#define set_openabove() ((void)0)
@@ -758,6 +762,23 @@ static int next_tabstop(int col)
return col + ((tabstop - 1) - (col % tabstop));
}
+#if ENABLE_FEATURE_VI_SETOPTS
+static int get_column(char *p)
+{
+ const char *r;
+ int co = 0;
+
+ for (r = begin_line(p); r < p; r++) {
+ if (*r == '\t')
+ co = next_tabstop(co);
+ else if ((unsigned char)*r < ' ' || *r == 0x7f)
+ co++; // display as ^X, use 2 columns
+ co++;
+ }
+ return co;
+}
+#endif
+
//----- Erase the Screen[] memory ------------------------------
static void screen_erase(void)
{
@@ -2103,6 +2124,17 @@ static char *char_insert(char *p, char c, int undo) // insert the char c at 'p'
p--;
p = text_hole_delete(p, p, ALLOW_UNDO_QUEUED);
}
+ } else if (c == '\t' && expandtab) { // expand tab
+ int col = get_column(p);
+ int next = next_tabstop(col);
+ for (; col <= next; ++col) {
+#if ENABLE_FEATURE_VI_UNDO
+ undo_push_insert(p, 1, undo);
+#else
+ modified_count++;
+#endif
+ p += 1 + stupid_insert(p, ' ');
+ }
#endif
} else if (c == term_orig.c_cc[VERASE] || c == 8 || c == 127) { // Is this a BS
if (p > text) {
@@ -2870,11 +2902,13 @@ static void colon(char *buf)
# if ENABLE_FEATURE_VI_SETOPTS
status_line_bold(
"%sautoindent "
+ "%sexpandtab "
"%sflash "
"%signorecase "
"%sshowmatch "
"tabstop=%u",
autoindent ? "" : "no",
+ expandtab ? "" : "no",
err_method ? "" : "no",
ignorecase ? "" : "no",
showmatch ? "" : "no",
@@ -3752,7 +3786,7 @@ static void do_cmd(int c)
i = count_lines(p, q); // # of lines we are shifting
for ( ; i > 0; i--, p = next_line(p)) {
if (c == '<') {
- // shift left- remove tab or 8 spaces
+ // shift left- remove tab or tabstop spaces
if (*p == '\t') {
// shrink buffer 1 char
text_hole_delete(p, p, allow_undo);
@@ -3766,8 +3800,17 @@ static void do_cmd(int c)
}
}
} else /* if (c == '>') */ {
- // shift right -- add tab or 8 spaces
- char_insert(p, '\t', allow_undo);
+ // shift right -- add tab or tabstop spaces
+ if (expandtab) {
+ for (j = 0; j < tabstop; ++j) {
+ char_insert(p, ' ', allow_undo);
+#if ENABLE_FEATURE_VI_UNDO
+ allow_undo = ALLOW_UNDO_CHAIN;
+#endif
+ }
+ } else {
+ char_insert(p, '\t', allow_undo);
+ }
}
#if ENABLE_FEATURE_VI_UNDO
allow_undo = ALLOW_UNDO_CHAIN;
--
2.30.2
_______________________________________________
busybox mailing list
busybox@busybox.net
http://lists.busybox.net/mailman/listinfo/busybox
[prev in list] [next in list] [prev in thread] [next in thread]
Configure |
About |
News |
Add a list |
Sponsored by KoreLogic