diff options
author | Ron Yorston <rmy@pobox.com> | 2021-07-10 13:00:04 +0300 |
---|---|---|
committer | Denys Vlasenko <vda.linux@googlemail.com> | 2021-07-13 15:42:20 +0300 |
commit | 2759201401cf87a9a8621edd9e5f44dfe838407c (patch) | |
tree | ca9db39df419b242c5ca1981c200dfcee6ec4e35 /editors | |
parent | 95ac4a48f17c2fdd2a10524c0b399e3be72d8f42 (diff) |
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>
Diffstat (limited to 'editors')
-rw-r--r-- | editors/vi.c | 19 |
1 files changed, 17 insertions, 2 deletions
diff --git a/editors/vi.c b/editors/vi.c index 070e0f55a..c6bb74cfb 100644 --- a/editors/vi.c +++ b/editors/vi.c @@ -2680,6 +2680,19 @@ static char *expand_args(char *args) #if ENABLE_FEATURE_VI_REGEX_SEARCH # 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 static char *regex_search(char *q, regex_t *preg, const char *Rorig, 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; } +#else /* !ENABLE_FEATURE_VI_REGEX_SEARCH */ +# define strchr_backslash(s, c) strchr(s, c) #endif /* ENABLE_FEATURE_VI_REGEX_SEARCH */ // 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 c = buf[1]; // what is the delimiter F = buf + 2; // start of "find" - R = strchr(F, c); // middle delimiter + R = strchr_backslash(F, c); // middle delimiter if (!R) goto colon_s_fail; len_F = R - F; *R++ = '\0'; // terminate "find" - flags = strchr(R, c); + flags = strchr_backslash(R, c); if (flags) { *flags++ = '\0'; // terminate "replace" gflag = *flags; |