diff options
| -rw-r--r-- | main.c | 91 |
1 files changed, 85 insertions, 6 deletions
@@ -1,3 +1,5 @@ +#define _POSIX_C_SOURCE 202511L + #include <stdint.h> #include <stddef.h> #include <err.h> @@ -5,6 +7,8 @@ #include <fcntl.h> #include <unistd.h> #include <sys/stat.h> +#include <sys/wait.h> +#include <signal.h> #define ARENA_IMPL #define UTF8_IMPL @@ -93,6 +97,72 @@ u32 move_par_down(Txt *t, u32 cur) { return txt_ofs(next_par(txt_at(t, cur))); } +typedef struct { + pid_t pid; + int from, to; +} ChildProcess; + +int popen2(const char *cmd, int *in, int *out) { + int rd[2], wr[2]; + if(pipe(rd)) return -1; + if(pipe(wr)) return -1; + pid_t p = fork(); + if(p < 0) return -1; + if(p == 0) { /* child */ + close(rd[1]); + dup2(rd[0], 0); + close(wr[0]); + dup2(wr[1], 1); + if (execl("/bin/sh", "sh", "-c", cmd, 0)) { + err(1, "execl"); + } + } + close(rd[0]); + close(wr[1]); + *in = rd[1]; + *out = wr[0]; + return p; +} + +int shell_replace(TxtLoc start, TxtLoc end, const char *cmd) { + if (txt_before(end, start)) { + TxtLoc t = start; + start = end; + end = t; + } + + int in, out; + int p = popen2(cmd, &in, &out); + if (p < 0) return -1; + + TxtLoc l = start; + while (txt_before(l, end)) { + char c = txt_byte(l); + ASSERT(write(in, &c, 1) == 1); + l = bnext(l); + } + close(in); + + char c = 0; + txt_delete_range(start, end); + DYNARR(char) buf = { 0 }; + DA_AFIT(&buf, &scratch, 1024); + for (;;) { + isize sz = read(out, &buf.v[buf.n], 1024); + if (sz < 0) { + close(out); + return -1; + } + if (!sz) break; + buf.n += sz; + DA_AFIT(&buf, &scratch, buf.n + 1024); + } + + start = txt_insert(start, buf.v, buf.n); + close(out); + return 0; +} + /* main */ #define ODD_ATTR (FG_CYAN | BG_BLACK) @@ -342,18 +412,27 @@ int main(int argc, const char **argv) { cur = txt_ofs(txt_delete_c(cnext(txt_at(&txt, cur)))); mode = 1; break; + case '0': + if (!count) { + motion(c); + break; + } + /* fallthrough */ case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': add_to_count: count = (count % 100000000) * 10 + c - '0'; break; - case '0': - if (count) goto add_to_count; - /* fallthrough */ - default: - if (!motion(c)) { - /* TODO: bell/flash? */ + case 'M': { + TxtLoc start = prev_par(txt_at(&txt, cur)); + TxtLoc end = next_par(txt_at(&txt, cur)); + if (shell_replace(start, end, "fmt -w80 -u")) { + err(1, "shell_replace"); } + if (cur > txt.len) cur = txt.len; + }; + default: + motion(c); break; } break; |
