commit 94943b8e5e88cd90374abc46d954657c6fc63f51
parent 0d01477d561d460a40b68ec469b23d9edb2e88a0
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(-)
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();