diff --git a/config.def.h b/config.def.h index 6f05dce..c79e1c8 100644 --- a/config.def.h +++ b/config.def.h @@ -470,3 +470,9 @@ static char ascii_printable[] = " !\"#$%&'()*+,-./0123456789:;<=>?" "@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_" "`abcdefghijklmnopqrstuvwxyz{|}~"; + +/* + * plumb_cmd is run on mouse button 3 click, with argument set to + * current selection and with cwd set to the cwd of the active shell + */ +static char *plumb_cmd = "plumber"; diff --git a/st.c b/st.c index a9338e1..28fa676 100644 --- a/st.c +++ b/st.c @@ -24,6 +24,7 @@ #include #elif defined(__OpenBSD__) || defined(__NetBSD__) || defined(__APPLE__) #include + #include #elif defined(__FreeBSD__) || defined(__DragonFly__) #include #endif @@ -231,6 +232,22 @@ static const uchar utfmask[UTF_SIZ + 1] = {0xC0, 0x80, 0xE0, 0xF0, 0xF8}; static const Rune utfmin[UTF_SIZ + 1] = { 0, 0, 0x80, 0x800, 0x10000}; static const Rune utfmax[UTF_SIZ + 1] = {0x10FFFF, 0x7F, 0x7FF, 0xFFFF, 0x10FFFF}; +int +subprocwd(char *path) +{ +#if defined(__linux) + if (snprintf(path, PATH_MAX, "/proc/%d/cwd", pid) < 0) + return -1; + return 0; +#elif defined(__OpenBSD__) + size_t sz = PATH_MAX; + int name[3] = {CTL_KERN, KERN_PROC_CWD, pid}; + if (sysctl(name, 3, path, &sz, 0, 0) == -1) + return -1; + return 0; +#endif +} + ssize_t xwrite(int fd, const char *s, size_t len) { diff --git a/st.h b/st.h index fa2eddf..3ea37f0 100644 --- a/st.h +++ b/st.h @@ -111,6 +111,8 @@ void *xmalloc(size_t); void *xrealloc(void *, size_t); char *xstrdup(const char *); +int subprocwd(char *); + /* config.h globals */ extern char *utmp; extern char *scroll; diff --git a/x.c b/x.c index 89786b8..a56d0e0 100644 --- a/x.c +++ b/x.c @@ -5,6 +5,7 @@ #include #include #include +#include #include #include #include @@ -683,6 +684,33 @@ xsetsel(char *str) setsel(str, CurrentTime); } +void +plumb(char *sel) +{ + if (sel == NULL) { + return; + } + char cwd[PATH_MAX]; + pid_t child; + if (subprocwd(cwd) != 0) { + return; + } + + switch (child = fork()) { + case -1: + return; + case 0: + if (chdir(cwd) != 0) { + exit(1); + } + if (execvp(plumb_cmd, (char *const []){plumb_cmd, sel, 0}) == -1) + exit(1); + exit(0); + default: + waitpid(child, NULL, 0); + } +} + void brelease(XEvent *e) { @@ -695,6 +723,13 @@ brelease(XEvent *e) return; if (e->xbutton.button == Button1) mousesel(e, 1); + else if (e->xbutton.button == Button3) { + if (!selected(evcol(e), evrow(e))) { + selstart(evcol(e), evrow(e), SNAP_WORD); + mousesel(e, 1); + } + plumb(xsel.primary); + } } void