aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRon Yorston <rmy@pobox.com>2021-04-17 09:25:11 +0100
committerDenys Vlasenko <vda.linux@googlemail.com>2021-04-20 11:21:43 +0200
commit310ef232809b34a75c120629b7b2c0d4af0dd50f (patch)
tree93e45b99655325f87dd5614c2838ef65b7a39cb4
parentd9136efd7ac5f7655376057e0ba28498a975216b (diff)
downloadbusybox-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.c64
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
766static 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
776static 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 ------------------------------
763static void screen_erase(void) 788static 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