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
[[ ]]
and(( ))
in that test? I would think just(( ))
would be enough assumingif
(which isif-shell
?) tests the return code. – Imperatorif "(( $(tmux -V | cut -c 6-) < 2.1 ))" "set -g mode-mouse on; set -g mouse-resize-pane on; set -g select-pane on; set -g select-window on"
fixes the problem, Can you post your comment as an answer. – Shopkeeper(( ))
can't handle the decimal numbers so if that works it is a different reason (or accidental). Does tmux have a way to test for features? (I assume you only want that turned on in versions that support it.) – Imperator[[
syntax is not supported when usingrun-shell
. Well, I should've known better since the documentation says that/usr/bin/sh
is used, and while that probably means bash, it may be running in a compatibility mode, and[[
is bash-specific. BUT, you can simply replace[[ <expr> ]]
withtest "<expr>"
to achieve the same result. – Trebizond