TL;DR some key improvements can:
- Keep good
sh
and tmux compatibility back to at least 1.8
- Free you from the
bc
requirement for portability
- Increase readability of the
if
statements
- Let you use
{}
on larger complicated nested string blocks, provided those are for 3.0 and newer
Version check
I prefer awk
and sed
(core linux tools) approach to getting the version:
run-shell 'tmux setenv -g TMUX_VERSION $(\
tmux -V | \
sed -En "s/^tmux[^0-9]*([.0-9]+).*/\1/p" | \
awk "{major=int(\$1); \
minor=\$1-major; \
print int(major*100+minor*10) }")'
This is very similar to solution that use string manipulation techniques, except I'm able to easily do math in awk
.
E.g.
tmux 1.3
becomes 103
tmux 3.2a
becomes 302
Now instead of having to remember the bc
/other expression every time you want to if-shell
, it's a fairly normal sh
expression.
'[ "${TMUX_VERSION}" -lt "200" ]' # Version < 2.0
'[ "${TMUX_VERSION}" -le "215" ]' # Version <= 2.15 (a pretend version 2.15)
Note Some ancient versions of GNU sed
don't like -E
flag and need -r
instead. (BSD (darwin) doesn't support -r
). These are all EOL and should no longer be a problem. But if that level of portability matters, an addition run-shell
test could resolve that distinction.
If-shells examples
if-shell -b '[ "${TMUX_VERSION}" -lt "200" ]' " \
setw -g mode-mouse on; \
set -g mouse-select-window on; \
set -g mouse-select-pane on; \
set -g mouse-resize-pane on; \
set -g mouse-utf on"
if-shell -b '[ "${TMUX_VERSION}" -ge "200" ]' " \
set-window-option -g mouse on"
{} strings
I could not get @Tom Hale solution using {}
to work. This appears to be a tmux 3.0 feature. Just having }
on a line by itself will upset tmux 1.8 - 2.9, so I can't figure out how to use it.
What I found works, is if I used '
as the outer most string quotes, then I can use {} internally, if and only if I escape it so that it is interpreted as a single line (although it will be readable as multiple lines for me)
To keep older versions of tmux happy:
{
and }
must come at the end of the line, no }
on their own
- Every line must end in
\
. The essentially means it's a single line, partially defeating the key multiline benefit of {}
. However this still improves readability and allows easier string nesting.
- Since every line must end in
\
, multiple command will still need ;
between them when on multiple lines (See copy-mode
below)
Rehash This parses successfully on 1.8 (I never test older) and newer, as long as the tmux version check is for versions 3.0 or greater. The examples above target versions 1 and 2, so cannot use the escaped {}
method
Snippet of a complicated example
if-shell -b '[ "${TMUX_VERSION}" -ge "300" ]' ' \
bind-key -T root MouseDown3Pane \
if-shell -F -t = "#{||:#{mouse_any_flag},#{&&:#{pane_in_mode},#{?#{m/r:(copy|view)-mode,#{pane_mode}},0,1}}}" \
"select-pane -t= ; send -M" { \
display-menu -t= -xM -yM -T \
"#[align=centre]#{pane_index} (#{pane_id})" \
"#{?#{m/r:(copy|view)-mode,#{pane_mode}},Go To Top,}" < "send -X history-top" \
"#{?#{m/r:(copy|view)-mode,#{pane_mode}},Go To Bottom,}" > "send -X history-bottom" \
"" \
"#{?mouse_word,Search For #[underscore]#{=/9/...:mouse_word},}" C-r { \
if -F "#{?#{m/r:(copy|view)-mode,#{pane_mode}},0,1}" \
"copy-mode -t=" ; \
send -Xt= search-backward "#{q:mouse_word}" \
} \
"#{?mouse_word,Type #[underscore]#{=/9/...:mouse_word},}" C-y { \
copy-mode -q ; \
send-keys -l -- "#{q:mouse_word}" \
} \
... } \
'
Life hack: The outer ''
can be replaced with {}
while you use your editor of choice for syntax highlighting, but you'll have to remember to put it back