summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--main.c64
1 files changed, 42 insertions, 22 deletions
diff --git a/main.c b/main.c
index 26c305e..1c3c653 100644
--- a/main.c
+++ b/main.c
@@ -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);