vi: allow delimiter in ':s' to be escaped
When regular expressions are allowed in search commands it becomes possible to escape the delimiter in search/replace commands. For example, this command will replace '/abc' with '/abc/': :s/\/abc/\/abc\//g The code to split the command into 'find' and 'replace' strings should allow for this possibility. VI_REGEX_SEARCH isn't enabled by default. When it is: function old new delta strchr_backslash - 38 +38 colon 4378 4373 -5 ------------------------------------------------------------------------------ (add/remove: 1/0 grow/shrink: 0/1 up/down: 38/-5) Total: 33 bytes Signed-off-by: Ron Yorston <rmy@pobox.com> Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
This commit is contained in:
parent
95ac4a48f1
commit
2759201401
19
editors/vi.c
19
editors/vi.c
@ -2680,6 +2680,19 @@ static char *expand_args(char *args)
|
|||||||
#if ENABLE_FEATURE_VI_REGEX_SEARCH
|
#if ENABLE_FEATURE_VI_REGEX_SEARCH
|
||||||
# define MAX_SUBPATTERN 10 // subpatterns \0 .. \9
|
# define MAX_SUBPATTERN 10 // subpatterns \0 .. \9
|
||||||
|
|
||||||
|
// Like strchr() but skipping backslash-escaped characters
|
||||||
|
static char *strchr_backslash(const char *s, int c)
|
||||||
|
{
|
||||||
|
for (; *s; ++s) {
|
||||||
|
if (*s == c) {
|
||||||
|
return (char *)s;
|
||||||
|
} else if (*s == '\\' && *++s == '\0') {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
// If the return value is not NULL the caller should free R
|
// If the return value is not NULL the caller should free R
|
||||||
static char *regex_search(char *q, regex_t *preg, const char *Rorig,
|
static char *regex_search(char *q, regex_t *preg, const char *Rorig,
|
||||||
size_t *len_F, size_t *len_R, char **R)
|
size_t *len_F, size_t *len_R, char **R)
|
||||||
@ -2728,6 +2741,8 @@ static char *regex_search(char *q, regex_t *preg, const char *Rorig,
|
|||||||
|
|
||||||
return found;
|
return found;
|
||||||
}
|
}
|
||||||
|
#else /* !ENABLE_FEATURE_VI_REGEX_SEARCH */
|
||||||
|
# define strchr_backslash(s, c) strchr(s, c)
|
||||||
#endif /* ENABLE_FEATURE_VI_REGEX_SEARCH */
|
#endif /* ENABLE_FEATURE_VI_REGEX_SEARCH */
|
||||||
|
|
||||||
// buf must be no longer than MAX_INPUT_LEN!
|
// buf must be no longer than MAX_INPUT_LEN!
|
||||||
@ -3151,12 +3166,12 @@ static void colon(char *buf)
|
|||||||
// replace the cmd line delimiters "/" with NULs
|
// replace the cmd line delimiters "/" with NULs
|
||||||
c = buf[1]; // what is the delimiter
|
c = buf[1]; // what is the delimiter
|
||||||
F = buf + 2; // start of "find"
|
F = buf + 2; // start of "find"
|
||||||
R = strchr(F, c); // middle delimiter
|
R = strchr_backslash(F, c); // middle delimiter
|
||||||
if (!R)
|
if (!R)
|
||||||
goto colon_s_fail;
|
goto colon_s_fail;
|
||||||
len_F = R - F;
|
len_F = R - F;
|
||||||
*R++ = '\0'; // terminate "find"
|
*R++ = '\0'; // terminate "find"
|
||||||
flags = strchr(R, c);
|
flags = strchr_backslash(R, c);
|
||||||
if (flags) {
|
if (flags) {
|
||||||
*flags++ = '\0'; // terminate "replace"
|
*flags++ = '\0'; // terminate "replace"
|
||||||
gflag = *flags;
|
gflag = *flags;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user