Hi all,

Attached is a patch which gives st the ability to spit out its current
screen text to another program. This can be added under shortcuts in
config.h, e.g.:


static Shortcut shortcuts[] = {
        ...
        { MODKEY, 'u', externalpipe, { .s = "xurls | dmenu -l 10 | xargs open" 
} },
};

Where xurls[1] is a script that pulls out urls from the text, then I can
pick one in dmenu and open[2] it in a browser.

If this doesn't qualify as core-st I'll happily stick it on the patches
page. Feedback welcome.


Rob


1: https://raw.github.com/bobrippling/perlbin/master/xurls
2: https://github.com/bobrippling/open
From 7982a2d238925028b45d5143db470e408b97469a Mon Sep 17 00:00:00 2001
From: Rob Pilling <robpill...@gmail.com>
Date: Fri, 20 Dec 2013 12:40:55 +0000
Subject: [PATCH] Add externalpipe() for piping out screen text

---
 st.c |   74 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++------
 1 file changed, 68 insertions(+), 6 deletions(-)

diff --git a/st.c b/st.c
index 4fb3311..adef257 100644
--- a/st.c
+++ b/st.c
@@ -299,6 +299,7 @@ typedef union {
 	unsigned int ui;
 	float f;
 	const void *v;
+	const char *s;
 } Arg;
 
 typedef struct {
@@ -313,6 +314,7 @@ static void clippaste(const Arg *);
 static void numlock(const Arg *);
 static void selpaste(const Arg *);
 static void xzoom(const Arg *);
+static void externalpipe(const Arg *);
 
 /* Config.h for applying patches and the configuration. */
 #include "config.h"
@@ -1204,15 +1206,22 @@ execsh(void) {
 void
 sigchld(int a) {
 	int stat = 0;
+	pid_t r;
 
-	if(waitpid(pid, &stat, 0) < 0)
-		die("Waiting for pid %hd failed: %s\n", pid, SERRNO);
+	r = wait(&stat);
+	if(r < 0)
+		die("wait(): %s\n", SERRNO);
 
-	if(WIFEXITED(stat)) {
-		exit(WEXITSTATUS(stat));
-	} else {
-		exit(EXIT_FAILURE);
+	if(r == pid){
+		/* _the_ sub porcess */
+		if(WIFEXITED(stat)) {
+			exit(WEXITSTATUS(stat));
+		} else {
+			exit(EXIT_FAILURE);
+		}
 	}
+
+	/* something else we've forked out */
 }
 
 void
@@ -2928,6 +2937,59 @@ xzoom(const Arg *arg) {
 }
 
 void
+externalpipe(const Arg *arg)
+{
+	int to[2]; /* 0 = read, 1 = write */
+	pid_t child;
+	int y, x;
+	void (*oldsigpipe)(int);
+
+	if(pipe(to) == -1)
+		return;
+
+	/* sigchld() handles this */
+	switch((child = fork())){
+		case -1:
+			close(to[0]), close(to[1]);
+			return;
+		case 0:
+			/* child */
+			close(to[1]);
+			dup2(to[0], STDIN_FILENO); /* 0<&to */
+			close(to[0]);
+			execvp(
+					"sh",
+					(char *const []){
+						"/bin/sh",
+						"-c",
+						(char *)arg->s,
+						0
+					});
+			exit(127);
+	}
+
+	/* parent */
+	close(to[0]);
+	/* ignore sigpipe for now, in case child exits early */
+	oldsigpipe = signal(SIGPIPE, SIG_IGN);
+
+	for(y = 0; y < term.row; y++){
+		for(x = 0; x < term.col; x++){
+			if(write(to[1], term.line[y][x].c, 1) == -1)
+				goto done;
+		}
+		if(write(to[1], "\n", 1) == -1)
+			break;
+	}
+
+done:
+	close(to[1]);
+
+	/* restore */
+	signal(SIGPIPE, oldsigpipe);
+}
+
+void
 xinit(void) {
 	XGCValues gcvalues;
 	Cursor cursor;
-- 
1.7.10.4

Reply via email to