tvi: search commands - 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 3efb0c5dc5d7be165d3a80ecdd144e895fed6aa6
 (DIR) parent d66f358f77184dde6bdfe021d09f7f3a01441f1a
 (HTM) Author: Ali Gholami Rudi <ali@rudi.ir>
       Date:   Thu, 14 May 2015 10:11:12 +0430
       
       vi: search commands
       
       Diffstat:
         M vi.c                                |      83 +++++++++++++++++++++++++++++++
       
       1 file changed, 83 insertions(+), 0 deletions(-)
       ---
 (DIR) diff --git a/vi.c b/vi.c
       t@@ -7,6 +7,7 @@
         */
        #include <ctype.h>
        #include <fcntl.h>
       +#include <regex.h>
        #include <stdio.h>
        #include <stdlib.h>
        #include <string.h>
       t@@ -18,6 +19,8 @@ int xrow, xcol, xtop;        /* current row, column, and top row */
        int xled = 1;                /* use the line editor */
        int xdir = 'L';                /* current direction context */
        int xquit;
       +static char vi_findlast[256];        /* the last searched keyword */
       +static int vi_finddir;                /* the last search direction */
        static char vi_charlast[8];        /* the last character searched via f, t, F, or T */
        static int vi_charcmd;                /* the character finding command */
        
       t@@ -141,6 +144,74 @@ static void lbuf_findchar(struct lbuf *lb, int *row, int *col, char *cs, int cmd
                        lbuf_lnnext(lb, row, col, -dir);
        }
        
       +static int lbuf_search(struct lbuf *lb, char *kw, int dir, int *r, int *c, int *len)
       +{
       +        regmatch_t subs[1];
       +        regex_t re;
       +        int found = 0;
       +        int row = *r, col = *c;
       +        int i;
       +        if (regcomp(&re, kw, REG_EXTENDED))
       +                return 1;
       +        for (i = row; !found && i >= 0 && i < lbuf_len(lb); i += dir) {
       +                char *s = lbuf_get(lb, i);
       +                int off = dir > 0 && row == i ? col + 1 : 0;
       +                while (!regexec(&re, s + off, LEN(subs), subs, 0)) {
       +                        if (dir < 0 && row == i && off + subs[0].rm_so >= col)
       +                                break;
       +                        found = 1;
       +                        *c = off + subs[0].rm_so;
       +                        *r = i;
       +                        *len = subs[0].rm_eo - subs[0].rm_so;
       +                        off += subs[0].rm_eo;
       +                        if (dir > 0)
       +                                break;
       +                }
       +        }
       +        regfree(&re);
       +        return !found;
       +}
       +
       +static int vi_search(int cmd, int cnt, int *row, int *col)
       +{
       +        int r = *row;
       +        int c = *col;
       +        int failed = 0;
       +        int i, len;
       +        int dir;
       +        if (cmd == '/' || cmd == '?') {
       +                char sign[4] = {cmd};
       +                char *kw;
       +                term_pos(xrows, led_pos(sign, 0));
       +                term_kill();
       +                if (!(kw = led_prompt(sign, "")))
       +                        return 1;
       +                vi_finddir = cmd == '/' ? +1 : -1;
       +                if (strchr(kw, cmd))
       +                        *strchr(kw, cmd) = '\0';
       +                if (kw[0])
       +                        snprintf(vi_findlast, sizeof(vi_findlast), "%s", kw);
       +                free(kw);
       +        }
       +        dir = cmd == 'N' ? -vi_finddir : vi_finddir;
       +        if (!vi_findlast[0] || !lbuf_len(xb))
       +                return 1;
       +        c = ren_off(lbuf_get(xb, *row), *col);
       +        for (i = 0; i < cnt; i++) {
       +                if (lbuf_search(xb, vi_findlast, dir, &r, &c, &len)) {
       +                        failed = 1;
       +                        break;
       +                }
       +                if (i + 1 < cnt && cmd == '/')
       +                        c += len;
       +        }
       +        if (!failed) {
       +                *row = r;
       +                *col = ren_pos(lbuf_get(xb, r), c);
       +        }
       +        return failed;
       +}
       +
        static int vi_motionln(int *row, int cmd, int pre1, int pre2)
        {
                int pre = (pre1 ? pre1 : 1) * (pre2 ? pre2 : 1);
       t@@ -341,6 +412,18 @@ static int vi_motion(int *row, int *col, int pre1, int pre2)
                case '|':
                        *col = pre - 1;
                        break;
       +        case '/':
       +                vi_search(c, pre, row, col);
       +                break;
       +        case '?':
       +                vi_search(c, pre, row, col);
       +                break;
       +        case 'n':
       +                vi_search(c, pre, row, col);
       +                break;
       +        case 'N':
       +                vi_search(c, pre, row, col);
       +                break;
                case 127:
                case TK_CTL('h'):
                        for (i = 0; i < pre; i++)