tvi: escaped delimiters in regular expressions - neatvi - [fork] simple vi-type editor with UTF-8 support
(HTM) git clone git://src.adamsgaard.dk/neatvi
(DIR) Log
(DIR) Files
(DIR) Refs
(DIR) README
---
(DIR) commit a162543d7ef56e666d8436be42e9180a4864a4e5
(DIR) parent 31e7e13a90023abeac92914774c31721ae0c22d9
(HTM) Author: Ali Gholami Rudi <ali@rudi.ir>
Date: Fri, 1 Jan 2016 09:49:33 +0330
vi: escaped delimiters in regular expressions
Diffstat:
M ex.c | 27 ++++-----------------------
M rset.c | 18 ++++++++++++++++++
M vi.c | 34 +++++++++++++++++++------------
M vi.h | 1 +
4 files changed, 44 insertions(+), 36 deletions(-)
---
(DIR) diff --git a/ex.c b/ex.c
t@@ -627,22 +627,6 @@ static int ec_mark(char *ec)
return 0;
}
-static char *readuntil(char **src, int delim)
-{
- struct sbuf *sbuf = sbuf_make();
- char *s = *src;
- /* reading the pattern */
- while (*s && *s != delim) {
- if (s[0] == '\\' && s[1])
- sbuf_chr(sbuf, (unsigned char) *s++);
- sbuf_chr(sbuf, (unsigned char) *s++);
- }
- if (*s) /* skipping the delimiter */
- s++;
- *src = s;
- return sbuf_done(sbuf);
-}
-
static int ec_substitute(char *ec)
{
char loc[EXLEN];
t@@ -652,15 +636,14 @@ static int ec_substitute(char *ec)
char *pats[1];
char *pat, *rep;
char *s;
- int delim;
int i;
ex_loc(ec, loc);
if (ex_region(loc, &beg, &end))
return 1;
s = ex_argeol(ec);
- delim = (unsigned char) *s++;
- pat = readuntil(&s, delim);
- rep = readuntil(&s, delim);
+ pat = re_read(&s);
+ s--;
+ rep = re_read(&s);
if (pat[0])
snprintf(xfindkwd, sizeof(xfindkwd), "%s", pat);
free(pat);
t@@ -751,7 +734,6 @@ static int ec_glob(char *ec)
int beg, end, not;
char *pats[1];
char *pat, *s;
- int delim;
int i;
ex_cmd(ec, cmd);
ex_loc(ec, loc);
t@@ -759,8 +741,7 @@ static int ec_glob(char *ec)
return 1;
not = strchr(cmd, '!') || cmd[0] == 'v';
s = ex_argeol(ec);
- delim = (unsigned char) *s++;
- pat = readuntil(&s, delim);
+ pat = re_read(&s);
if (pat[0])
snprintf(xfindkwd, sizeof(xfindkwd), "%s", pat);
free(pat);
(DIR) diff --git a/rset.c b/rset.c
t@@ -117,3 +117,21 @@ void rset_free(struct rset *rs)
free(rs->grp);
free(rs);
}
+
+/* read a regular expression enclosed in a delimiter */
+char *re_read(char **src)
+{
+ struct sbuf *sbuf = sbuf_make();
+ char *s = *src;
+ int delim = (unsigned char) *s++;
+ if (!delim)
+ return NULL;
+ while (*s && *s != delim) {
+ if (s[0] == '\\' && s[1])
+ if (*(++s) != delim)
+ sbuf_chr(sbuf, '\\');
+ sbuf_chr(sbuf, (unsigned char) *s++);
+ }
+ *src = *s ? s + 1 : s;
+ return sbuf_done(sbuf);
+}
(DIR) diff --git a/vi.c b/vi.c
t@@ -20,6 +20,7 @@ static int vi_ybuf; /* current yank buffer */
static int vi_pcol; /* the column requested by | command */
static int vi_printed; /* ex_print() calls since the last command */
static int vi_scroll; /* scroll amount for ^f and ^d*/
+static int vi_soset, vi_so; /* search offset; 1 in "/kw/1" */
static void vi_wait(void)
{
t@@ -213,20 +214,29 @@ static int vi_search(int cmd, int cnt, int *row, int *off)
int failed = 0;
int len = 0;
int i, dir;
- char *soff = "";
if (cmd == '/' || cmd == '?') {
char sign[4] = {cmd};
+ struct sbuf *sb;
char *kw = vi_prompt(sign, ex_kmap());
+ char *re;
if (!kw)
return 1;
- xfinddir = cmd == '/' ? +1 : -1;
- if (kw[0])
- snprintf(xfindkwd, sizeof(xfindkwd), "%s", kw);
- if (strchr(xfindkwd, cmd)) {
- soff = strchr(xfindkwd, cmd) + 1;
- *strchr(xfindkwd, cmd) = '\0';
- }
+ sb = sbuf_make();
+ sbuf_chr(sb, cmd);
+ sbuf_str(sb, kw);
free(kw);
+ kw = sbuf_buf(sb);
+ if ((re = re_read(&kw))) {
+ xfinddir = cmd == '/' ? +1 : -1;
+ if (re[0])
+ snprintf(xfindkwd, sizeof(xfindkwd), "%s", re);
+ while (isspace(*kw))
+ kw++;
+ vi_soset = !!kw[0];
+ vi_so = atoi(kw);
+ free(re);
+ }
+ sbuf_free(sb);
}
dir = cmd == 'N' ? -xfinddir : xfinddir;
if (!xfindkwd[0] || !lbuf_len(xb))
t@@ -243,14 +253,12 @@ static int vi_search(int cmd, int cnt, int *row, int *off)
if (!failed) {
*row = r;
*off = o;
- while (soff[0] && isspace((unsigned char) soff[0]))
- soff++;
- if (soff[0]) {
+ if (vi_soset) {
*off = -1;
- if (*row + atoi(soff) < 0 || *row + atoi(soff) >= lbuf_len(xb))
+ if (*row + vi_so < 0 || *row + vi_so >= lbuf_len(xb))
failed = 1;
else
- *row += atoi(soff);
+ *row += vi_so;
}
}
if (failed)
(DIR) diff --git a/vi.h b/vi.h
t@@ -51,6 +51,7 @@ void sbuf_cut(struct sbuf *s, int len);
struct rset *rset_make(int n, char **pat, int flg);
int rset_find(struct rset *re, char *s, int n, int *grps, int flg);
void rset_free(struct rset *re);
+char *re_read(char **src);
/* rendering lines */
int *ren_position(char *s);