aboutsummaryrefslogtreecommitdiff
path: root/editors/vi.c
diff options
context:
space:
mode:
authorRon Yorston <rmy@pobox.com>2021-04-06 22:11:21 +0100
committerDenys Vlasenko <vda.linux@googlemail.com>2021-04-08 12:50:01 +0200
commit9f017d9db0eb5522eb9c140a2d839461c677eb8e (patch)
tree154b0b9921a0cb009bcbf693557c82980b01101b /editors/vi.c
parent24198f652f10dca5603df7c704263358ca21f5ce (diff)
downloadbusybox-w32-9f017d9db0eb5522eb9c140a2d839461c677eb8e.tar.gz
busybox-w32-9f017d9db0eb5522eb9c140a2d839461c677eb8e.tar.bz2
busybox-w32-9f017d9db0eb5522eb9c140a2d839461c677eb8e.zip
vi: changes to option handling
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. Issue an error message if: - an option is not implemented - an option that takes a value has no '=' or has a 'no' prefix - a boolean option has a '=' function old new delta colon 2944 3003 +59 .rodata 103171 103189 +18 vi_main 274 270 -4 setops 73 - -73 ------------------------------------------------------------------------------ (add/remove: 0/1 grow/shrink: 2/1 up/down: 77/-77) Total: 0 bytes v2: Try harder to detect invalid options. Thanks to Peter D for pointing this out. Signed-off-by: Ron Yorston <rmy@pobox.com> Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
Diffstat (limited to 'editors/vi.c')
-rw-r--r--editors/vi.c91
1 files changed, 57 insertions, 34 deletions
diff --git a/editors/vi.c b/editors/vi.c
index 04d584fec..1c5a32bf9 100644
--- a/editors/vi.c
+++ b/editors/vi.c
@@ -278,16 +278,23 @@ struct globals {
278 int text_size; // size of the allocated buffer 278 int text_size; // size of the allocated buffer
279 279
280 // the rest 280 // the rest
281 smallint vi_setops; 281 smallint vi_setops; // set by setops()
282#define VI_AUTOINDENT 1 282#define VI_AUTOINDENT (1 << 0)
283#define VI_SHOWMATCH 2 283#define VI_ERR_METHOD (1 << 1)
284#define VI_IGNORECASE 4 284#define VI_IGNORECASE (1 << 2)
285#define VI_ERR_METHOD 8 285#define VI_SHOWMATCH (1 << 3)
286#define VI_TABSTOP (1 << 4)
286#define autoindent (vi_setops & VI_AUTOINDENT) 287#define autoindent (vi_setops & VI_AUTOINDENT)
287#define showmatch (vi_setops & VI_SHOWMATCH ) 288#define err_method (vi_setops & VI_ERR_METHOD) // indicate error with beep or flash
288#define ignorecase (vi_setops & VI_IGNORECASE) 289#define ignorecase (vi_setops & VI_IGNORECASE)
289// indicate error with beep or flash 290#define showmatch (vi_setops & VI_SHOWMATCH )
290#define err_method (vi_setops & VI_ERR_METHOD) 291// order of constants and strings must match
292#define OPTS_STR \
293 "ai\0""autoindent\0" \
294 "fl\0""flash\0" \
295 "ic\0""ignorecase\0" \
296 "sm\0""showmatch\0" \
297 "ts\0""tabstop\0"
291 298
292#if ENABLE_FEATURE_VI_READONLY 299#if ENABLE_FEATURE_VI_READONLY
293 smallint readonly_mode; 300 smallint readonly_mode;
@@ -2380,17 +2387,38 @@ static char *get_address(char *p, int *b, int *e) // get two colon addrs, if pre
2380} 2387}
2381 2388
2382# if ENABLE_FEATURE_VI_SET && ENABLE_FEATURE_VI_SETOPTS 2389# if ENABLE_FEATURE_VI_SET && ENABLE_FEATURE_VI_SETOPTS
2383static void setops(const char *args, const char *nm_longname, int flg_no, int opt) 2390static void setops(char *args, int flg_no)
2384{ 2391{
2385 const char *a = args + flg_no; 2392 char *eq;
2393 int index;
2394
2395 eq = strchr(args, '=');
2396 if (eq) *eq = '\0';
2397 index = index_in_strings(OPTS_STR, args + flg_no);
2398 if (eq) *eq = '=';
2399 if (index < 0) {
2400 bad:
2401 status_line_bold("bad option: %s", args);
2402 return;
2403 }
2386 2404
2387 if (strcmp(a, nm_longname) == 0 2405 index = 1 << (index >> 1); // convert to VI_bit
2388 || strcmp(a, nm_longname + 3) == 0 2406
2389 ) { 2407 if (index & VI_TABSTOP) {
2390 if (flg_no) 2408 int t;
2391 vi_setops &= ~opt; 2409 if (!eq || flg_no) // no "=NNN" or it is "notabstop"?
2392 else 2410 goto bad;
2393 vi_setops |= opt; 2411 t = bb_strtou(eq + 1, NULL, 10);
2412 if (t <= 0 || t > MAX_TABSTOP)
2413 goto bad;
2414 tabstop = t;
2415 return;
2416 }
2417 if (eq) goto bad; // boolean option has "="?
2418 if (flg_no) {
2419 vi_setops &= ~index;
2420 } else {
2421 vi_setops |= index;
2394 } 2422 }
2395} 2423}
2396# endif 2424# endif
@@ -2750,10 +2778,10 @@ static void colon(char *buf)
2750# if ENABLE_FEATURE_VI_SET 2778# if ENABLE_FEATURE_VI_SET
2751 } else if (strncmp(cmd, "set", i) == 0) { // set or clear features 2779 } else if (strncmp(cmd, "set", i) == 0) { // set or clear features
2752# if ENABLE_FEATURE_VI_SETOPTS 2780# if ENABLE_FEATURE_VI_SETOPTS
2753 char *argp; 2781 char *argp, *argn, oldch;
2754# endif 2782# endif
2755 // only blank is regarded as args delimiter. What about tab '\t'? 2783 // only blank is regarded as args delimiter. What about tab '\t'?
2756 if (!args[0] || strcasecmp(args, "all") == 0) { 2784 if (!args[0] || strcmp(args, "all") == 0) {
2757 // print out values of all options 2785 // print out values of all options
2758# if ENABLE_FEATURE_VI_SETOPTS 2786# if ENABLE_FEATURE_VI_SETOPTS
2759 status_line_bold( 2787 status_line_bold(
@@ -2777,17 +2805,12 @@ static void colon(char *buf)
2777 i = 0; 2805 i = 0;
2778 if (argp[0] == 'n' && argp[1] == 'o') // "noXXX" 2806 if (argp[0] == 'n' && argp[1] == 'o') // "noXXX"
2779 i = 2; 2807 i = 2;
2780 setops(argp, "ai""\0""autoindent", i, VI_AUTOINDENT); 2808 argn = skip_non_whitespace(argp);
2781 setops(argp, "fl""\0""flash" , i, VI_ERR_METHOD); 2809 oldch = *argn;
2782 setops(argp, "ic""\0""ignorecase", i, VI_IGNORECASE); 2810 *argn = '\0';
2783 setops(argp, "sm""\0""showmatch" , i, VI_SHOWMATCH ); 2811 setops(argp, i);
2784 if (strncmp(argp, "tabstop=", 8) == 0) { 2812 *argn = oldch;
2785 int t = bb_strtou(argp + 8, NULL, 10); 2813 argp = skip_whitespace(argn);
2786 if (t > 0 && t <= MAX_TABSTOP)
2787 tabstop = t;
2788 }
2789 argp = skip_non_whitespace(argp);
2790 argp = skip_whitespace(argp);
2791 } 2814 }
2792# endif /* FEATURE_VI_SETOPTS */ 2815# endif /* FEATURE_VI_SETOPTS */
2793# endif /* FEATURE_VI_SET */ 2816# endif /* FEATURE_VI_SET */
@@ -4383,10 +4406,10 @@ int vi_main(int argc, char **argv)
4383 } 4406 }
4384#endif 4407#endif
4385 4408
4386 // autoindent is not default in vim 7.3 4409 // 0: all of our options are disabled by default in vim
4387 vi_setops = /*VI_AUTOINDENT |*/ VI_SHOWMATCH | VI_IGNORECASE; 4410 //vi_setops = 0;
4388 // 1- process $HOME/.exrc file (not inplemented yet) 4411 // 1- process EXINIT variable from environment
4389 // 2- process EXINIT variable from environment 4412 // 2- if EXINIT is unset process $HOME/.exrc file (not inplemented yet)
4390 // 3- process command line args 4413 // 3- process command line args
4391#if ENABLE_FEATURE_VI_COLON 4414#if ENABLE_FEATURE_VI_COLON
4392 { 4415 {