sites

public wiki contents of suckless.org
git clone git://git.suckless.org/sites
Log | Files | Refs

commit c356e234ffd9fff1f39686fd3aa15ab39ec4790d
parent 04c065b55377ca49489ca5a075617a0e81aed817
Author: meator <meator.dev@gmail.com>
Date:   Thu, 27 Oct 2022 15:52:27 +0200

[st][patch][newterm] Add tmux support + update

Diffstat:
Mst.suckless.org/patches/newterm/index.md | 18++++++++++++++++++
Ast.suckless.org/patches/newterm/st-newterm-0.9-tabbed.diff | 38++++++++++++++++++++++++++++++++++++++
Ast.suckless.org/patches/newterm/st-newterm-0.9-tmux.diff | 140+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Ast.suckless.org/patches/newterm/st-newterm-0.9.diff | 112+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
4 files changed, 308 insertions(+), 0 deletions(-)

diff --git a/st.suckless.org/patches/newterm/index.md b/st.suckless.org/patches/newterm/index.md @@ -16,6 +16,20 @@ will have no parent process). To have newterm working with tabbed, apply the st-newterm-0.8.2-tabbed.diff patch on top of st-newterm-0.8.2.diff. +To have tmux support, apply the st-newterm-0.9-tmux.diff patch on top of +st-newterm-0.9.diff. + +With the tmux patch, newterm won't launch a new terminal with the CWD of the tmux +client itself, but it will use the CWD of the current process in the tmux session +running under st. + +The tmux client must be a direct child of st in order to make newterm detect it +(you'll need to use `exec tmux` or similar). If the child of st isn't a tmux +client, newterm will fallback to the CWD of st's child (which is what newterm +does without the tmux patch). + +The tmux patch only works on Linux. + Download -------- @@ -23,9 +37,13 @@ Download * [st-newterm-0.8.2-tabbed.diff](st-newterm-0.8.2-tabbed.diff) * [st-newterm-orphan-20210712-4536f46.diff](st-newterm-orphan-20210712-4536f46.diff) * [st-newterm-20220221-0.8.5.diff](st-newterm-20220221-0.8.5.diff) +* [st-newterm-0.9.diff](st-newterm-0.9.diff) + * [st-newterm-0.9-tabbed.diff](st-newterm-0.9-tabbed.diff) + * [st-newterm-0.9-tmux.diff](st-newterm-0.9-tmux.diff) Authors ------- * Matías Lang * Stein Bakkeby (orphan version) * Gaspar Vardanyan (tabbed support) +* [Meator](https://github.com/meator) - <meator.dev@gmail.com> (all of the st-newterm-0.9* patches) diff --git a/st.suckless.org/patches/newterm/st-newterm-0.9-tabbed.diff b/st.suckless.org/patches/newterm/st-newterm-0.9-tabbed.diff @@ -0,0 +1,38 @@ +From 88559b5cb6ed3f996fc00e923f9ded3c0b353fc5 Mon Sep 17 00:00:00 2001 +From: meator <meator.dev@gmail.com> +Date: Wed, 26 Oct 2022 14:06:49 +0200 +Subject: [PATCH] Make newterm work with the tabbed patch + +This commit is an updated version of st-newterm-0.8.2-tabbed.diff. +--- + st.c | 7 ++++++- + 1 file changed, 6 insertions(+), 1 deletion(-) + +diff --git a/st.c b/st.c +index 0261283..e4a9021 100644 +--- a/st.c ++++ b/st.c +@@ -1061,6 +1061,7 @@ tswapscreen(void) + void + newterm(const Arg* a) + { ++ char *tabbed_win; + switch (fork()) { + case -1: + die("fork failed: %s\n", strerror(errno)); +@@ -1073,7 +1074,11 @@ newterm(const Arg* a) + break; + case 0: + chdir_by_pid(pid); +- execl("/proc/self/exe", argv0, NULL); ++ tabbed_win = getenv("XEMBED"); ++ if (tabbed_win) ++ execl("/proc/self/exe", argv0, "-w", tabbed_win, NULL); ++ else ++ execl("/proc/self/exe", argv0, NULL); + _exit(1); + break; + default: +-- +2.38.0 + diff --git a/st.suckless.org/patches/newterm/st-newterm-0.9-tmux.diff b/st.suckless.org/patches/newterm/st-newterm-0.9-tmux.diff @@ -0,0 +1,140 @@ +From 6640cf9809086d8cfb2363571d3e71a1a7a9f6bd Mon Sep 17 00:00:00 2001 +From: meator <meator.dev@gmail.com> +Date: Tue, 25 Oct 2022 20:19:28 +0200 +Subject: [PATCH] Add support for tmux in newterm + +This commit tries to figure out if st's child is tmux and if so, it +launches a shell with the CWD of the current process in the tmux session +instead of the tmux client itself. + +This is heavily inspired by +https://gist.github.com/TiddoLangerak/c61e1e48df91192f9554 (but +converted to C). + +Tmux has to be a direct child of st. This means that you'll have to +usually use the 'exec' shell builtin to attach tmux sessions. + +This patch only works on Linux. Other systems use different procfs which +is incompatible or don't have procfs at all (or it's optional). +--- + st.c | 83 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++- + 1 file changed, 82 insertions(+), 1 deletion(-) + +diff --git a/st.c b/st.c +index 0261283..b95bf7a 100644 +--- a/st.c ++++ b/st.c +@@ -221,6 +221,8 @@ static char base64dec_getc(const char **); + + static ssize_t xwrite(int, const char *, size_t); + ++static int gettmuxpts(void); ++ + /* Globals */ + static Term term; + static Selection sel; +@@ -1061,6 +1063,12 @@ tswapscreen(void) + void + newterm(const Arg* a) + { ++ int pts; ++ FILE *fsession, *fpid; ++ char session[5]; ++ char pidstr[10]; ++ char buf[48]; ++ size_t size; + switch (fork()) { + case -1: + die("fork failed: %s\n", strerror(errno)); +@@ -1072,7 +1080,37 @@ newterm(const Arg* a) + _exit(1); + break; + case 0: +- chdir_by_pid(pid); ++ signal(SIGCHLD, SIG_DFL); /* pclose() needs to use wait() */ ++ pts = gettmuxpts(); ++ if (pts != -1) { ++ snprintf(buf, sizeof buf, "tmux lsc -t /dev/pts/%d -F \"#{client_session}\"", pts); ++ fsession = popen(buf, "r"); ++ if (!fsession) { ++ fprintf(stderr, "Couldn't launch tmux."); ++ _exit(1); ++ } ++ size = fread(session, 1, sizeof session, fsession); ++ if (pclose(fsession) != 0 || size == 0) { ++ fprintf(stderr, "Couldn't get tmux session."); ++ _exit(1); ++ } ++ session[size - 1] = '\0'; /* size - 1 is used to also trim the \n */ ++ ++ snprintf(buf, sizeof buf, "tmux list-panes -st %s -F \"#{pane_pid}\"", session); ++ fpid = popen(buf, "r"); ++ if (!fpid) { ++ fprintf(stderr, "Couldn't launch tmux."); ++ _exit(1); ++ } ++ size = fread(pidstr, 1, sizeof pidstr, fpid); ++ if (pclose(fpid) != 0 || size == 0) { ++ fprintf(stderr, "Couldn't get tmux session."); ++ _exit(1); ++ } ++ pidstr[size - 1] = '\0'; ++ } ++ ++ chdir_by_pid(pts != -1 ? atol(pidstr) : pid); + execl("/proc/self/exe", argv0, NULL); + _exit(1); + break; +@@ -1092,6 +1130,49 @@ chdir_by_pid(pid_t pid) + return chdir(buf); + } + ++/* returns the pty of tmux client or -1 if the child of st isn't tmux */ ++static int ++gettmuxpts(void) ++{ ++ char buf[32]; ++ char comm[17]; ++ int tty; ++ FILE *fstat; ++ FILE *fcomm; ++ size_t numread; ++ ++ snprintf(buf, sizeof buf, "/proc/%ld/comm", (long)pid); ++ ++ fcomm = fopen(buf, "r"); ++ if (!fcomm) { ++ fprintf(stderr, "Couldn't open %s: %s\n", buf, strerror(errno)); ++ _exit(1); ++ } ++ ++ numread = fread(comm, 1, sizeof comm - 1, fcomm); ++ comm[numread] = '\0'; ++ ++ fclose(fcomm); ++ ++ if (strcmp("tmux: client\n", comm) != 0) ++ return -1; ++ ++ snprintf(buf, sizeof buf, "/proc/%ld/stat", (long)pid); ++ fstat = fopen(buf, "r"); ++ if (!fstat) { ++ fprintf(stderr, "Couldn't open %s: %s\n", buf, strerror(errno)); ++ _exit(1); ++ } ++ ++ /* ++ * We can't skip the second field with %*s because it contains a space so ++ * we skip strlen("tmux: client") + 2 for the braces which is 14. ++ */ ++ fscanf(fstat, "%*d %*14c %*c %*d %*d %*d %d", &tty); ++ fclose(fstat); ++ return ((0xfff00000 & tty) >> 12) | (0xff & tty); ++} ++ + void + tscrolldown(int orig, int n) + { +-- +2.38.0 + diff --git a/st.suckless.org/patches/newterm/st-newterm-0.9.diff b/st.suckless.org/patches/newterm/st-newterm-0.9.diff @@ -0,0 +1,112 @@ +From e1cf625f4f225a007a5835421896089669195e02 Mon Sep 17 00:00:00 2001 +From: meator <meator.dev@gmail.com> +Date: Wed, 26 Oct 2022 13:05:38 +0200 +Subject: [PATCH] Add shortcut to spawn new terminal in the current dir + +This commit is inspired by Santtu's st-newterm-20220221-0.8.5.diff. It +removes the unused res variable, it makes use of _exit() instead of +exit() and it replaces execlp() with execl() (PATH searching is useless +when the path is absolute). +--- + config.def.h | 1 + + st.c | 38 ++++++++++++++++++++++++++++++++++++++ + st.h | 1 + + 3 files changed, 40 insertions(+) + +diff --git a/config.def.h b/config.def.h +index 91ab8ca..7c75246 100644 +--- a/config.def.h ++++ b/config.def.h +@@ -201,6 +201,7 @@ static Shortcut shortcuts[] = { + { TERMMOD, XK_Y, selpaste, {.i = 0} }, + { ShiftMask, XK_Insert, selpaste, {.i = 0} }, + { TERMMOD, XK_Num_Lock, numlock, {.i = 0} }, ++ { TERMMOD, XK_Return, newterm, {.i = 0} }, + }; + + /* +diff --git a/st.c b/st.c +index 62def59..0261283 100644 +--- a/st.c ++++ b/st.c +@@ -20,6 +20,8 @@ + #include "st.h" + #include "win.h" + ++extern char *argv0; ++ + #if defined(__linux) + #include <pty.h> + #elif defined(__OpenBSD__) || defined(__NetBSD__) || defined(__APPLE__) +@@ -153,6 +155,7 @@ typedef struct { + } STREscape; + + static void execsh(char *, char **); ++static int chdir_by_pid(pid_t pid); + static void stty(char **); + static void sigchld(int); + static void ttywriteraw(const char *, size_t); +@@ -806,6 +809,7 @@ ttynew(const char *line, char *cmd, const char *out, char **args) + if (pledge("stdio rpath tty proc", NULL) == -1) + die("pledge\n"); + #endif ++ fcntl(m, F_SETFD, FD_CLOEXEC); + close(s); + cmdfd = m; + signal(SIGCHLD, sigchld); +@@ -1054,6 +1058,40 @@ tswapscreen(void) + tfulldirt(); + } + ++void ++newterm(const Arg* a) ++{ ++ switch (fork()) { ++ case -1: ++ die("fork failed: %s\n", strerror(errno)); ++ break; ++ case 0: ++ switch (fork()) { ++ case -1: ++ fprintf(stderr, "fork failed: %s\n", strerror(errno)); ++ _exit(1); ++ break; ++ case 0: ++ chdir_by_pid(pid); ++ execl("/proc/self/exe", argv0, NULL); ++ _exit(1); ++ break; ++ default: ++ _exit(0); ++ } ++ default: ++ wait(NULL); ++ } ++} ++ ++static int ++chdir_by_pid(pid_t pid) ++{ ++ char buf[32]; ++ snprintf(buf, sizeof buf, "/proc/%ld/cwd", (long)pid); ++ return chdir(buf); ++} ++ + void + tscrolldown(int orig, int n) + { +diff --git a/st.h b/st.h +index fd3b0d8..f2b03b0 100644 +--- a/st.h ++++ b/st.h +@@ -81,6 +81,7 @@ void die(const char *, ...); + void redraw(void); + void draw(void); + ++void newterm(const Arg *); + void printscreen(const Arg *); + void printsel(const Arg *); + void sendbreak(const Arg *); +-- +2.38.0 +