From 8d91e51f7b554aa85be6e3b5cd7dde6a02a3c2d0 Mon Sep 17 00:00:00 2001 From: dogeystamp Date: Tue, 2 Jan 2024 12:27:48 -0500 Subject: [PATCH] [st] patch: externalpipe --- suckless/st/config.def.h | 5 +++ suckless/st/st.c | 78 +++++++++++++++++++++++++++++++++++++++- suckless/st/st.h | 1 + 3 files changed, 83 insertions(+), 1 deletion(-) diff --git a/suckless/st/config.def.h b/suckless/st/config.def.h index e14775c..64c6a99 100644 --- a/suckless/st/config.def.h +++ b/suckless/st/config.def.h @@ -183,6 +183,10 @@ static MouseShortcut mshortcuts[] = { { XK_ANY_MOD, Button5, ttysend, {.s = "\005"} }, }; +static char *screeneditcmd[] = { "/bin/sh", "-c", + "screen-edit.sh", + "externalpipe", NULL }; + /* Internal keyboard shortcuts. */ #define MODKEY Mod1Mask #define TERMMOD (ControlMask|ShiftMask) @@ -204,6 +208,7 @@ static Shortcut shortcuts[] = { { ShiftMask, XK_Page_Up, kscrollup, {.i = -1} }, { ShiftMask, XK_Page_Down, kscrolldown, {.i = -1} }, { TERMMOD, XK_Return, newterm, {.i = 0} }, + { TERMMOD, XK_U, externalpipe, { .v = screeneditcmd } }, }; /* diff --git a/suckless/st/st.c b/suckless/st/st.c index cd8d8f9..1ecca39 100644 --- a/suckless/st/st.c +++ b/suckless/st/st.c @@ -46,6 +46,7 @@ #define TLINE(y) ((y) < term.scr ? term.hist[((y) + term.histi - \ term.scr + HISTSIZE + 1) % HISTSIZE] : \ term.line[(y) - term.scr]) +#define TLINE_HIST(y) ((y) <= HISTSIZE-term.row+2 ? term.hist[(y)] : term.line[(y-HISTSIZE+term.row-3)]) enum term_mode { MODE_WRAP = 1 << 0, @@ -426,6 +427,20 @@ tlinelen(int y) return i; } +int +tlinehistlen(int y) +{ + int i = term.col; + + if (TLINE_HIST(y)[i - 1].mode & ATTR_WRAP) + return i; + + while (i > 0 && TLINE_HIST(y)[i - 1].u == ' ') + --i; + + return i; +} + void selstart(int col, int row, int snap) { @@ -726,8 +741,14 @@ sigchld(int a) if ((p = waitpid(pid, &stat, WNOHANG)) < 0) die("waiting for pid %hd failed: %s\n", pid, strerror(errno)); - if (pid != p) + if (pid != p) { + if (p == 0 && wait(&stat) < 0) + die("wait: %s\n", strerror(errno)); + + /* reinstall sigchld handler */ + signal(SIGCHLD, sigchld); return; + } if (WIFEXITED(stat) && WEXITSTATUS(stat)) die("child exited with status %d\n", WEXITSTATUS(stat)); @@ -2084,6 +2105,61 @@ strparse(void) } } +void +externalpipe(const Arg *arg) +{ + int to[2]; + char buf[UTF_SIZ]; + void (*oldsigpipe)(int); + Glyph *bp, *end; + int lastpos, n, newline; + + if (pipe(to) == -1) + return; + + switch (fork()) { + case -1: + close(to[0]); + close(to[1]); + return; + case 0: + dup2(to[0], STDIN_FILENO); + close(to[0]); + close(to[1]); + execvp(((char **)arg->v)[0], (char **)arg->v); + fprintf(stderr, "st: execvp %s\n", ((char **)arg->v)[0]); + perror("failed"); + exit(0); + } + + close(to[0]); + /* ignore sigpipe for now, in case child exists early */ + oldsigpipe = signal(SIGPIPE, SIG_IGN); + newline = 0; + for (n = 0; n <= HISTSIZE + 2; n++) { + bp = TLINE_HIST(n); + lastpos = MIN(tlinehistlen(n) + 1, term.col) - 1; + if (lastpos < 0) + break; + if (lastpos == 0) + continue; + end = &bp[lastpos + 1]; + for (; bp < end; ++bp) + if (xwrite(to[1], buf, utf8encode(bp->u, buf)) < 0) + break; + if ((newline = TLINE_HIST(n)[lastpos].mode & ATTR_WRAP)) + continue; + if (xwrite(to[1], "\n", 1) < 0) + break; + newline = 0; + } + if (newline) + (void)xwrite(to[1], "\n", 1); + close(to[1]); + /* restore */ + signal(SIGPIPE, oldsigpipe); +} + void strdump(void) { diff --git a/suckless/st/st.h b/suckless/st/st.h index f638558..0757c29 100644 --- a/suckless/st/st.h +++ b/suckless/st/st.h @@ -85,6 +85,7 @@ void draw(void); void kscrolldown(const Arg *); void kscrollup(const Arg *); void newterm(const Arg *); +void externalpipe(const Arg *); void printscreen(const Arg *); void printsel(const Arg *); void sendbreak(const Arg *);