diff options
| -rw-r--r-- | main.c | 64 |
1 files changed, 42 insertions, 22 deletions
@@ -9,6 +9,7 @@ #include <sys/stat.h> #include <sys/wait.h> #include <signal.h> +#include <poll.h> #define ARENA_IMPL #define UTF8_IMPL @@ -116,9 +117,9 @@ int popen2(const char *cmd, int *in, int *out) { if(p < 0) return -1; if(p == 0) { /* child */ close(rd[1]); - dup2(rd[0], 0); close(wr[0]); - dup2(wr[1], 1); + dup2(rd[0], STDIN_FILENO); + dup2(wr[1], STDOUT_FILENO); if (execl("/bin/sh", "sh", "-c", cmd, 0)) { err(1, "execl"); } @@ -143,26 +144,45 @@ int shell_replace(TxtLoc start, TxtLoc end, const char *cmd) { int p = popen2(cmd, &in, &out); if (p < 0) return -1; - txt_write_range(in, start, end); - close(in); - - start = txt_delete_range(start, end); - DYNARR(char) buf = { 0 }; - DA_AFIT(&buf, &scratch, 8192); - for (;;) { - isize sz = read(out, &buf.v[buf.n], 8192); - if (sz < 0) { + struct pollfd pfds[2] = { + { .fd = in, .events = POLLOUT }, + { .fd = out, .events = POLLIN } + }; + Str wrs = txt_collect_range(start, end, &scratch); + DYNARR(char) rds = { 0 }; + u32 wr_i = 0; + cur = txt_delete_range(start, end); + while ((pfds[0].fd >= 0 || pfds[1].fd >= 0) && poll(pfds, 2, 100) >= 0) { + const u32 chunksz = 8L << 10; + if (pfds[0].revents & POLLOUT) { + u32 wr_n = wrs.n - wr_i; + if (wr_n > chunksz) wr_n = chunksz; + isize r = write(in, wrs.s + wr_i, wr_n); + if (r > 0) { + wr_i += wr_n; + } else { + close(in); + pfds[0].fd = -1; + } + } else if (pfds[0].revents & (POLLERR | POLLHUP | POLLNVAL)) { + close(in); + pfds[0].fd = -1; + } + if (pfds[1].revents & POLLIN) { + DA_AFIT(&rds, &scratch, rds.n + (-rds.n & (chunksz-1)) + chunksz); + isize r = read(out, &rds.v[rds.n], chunksz); + if (r > 0) { + rds.n += r; + } else { + close(out); + pfds[1].fd = -1; + } + } else if (pfds[1].revents & (POLLERR | POLLHUP | POLLNVAL)) { close(out); - return -1; + pfds[1].fd = -1; } - if (!sz) break; - buf.n += sz; - DA_AFIT(&buf, &scratch, buf.n + (-buf.n & 8191) + 8192); } - close(out); - - end = txt_insert(start, buf.v, buf.n); - cur = end; + cur = txt_insert(cur, rds.v, rds.n); while (cur_ofs--) cur = cprev(cur); return 0; } @@ -355,12 +375,12 @@ void test_edits(void) { } int main(int argc, const char **argv) { - scratch = arena_init(1L << 20); + scratch = arena_init(128L << 20); vui_init(); vui_curs_vis(1); vui_redraw_fn(draw); - const char *path = "test.txt"; - //const char *path = "/usr/share/dict/words"; + //const char *path = "test.txt"; + const char *path = "/usr/share/dict/words"; if (argc > 1) path = argv[1]; if (txt_load(&txt, path)) err(1, "couldn't open file"); cur = txt_end(&txt); |
