[st] patch: externalpipe

This commit is contained in:
dogeystamp 2024-01-02 12:27:48 -05:00
parent 5c16760c03
commit 8d91e51f7b
3 changed files with 83 additions and 1 deletions

View File

@ -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 } },
};
/*

View File

@ -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)
{

View File

@ -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 *);