diff options
author | Ron Yorston <rmy@pobox.com> | 2021-04-17 09:25:11 +0100 |
---|---|---|
committer | Denys Vlasenko <vda.linux@googlemail.com> | 2021-04-20 11:21:43 +0200 |
commit | 310ef232809b34a75c120629b7b2c0d4af0dd50f (patch) | |
tree | 93e45b99655325f87dd5614c2838ef65b7a39cb4 | |
parent | d9136efd7ac5f7655376057e0ba28498a975216b (diff) | |
download | busybox-w32-310ef232809b34a75c120629b7b2c0d4af0dd50f.tar.gz busybox-w32-310ef232809b34a75c120629b7b2c0d4af0dd50f.tar.bz2 busybox-w32-310ef232809b34a75c120629b7b2c0d4af0dd50f.zip |
vi: add expandtab option
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 679 +116
next_column - 48 +48
.rodata 105211 105236 +25
colon 3844 3855 +11
refresh 1000 982 -18
move_to_col 83 59 -24
------------------------------------------------------------------------------
(add/remove: 1/0 grow/shrink: 3/2 up/down: 200/-42) Total: 158 bytes
Signed-off-by: Peter D <urmum69@snopyta.org>
Signed-off-by: Ron Yorston <rmy@pobox.com>
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
-rw-r--r-- | editors/vi.c | 64 |
1 files changed, 47 insertions, 17 deletions
diff --git a/editors/vi.c b/editors/vi.c index 09f6eca6d..de7a43325 100644 --- a/editors/vi.c +++ b/editors/vi.c | |||
@@ -289,11 +289,13 @@ struct globals { | |||
289 | #if ENABLE_FEATURE_VI_SETOPTS | 289 | #if ENABLE_FEATURE_VI_SETOPTS |
290 | smallint vi_setops; // set by setops() | 290 | smallint vi_setops; // set by setops() |
291 | #define VI_AUTOINDENT (1 << 0) | 291 | #define VI_AUTOINDENT (1 << 0) |
292 | #define VI_ERR_METHOD (1 << 1) | 292 | #define VI_EXPANDTAB (1 << 1) |
293 | #define VI_IGNORECASE (1 << 2) | 293 | #define VI_ERR_METHOD (1 << 2) |
294 | #define VI_SHOWMATCH (1 << 3) | 294 | #define VI_IGNORECASE (1 << 3) |
295 | #define VI_TABSTOP (1 << 4) | 295 | #define VI_SHOWMATCH (1 << 4) |
296 | #define VI_TABSTOP (1 << 5) | ||
296 | #define autoindent (vi_setops & VI_AUTOINDENT) | 297 | #define autoindent (vi_setops & VI_AUTOINDENT) |
298 | #define expandtab (vi_setops & VI_EXPANDTAB ) | ||
297 | #define err_method (vi_setops & VI_ERR_METHOD) // indicate error with beep or flash | 299 | #define err_method (vi_setops & VI_ERR_METHOD) // indicate error with beep or flash |
298 | #define ignorecase (vi_setops & VI_IGNORECASE) | 300 | #define ignorecase (vi_setops & VI_IGNORECASE) |
299 | #define showmatch (vi_setops & VI_SHOWMATCH ) | 301 | #define showmatch (vi_setops & VI_SHOWMATCH ) |
@@ -301,6 +303,7 @@ struct globals { | |||
301 | // order of constants and strings must match | 303 | // order of constants and strings must match |
302 | #define OPTS_STR \ | 304 | #define OPTS_STR \ |
303 | "ai\0""autoindent\0" \ | 305 | "ai\0""autoindent\0" \ |
306 | "et\0""expandtab\0" \ | ||
304 | "fl\0""flash\0" \ | 307 | "fl\0""flash\0" \ |
305 | "ic\0""ignorecase\0" \ | 308 | "ic\0""ignorecase\0" \ |
306 | "sm\0""showmatch\0" \ | 309 | "sm\0""showmatch\0" \ |
@@ -309,6 +312,7 @@ struct globals { | |||
309 | #define clear_openabove() (vi_setops &= ~VI_TABSTOP) | 312 | #define clear_openabove() (vi_setops &= ~VI_TABSTOP) |
310 | #else | 313 | #else |
311 | #define autoindent (0) | 314 | #define autoindent (0) |
315 | #define expandtab (0) | ||
312 | #define err_method (0) | 316 | #define err_method (0) |
313 | #define openabove (0) | 317 | #define openabove (0) |
314 | #define set_openabove() ((void)0) | 318 | #define set_openabove() ((void)0) |
@@ -759,6 +763,27 @@ static int next_tabstop(int col) | |||
759 | return col + ((tabstop - 1) - (col % tabstop)); | 763 | return col + ((tabstop - 1) - (col % tabstop)); |
760 | } | 764 | } |
761 | 765 | ||
766 | static int next_column(char c, int co) | ||
767 | { | ||
768 | if (c == '\t') | ||
769 | co = next_tabstop(co); | ||
770 | else if ((unsigned char)c < ' ' || c == 0x7f) | ||
771 | co++; // display as ^X, use 2 columns | ||
772 | return co + 1; | ||
773 | } | ||
774 | |||
775 | #if ENABLE_FEATURE_VI_SETOPTS | ||
776 | static int get_column(char *p) | ||
777 | { | ||
778 | const char *r; | ||
779 | int co = 0; | ||
780 | |||
781 | for (r = begin_line(p); r < p; r++) | ||
782 | co = next_column(*r, co); | ||
783 | return co; | ||
784 | } | ||
785 | #endif | ||
786 | |||
762 | //----- Erase the Screen[] memory ------------------------------ | 787 | //----- Erase the Screen[] memory ------------------------------ |
763 | static void screen_erase(void) | 788 | static void screen_erase(void) |
764 | { | 789 | { |
@@ -838,11 +863,7 @@ static void sync_cursor(char *d, int *row, int *col) | |||
838 | do { // drive "co" to correct column | 863 | do { // drive "co" to correct column |
839 | if (*tp == '\n') //vda || *tp == '\0') | 864 | if (*tp == '\n') //vda || *tp == '\0') |
840 | break; | 865 | break; |
841 | if (*tp == '\t') { | 866 | co = next_column(*tp, co) - 1; |
842 | co = next_tabstop(co); | ||
843 | } else if ((unsigned char)*tp < ' ' || *tp == 0x7f) { | ||
844 | co++; // display as ^X, use 2 columns | ||
845 | } | ||
846 | // inserting text before a tab, don't include its position | 867 | // inserting text before a tab, don't include its position |
847 | if (cmd_mode && tp == d - 1 && *d == '\t') { | 868 | if (cmd_mode && tp == d - 1 && *d == '\t') { |
848 | co++; | 869 | co++; |
@@ -1807,12 +1828,8 @@ static char *move_to_col(char *p, int l) | |||
1807 | do { | 1828 | do { |
1808 | if (*p == '\n') //vda || *p == '\0') | 1829 | if (*p == '\n') //vda || *p == '\0') |
1809 | break; | 1830 | break; |
1810 | if (*p == '\t') { | 1831 | co = next_column(*p, co); |
1811 | co = next_tabstop(co); | 1832 | } while (co <= l && p++ < end); |
1812 | } else if (*p < ' ' || *p == 127) { | ||
1813 | co++; // display as ^X, use 2 columns | ||
1814 | } | ||
1815 | } while (++co <= l && p++ < end); | ||
1816 | return p; | 1833 | return p; |
1817 | } | 1834 | } |
1818 | 1835 | ||
@@ -2104,6 +2121,17 @@ static char *char_insert(char *p, char c, int undo) // insert the char c at 'p' | |||
2104 | p--; | 2121 | p--; |
2105 | p = text_hole_delete(p, p, ALLOW_UNDO_QUEUED); | 2122 | p = text_hole_delete(p, p, ALLOW_UNDO_QUEUED); |
2106 | } | 2123 | } |
2124 | } else if (c == '\t' && expandtab) { // expand tab | ||
2125 | int col = get_column(p); | ||
2126 | col = next_tabstop(col) - col + 1; | ||
2127 | while (col--) { | ||
2128 | # if ENABLE_FEATURE_VI_UNDO | ||
2129 | undo_push_insert(p, 1, undo); | ||
2130 | # else | ||
2131 | modified_count++; | ||
2132 | # endif | ||
2133 | p += 1 + stupid_insert(p, ' '); | ||
2134 | } | ||
2107 | #endif | 2135 | #endif |
2108 | } else if (c == term_orig.c_cc[VERASE] || c == 8 || c == 127) { // Is this a BS | 2136 | } else if (c == term_orig.c_cc[VERASE] || c == 8 || c == 127) { // Is this a BS |
2109 | if (p > text) { | 2137 | if (p > text) { |
@@ -2871,11 +2899,13 @@ static void colon(char *buf) | |||
2871 | # if ENABLE_FEATURE_VI_SETOPTS | 2899 | # if ENABLE_FEATURE_VI_SETOPTS |
2872 | status_line_bold( | 2900 | status_line_bold( |
2873 | "%sautoindent " | 2901 | "%sautoindent " |
2902 | "%sexpandtab " | ||
2874 | "%sflash " | 2903 | "%sflash " |
2875 | "%signorecase " | 2904 | "%signorecase " |
2876 | "%sshowmatch " | 2905 | "%sshowmatch " |
2877 | "tabstop=%u", | 2906 | "tabstop=%u", |
2878 | autoindent ? "" : "no", | 2907 | autoindent ? "" : "no", |
2908 | expandtab ? "" : "no", | ||
2879 | err_method ? "" : "no", | 2909 | err_method ? "" : "no", |
2880 | ignorecase ? "" : "no", | 2910 | ignorecase ? "" : "no", |
2881 | showmatch ? "" : "no", | 2911 | showmatch ? "" : "no", |
@@ -3753,7 +3783,7 @@ static void do_cmd(int c) | |||
3753 | i = count_lines(p, q); // # of lines we are shifting | 3783 | i = count_lines(p, q); // # of lines we are shifting |
3754 | for ( ; i > 0; i--, p = next_line(p)) { | 3784 | for ( ; i > 0; i--, p = next_line(p)) { |
3755 | if (c == '<') { | 3785 | if (c == '<') { |
3756 | // shift left- remove tab or 8 spaces | 3786 | // shift left- remove tab or tabstop spaces |
3757 | if (*p == '\t') { | 3787 | if (*p == '\t') { |
3758 | // shrink buffer 1 char | 3788 | // shrink buffer 1 char |
3759 | text_hole_delete(p, p, allow_undo); | 3789 | text_hole_delete(p, p, allow_undo); |
@@ -3767,7 +3797,7 @@ static void do_cmd(int c) | |||
3767 | } | 3797 | } |
3768 | } | 3798 | } |
3769 | } else /* if (c == '>') */ { | 3799 | } else /* if (c == '>') */ { |
3770 | // shift right -- add tab or 8 spaces | 3800 | // shift right -- add tab or tabstop spaces |
3771 | char_insert(p, '\t', allow_undo); | 3801 | char_insert(p, '\t', allow_undo); |
3772 | } | 3802 | } |
3773 | #if ENABLE_FEATURE_VI_UNDO | 3803 | #if ENABLE_FEATURE_VI_UNDO |