I suppose this patch isn't mature enough, so you are welcome.

Content
  * added -m/-M command line options to demand/ignore multiplexer
    (using only -m option to toggle defaults isn't robust enough)
  * config options to specify exec wrapper and finalizing commands
  * sessions are named after the -n option (if specified)
  ~ adaptable to other multiplexers / etc. beside tmux (not tested)

Discussion
  * problems when using patch with other software (dvtm, byobu, etc)
  * other possible wrappers beside tmux (?) fitting overall idea
  * any opinion from alternative implementation till vars naming


# FEATURE

Behavior
  * killing terminal by WM cleanly kills the embedded tmux session
    => only created by the same terminal session is killed
  * detached session stays alive (terminal closes on detach)
  * attaching to the session from another terminal and closing
    former one will relocate the session without killing
    (however, now it behaves like any ordinary independent session)

Advantage
  + using tmux by default or demand it explicitly by -m/-M
  + arguments after -e are used as command for tmux new-session
  + no need for additional monitoring script
    => cleaner process tree, lesser startup time
  + no need for arguable options in your ~/.tmux.conf
    => all your other tmux sessions aren't affected


# ALTERNATIVES

## Tmux wrapper (bash only!)

$ st -e r.tmux
$ cat r.tmux
  #!/bin/bash -e
  trap "tmux list-clients -t st-$$ 2>/dev/null |
  { read -r _ && ! read -n1 -r _; } &&
  tmux kill-session -t st-$$
  " INT TERM EXIT
  tmux new-session -s st-$$ -- "$@"

Comparison
  + works the same way as the patch in question (see Behavior)
  + can be used even with packaged 'st' (no src hacking required)
  - related WM shortcuts must be changed to $ st -e r.tmux ...
  - creates additional process, cluttering your process tree
  - shell on exit must propagate HUP to childs and call EXIT trap
    => so it only works in bash? (dash, etc. are out of question)


## Tmux native

~/.tmux.conf:
  set -g destroy-unattached on

Comparison
  + easy (one option with support from the box)
  + no need to modify any st sources or WM shortcuts
  - works only with tmux
  - always destroys any unattached session (even on manual detach!)
  ~ useful if you use tmux for multiplexing only and rarely detach
    * you can switch option manually each time before detach
    * or bind it (with one-time-set guards) to 'pref d'
    * option can be guarded in config to be disabled for SSH
    * also for global tmux session you can use separate tmux.conf
98fae82da42d038b9ed0c87b557524fd03345191 tmux support
diff --git a/config.def.h b/config.def.h
index b41747f..ed4a329 100644
--- a/config.def.h
+++ b/config.def.h
@@ -20,6 +20,14 @@ static char shell[] = "/bin/sh";
 static char *utmp = NULL;
 static char stty_args[] = "stty raw pass8 nl -echo -iexten -cstopb 38400";

+/* Multiplexer wrapper */
+static int use_mux = 0;
+static char *mux_new[] = {"/usr/bin/tmux", "new-session", "-s", NULL, "--"};
+static char mux_post[] =
+       "tmux list-clients -t \"$MUX_NM\" 2>/dev/null"
+       "| { read -r _ && ! read -r _; }"
+       "&& tmux kill-session -t \"$MUX_NM\"";
+
 /* identification sequence returned in DA and DECID */
 static char vtiden[] = "\033[?6c";

diff --git a/st.c b/st.c
index 2594c65..d41b805 100644
--- a/st.c
+++ b/st.c
@@ -560,6 +560,9 @@ typedef struct {
 static Fontcache frc[16];
 static int frclen = 0;

+/* Multiplexer session name */
+static char mux_nm[64] = {0};
+
 ssize_t
 xwrite(int fd, const char *s, size_t len)
 {
@@ -1366,6 +1369,16 @@ execsh(void)
        signal(SIGTERM, SIG_DFL);
        signal(SIGALRM, SIG_DFL);

+       if (use_mux) {
+               int i = sizeof(mux_new)/sizeof(mux_new[0]), j = 0;
+               while(args[j++]);
+               char *margs[i + j];
+               while(j--) { margs[i + j] = args[j]; }
+               while(i--) { margs[i] = mux_new[i] ? mux_new[i] : mux_nm; }
+               execvp(mux_new[0], margs);
+               _exit(1);
+       }
+
        execvp(prog, args);
        _exit(1);
 }
@@ -4177,6 +4190,11 @@ cmessage(XEvent *e)
                        xw.state &= ~WIN_FOCUSED;
                }
        } else if (e->xclient.data.l[0] == xw.wmdeletewin) {
+               if (use_mux) {
+                       setenv("MUX_NM", mux_nm, 1);
+                       if (system(mux_post) != 0)
+                               fprintf(stderr, "mux_post execution error\n");
+               }
                /* Send SIGHUP to shell */
                kill(pid, SIGHUP);
                exit(0);
@@ -4325,7 +4343,7 @@ usage(void)
        die("usage: %s [-aiv] [-c class] [-f font] [-g geometry]"
            " [-n name] [-o file]\n"
            "          [-T title] [-t title] [-w windowid]"
-           " [[-e] command [args ...]]\n"
+           " [-m|-M] [[-e] command [args ...]]\n"
            "       %s [-aiv] [-c class] [-f font] [-g geometry]"
            " [-n name] [-o file]\n"
            "          [-T title] [-t title] [-w windowid] -l line"
@@ -4368,6 +4386,12 @@ main(int argc, char *argv[])
        case 'l':
                opt_line = EARGF(usage());
                break;
+       case 'm':
+               use_mux = 1;
+               break;
+       case 'M':
+               use_mux = 0;
+               break;
        case 'n':
                opt_name = EARGF(usage());
                break;
@@ -4392,6 +4416,9 @@ run:
                if (!opt_title && !opt_line)
                        opt_title = basename(xstrdup(argv[0]));
        }
+       if (use_mux) {
+               snprintf(mux_nm, sizeof(mux_nm), "%.43s-%d", (opt_name ? 
opt_name : "st"), getpid());
+       }
        setlocale(LC_CTYPE, "");
        XSetLocaleModifiers("");
        tnew(MAX(cols, 1), MAX(rows, 1));
#!/bin/bash
trap "tmux list-clients -t st-$$ 2>/dev/null |
{ read -r _ && ! read -n1 -r _; } &&
tmux kill-session -t st-$$
" INT TERM EXIT
tmux new-session -s st-$$ -- "$@"

Reply via email to