How do I set tmux window name from within a Bash script? - tmux

In one of my tmux windows, I run a Weechat IRC client inside a Docker container, which I instantiate using a Bash script, which makes the tmux window name "bash". https://imgur.com/a/Dc20YEB
I would like the tmux window name to be "weechat", as if I had run a locally installed weechat - as is the case with man or nvim.
I understand there is a difference between "window names" and "pane titles", and that I can set the window name using (as detailed in the man page):
tmux set-option allow-rename on
tmux select-pane -T fooname
printf '\033kWINDOW_NAME\033\\'
But this changes my window name to 1:tpreston#hostname:~*. I'm running tmux 2.9a on Fedora 30.
These are my options
activity-action other
assume-paste-time 1
base-index 0
bell-action any
default-command ""
default-shell "/bin/bash"
default-size "80x24"
destroy-unattached off
detach-on-destroy on
display-panes-active-colour red
display-panes-colour blue
display-panes-time 1000
display-time 4000
history-limit 50000
key-table "root"
lock-after-time 0
lock-command "lock -np"
message-command-style fg=yellow,bg=black
message-style fg=black,bg=yellow
mouse on
prefix C-Space
prefix2 None
renumber-windows off
repeat-time 500
set-titles off
set-titles-string "#S:#I:#W - \"#T\" #{session_alerts}"
silence-action other
status on
status-bg green
status-fg black
status-format[0] "#[align=left range=left #{status-left-style}]#{T;=/#{status-left-length}:status-left}#[norange default]#[list=on align=#{status-justify}]#[list=left-marker]<#[list=right-marker]>#[list=on]#{W:#[range=window|#{window_index} #{window-status-style}#{?#{&&:#{window_last_flag},#{!=:#{window-status-last-style},default}}, #{window-status-last-style},}#{?#{&&:#{window_bell_flag},#{!=:#{window-status-bell-style},default}}, #{window-status-bell-style},#{?#{&&:#{||:#{window_activity_flag},#{window_silence_flag}},#{!=:#{window-status-activity-style},default}}, #{window-status-activity-style},}}]#{T:window-status-format}#[norange default]#{?window_end_flag,,#{window-status-separator}},#[range=window|#{window_index} list=focus #{?#{!=:#{window-status-current-style},default},#{window-status-current-style},#{window-status-style}}#{?#{&&:#{window_last_flag},#{!=:#{window-status-last-style},default}}, #{window-status-last-style},}#{?#{&&:#{window_bell_flag},#{!=:#{window-status-bell-style},default}}, #{window-status-bell-style},#{?#{&&:#{||:#{window_activity_flag},#{window_silence_flag}},#{!=:#{window-status-activity-style},default}}, #{window-status-activity-style},}}]#{T:window-status-current-format}#[norange list=on default]#{?window_end_flag,,#{window-status-separator}}}#[nolist align=right range=right #{status-right-style}]#{T;=/#{status-right-length}:status-right}#[norange default]"
status-format[1] "#[align=centre]#{P:#{?pane_active,#[reverse],}#{pane_index}[#{pane_width}x#{pane_height}]#[default] }"
status-interval 5
status-justify left
status-keys emacs
status-left "[#S] "
status-left-length 10
status-left-style default
status-position bottom
status-right "#(/home/tpreston/.tmux/plugins/tmux-battery/scripts/battery_status_bg.sh) b:#(/home/tpreston/.tmux/plugins/tmux-battery/scripts/battery_icon.sh)#(/home/tpreston/.tmux/plugins/tmux-battery/scripts/battery_percentage.sh) | %a %F %H:%M "
status-right-length 40
status-right-style default
status-style fg=black,bg=green
update-environment[0] "DISPLAY"
update-environment[1] "KRB5CCNAME"
update-environment[2] "SSH_ASKPASS"
update-environment[3] "SSH_AUTH_SOCK"
update-environment[4] "SSH_AGENT_PID"
update-environment[5] "SSH_CONNECTION"
update-environment[6] "WINDOWID"
update-environment[7] "XAUTHORITY"
visual-activity off
visual-bell off
visual-silence off
word-separators " -_#"

# rename window name of current window
tmux rename-window newname
# rename another window
tmux rename-window -t <target> new-name
The parameter <target> could be
window name
window index
window name or index with session prefix: <session>:<window>

tmux select-pane -T fooname
This sets the pane title not the window name. Use "tmux rename-window" to change the window name.
tmux set-option allow-rename on
printf '\033kWINDOW_NAME\033\'
This does change the window name.
But this changes my window name to 1:tpreston#hostname:~*
This is because something else is renaming the window, probably your shell is doing it as part of the prompt.
If you want to have allow-rename on and use the \033k escape sequence yourself, you will need to track this down and disable it.
If your script is running on the same host as tmux, it might be better just to leave allow-rename off and run "tmux renamew weechat" from the script.

Related

Tmux conditional color setting

Is it possible to set window color depends on the other window-option?
When a windows has synchronize-panes enabled, I don't want to accidentally press C-d, or all panes will be closed.
So what I'm trying to do is to change window color on statusline based on synchronize-panes:
(the following config doesn't work, though)
bind-key S setw synchronize-panes \; \ # toggles the option
set -w window-status-bg '#{?pane_synchronized,yellow,default}' \; \ # error: bad color
set -w window-status-current-fg '#{?pane_synchronized,yellow,default}' # error: bad color
The most possible solution I can thought of is to use if-shell, but I prefer not to fork a shell just to read option of itself, if possible.
EDIT: This if-shell solution works for me on tmux 2.7
My statusline cyan colored, if synchronize-panes is enabled, cyan becomes yellow.
bind-key S setw synchronize-panes \; \
if-shell '[ #{pane_synchronized} -eq 1 ]' \
'set -w window-status-style fg=black,bg=yellow ; set -w window-status-current-style fg=yellow,bg=black' \
'set -w window-status-style fg=black,bg=cyan ; set -w window-status-current-style fg=cyan,bg=black'
EDIT: Problem solved, my setting is now changed to this:
bind-key S setw synchronize-panes
sync_ind_colour="#{?pane_synchronized,yellow,cyan}"
set -g window-status-format "#[fg=black,bg=${sync_ind_colour}][#I#{?#{!=:#W,},:,}#W]"
set -g window-status-current-format "#[fg=${sync_ind_colour},bg=black][#I#{?#{!=:#W,},:,}#W]"
Looks a little bit scary but it's still readable.
It shouldn't be necessary to use if-shell for this. You can use conditionals in format options, but not in styles. The following minimal configuration should do what you want.
# toggle pane synchronisation mode
bind-key S setw synchronize-panes
# Variables
sync_ind_colour="#{?pane_synchronized,yellow,cyan}"
# status format
setw -g window-status-format "#[fg=black,bg=${sync_ind_colour}]#I #W"
setw -g window-status-current-format "#[fg=${sync_ind_colour},bg=black][#I #W]"
Note that I set the text of the window status to #I #W (and [#I #W] for active) as an example, but that's irrelevant to the question.
It's also not necessary to use a variable (sync_ind_colour, synchronise indicator colour), but it's simpler than defining the same conditional in both the window-status-format and the window-status-current-format variables.

tmux: allow-rename, but ALSO override?

I'd like to be able to issue a command like this:
tmux new-window -n irc ssh -t eco /usr/bin/weechat
and have the title of the new window be "irc". Instead, as soon as weechat launches, the title changes to weechat.
I had been under the impression based on the tmux man page that if you set a window title explicitly, automatic-rename would be disabled for you:
automatic-rename
[...] This flag is automatically disabled for an individual window when a
name is specified at creation with new-window or new-session, or later
with rename-window, or with a terminal escape sequence.
But that seems to not be the case. What am I missing here? I do want automatic-rename in most cases - I just want to also be able to specify -n windowname and have it take precedence.

tmux: how to toggle "on" and "off" options with the same key

This is a bit of my tmux.conf
cat tmux.conf
...
bind a set-window-option synchronize-panes on
bind b set-window-option synchronize-panes off
As you can see, sync and unsync options for panes are bound to two different keys. Is it possible to toggle sync/unsync with the same key?
If you don't explicitly specify "on" or "off", the option will get toggled. The following would suffice:
bind-key a set-window-option synchronize-panes\; display-message "synchronize-panes is now #{?pane_synchronized,on,off}"
don't attach on or off. it's toggle
bind-key a set-window-option synchronize-panes
This should be possible with a combination of run-shell and tmux show-option, something like (tested in tmux 2.3):
bind a run-shell "if [[ `tmux show-options -w | grep 'synchronize-panes.*on'` ]]; then toggle=off; else export toggle=on; fi; tmux display-message \"sync panes tmux: \$toggle\"; tmux set-option -w synchronize-panes \$toggle &> /dev/null"
(this is a variation of a mouse-mode toggle found on the TMux user mailing list)
Here's an example of toggling the mouse on and off with ^M:
bind-key c-M set-option -g mouse \; display-message 'Mouse #{?mouse,on,off}'
A more generic solution based on the answer by Frank Schmitt:
!/usr/bin/bash
USAGE="USAGE: $0 OPTION_NAME ON_STATE OFF_STATE"
OPTION_NAME=$1
ON_STATE=$2
OFF_STATE=$3
if [[ "$#" != 3 ]]; then
echo $USAGE
exit 1
fi
if [[ `tmux show-option -w | grep "$OPTION_NAME $ON_STATE"` ]]; then
OPTION_VALUE=$OFF_STATE
else
OPTION_VALUE=$ON_STATE
fi
tmux display-message "monitor activity: $OPTION_NAME $OPTION_VALUE"
tmux set-option -w $OPTION_NAME $OPTION_VALUE > /dev/null
The script takes the name of the option, the on value and the off value. Not very well tested but works for simple cases like:
PATH_TO_SCRIPT_ABOVE monitor-activity on off
In your .tmux.conf:
bind-key <SOME_KEY> run-shell "tmux_toggle_option monitor-activity on off"

How can I bind a key to switch to last-pane, or if there are no panes, last-window?

If I'm working in a widescreen monitor I like to primarily use two panes and switch between them with C-a Ca.
If I'm working on a square monitor I'll use two windows. I'd like to be able to switch between them with C-a C-a as well without changing my tmux.conf.
If you always want C-a to
switch between panes when the active window has more than one pane, and
switch between windows when the active window has only one pane,
then you can use an if-shell that counts the number of panes in the active window to decide between last-pane and last-window:
bind-key C-a if-shell 'test $(tmux list-panes | wc -l) -gt 1' 'last-pane' 'last-window'
It will still be “up to you” to rearrange your panes when switching between “wide” and “square” configurations (e.g. via break-pane and join-pane).
In tmux 1.8 if-shell and run-shell do format expansion, so you can simply the shell command a bit:
bind-key C-a if-shell 'test #{window_panes} -gt 1' 'last-pane' 'last-window'
I'd like to suggest the following (adjust 80 to distinguish between your two terminal widths)
if-shell '[ "$COLUMNS" -gt 80 ]' 'bind-key C-a "select-window -t :.+"' 'bind-key C-a "next-window"'
but I'm either messing up the syntax, or COLUMNS isn't set in the relevant tmux environment, as the above shell expression always evaluates false for me.

How can you tell which pane in Tmux is focused?

I'm starting to use tmux (I'm thinking of switching from screen), but I'm having a hard time telling which pane is focused when I split a window into multiple panes. Is there a config customization or something that can highlight the focused pane a little more explicitly?
Here are the relevant settings:
pane-active-border-style fg=colour,bg=colour
Set the pane border colour for the currently active pane.
So, try adding something like this to your ~/.tmux.conf:
set-option -g pane-active-border-style fg=blue
That will set a blue border around the active pane. The pane-active-border-style bg=colour option can be used for a more visible solution, as well.
As answered in another post it is now possible in tmux 2.1 to set the colours of individual panes. Ones can use:
set -g window-style 'fg=colour247,bg=colour236'
set -g window-active-style 'fg=colour250,bg=black'
in the ~/.tmux.conf file to show a difference between the active/inactive panes.
With Vim If you find it does not work with Vim panes, it might be down to the colourscheme you are using. First, try another colourscheme such as pablo. For further details, see the other post.
Customize status-left and use the #P character pair, which is the pane number. You will probably want to include more than just the pane number in the status bar, but here is an example of the line you would add to your ~/.tmux.conf for just the pane number:
set-option -g status-left '#P'
See the tmux man page for more character pairs: http://manpages.ubuntu.com/manpages/precise/en/man1/tmux.1.html
One Solution that works for me is to add a display-pane at the end of the hotkey for a pane switch. This displays all the pane numbers, with the current pane in a different color. You can also use <escape_key> + q to display pane numbers.
I use alt+h/j/k/l to switch between panes, and I use the following binding.
bind -n M-j select-pane -D \; display-pane
bind -n M-k select-pane -U \; display-pane
bind -n M-h select-pane -L \; display-pane
bind -n M-l select-pane -R \; display-pane
I wanted the active pane's borders to be brighter than other panes,
so I went with this (works in tmux 1.8 w/CentOS 7):
~/.tmux.conf fragment
# rgb hex codes from https://www.rapidtables.com/web/color/RGB_Color.html
set-option -g pane-active-border-fg '#33FF33' # brighter green
set-option -g pane-border-fg '#006600' # darker green
The tmux man page says hex-RGB colors will be approximated, and I find the hex codes easier to understand than remembering "colour47" (out of colour0-255) is a kind of light green (as described in How does the tmux color palette work?).
tmux man-page excerpt:
message-bg colour
Set status line message background colour, ...etc...
or a hexadecimal RGB string such as ‘#ffffff’, which chooses the closest
match from the default 256-colour set.
For tmux 3 I was able to set the following in my .tmux.conf for a subtle border indicator:
set-option -g pane-active-border-style bg=yellow

Resources