make input handling more flexible - sob - simple output bar
 (HTM) git clone git://git.codemadness.org/sob
 (DIR) Log
 (DIR) Files
 (DIR) Refs
 (DIR) README
 (DIR) LICENSE
       ---
 (DIR) commit 94943b8e5e88cd90374abc46d954657c6fc63f51
 (DIR) parent 0d01477d561d460a40b68ec469b23d9edb2e88a0
 (HTM) Author: Hiltjo Posthuma <hiltjo@codemadness.org>
       Date:   Fri, 10 Oct 2014 21:54:57 +0000
       
       make input handling more flexible
       
       - improve non-blocked reads.
       - allow to pipe multiple lines using callbacks (same as handleinput for
         cb_* callbacks).
       - change -l to -i, because input can now be more than just text.
       
       Diffstat:
         M sob.c                               |     114 ++++++++++++++++---------------
       
       1 file changed, 58 insertions(+), 56 deletions(-)
       ---
 (DIR) diff --git a/sob.c b/sob.c
       @@ -30,6 +30,9 @@ struct line {
                size_t collen;     /* total length (in columns) */
        };
        
       +static void   cb_pipe_insert(const char *, size_t);
       +static void   cb_pipe_replaceword(const char *, size_t);
       +
        static void   line_clear(void);
        static void   line_copywordcursor(char *, size_t);
        static void   line_cursor_begin(void);
       @@ -56,10 +59,10 @@ static void   line_out(void);
        static void   line_prompt(void);
        static int    line_promptlen(void);
        static int    line_pipeto(char **);
       -static void   line_set(const char *);
        static int    line_wordpipeto(char **);
       -static int    pipe_readline(int, int, char *, char *, size_t);
       -static int    pipe_cmd(char *[], char *, char *, size_t);
       +
       +static int    pipe_readline(int, int, char *, void (*)(const char *, size_t));
       +static int    pipe_cmd(char *[], char *, void (*)(const char *, size_t));
        
        static void   cleanup(void);
        static void   gettermsize(void);
       @@ -211,13 +214,6 @@ line_inserttext(const char *s)
                line.collen = colw(line.line, line.bytesiz);
        }
        
       -static void
       -line_set(const char *s)
       -{
       -        memset(&line, 0, sizeof(line));
       -        line_inserttext(s);
       -}
       -
        /* like mksh, toggle counting of escape codes in prompt with "\x01" */
        static int
        line_promptlen(void)
       @@ -537,10 +533,10 @@ line_copywordcursor(char *buf, size_t bufsiz)
        }
        
        static int
       -pipe_readline(int fd_in, int fd_out, char *writestr, char *outbuf,
       -        size_t outbufsiz)
       +pipe_readline(int fd_in, int fd_out, char *writestr,
       +        void (*f)(const char *, size_t))
        {
       -        char buf[PIPE_BUF], *p;
       +        char buf[PIPE_BUF];
                struct timeval tv;
                fd_set fdr, fdw;
                int r, w, maxfd, status = -1, haswritten = 0;
       @@ -567,17 +563,21 @@ pipe_readline(int fd_in, int fd_out, char *writestr, char *outbuf,
        
                        if(haswritten) {
                                if(FD_ISSET(fd_in, &fdr)) {
       -                                /* read until newline */
       -                                if((r = read(fd_in, buf, sizeof(buf))) == -1)
       -                                        goto fini;
       -                                buf[r] = '\0';
       -                                if(outbuf) {
       -                                        if((p = strpbrk(buf, "\r\n")))
       -                                                *p = '\0';
       -                                        strlcpy(outbuf, buf, outbufsiz);
       +                                while(1) {
       +                                        if((r = read(fd_in, buf, sizeof(buf))) == -1) {
       +                                                if(errno == EINTR)
       +                                                        continue;
       +                                                goto fini;
       +                                        } else {
       +                                                buf[r] = '\0';
       +                                                if(f)
       +                                                        f(buf, r);
       +                                                if(!r) {
       +                                                        status = 0;
       +                                                        goto fini;
       +                                                }
       +                                        }
                                        }
       -                                status = 0;
       -                                goto fini;
                                }
                        } else {
                                if(FD_ISSET(fd_out, &fdw)) {
       @@ -599,7 +599,7 @@ fini:
        }
        
        static int
       -pipe_cmd(char *cmd[], char *writestr, char *outbuf, size_t outbufsiz)
       +pipe_cmd(char *cmd[], char *writestr, void (*f)(const char *, size_t))
        {
                struct sigaction sa;
                pid_t pid;
       @@ -640,48 +640,46 @@ pipe_cmd(char *cmd[], char *writestr, char *outbuf, size_t outbufsiz)
                        sa.sa_handler = SIG_IGN;
                        sigaction(SIGPIPE, &sa, NULL);
        
       -                if(pipe_readline(cp[0], pc[1], writestr, outbuf, outbufsiz) == -1)
       +                if(pipe_readline(cp[0], pc[1], writestr, f) == -1)
                                return -1;
                }
                return 0;
        }
        
       +static void
       +cb_pipe_insert(const char *buf, size_t len)
       +{
       +        if(!len)
       +                return;
       +        memset(&line, 0, sizeof(line));
       +        handleinput((unsigned char *)buf, len);
       +}
       +
       +static void
       +cb_pipe_replaceword(const char *buf, size_t len)
       +{
       +        if(!len)
       +                return;
       +        line_delwordcursor();
       +        handleinput((unsigned char *)buf, len);
       +}
       +
        static int
        line_pipeto(char **cmd)
        {
       -        char buf[BUFSIZ];
       -
       -        if(pipe_cmd(cmd, line.line, buf, sizeof(buf)) == -1)
       -                return -1;
       -        if(buf[0] == '\0')
       -                return -1;
       -        line_set(buf);
       -        line_cursor_end();
       -        line_draw();
       -        return 0;
       +        return pipe_cmd(cmd, line.line, cb_pipe_insert);
        }
        
        /* pipe word under cursor and replace it */
        static int
        line_wordpipeto(char **cmd)
        {
       -        char wordbuf[BUFSIZ], outbuf[BUFSIZ];
       +        char wordbuf[BUFSIZ];
        
       -        outbuf[0] = '\0';
                wordbuf[0] = '\0';
                line_copywordcursor(wordbuf, sizeof(wordbuf));
        
       -        if(pipe_cmd((char**)cmd, wordbuf, outbuf,
       -                   sizeof(outbuf)) == -1)
       -                return -1;
       -        if(outbuf[0] == '\0')
       -                return -1;
       -
       -        line_delwordcursor();
       -        line_inserttext(outbuf);
       -        line_draw();
       -
       -        return 0;
       +        return pipe_cmd((char**)cmd, wordbuf, cb_pipe_replaceword);
        }
        
        static void
       @@ -736,7 +734,7 @@ gettermsize(void)
        static void
        resize(void)
        {
       -        pipe_cmd((char **)resizecmd, line.line, NULL, 0);
       +        pipe_cmd((char **)resizecmd, line.line, NULL);
        }
        
        static void
       @@ -795,9 +793,10 @@ run(void)
                int r, status = -1;
                unsigned char buf[BUFSIZ];
        
       -        line_draw();
       -
       -        fcntl(STDIN_FILENO, F_SETFL, O_NONBLOCK);
       +        if(isrunning) {
       +                line_draw();
       +                fcntl(STDIN_FILENO, F_SETFL, O_NONBLOCK);
       +        }
                while(isrunning) {
                        FD_ZERO(&fdr);
                        FD_SET(STDIN_FILENO, &fdr);
       @@ -832,16 +831,18 @@ fini:
        static void
        usage(void)
        {
       -        fprintf(stderr, "usage: %s [-l line] [-p prompt]\n", argv0);
       +        fprintf(stderr, "usage: %s [-i input] [-p prompt]\n", argv0);
                exit(EXIT_FAILURE);
        }
        
        int
        main(int argc, char **argv)
        {
       +        char *input = NULL;
       +
                ARGBEGIN {
       -        case 'l':
       -                line_set(EARGF(usage()));
       +        case 'i':
       +                input = EARGF(usage());
                        break;
                case 'p':
                        prompt = EARGF(usage());
       @@ -852,9 +853,10 @@ main(int argc, char **argv)
        
                lineoutfp = stdout;
                outfp = stderr;
       -
                setlocale(LC_ALL, "");
                setup();
       +        if(input)
       +                handleinput((unsigned char *)input, strlen(input));
                run();
                cleanup();