URI: 
       tex: reading from and writing to commands - neatvi - [fork] simple vi-type editor with UTF-8 support
  HTML git clone git://src.adamsgaard.dk/neatvi
   DIR Log
   DIR Files
   DIR Refs
   DIR README
       ---
   DIR commit 0225a76aa55a2d0dae9ac2a6d98f9c19de3b52c2
   DIR parent 1a71c8b9dd2cf614712d7ebdab0c8a8f0f624a22
  HTML Author: Ali Gholami Rudi <ali@rudi.ir>
       Date:   Tue, 16 Jun 2015 10:01:19 +0430
       
       ex: reading from and writing to commands
       
       ":r !cmd" and ":w !cmd".
       
       Diffstat:
         M cmd.c                               |      42 ++++++++++++++++---------------
         M ex.c                                |      81 +++++++++++++++++++++----------
         M vi.c                                |      31 ++++++++++++++++++++++++++++++-
         M vi.h                                |       3 ++-
       
       4 files changed, 110 insertions(+), 47 deletions(-)
       ---
   DIR diff --git a/cmd.c b/cmd.c
       t@@ -50,24 +50,30 @@ static int cmd_make(char **argv, int *ifd, int *ofd)
                return pid;
        }
        
       -char *cmd_pipe(char *cmd, char *s)
       +/* execute a command; process input if iproc and process output if oproc */
       +char *cmd_pipe(char *cmd, char *ibuf, int iproc, int oproc)
        {
                char *argv[] = {"/bin/sh", "-c", cmd, NULL};
                struct pollfd fds[3];
       -        struct sbuf *sb;
       +        struct sbuf *sb = NULL;
                char buf[512];
       -        int ifd = 0, ofd = 0;
       -        int slen = strlen(s);
       +        int ifd = -1, ofd = -1;
       +        int slen = iproc ? strlen(ibuf) : 0;
                int nw = 0;
       -        int pid = cmd_make(argv, &ifd, &ofd);
       +        int pid = cmd_make(argv, iproc ? &ifd : NULL, oproc ? &ofd : NULL);
                if (pid <= 0)
                        return NULL;
       -        sb = sbuf_make();
       +        if (oproc)
       +                sb = sbuf_make();
       +        if (!iproc) {
       +                signal(SIGINT, SIG_IGN);
       +                term_done();
       +        }
                fds[0].fd = ofd;
                fds[0].events = POLLIN;
                fds[1].fd = ifd;
                fds[1].events = POLLOUT;
       -        fds[2].fd = 0;
       +        fds[2].fd = iproc ? 0 : -1;
                fds[2].events = POLLIN;
                while ((fds[0].fd >= 0 || fds[1].fd >= 0) && poll(fds, 3, 200) >= 0) {
                        if (fds[0].revents & POLLIN) {
       t@@ -80,7 +86,7 @@ char *cmd_pipe(char *cmd, char *s)
                                fds[0].fd = -1;
                        }
                        if (fds[1].revents & POLLOUT) {
       -                        int ret = write(fds[1].fd, s + nw, slen - nw);
       +                        int ret = write(fds[1].fd, ibuf + nw, slen - nw);
                                if (ret > 0)
                                        nw += ret;
                                if (ret <= 0 || nw == slen)
       t@@ -101,21 +107,17 @@ char *cmd_pipe(char *cmd, char *s)
                close(ifd);
                close(ofd);
                waitpid(pid, NULL, 0);
       -        return sbuf_done(sb);
       +        if (!iproc) {
       +                term_init();
       +                signal(SIGINT, SIG_DFL);
       +        }
       +        if (oproc)
       +                return sbuf_done(sb);
       +        return NULL;
        }
        
        int cmd_exec(char *cmd)
        {
       -        char *argv[] = {"/bin/sh", "-c", cmd, NULL};
       -        int pid = cmd_make(argv, NULL, NULL);
       -        if (pid <= 0)
       -                return 1;
       -        signal(SIGINT, SIG_IGN);
       -        term_done();
       -        printf("\n");
       -        waitpid(pid, NULL, 0);
       -        printf("[terminated]\n");
       -        getchar();
       -        term_init();
       +        cmd_pipe(cmd, NULL, 0, 0);
                return 0;
        }
   DIR diff --git a/ex.c b/ex.c
       t@@ -143,6 +143,15 @@ static char *ex_arg(char *s, char *arg)
                return s;
        }
        
       +static char *ex_argeol(char *ec)
       +{
       +        char arg[EXLEN];
       +        char *s = ex_cmd(ec, arg);
       +        while (isspace((unsigned char) *s))
       +                s++;
       +        return s;
       +}
       +
        static int ex_search(char *pat)
        {
                struct sbuf *kw;
       t@@ -324,23 +333,32 @@ static int ec_read(char *ec)
        {
                char arg[EXLEN], loc[EXLEN];
                char msg[128];
       -        char *path;
       -        int fd;
                int beg, end;
       +        char *path;
       +        char *obuf;
                int n = lbuf_len(xb);
                ex_arg(ec, arg);
                ex_loc(ec, loc);
                path = arg[0] ? arg : ex_path();
       -        fd = open(path, O_RDONLY);
       -        if (fd < 0) {
       -                ex_show("read failed\n");
       -                return 1;
       -        }
                if (ex_region(loc, &beg, &end))
                        return 1;
       -        lbuf_rd(xb, fd, lbuf_len(xb) ? end : 0);
       -        close(fd);
       -        xrow = end + lbuf_len(xb) - n;
       +        if (arg[0] == '!') {
       +                if (ex_expand(arg, ex_argeol(ec)))
       +                        return 1;
       +                obuf = cmd_pipe(arg + 1, NULL, 0, 1);
       +                if (obuf)
       +                        lbuf_put(xb, MIN(xrow + 1, lbuf_len(xb)), obuf);
       +                free(obuf);
       +        } else {
       +                int fd = open(path, O_RDONLY);
       +                if (fd < 0) {
       +                        ex_show("read failed\n");
       +                        return 1;
       +                }
       +                lbuf_rd(xb, fd, lbuf_len(xb) ? end : 0);
       +                close(fd);
       +        }
       +        xrow = end + lbuf_len(xb) - n - 1;
                snprintf(msg, sizeof(msg), "\"%s\"  %d lines  [r]\n",
                                path, lbuf_len(xb) - n);
                ex_show(msg);
       t@@ -352,8 +370,8 @@ static int ec_write(char *ec)
                char cmd[EXLEN], arg[EXLEN], loc[EXLEN];
                char msg[128];
                char *path;
       +        char *ibuf;
                int beg, end;
       -        int fd;
                ex_cmd(ec, cmd);
                ex_arg(ec, arg);
                ex_loc(ec, loc);
       t@@ -364,13 +382,22 @@ static int ec_write(char *ec)
                        beg = 0;
                        end = lbuf_len(xb);
                }
       -        fd = open(path, O_WRONLY | O_CREAT | O_TRUNC, 0600);
       -        if (fd < 0) {
       -                ex_show("write failed\n");
       -                return 1;
       +        if (arg[0] == '!') {
       +                if (ex_expand(arg, ex_argeol(ec)))
       +                        return 1;
       +                ibuf = lbuf_cp(xb, beg, end);
       +                ex_print(NULL);
       +                cmd_pipe(arg + 1, ibuf, 1, 0);
       +                free(ibuf);
       +        } else {
       +                int fd = open(path, O_WRONLY | O_CREAT | O_TRUNC, 0600);
       +                if (fd < 0) {
       +                        ex_show("write failed\n");
       +                        return 1;
       +                }
       +                lbuf_wr(xb, fd, beg, end);
       +                close(fd);
                }
       -        lbuf_wr(xb, fd, beg, end);
       -        close(fd);
                snprintf(msg, sizeof(msg), "\"%s\"  %d lines  [w]\n",
                                path, end - beg);
                ex_show(msg);
       t@@ -437,7 +464,7 @@ static int ec_print(char *ec)
                if (ex_region(loc, &beg, &end))
                        return 1;
                for (i = beg; i < end; i++)
       -                ex_show(lbuf_get(xb, i));
       +                ex_print(lbuf_get(xb, i));
                xrow = end;
                return 0;
        }
       t@@ -504,7 +531,7 @@ static int ec_lnum(char *ec)
                if (ex_region(loc, &beg, &end))
                        return 1;
                sprintf(msg, "%d\n", end);
       -        ex_show(msg);
       +        ex_print(msg);
                return 0;
        }
        
       t@@ -589,24 +616,28 @@ static int ec_substitute(char *ec)
        
        static int ec_exec(char *ec)
        {
       -        char cmd[EXLEN];
                char arg[EXLEN];
                ex_modifiedbuffer(NULL);
       -        if (ex_expand(arg, ex_cmd(ec, cmd)))
       +        if (ex_expand(arg, ex_argeol(ec)))
                        return 1;
       -        return cmd_exec(arg);
       +        ex_print(NULL);
       +        if (cmd_exec(arg))
       +                return 1;
       +        return 0;
        }
        
        static int ec_make(char *ec)
        {
       -        char cmd[EXLEN];
                char arg[EXLEN];
                char make[EXLEN];
                ex_modifiedbuffer(NULL);
       -        if (ex_expand(arg, ex_cmd(ec, cmd)))
       +        if (ex_expand(arg, ex_argeol(ec)))
                        return 1;
                sprintf(make, "make %s", arg);
       -        return cmd_exec(make);
       +        ex_print(NULL);
       +        if (cmd_exec(make))
       +                return 1;
       +        return 0;
        }
        
        static struct option {
   DIR diff --git a/vi.c b/vi.c
       t@@ -21,6 +21,16 @@ static int vi_arg1, vi_arg2;        /* the first and second arguments */
        static int vi_ybuf;                /* current yank buffer */
        static char *vi_kmap;                /* current insertion keymap */
        static int vi_pcol;                /* the column requested by | command */
       +static int vi_printed;                /* ex_print() calls since the last command */
       +
       +static void vi_wait(void)
       +{
       +        if (vi_printed > 1) {
       +                free(ex_read("[enter to continue]"));
       +                vi_msg[0] = '\0';
       +        }
       +        vi_printed = 0;
       +}
        
        static void vi_drawmsg(void)
        {
       t@@ -77,6 +87,7 @@ static char *vi_prompt(char *msg, char **kmap)
                return led_prompt(msg, "", kmap);
        }
        
       +/* read an ex input line */
        char *ex_read(char *msg)
        {
                struct sbuf *sb;
       t@@ -97,6 +108,7 @@ char *ex_read(char *msg)
                return sbuf_done(sb);
        }
        
       +/* show an ex message */
        void ex_show(char *msg)
        {
                if (xvis) {
       t@@ -109,6 +121,22 @@ void ex_show(char *msg)
                }
        }
        
       +/* print an ex output line */
       +void ex_print(char *line)
       +{
       +        if (xvis) {
       +                vi_printed += line ? 1 : 2;
       +                if (line)
       +                        snprintf(vi_msg, sizeof(vi_msg), "%s", line);
       +                if (line)
       +                        led_print(line, -1);
       +                term_chr('\n');
       +        } else {
       +                if (line)
       +                        ex_show(line);
       +        }
       +}
       +
        static int vi_yankbuf(void)
        {
                int c = vi_read();
       t@@ -680,7 +708,7 @@ static void vi_pipe(int r1, int r2)
                if (!cmd)
                        return;
                text = lbuf_cp(xb, r1, r2 + 1);
       -        rep = cmd_pipe(cmd, text);
       +        rep = cmd_pipe(cmd, text, 1, 1);
                if (rep) {
                        lbuf_rm(xb, r1, r2 + 1);
                        lbuf_put(xb, r1, rep);
       t@@ -1210,6 +1238,7 @@ static void vi(void)
                        xoff = ren_noeol(lbuf_get(xb, xrow), xoff);
                        if (redraw)
                                xcol = vi_off2col(xb, xrow, xoff);
       +                vi_wait();
                        if (redraw || xtop != otop)
                                vi_draw(xcol);
                        if (vi_msg[0])
   DIR diff --git a/vi.h b/vi.h
       t@@ -136,6 +136,7 @@ int led_pos(char *s, int pos);
        void ex(void);
        void ex_command(char *cmd);
        char *ex_read(char *msg);
       +void ex_print(char *line);
        void ex_show(char *msg);
        void ex_init(char **files);
        void ex_done(void);
       t@@ -146,7 +147,7 @@ struct lbuf *ex_lbuf(void);
        #define xb         ex_lbuf()
        
        /* process management */
       -char *cmd_pipe(char *cmd, char *s);
       +char *cmd_pipe(char *cmd, char *s, int iproc, int oproc);
        int cmd_exec(char *cmd);
        
        /* syntax highlighting */