Since commit 70ee23399 (vi: code shrink) the ':set' command is
unable to process multiple options on a line.  Fix this by
temporarily null-terminating each option.

Change the default setting for all options to off to match vim.
Actually, 'flash' isn't an option in vim, only traditional vi,
where it's on by default.  In vim the corresponding option is
'visualbell' which defaults to off.  POSIX doesn't have either
of these.

Allow the abbreviation 'ts' for the 'tabstop' option.

function                                             old     new   delta
colon                                               3292    3297      +5
.rodata                                           105142  105145      +3
vi_main                                              305     301      -4
setops                                                85       -     -85
------------------------------------------------------------------------------
(add/remove: 0/1 grow/shrink: 2/1 up/down: 8/-89)             Total: -81 bytes

Signed-off-by: Ron Yorston <r...@pobox.com>
---
 editors/vi.c | 80 ++++++++++++++++++++++++++++++++--------------------
 1 file changed, 50 insertions(+), 30 deletions(-)

diff --git a/editors/vi.c b/editors/vi.c
index e48ad68c7..33976e9ad 100644
--- a/editors/vi.c
+++ b/editors/vi.c
@@ -287,10 +287,12 @@ struct globals {
 
        // the rest
        smallint vi_setops;
-#define VI_AUTOINDENT 1
-#define VI_SHOWMATCH  2
-#define VI_IGNORECASE 4
-#define VI_ERR_METHOD 8
+// the order of these values must match that in 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 autoindent (vi_setops & VI_AUTOINDENT)
 #define showmatch  (vi_setops & VI_SHOWMATCH )
 #define ignorecase (vi_setops & VI_IGNORECASE)
@@ -2408,17 +2410,40 @@ static char *get_address(char *p, int *b, int *e)       
// get two colon addrs, if pre
 }
 
 # if ENABLE_FEATURE_VI_SET && ENABLE_FEATURE_VI_SETOPTS
-static void setops(const char *args, const char *nm_longname, int flg_no, int 
opt)
+// order must match option flags
+#define OPTS \
+               "ai\0""autoindent\0" \
+               "fl\0""flash\0" \
+               "ic\0""ignorecase\0" \
+               "sm\0""showmatch\0" \
+               "ts\0""tabstop\0"
+
+static void setops(const char *args, int flg_no)
 {
-       const char *a = args + flg_no;
+       char *eq;
+       int index, opt;
+
+       // check for options with "=", they don't take "no" as a prefix
+       eq = strchr(args, '=');
+       if (eq) {
+               *eq = '\0';
+               flg_no = 0;
+       }
 
-       if (strcmp(a, nm_longname) == 0
-        || strcmp(a, nm_longname + 3) == 0
-       ) {
-               if (flg_no)
-                       vi_setops &= ~opt;
-               else
-                       vi_setops |= opt;
+       index = index_in_strings(OPTS, args + flg_no);
+       if (index == -1)
+               return;
+
+       opt = 1 << (index/2);
+       if (opt == VI_TABSTOP) {
+               int t = bb_strtou(eq + 1, NULL, 10);
+               if (t > 0 && t <= MAX_TABSTOP)
+                       tabstop = t;
+       }
+       else if (flg_no) {
+               vi_setops &= ~opt;
+       } else {
+               vi_setops |= opt;
        }
 }
 # endif
@@ -2778,10 +2803,10 @@ static void colon(char *buf)
 # if ENABLE_FEATURE_VI_SET
        } else if (strncmp(cmd, "set", i) == 0) {       // set or clear features
 #  if ENABLE_FEATURE_VI_SETOPTS
-               char *argp;
+               char *argp, *argn, oldch;
 #  endif
                // only blank is regarded as args delimiter. What about tab 
'\t'?
-               if (!args[0] || strcasecmp(args, "all") == 0) {
+               if (!args[0] || strcmp(args, "all") == 0) {
                        // print out values of all options
 #  if ENABLE_FEATURE_VI_SETOPTS
                        status_line_bold(
@@ -2805,17 +2830,12 @@ static void colon(char *buf)
                        i = 0;
                        if (argp[0] == 'n' && argp[1] == 'o') // "noXXX"
                                i = 2;
-                       setops(argp, "ai""\0""autoindent", i, VI_AUTOINDENT);
-                       setops(argp, "fl""\0""flash"     , i, VI_ERR_METHOD);
-                       setops(argp, "ic""\0""ignorecase", i, VI_IGNORECASE);
-                       setops(argp, "sm""\0""showmatch" , i, VI_SHOWMATCH );
-                       if (strncmp(argp, "tabstop=", 8) == 0) {
-                               int t = bb_strtou(argp + 8, NULL, 10);
-                               if (t > 0 && t <= MAX_TABSTOP)
-                                       tabstop = t;
-                       }
-                       argp = skip_non_whitespace(argp);
-                       argp = skip_whitespace(argp);
+                       argn = skip_non_whitespace(argp);
+                       oldch = *argn;
+                       *argn = '\0';
+                       setops(argp, i);
+                       *argn = oldch;
+                       argp = skip_whitespace(argn);
                }
 #  endif /* FEATURE_VI_SETOPTS */
 # endif /* FEATURE_VI_SET */
@@ -4442,10 +4462,10 @@ int vi_main(int argc, char **argv)
        }
 #endif
 
-       // autoindent is not default in vim 7.3
-       vi_setops = /*VI_AUTOINDENT |*/ VI_SHOWMATCH | VI_IGNORECASE;
-       //  1-  process $HOME/.exrc file (not inplemented yet)
-       //  2-  process EXINIT variable from environment
+       // all of our options are disabled by default in vim
+       //vi_setops = 0;
+       //  1-  process EXINIT variable from environment
+       //  2-  if EXINIT is unset process $HOME/.exrc file (not inplemented 
yet)
        //  3-  process command line args
 #if ENABLE_FEATURE_VI_COLON
        {
-- 
2.30.2

_______________________________________________
busybox mailing list
busybox@busybox.net
http://lists.busybox.net/mailman/listinfo/busybox

Reply via email to