tvi: repeat and execute 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 901e0cd396e087f435fa96b51196d01d0f94ca18
 (DIR) parent 04a3edea64e70aae164a0550acaf5bf18ccac472
 (HTM) Author: Ali Gholami Rudi <ali@rudi.ir>
       Date:   Tue,  2 Jun 2015 19:37:04 +0430
       
       vi: repeat and execute commands
       
       Diffstat:
         M term.c                              |      45 +++++++++++++++++++++++++------
         M vi.c                                |      39 +++++++++++++++++++++++++++++++
         M vi.h                                |       2 ++
       
       3 files changed, 78 insertions(+), 8 deletions(-)
       ---
 (DIR) diff --git a/term.c b/term.c
       t@@ -109,17 +109,46 @@ int term_cols(void)
                return cols;
        }
        
       +static char ibuf[4096];                /* input character buffer */
       +static char icmd[4096];                /* read after the last term_cmd() */
       +static int ibuf_pos, ibuf_cnt;        /* ibuf[] position and length */
       +static int icmd_pos;                /* icmd[] position */
       +
       +/* read s before reading from the terminal */
       +void term_push(char *s, int n)
       +{
       +        n = MIN(n, sizeof(ibuf) - ibuf_cnt);
       +        memcpy(ibuf + ibuf_cnt, s, n);
       +        ibuf_cnt += n;
       +}
       +
       +/* return a static buffer containing inputs read since the last term_cmd() */
       +char *term_cmd(int *n)
       +{
       +        *n = icmd_pos;
       +        icmd_pos = 0;
       +        return icmd;
       +}
       +
        int term_read(int ms)
        {
                struct pollfd ufds[1];
       -        char b;
       -        ufds[0].fd = 0;
       -        ufds[0].events = POLLIN;
       -        if (poll(ufds, 1, ms * 1000) <= 0)
       -                return -1;
       -        if (read(0, &b, 1) <= 0)
       -                return -1;
       -        return (unsigned char) b;
       +        char n, c;
       +        if (ibuf_pos >= ibuf_cnt) {
       +                ufds[0].fd = 0;
       +                ufds[0].events = POLLIN;
       +                if (poll(ufds, 1, ms * 1000) <= 0)
       +                        return -1;
       +                /* read a single input character */
       +                if ((n = read(0, ibuf, 1)) <= 0)
       +                        return -1;
       +                ibuf_cnt = n;
       +                ibuf_pos = 0;
       +        }
       +        c = ibuf_pos < ibuf_cnt ? (unsigned char) ibuf[ibuf_pos++] : -1;
       +        if (icmd_pos < sizeof(icmd))
       +                icmd[icmd_pos++] = c;
       +        return c;
        }
        
        /* return a static string that changes text attributes from old to att */
 (DIR) diff --git a/vi.c b/vi.c
       t@@ -907,6 +907,30 @@ static int vc_replace(void)
                return 0;
        }
        
       +static char rep_cmd[4096];        /* the last command */
       +static int rep_len;
       +
       +static void vc_repeat(void)
       +{
       +        term_push(rep_cmd, rep_len);
       +}
       +
       +static void vc_execute(void)
       +{
       +        static int exec_buf;
       +        int lnmode;
       +        int c = vi_read();
       +        char *buf;
       +        if (TK_INT(c))
       +                return;
       +        if (c == '@')
       +                c = exec_buf;
       +        exec_buf = c;
       +        buf = reg_get(exec_buf, &lnmode);
       +        if (buf)
       +                term_push(buf, strlen(buf));
       +}
       +
        static void vi(void)
        {
                int xcol;
       t@@ -926,6 +950,7 @@ static void vi(void)
                        int noff = ren_noeol(lbuf_get(xb, xrow), xoff);
                        int otop = xtop;
                        int mv, n;
       +                term_cmd(&n);
                        vi_arg2 = 0;
                        vi_ybuf = vi_yankbuf();
                        vi_arg1 = vi_prefix();
       t@@ -946,6 +971,7 @@ static void vi(void)
                                if (mv == '|')
                                        xcol = vi_pcol;
                        } else if (mv == 0) {
       +                        char *cmd;
                                int c = vi_read();
                                int z, g;
                                if (c <= 0)
       t@@ -1109,9 +1135,22 @@ static void vi(void)
                                        if (!vc_motion('~'))
                                                redraw = 1;
                                        break;
       +                        case '.':
       +                                vc_repeat();
       +                                break;
       +                        case '@':
       +                                vc_execute();
       +                                break;
                                default:
                                        continue;
                                }
       +                        cmd = term_cmd(&n);
       +                        if (strchr("!<>ACDIJOPRSXYacdioprsxy~", c)) {
       +                                if (n < sizeof(rep_cmd)) {
       +                                        memcpy(rep_cmd, cmd, n);
       +                                        rep_len = n;
       +                                }
       +                        }
                        }
                        if (xrow < 0 || xrow >= lbuf_len(xb))
                                xrow = lbuf_len(xb) ? lbuf_len(xb) - 1 : 0;
 (DIR) diff --git a/vi.h b/vi.h
       t@@ -116,6 +116,8 @@ int term_read(int timeout);
        void term_record(void);
        void term_commit(void);
        char *term_att(int att, int old);
       +void term_push(char *s, int n);
       +char *term_cmd(int *n);
        
        #define TK_CTL(x)        ((x) & 037)
        #define TK_INT(c)        ((c) < 0 || (c) == TK_ESC || (c) == TK_CTL('c'))