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);