From 7fab7dd6fb14f6c2215a78866b0cd0e395994c63 Mon Sep 17 00:00:00 2001 From: Marty Oehme Date: Sat, 27 Jul 2019 12:29:47 +0000 Subject: [PATCH] [tmux] Add remote session nesting If calling a tmux session within a tmux session, pressing F12 will toggle between sending commands to the outer or inner session. If the outer session is inactive its status-bar will be slightly greyed out to show that no commands will reach it. If the inner session is a remote ssh session, it will set some additional stylings for the status-bar to further differentiate the two. --- .config/tmux/tmux.conf | 35 +++++++++++++++++++++++++++++++ .config/tmux/tmux.remote.conf | 10 +++++++++ .local/bin/test/tm.bats | 39 +++++++++++++++++++++++++++++++++++ .local/bin/tm | 22 ++++++++++---------- 4 files changed, 95 insertions(+), 11 deletions(-) create mode 100644 .config/tmux/tmux.remote.conf create mode 100644 .local/bin/test/tm.bats diff --git a/.config/tmux/tmux.conf b/.config/tmux/tmux.conf index 96463cd..4a06f67 100644 --- a/.config/tmux/tmux.conf +++ b/.config/tmux/tmux.conf @@ -157,3 +157,38 @@ set -g status-left "#[fg=#c8c8c8,bg=#2e2e2e] #S #[fg=#2e2e2e,bg=#2e2e2e,nobold,n set -g status-right "#[fg=#2e2e2e,bg=#2e2e2e,nobold,nounderscore,noitalics]#{prefix_highlight} #[fg=#c8c8c8,bg=#2e2e2e] %H:%M:%S #[fg=#2e2e2e,bg=#2e2e2e,nobold,nounderscore,noitalics]#[fg=#c8c8c8,bg=#2e2e2e] %d-%b-%y #[fg=#2e2e2e,bg=#2e2e2e,nobold,nounderscore,noitalics]#[fg=#c8c8c8,bg=#2e2e2e] #H " setw -g window-status-format "#[fg=#2e2e2e,bg=#2e2e2e,nobold,nounderscore,noitalics]#[default] #I #W #[fg=#2e2e2e,bg=#2e2e2e,nobold,nounderscore,noitalics]" setw -g window-status-current-format "#[fg=#2e2e2e,bg=#2e2e2e,nobold,nounderscore,noitalics]#[fg=#c8c8c8,bg=#2e2e2e]  #I #W #[fg=#2e2e2e,bg=#2e2e2e,nobold,nounderscore,noitalics]" + +######################## +## 5. Nested Sessions ## +######################## +# from: https://github.com/samoshkin/tmux-config/blob/master/tmux/tmux.conf +# all credit to samoshkin + +# Session is considered to be remote when we ssh into host +if-shell 'test -n "$SSH_CLIENT"' \ + 'source-file $XDG_CONFIG_HOME/tmux/tmux.remote.conf' + +# We want to have single prefix key "C-a", usable both for local and remote session +# we don't want to "C-a" + "a" approach either +# Idea is to turn off all key bindings and prefix handling on local session, +# so that all keystrokes are passed to inner/remote session + +# see: toggle on/off all keybindings · Issue #237 · tmux/tmux - https://github.com/tmux/tmux/issues/237 + +# Also, change some visual styles when window keys are off +bind -T root F12 \ + set prefix None \;\ + set key-table off \;\ + set status-style fg="colour245",bg="colour238" \;\ + set window-status-current-format "#[fg=$color_window_off_status_bg,bg=$color_window_off_status_current_bg]$separator_powerline_right#[default] #I:#W# #[fg=$color_window_off_status_current_bg,bg=$color_window_off_status_bg]$separator_powerline_right#[default]" \;\ + set window-status-current-style fg="colour232",bg="colour254","bold" \;\ + if -F '#{pane_in_mode}' 'send-keys -X cancel' \;\ + refresh-client -S \;\ + +bind -T off F12 \ + set -u prefix \;\ + set -u key-table \;\ + set -u status-style \;\ + set -u window-status-current-style \;\ + set -u window-status-current-format \;\ + refresh-client -S diff --git a/.config/tmux/tmux.remote.conf b/.config/tmux/tmux.remote.conf new file mode 100644 index 0000000..defe108 --- /dev/null +++ b/.config/tmux/tmux.remote.conf @@ -0,0 +1,10 @@ +# show status bar at bottom for remote session, +set -g status-position bottom + +# Set port of SSH remote tunnel, where tmux will pipe buffers to transfer on local machine for copy +set -g @copy_backend_remote_tunnel_port 11988 + +# In remote mode we don't show "clock" and "battery status" widgets +set -g status-left "#[fg=#c8c8c8,bg=#2e2e2e][SSH]#S #[fg=#2e2e2e,bg=#2e2e2e,nobold,nounderscore,noitalics]#[fg=#c8c8c8,bg=#2e2e2e] #(whoami) #[fg=#2e2e2e,bg=#2e2e2e,nobold,nounderscore,noitalics]#[fg=#c8c8c8,bg=#2e2e2e] #I:#P #[fg=#2e2e2e,bg=#2e2e2e,nobold,nounderscore,noitalics]" +set -g status-right "#{prefix_highlight} $wg_is_keys_off $wg_is_zoomed #{sysstat_cpu} | #{sysstat_mem} | #{sysstat_loadavg} | $wg_user_host | #{online_status}" +set -g status-right "#[fg=#2e2e2e,bg=#2e2e2e,nobold,nounderscore,noitalics]#{prefix_highlight} #H " diff --git a/.local/bin/test/tm.bats b/.local/bin/test/tm.bats new file mode 100644 index 0000000..b11e425 --- /dev/null +++ b/.local/bin/test/tm.bats @@ -0,0 +1,39 @@ +setup() { + fut="$BATS_TEST_DIRNAME/../tm" +} + +teardown() { + rm -rf $BATS_TMPDIR/xdg/* +} + +@test "runs correctly if invoked without arguments" { + run $fut + echo "$BATS_TEST_DIRNAME/../tm" + [ "$status" -eq 0 ] +} + +@test "Errors out if passed a non-existent session file (and some session name)" { + run $fut IDONT_EXIST_HERE.session sessionname + echo "STATUS: $output" + [ "$status" -eq 1 ] + echo "OUTPUT: $output" + [ "$output" = "can not source session file: 'IDONT_EXIST_HERE.session' does not exist." ] +} + +@test "Runs without errors when session file exists in PWD" { + touch $PWD/exists.session + run $fut exists.session sessionname + rm $PWD/exists.session + + [ "$status" -eq 0 ] +} + +@test "Runs without errors when session file exists in XDG_CONFIG_HOME/tmux/sessions/" { + export XDG_CONFIG_HOME=$BATS_TMPDIR + mkdir -p $XDG_CONFIG_HOME/tmux/sessions + sesdir=$XDG_CONFIG_HOME/tmux/sessions + touch $sesdir/exists.session + run $fut exists.session sessionname + + [ "$status" -eq 0 ] +} diff --git a/.local/bin/tm b/.local/bin/tm index 87b8646..afdeea8 100755 --- a/.local/bin/tm +++ b/.local/bin/tm @@ -3,7 +3,7 @@ # Attach to a tmux session, or create it if it doesnt exist if [ "$1" = '-h' ] || [ "$1" = '--help' ]; then -cat <<-EOF + cat <<-EOF Usage: $0 [FILE] [NAME] Attach to an existing tmux session, or bootstrap a new session. @@ -54,7 +54,7 @@ _not_in_tmux() { } _session_exists() { - if tmux has-session -t "$session_name" > /dev/null 2>&1; then + if tmux has-session -t "$session_name" >/dev/null 2>&1; then true else false @@ -67,13 +67,13 @@ _create_detached_session() { _load_env_session_file() { if [ -f ./.tmux.session ]; then - xargs -L1 tmux < ./.tmux.session + xargs -L1 tmux <./.tmux.session fi } _load_session_file() { if [ -f "$session_file" ]; then - xargs -L1 tmux < "$session_file" + xargs -L1 tmux <"$session_file" fi } @@ -92,7 +92,7 @@ _set_session_vars() { # set up session name and config file - if passed in as arguments if [ "$#" -eq 2 ]; then if ! _file_exists "$1" && ! _file_exists "${session_dir}${1}"; then - echo "$0: can not source configuration file: '${1}' does not exist." + echo >&2 "can not source session file: '${1}' does not exist." exit 1 fi _set_session_file_path "$1" @@ -106,12 +106,12 @@ _set_session_vars() { # set default session name if none was passed if [ -z "$session_name" ]; then - # only if we have a filename should we append it to the session name - if [ -n "$session_file" ]; then - fname=/$(basename "$session_file" .session) - fi - # default to parent directory name / config file name for the session - session_name=$(basename "$PWD" | sed 's/[^a-zA-Z0-9\-]//g' | tr . -)"$fname" + # only if we have a filename should we append it to the session name + if [ -n "$session_file" ]; then + fname=/$(basename "$session_file" .session) + fi + # default to parent directory name / config file name for the session + session_name=$(basename "$PWD" | sed 's/[^a-zA-Z0-9\-]//g' | tr . -)"$fname" fi }