st

Unnamed repository; edit this file 'description' to name the repository.
git clone git://git.nihaljere.xyz/st
Log | Files | Refs | README | LICENSE

commit 1ac94ef5a8f893183700799ae8096664043afbcf
parent b145b87ab7eae711275a5ea8ad4568980d8b2970
Author: Michael Forney <mforney@mforney.org>
Date:   Wed,  2 Dec 2020 17:54:35 -0800

Add support for plumbing via right click

Diffstat:
Mconfig.def.h | 5+++++
Mst.c | 79+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++------------
2 files changed, 72 insertions(+), 12 deletions(-)

diff --git a/config.def.h b/config.def.h @@ -460,3 +460,8 @@ static char ascii_printable[] = "@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_" "`abcdefghijklmnopqrstuvwxyz{|}~"; +/* + * plumb_cmd is run on mouse button 3 click, with first NULL set to + * current selection and with cwd set to the cwd of the active shell + */ +static char *plumb_cmd[] = {"plumb", NULL, NULL}; diff --git a/st.c b/st.c @@ -44,6 +44,9 @@ char *argv0; #elif defined(__FreeBSD__) || defined(__DragonFly__) #include <libutil.h> #endif +#if defined(__OpenBSD__) + #include <sys/sysctl.h> +#endif /* Arbitrary sizes */ @@ -558,6 +561,8 @@ static void *xmalloc(size_t); static void *xrealloc(void *, size_t); static char *xstrdup(char *); +static int subprocwd(char *, size_t); + static void usage(void); static struct wl_registry_listener reglistener = { regglobal, regglobalremove }; @@ -579,6 +584,7 @@ static struct wl_data_source_listener datasrclistener = { datasrctarget, datasrcsend, datasrccancelled }; /* Globals */ +static int plumbsel; static DC dc; static Wayland wl; static WLD wld; @@ -763,6 +769,21 @@ utf8validate(Rune *u, size_t i) return i; } +int +subprocwd(char *path, size_t len) +{ +#if defined(__linux__) + if (snprintf(path, len, "/proc/%d/cwd", pid) < 0) + return -1; + return 0; +#elif defined(__OpenBSD__) + int name[3] = {CTL_KERN, KERN_PROC_CWD, pid}; + if (sysctl(name, 3, path, &len, 0, 0) == -1) + return -1; + return 0; +#endif +} + void selinit(void) { @@ -1166,6 +1187,29 @@ wlsetsel(char *str, uint32_t serial) } void +plumbinit(void) +{ + for (plumbsel = 0; plumb_cmd[plumbsel]; ++plumbsel) + ; +} + +void +plumb(char *sel) +{ + char cwd[PATH_MAX]; + + if (!sel || subprocwd(cwd, sizeof(cwd)) != 0) + return; + plumb_cmd[plumbsel] = sel; + + if (fork() == 0) { + if (chdir(cwd) == 0) + execvp(plumb_cmd[0], plumb_cmd); + _exit(1); + } +} + +void die(const char *errstr, ...) { va_list ap; @@ -1227,15 +1271,18 @@ sigchld(int a) int stat; pid_t p; - if ((p = waitpid(pid, &stat, WNOHANG)) < 0) - die("Waiting for pid %hd failed: %s\n", pid, strerror(errno)); - - if (pid != p) - return; - - if (!WIFEXITED(stat) || WEXITSTATUS(stat)) - die("child finished with error '%d'\n", stat); - exit(0); + for (;;) { + p = waitpid(-1, &stat, WNOHANG); + if (p == 0) + break; + if (p < 0) + die("waitpid: %s\n", strerror(errno)); + if (pid == p) { + if (!WIFEXITED(stat) || WEXITSTATUS(stat)) + die("child finished with error '%d'\n", stat); + exit(0); + } + } } @@ -4223,16 +4270,23 @@ ptrbutton(void * data, struct wl_pointer * pointer, uint32_t serial, switch (state) { case WL_POINTER_BUTTON_STATE_RELEASED: - if (button == BTN_MIDDLE) { + switch (button) { + case BTN_MIDDLE: selpaste(NULL); - } else if (button == BTN_LEFT) { + break; + case BTN_LEFT: if (sel.mode == SEL_READY) { getbuttoninfo(); selcopy(serial); - } else + } else { selclear(); + } sel.mode = SEL_IDLE; tsetdirt(sel.nb.y, sel.ne.y); + break; + case BTN_RIGHT: + plumb(sel.primary); + break; } break; @@ -4556,6 +4610,7 @@ main(int argc, char *argv[]) } ARGEND; run: + plumbinit(); if (argc > 0) { /* eat all remaining arguments */ opt_cmd = argv;