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>
This commit is contained in:
parent
24198f652f
commit
9f017d9db0
91
editors/vi.c
91
editors/vi.c
@ -278,16 +278,23 @@ struct globals {
|
|||||||
int text_size; // size of the allocated buffer
|
int text_size; // size of the allocated buffer
|
||||||
|
|
||||||
// the rest
|
// the rest
|
||||||
smallint vi_setops;
|
smallint vi_setops; // set by setops()
|
||||||
#define VI_AUTOINDENT 1
|
#define VI_AUTOINDENT (1 << 0)
|
||||||
#define VI_SHOWMATCH 2
|
#define VI_ERR_METHOD (1 << 1)
|
||||||
#define VI_IGNORECASE 4
|
#define VI_IGNORECASE (1 << 2)
|
||||||
#define VI_ERR_METHOD 8
|
#define VI_SHOWMATCH (1 << 3)
|
||||||
|
#define VI_TABSTOP (1 << 4)
|
||||||
#define autoindent (vi_setops & VI_AUTOINDENT)
|
#define autoindent (vi_setops & VI_AUTOINDENT)
|
||||||
#define showmatch (vi_setops & VI_SHOWMATCH )
|
#define err_method (vi_setops & VI_ERR_METHOD) // indicate error with beep or flash
|
||||||
#define ignorecase (vi_setops & VI_IGNORECASE)
|
#define ignorecase (vi_setops & VI_IGNORECASE)
|
||||||
// indicate error with beep or flash
|
#define showmatch (vi_setops & VI_SHOWMATCH )
|
||||||
#define err_method (vi_setops & VI_ERR_METHOD)
|
// order of constants and strings must match
|
||||||
|
#define OPTS_STR \
|
||||||
|
"ai\0""autoindent\0" \
|
||||||
|
"fl\0""flash\0" \
|
||||||
|
"ic\0""ignorecase\0" \
|
||||||
|
"sm\0""showmatch\0" \
|
||||||
|
"ts\0""tabstop\0"
|
||||||
|
|
||||||
#if ENABLE_FEATURE_VI_READONLY
|
#if ENABLE_FEATURE_VI_READONLY
|
||||||
smallint readonly_mode;
|
smallint readonly_mode;
|
||||||
@ -2380,17 +2387,38 @@ 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
|
# if ENABLE_FEATURE_VI_SET && ENABLE_FEATURE_VI_SETOPTS
|
||||||
static void setops(const char *args, const char *nm_longname, int flg_no, int opt)
|
static void setops(char *args, int flg_no)
|
||||||
{
|
{
|
||||||
const char *a = args + flg_no;
|
char *eq;
|
||||||
|
int index;
|
||||||
|
|
||||||
if (strcmp(a, nm_longname) == 0
|
eq = strchr(args, '=');
|
||||||
|| strcmp(a, nm_longname + 3) == 0
|
if (eq) *eq = '\0';
|
||||||
) {
|
index = index_in_strings(OPTS_STR, args + flg_no);
|
||||||
if (flg_no)
|
if (eq) *eq = '=';
|
||||||
vi_setops &= ~opt;
|
if (index < 0) {
|
||||||
else
|
bad:
|
||||||
vi_setops |= opt;
|
status_line_bold("bad option: %s", args);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
index = 1 << (index >> 1); // convert to VI_bit
|
||||||
|
|
||||||
|
if (index & VI_TABSTOP) {
|
||||||
|
int t;
|
||||||
|
if (!eq || flg_no) // no "=NNN" or it is "notabstop"?
|
||||||
|
goto bad;
|
||||||
|
t = bb_strtou(eq + 1, NULL, 10);
|
||||||
|
if (t <= 0 || t > MAX_TABSTOP)
|
||||||
|
goto bad;
|
||||||
|
tabstop = t;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (eq) goto bad; // boolean option has "="?
|
||||||
|
if (flg_no) {
|
||||||
|
vi_setops &= ~index;
|
||||||
|
} else {
|
||||||
|
vi_setops |= index;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
# endif
|
# endif
|
||||||
@ -2750,10 +2778,10 @@ static void colon(char *buf)
|
|||||||
# if ENABLE_FEATURE_VI_SET
|
# if ENABLE_FEATURE_VI_SET
|
||||||
} else if (strncmp(cmd, "set", i) == 0) { // set or clear features
|
} else if (strncmp(cmd, "set", i) == 0) { // set or clear features
|
||||||
# if ENABLE_FEATURE_VI_SETOPTS
|
# if ENABLE_FEATURE_VI_SETOPTS
|
||||||
char *argp;
|
char *argp, *argn, oldch;
|
||||||
# endif
|
# endif
|
||||||
// only blank is regarded as args delimiter. What about tab '\t'?
|
// 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
|
// print out values of all options
|
||||||
# if ENABLE_FEATURE_VI_SETOPTS
|
# if ENABLE_FEATURE_VI_SETOPTS
|
||||||
status_line_bold(
|
status_line_bold(
|
||||||
@ -2777,17 +2805,12 @@ static void colon(char *buf)
|
|||||||
i = 0;
|
i = 0;
|
||||||
if (argp[0] == 'n' && argp[1] == 'o') // "noXXX"
|
if (argp[0] == 'n' && argp[1] == 'o') // "noXXX"
|
||||||
i = 2;
|
i = 2;
|
||||||
setops(argp, "ai""\0""autoindent", i, VI_AUTOINDENT);
|
argn = skip_non_whitespace(argp);
|
||||||
setops(argp, "fl""\0""flash" , i, VI_ERR_METHOD);
|
oldch = *argn;
|
||||||
setops(argp, "ic""\0""ignorecase", i, VI_IGNORECASE);
|
*argn = '\0';
|
||||||
setops(argp, "sm""\0""showmatch" , i, VI_SHOWMATCH );
|
setops(argp, i);
|
||||||
if (strncmp(argp, "tabstop=", 8) == 0) {
|
*argn = oldch;
|
||||||
int t = bb_strtou(argp + 8, NULL, 10);
|
argp = skip_whitespace(argn);
|
||||||
if (t > 0 && t <= MAX_TABSTOP)
|
|
||||||
tabstop = t;
|
|
||||||
}
|
|
||||||
argp = skip_non_whitespace(argp);
|
|
||||||
argp = skip_whitespace(argp);
|
|
||||||
}
|
}
|
||||||
# endif /* FEATURE_VI_SETOPTS */
|
# endif /* FEATURE_VI_SETOPTS */
|
||||||
# endif /* FEATURE_VI_SET */
|
# endif /* FEATURE_VI_SET */
|
||||||
@ -4383,10 +4406,10 @@ int vi_main(int argc, char **argv)
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// autoindent is not default in vim 7.3
|
// 0: all of our options are disabled by default in vim
|
||||||
vi_setops = /*VI_AUTOINDENT |*/ VI_SHOWMATCH | VI_IGNORECASE;
|
//vi_setops = 0;
|
||||||
// 1- process $HOME/.exrc file (not inplemented yet)
|
// 1- process EXINIT variable from environment
|
||||||
// 2- process EXINIT variable from environment
|
// 2- if EXINIT is unset process $HOME/.exrc file (not inplemented yet)
|
||||||
// 3- process command line args
|
// 3- process command line args
|
||||||
#if ENABLE_FEATURE_VI_COLON
|
#if ENABLE_FEATURE_VI_COLON
|
||||||
{
|
{
|
||||||
|
Loading…
Reference in New Issue
Block a user