tcmd: execute shell commands - neatvi - [fork] simple vi-type editor with UTF-8… | |
git clone git://src.adamsgaard.dk/neatvi | |
Log | |
Files | |
Refs | |
README | |
--- | |
commit 58191346a45866137a12738b1b82b31f40a673aa | |
parent 6e9f030b017fe128151501d6c0bad0c6e72a8c73 | |
Author: Ali Gholami Rudi <[email protected]> | |
Date: Fri, 15 May 2015 14:20:23 +0430 | |
cmd: execute shell commands | |
Diffstat: | |
M Makefile | 2 +- | |
A cmd.c | 91 +++++++++++++++++++++++++++++… | |
M vi.c | 42 +++++++++++++++++++++++++----… | |
M vi.h | 3 +++ | |
4 files changed, 129 insertions(+), 9 deletions(-) | |
--- | |
diff --git a/Makefile b/Makefile | |
t@@ -2,7 +2,7 @@ CC = cc | |
CFLAGS = -Wall -O2 | |
LDFLAGS = | |
-OBJS = vi.o ex.o lbuf.o sbuf.o ren.o dir.o reg.o led.o uc.o term.o rset.o | |
+OBJS = vi.o ex.o lbuf.o sbuf.o ren.o dir.o reg.o led.o uc.o term.o rset.o cmd.o | |
all: vi | |
%.o: %.c | |
diff --git a/cmd.c b/cmd.c | |
t@@ -0,0 +1,91 @@ | |
+#include <poll.h> | |
+#include <stdio.h> | |
+#include <stdlib.h> | |
+#include <string.h> | |
+#include <unistd.h> | |
+#include <sys/wait.h> | |
+#include "vi.h" | |
+ | |
+static int cmd_make(char **argv, int *ifd, int *ofd) | |
+{ | |
+ int pid; | |
+ int pipefds0[2]; | |
+ int pipefds1[2]; | |
+ if (ifd) | |
+ pipe(pipefds0); | |
+ if (ofd) | |
+ pipe(pipefds1); | |
+ if (!(pid = fork())) { | |
+ if (ifd) { /* setting up stdin */ | |
+ close(0); | |
+ dup(pipefds0[0]); | |
+ close(pipefds0[1]); | |
+ close(pipefds0[0]); | |
+ } | |
+ if (ofd) { /* setting up stdout */ | |
+ close(1); | |
+ dup(pipefds1[1]); | |
+ close(pipefds1[0]); | |
+ close(pipefds1[1]); | |
+ } | |
+ execvp(argv[0], argv); | |
+ exit(1); | |
+ } | |
+ if (ifd) | |
+ close(pipefds0[0]); | |
+ if (ofd) | |
+ close(pipefds1[1]); | |
+ if (pid < 0) { | |
+ if (ifd) | |
+ close(pipefds0[1]); | |
+ if (ofd) | |
+ close(pipefds1[0]); | |
+ return -1; | |
+ } | |
+ if (ifd) | |
+ *ifd = pipefds0[1]; | |
+ if (ofd) | |
+ *ofd = pipefds1[0]; | |
+ return pid; | |
+} | |
+ | |
+char *cmd_pipe(char *cmd, char *s) | |
+{ | |
+ char *argv[] = {"/bin/sh", "-c", cmd, NULL}; | |
+ struct pollfd fds[2]; | |
+ struct sbuf *sb; | |
+ char buf[512]; | |
+ int ifd = 0, ofd = 0; | |
+ int slen = strlen(s); | |
+ int nw = 0; | |
+ int pid = cmd_make(argv, &ifd, &ofd); | |
+ if (pid <= 0) | |
+ return NULL; | |
+ sb = sbuf_make(); | |
+ fds[0].fd = ofd; | |
+ fds[0].events = POLLIN; | |
+ fds[1].fd = ifd; | |
+ fds[1].events = POLLOUT; | |
+ while ((fds[0].fd >= 0 || fds[1].fd >= 0) && poll(fds, 3, 200) >= 0) { | |
+ if (fds[0].revents & POLLIN) { | |
+ int ret = read(fds[0].fd, buf, sizeof(buf)); | |
+ if (ret > 0) | |
+ sbuf_mem(sb, buf, ret); | |
+ if (ret < 0) | |
+ close(fds[0].fd); | |
+ } else if (fds[0].revents & (POLLERR | POLLHUP | POLLNVAL)) { | |
+ fds[0].fd = -1; | |
+ } | |
+ if (fds[1].revents & POLLOUT) { | |
+ int ret = write(fds[1].fd, s + nw, slen - nw); | |
+ if (ret > 0) | |
+ nw += ret; | |
+ if (ret <= 0 || nw == slen) | |
+ close(fds[1].fd); | |
+ } else if (fds[1].revents & (POLLERR | POLLHUP | POLLNVAL)) { | |
+ fds[1].fd = -1; | |
+ } | |
+ } | |
+ waitpid(pid, NULL, 0); | |
+ return sbuf_done(sb); | |
+} | |
diff --git a/vi.c b/vi.c | |
t@@ -62,6 +62,13 @@ static char *vi_char(void) | |
return TK_INT(key) ? NULL : led_keymap(key); | |
} | |
+static char *vi_prompt(char *msg) | |
+{ | |
+ term_pos(xrows, led_pos(msg, 0)); | |
+ term_kill(); | |
+ return led_prompt(msg, ""); | |
+} | |
+ | |
static int vi_yankbuf(void) | |
{ | |
int c = vi_read(); | |
t@@ -189,10 +196,8 @@ static int vi_search(int cmd, int cnt, int *row, int *col) | |
char *off = ""; | |
if (cmd == '/' || cmd == '?') { | |
char sign[4] = {cmd}; | |
- char *kw; | |
- term_pos(xrows, led_pos(sign, 0)); | |
- term_kill(); | |
- if (!(kw = led_prompt(sign, ""))) | |
+ char *kw = vi_prompt(sign); | |
+ if (!kw) | |
return 1; | |
vi_finddir = cmd == '/' ? +1 : -1; | |
if (kw[0]) | |
t@@ -332,7 +337,7 @@ static int vi_motionln(int *row, int cmd) | |
break; | |
default: | |
if (c == cmd) { | |
- *row = MIN(*row + cnt - 1, lbuf_len(xb) - 1); | |
+ *row = MAX(0, MIN(*row + cnt - 1, lbuf_len(xb) - 1)); | |
break; | |
} | |
vi_back(c); | |
t@@ -667,6 +672,26 @@ static void vi_change(int r1, int c1, int r2, int c2, int… | |
free(post); | |
} | |
+static void vi_pipe(int r1, int c1, int r2, int c2, int lnmode, int closed) | |
+{ | |
+ char *text; | |
+ char *rep; | |
+ char *cmd = vi_prompt("!"); | |
+ if (!cmd) | |
+ return; | |
+ if (r2 < r1) | |
+ swap(&r1, &r2); | |
+ text = lbuf_cp(xb, r1, r2 + 1); | |
+ rep = cmd_pipe(cmd, text); | |
+ if (rep) { | |
+ lbuf_rm(xb, r1, r2 + 1); | |
+ lbuf_put(xb, r1, rep); | |
+ } | |
+ free(cmd); | |
+ free(text); | |
+ free(rep); | |
+} | |
+ | |
static int vc_motion(int cmd) | |
{ | |
int r1 = xrow, r2 = xrow; /* region rows */ | |
t@@ -698,6 +723,8 @@ static int vc_motion(int cmd) | |
vi_delete(r1, c1, r2, c2, lnmode, closed); | |
if (cmd == 'c') | |
vi_change(r1, c1, r2, c2, lnmode, closed); | |
+ if (cmd == '!') | |
+ vi_pipe(r1, c1, r2, c2, lnmode, closed); | |
return 0; | |
} | |
t@@ -950,9 +977,7 @@ static void vi(void) | |
redraw = 1; | |
break; | |
case ':': | |
- term_pos(xrows, led_pos(":", 0)); | |
- term_kill(); | |
- ln = led_prompt(":", ""); | |
+ ln = vi_prompt(":"); | |
if (ln && ln[0]) { | |
ex_command(ln); | |
redraw = 1; | |
t@@ -964,6 +989,7 @@ static void vi(void) | |
case 'c': | |
case 'd': | |
case 'y': | |
+ case '!': | |
if (!vc_motion(c)) | |
redraw = 1; | |
break; | |
diff --git a/vi.h b/vi.h | |
t@@ -119,6 +119,9 @@ int led_pos(char *s, int pos); | |
void ex(void); | |
void ex_command(char *cmd); | |
+/* process management */ | |
+char *cmd_pipe(char *cmd, char *s); | |
+ | |
/* global variables */ | |
extern int xvis; | |
extern struct lbuf *xb; |