st

My fork of st.
git clone git://git.alex.balgavy.eu/st.git
Log | Files | Refs | README | LICENSE

commit 7c2dc6f90d78371bf05bd0f08bced114946c9c2b
parent 073b29409d24fdcdfd359aa024601a3a8a5ea3af
Author: Alex Balgavy <alexander.balgavy@spaceapplications.com>
Date:   Tue, 17 Jun 2025 11:23:30 +0200

External pipe

Diffstat:
Mconfig.h | 8++++++++
Mst.c | 80+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++--
Mst.h | 1+
3 files changed, 87 insertions(+), 2 deletions(-)

diff --git a/config.h b/config.h @@ -225,8 +225,13 @@ static MouseShortcut mshortcuts[] = { /* Internal keyboard shortcuts. */ #define MODKEY Mod4Mask +#define ALTKEY Mod1Mask #define TERMMOD (ControlMask|ShiftMask) +static char *openurlcmd[] = { "/bin/sh", "-c", "st-urlhandler -o", "externalpipe", NULL }; +static char *copyurlcmd[] = { "/bin/sh", "-c", "st-urlhandler -c", "externalpipe", NULL }; +static char *copyoutput[] = { "/bin/sh", "-c", "st-copyout", "externalpipe", NULL }; + static Shortcut shortcuts[] = { /* mask keysym function argument */ { XK_ANY_MOD, XK_Break, sendbreak, {.i = 0} }, @@ -243,6 +248,9 @@ static Shortcut shortcuts[] = { { TERMMOD, XK_Num_Lock, numlock, {.i = 0} }, { MODKEY|ShiftMask, XK_Up, kscrollup, {.i = -1} }, { MODKEY|ShiftMask, XK_Down, kscrolldown, {.i = -1} }, + { ALTKEY, XK_l, externalpipe, {.v = openurlcmd } }, + { ALTKEY, XK_y, externalpipe, {.v = copyurlcmd } }, + { ALTKEY, XK_o, externalpipe, {.v = copyoutput } }, }; /* diff --git a/st.c b/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, @@ -432,6 +433,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) { @@ -732,8 +747,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)); @@ -817,7 +838,7 @@ ttynew(const char *line, char *cmd, const char *out, char **args) break; default: #ifdef __OpenBSD__ - if (pledge("stdio rpath tty proc", NULL) == -1) + if (pledge("stdio rpath tty proc exec", NULL) == -1) die("pledge\n"); #endif close(s); @@ -2000,6 +2021,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 exits 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) { size_t i; diff --git a/st.h b/st.h @@ -83,6 +83,7 @@ void draw(void); void kscrolldown(const Arg *); void kscrollup(const Arg *); +void externalpipe(const Arg *); void printscreen(const Arg *); void printsel(const Arg *); void sendbreak(const Arg *);