commit ca027cf4653062fea14a6cceff079b09cd351ce2
Author: jeromenerf <[email protected]>
Date:   Mon Sep 11 19:05:23 2017 +0200

    [st] patch right_click_to_plumb
    
    Plan9's acme/plumber like feature to send the primary selection to the
    user specified plumber.

diff --git a/st.suckless.org/patches/right_click_to_plumb/index.md 
b/st.suckless.org/patches/right_click_to_plumb/index.md
new file mode 100644
index 00000000..2a653a52
--- /dev/null
+++ b/st.suckless.org/patches/right_click_to_plumb/index.md
@@ -0,0 +1,53 @@
+# Right click to plumb
+
+Pretty much like plan9's acme and plumber: right-click some selected text to 
send it to the plumbing program of your choosing:
+
+- open an URL in a browser
+- view an image, PDF, ...
+- jump from logs to editor, at the specified line/col
+- etc
+
+The shell current working directory is set by the shell via `OSC 7` (borrowed 
from vte, see `/etc/profile.d/vte.sh` if you have it installed).
+
+For zsh :
+
+```sh
+__vte_urlencode() (
+  # This is important to make sure string manipulation is handled
+  # byte-by-byte.
+  LC_ALL=C
+  str="$1"
+  while [ -n "$str" ]; do
+    safe="${str%%[!a-zA-Z0-9/:_\.\-\!\'\(\)~]*}"
+    printf "%s" "$safe"
+    str="${str#"$safe"}"
+    if [ -n "$str" ]; then
+      printf "%%%02X" "'$str"
+      str="${str#?}"
+    fi
+  done
+)
+
+__vte_osc7 () {
+  printf "]7;%s%s" "${HOSTNAME:-}" "$(__vte_urlencode "${PWD}")"
+}
+
+[ -n "$ZSH_VERSION"  ] && precmd_functions+=(__vte_osc7)
+```
+
+The patch itself only adds a `cwd` global and a button3 entry that will run a 
shell, change directory to cwd and run the plumber with the primary selection. 
Maybe I should use pass cwd as an argument too, like plan9 plumber does.
+
+The plumbing program can be defined via `config.h`: 
+
+```h
+static char plumber[] = "plumb.sh";
+```
+
+## Download
+
+* [right_click_to_plumb.diff](right_click_to_plumb.diff) (2017-09-11)
+
+## Authors
+
+* [jerome](http://blog.jardinmagique.info) <[email protected]>
+
diff --git 
a/st.suckless.org/patches/right_click_to_plumb/right_click_to_plumb.diff 
b/st.suckless.org/patches/right_click_to_plumb/right_click_to_plumb.diff
new file mode 100644
index 00000000..f9f52d1d
--- /dev/null
+++ b/st.suckless.org/patches/right_click_to_plumb/right_click_to_plumb.diff
@@ -0,0 +1,63 @@
+diff --git a/st.c b/st.c
+index ae93ade..ff531a3 100644
+--- a/st.c
++++ b/st.c
+@@ -218,6 +218,8 @@ char *opt_line  = NULL;
+ char *opt_name  = NULL;
+ char *opt_title = NULL;
+ int oldbutton   = 3; /* button event on startup: 3 = release */
++char *cwd = NULL;
++char *plumber_cmd = plumber;
+ 
+ static CSIEscape csiescseq;
+ static STREscape strescseq;
+@@ -1858,6 +1860,9 @@ strhandle(void)
+       switch (strescseq.type) {
+       case ']': /* OSC -- Operating System Command */
+               switch (par) {
++              case 7:
++                      if (narg > 1 && access(strescseq.args[1], X_OK) != -1)
++                              cwd = strescseq.args[1];
+               case 0:
+               case 1:
+               case 2:
+diff --git a/x.c b/x.c
+index fbfd350..02ba92d 100644
+--- a/x.c
++++ b/x.c
+@@ -140,6 +140,9 @@ static DC dc;
+ static XWindow xw;
+ static XSelection xsel;
+ 
++extern char *cwd;
++extern char *plumber_cmd;
++
+ /* Font Ring Cache */
+ enum {
+       FRC_NORMAL,
+@@ -512,6 +515,9 @@ xsetsel(char *str, Time t)
+ void
+ brelease(XEvent *e)
+ {
++      pid_t child;
++      char cmd[100 + strlen(cwd)];
++
+       if (IS_SET(MODE_MOUSE) && !(e->xbutton.state & forceselmod)) {
+               mousereport(e);
+               return;
+@@ -519,6 +525,15 @@ brelease(XEvent *e)
+ 
+       if (e->xbutton.button == Button2) {
+               xselpaste();
++      } else if (e->xbutton.button == Button3) {
++              switch(child = fork()) {
++                      case -1: 
++                              return;
++                      case 0: 
++                              sprintf(cmd, "(cd %s ; %s %s)", cwd, 
plumber_cmd, sel.primary);
++                              execvp( "sh", (char *const []){ "/bin/sh", 
"-c", cmd, 0 });
++                              exit(127);
++              }
+       } else if (e->xbutton.button == Button1) {
+               if (sel.mode == SEL_READY) {
+                       getbuttoninfo(e);


Reply via email to