How to write if statement in .tmux.conf to set different options for different tmux versions?
Asked Answered
S

16

63

I have a .tmux.conf which I use on different machines with different tmux versions installed.

I want to set different mouse options, depending on the tmux version. On one machine I have version 2.0 on the other 2.1.

I do not get his part right

if "[[(( $(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" "set -g mouse on"

When I source the file

$ tmux source-file .tmux.conf

I get this message

.tmux.conf:12: unknown command: set -g mouse-resize-pane on

The machine where I run it has version 2.1 so it shouldn't set the four options.

I want to set the four options when running tmux 2.0 or less or the one option when running tmux 2.1.

This bash statement works

$ tmux -V
tmux 2.1
$ if [[(( $(tmux -V | cut -c 6-) < 2.1 ))]];then echo $?;else echo $?;fi
1
Shopkeeper answered 26/1, 2016 at 14:39 Comment(6)
Why do you have both [[ ]] and (( )) in that test? I would think just (( )) would be enough assuming if (which is if-shell?) tests the return code.Imperator
fixing the if statement to if "(( $(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
Actually (( )) 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
I do not know if tmux can test for features, I am rather new to tmux.Shopkeeper
os detect: superuser.com/questions/539595/…Wampumpeag
I just learned "the hard way" that the [[ syntax is not supported when using run-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> ]] with test "<expr>" to achieve the same result.Trebizond
P
73

Based on @ericx's answer and @thiagowfx's answer I put the following together which covers many of the listed incompatibilties from version 2.0 onwards:

# Version-specific commands [grumble, grumble]
# See: https://github.com/tmux/tmux/blob/master/CHANGES
run-shell 'tmux setenv -g TMUX_VERSION $(tmux -V | \
                           sed -En "s/^tmux[^0-9]*([.0-9]+).*/\1/p")'

if-shell -b '[ "$(echo "$TMUX_VERSION < 2.1" | bc)" = 1 ]' {
    set -g mouse-select-pane on; set -g mode-mouse on
    set -g mouse-resize-pane on; set -g mouse-select-window on
    set -g message-fg red
    set -g message-bg black
    set -g message-attr bright
    set -g window-status-bg default
    set -g window-status-fg default
    set -g window-status-current-attr bold
    set -g window-status-current-bg cyan
    set -g window-status-current-fg default
    set -g window-status-bell-fg red
    set -g window-status-bell-bg black
    set -g window-status-activity-fg white
    set -g window-status-activity-bg black
}

# In version 2.1 "mouse" replaced the previous 4 mouse options
if-shell -b '[ "$(echo "$TMUX_VERSION >= 2.1" | bc)" = 1 ]' {
    set -g mouse on
}

# UTF8 is autodetected in 2.2 onwards, but errors if explicitly set
if-shell -b '[ "$(echo "$TMUX_VERSION < 2.2" | bc)" = 1 ]' \
    set -g utf8 on
    set -g status-utf8 on
    set -g mouse-utf8 on
}

# bind-key syntax changed in 2.4 -- selection / copy / paste
if-shell -b '[ "$(echo "$TMUX_VERSION < 2.4" | bc)" = 1 ]' {
    bind-key -t vi-copy v   begin-selection
    bind-key -t vi-copy V   send -X select-line
    bind-key -t vi-copy C-v rectangle-toggle
    bind-key -t vi-copy y   copy-pipe 'xclip -selection clipboard -in'
}

# Newer versions
if-shell -b '[ "$(echo "$TMUX_VERSION < 2.9" | bc)" = 1 ]' {
    bind-key -T copy-mode-vi v   send -X begin-selection
    bind-key -T copy-mode-vi V   send -X select-line
    bind-key -T copy-mode-vi C-v send -X rectangle-toggle
    bind-key -T copy-mode-vi y   send -X copy-pipe-and-cancel 'xclip -selection clipboard -in'
}

if-shell -b '[ "$(echo "$TMUX_VERSION >= 2.9" | bc)" = 1 ]' {
    set -g message-style fg=red,bg=black
    set -g message-style bright
    set -g window-status-style          fg=default,bg=default
    set -g window-status-current-style  fg=default,bg=cyan,bold
    set -g window-status-bell-style     fg=red,bg=black
    set -g window-status-activity-style fg=white,bg=black
}

I raised an issue about the problems with tmux's non-backward-compatibility here. The summary is that the tmux devs will not support backward compatibility, nor will they adopt a version numbering scheme which highlights which versions contain breaking changes. 😢

I raised an issue to support numeric comparators for %if which was implemented in v3.0.

Peri answered 1/12, 2016 at 3:49 Comment(17)
Thanks Tom, this is great. I've added a thank you to you on my repo github.com/sixarm/sixarm_tmux_dotfilesEnshrine
As someone who uses the same dotfiles on OSX and 2-3 different linux boxes, I can't thank you enough! This answer seems to be the most versatile of them all.Dermatologist
this is pointed out below in Micah's answer, but I was having issues due to missing semicolons here before the back slashes (it was all being interpreted as a single long command). Thanks for the example!Autumn
@TonyClifton Indeed, not only the missing semicolons cause problems, but also everything past the first comment char (#) was ignored in my case ...Kwasi
@Griddo thanks for the edit. I've updated based on v2.9, but as I didn't encounter the issues you experienced, I'd appreciate your review. What version are you using which baulks at the # and lack of ;?Peri
@TomHale I'm currently using v2.6 on linux mint and also something >v2.4 as well as v2.8 on WSL debian. See this minimal example which exactly reproduces the two errors.Kwasi
It should be noted that these version checks will not work if there are letters and other characters in the release version. In the spirit of tmux's FU SEMVER, I offer up the last two releases on GitHub that defy these version checks: 2.9a and 3.0-rc3. github.com/tmux/tmux/releasesLacking
$(tmux -V | cut -c -8 | cut -d' ' -f2)Lacking
Thanks for the heads-up @danemacmillan. Their release management is FUBAR. I've updated with a single sed -n.Peri
@TomHale, the setenv line doesn't work for version tmux.orig 2.8 value. sed -En "s/^tmux.* ... does work.Celibate
@Celibate Sorry, but I don't quite follow. Please suggest an edit.Peri
@TomHale, My tmux -V returns the string tmux.orig 2.8. This value doesn't work with the run-shell sed command. Change the sed pattern to s/^tmux.* .... (add .* after "tmux"). Suggest edit didn't work since change needs to be 6 characters long and mine is just 2-chars :)Celibate
The current head of master has the version string: tmux next-3.3 The pattern in the answer didn't work, an (other) appropriate pattern for sed is: bash sed -En "s/^tmux[^0-9]*([.0-9]+).*/\1/p" I read your linked issue, & I share your disappointment in the maintainers' attitude towards semver. As you pointed out, that 23 minutes of .conf fixup for one dev -> thousands of cumilative person-hours across the userbase.Barmen
Hey, just regarding this, one way to clean-up your tmux.conf that implements this so it's a little more DRY: You can store your shell test strings in tmux env vars, (since 0.8 in 2008) and interpolate them @ run time for if-shell: V33_GTE='[ "$(echo "$TMUX_VERSION >= 3.3" | bc)" = 1 ]' V33_LT='[ "$(echo "$TMUX_VERSION < 3.3" | bc)" = 1 ]' if "$V33_GTE" bind -N "Mouse mode off" MBarmen
@MatthewStrasiotto Sorry, I don't follow, what repetition does this remove?Peri
@TomHale instead of copy-pasting & evaluating the same shell test, you wind up copy pasting an env-var that stores the test & evaluating that. The benefit is marginal reallyBarmen
To avoid having to use bc (which isn't installed on some of the machines I often log into remotely) I've been doing this: run-shell "tmux setenv -g TMUX_VERSION $(tmux -V | sed -E 's/^[^0-9]*//; s/[^0-9]*$//' | awk -F. '{ printf \"%d.%02d\", $1, $2 }')" and then if-shell 'bash -c "if [[ $TMUX_VERSION < 1.09 ]]; then :; else false; fi"' '...'. That is, I format the version in a way that can be compared lexicographically, and use the regular bash < and > operators to compare them as strings. It works on tmux 1.8, 2.1 and 3.1b, but I haven't tested exhaustively.Saltigrade
I
28

if-shell doesn't always work. Instead, I use a shell script for loading the correct version of tmux.conf:

In .tmux.conf:

run-shell "bash ~/.tmux/verify_tmux_version.sh"

In verify_tmux_version.sh:

#!/bin/bash

verify_tmux_version () {
    tmux_home=~/.tmux
    tmux_version="$(tmux -V | cut -c 6-)"

    if [[ $(echo "$tmux_version >= 2.1" | bc) -eq 1 ]] ; then
        tmux source-file "$tmux_home/tmux_2.1_up.conf"
        exit
    elif [[ $(echo "$tmux_version >= 1.9" | bc) -eq 1 ]] ; then
        tmux source-file "$tmux_home/tmux_1.9_to_2.1.conf"
        exit
    else
        tmux source-file "$tmux_home/tmux_1.9_down.conf"
        exit
    fi
}

verify_tmux_version

For more details: https://gist.github.com/vincenthsu/6847a8f2a94e61735034e65d17ca0d66

Immesh answered 30/4, 2016 at 9:48 Comment(5)
That bc hack is hardcore.Wampumpeag
The configuration management is already non-trivial managing 3 configuration files. The tmux devs introduce incompatibilities quite a bit and will probably continue to do so. I prefer a solution using only .tmux.conf which I based on this answer.Peri
I have tried the if-shell solution, but I can't find a way to detect the version numbers correctly on my 3 machines (Ubuntu 14.04 (tmux 1.8), Ubuntu 16.04 (tmux 2.1) and macOS Sierra (tmux 2.3)). So I choose to call bash directly. I would be happy if someone make "only one .tmux.conf" work.Immesh
That bc hack is so hardcore it fails for me: my tmux version is "3.0a", @CiroSantilliПутлерКапут六四事 Can be fixed with tmux_version="$(tmux -V | cut -c 6-8)"Euroclydon
@Euroclydon that has nothing to do with the bc hack, just the cut part is pretty unreliable! - also your fix will break for other outputs like tmux next-3.3 or even if just one part uses more than one digit. || although it gets a little bit longer, i use sed instead of cut which works for all cases known: sed -E -e 's/[[:alpha:][:space:][:punct:]]*([[:digit:]]*\.?[[:digit:]]+).*/\1/'Katelin
T
25

This is kind of a hassle. The correct way to do this within tmux (not relying on an external shell script) combines features of both Vincent and jdloft's responses.

The if-shell command in tmux is used as

if-shell [-bF] [-t target-pane] shell-command command [command]
               (alias: if)
    Execute the first command if shell-command returns success or the second command otherwise.  Before
    being executed, shell-command is expanded using the rules specified in the FORMATS section, including
    those relevant to target-pane.  With -b, shell-command is run in the background.

    If -F is given, shell-command is not executed but considered success if neither empty nor zero (after
         formats are expanded).

Note that tmux shell-command expansion will expand variables of the form #{pane_current_path} but otherwise will leave the command alone.

More importantly, note that tmux uses /bin/sh -c to execute the shell command we specify. Thus, the command must be POSIX compliant, so tests of the form [[ are not guaranteed to be portable. Modern Ubuntu and Debian systems, for example, symlink /bin/sh to dash.

We want to run a POSIX compliant shell command that tests the tmux version and returns 0 (true) if the desired version is found.

if-shell '[ $(echo "$(tmux -V | cut -d" " -f2) >= 2.1" | bc) -eq 1 ]' \
    'command if true' \
    'command if false'

Example:

if-shell '[ $(echo "$(tmux -V | cut -d" " -f2) >= 2.1" | bc) -eq 1 ]' \
    'set -g mouse on; set -g mouse-utf8 on' \
    'set -g mode-mouse on; set -g mouse-resize-pane on; set -g mouse-select-pane on; set -g mouse-select-window on' 

This correctly deals with the fact that we are doing floating point arithmetic, so bc is required. Additionally, there is no need for an if/then/else/fi construct, as the [ operator produces a truthy value by itself.

A couple notes

  • Lines continuing onto the next line cannot have trailing comments or tmux will give an "unknown command" error message.
  • The "command if false" can be omitted.
  • Multiple commands for either true or false can be combined using ;
  • The command is run on the underlying shell using /bin/sh -c. Other approaches that use [[ or other non-POSIX syntax are not guaranteed to work.

EDIT: A previous version of this answer used [[, which doesn't work on systems that don't use bash. Replacing with [ solves this.

Tanka answered 13/10, 2016 at 20:48 Comment(4)
I'm wondering if there's a way to make this work with nested if statements.Leighton
I'm sure you could @Carl, but your quoting of " characters would get hairy. @pana You'll need a ; between lines 2 and 3 in the last example. Also, you have mouse twice. See my answer for an example of a continuation within a continuation.Peri
Minor nit: [ is not an operator, it is a command. This is only an important distinction because many people mistake [ as being part of the shell grammar, which it is not.Woodsy
This is an excellent answer. I was able to achieve what I was after and I learned a few things about tmux and Bash. Thanks!Natalee
R
20

I also stumbled over configuration mismatches in different tmux versions. After reviewing all the solutions here and in this related question on SuperUser, I've implemented the following variant:

# Version-specific configuration can be placed in ~/.tmux/${TMUX_VERSION}/*.conf
run-shell "for conf in ~/.tmux/$(tmux -V | cut -d' ' -f2)/*.conf; do tmux source-file \"\$conf\"; done"

With this, version-specific configuration can be put in (multiple) configuration snippets for a particular version. This is similar to the solution of @VincentHsu, but:

  • It does not require an external shell script.
  • It does not segregate into fixed version ranges (... / 1.9 to 2.0 / 2.1 ...). Instead, one can use (sym)links to share a configuration snippet among multiple tmux versions.
  • It does not hardcode a single filename for a version. By allowing multiple configuration snippets for each version, parts can be shared among versions while others are kept version-specific. This should offer the utmost flexibility.
  • There's just a single configuration element in the original ~/.tmux.conf. Other solutions like the one from @TomHale duplicate the version test for each configuration element.
Ratan answered 27/1, 2017 at 10:10 Comment(0)
F
8

On some machines I was getting a false-positive result with the double bracket ('[[') syntax. So I came up with an alternative using awk:

# Enable mouse for different versions of tmux
# (If 'awk' exits with status 0, 'if-shell' evaluates to true)
# tmux < v2.1:
if-shell "tmux -V | awk '{exit !($2 < \"2.1\")}'" \
    "setw -g mode-mouse on ; set -g mouse-select-pane on ; set -g mouse-resize-pane on ; set -g mouse-select-window on ;"
# tmux >= v2.1:
if-shell "tmux -V | awk '{exit !($2 >= \"2.1\")}'" \
    "set -g mouse on ;"
Foremast answered 30/12, 2016 at 7:1 Comment(3)
Brilliant solution, that should be the accepted answer! Thanks (I'd add head -1 | after tmux -V | in case they will include more lines into its description later.)Pipestone
@Pipestone Should not be necessary, as the exit already causes awk to stop processing on first line.Loo
@raimue, thanks, I didn't know that, it seems to work indeed: echo -e "tmux 2.0-master\ntmux 2.8" | awk '{exit !($2 < "2.1")}' && echo ok || echo noPipestone
G
7

Tmux's if-shell can be used to check the ZSH version.

[[ `tmux -V | cut -d' ' -f2` -lt 2.1 ]]

checks whether or not the tmux version is greater than or equal to 2.1. Using this we can set your mouse commands depending on the ZSH version.

if-shell "[[ `tmux -V | cut -d' ' -f2` -lt 2.1 ]]" \
    'set -g mode-mouse on; set -g mouse-resize-pane on; set -g mouse-select-pane on; set -g mouse-select-window on'

And set it for later versions of tmux:

if-shell "[[ `tmux -V | cut -d' ' -f2` -ge 2.1 ]]" \
    'set -g mouse on; set -g mouse-utf8 on'
Gilletta answered 4/4, 2016 at 23:21 Comment(7)
The if-shell configuration for tmux <2.1 seems not working. Even with tmux 2.0, the bash shell says true for if [[ $(tmux -V | cut -d' ' -f2) -lt 2.1 ]]; then echo 'true'; true; else echo 'false'; false; fi, but with if-shell "if [[ $(tmux -V | cut -d' ' -f2) -lt 2.1 ]]; then true; else false; fi" "display true;" "display false;", tmux says that unknown command: display 2. It means the shell command is evaluated as false.Ouch
I get the same problem. if-shell always get false return. anyone coule please me?Voiced
This simply doesn't work. Just try running [[ `tmux -V | cut -d' ' -f2` -lt 2.1 ]] in bash. I get -bash: [[: 2.2: syntax error: invalid arithmetic operator (error token is ".2"). The reason is that these test operators don't handle floating points, for which you need bc.Tanka
Sorry, I was testing in Z shell which allows the use of the "-lt" operator like that. Try replacing it with the '<' symbol (and the '>' symbol for greater than).Gilletta
A cat dies whenever somebody does boolean ? true : false instead of boolean onlyWaldman
Hey, has anyone ever got this to work? tmux 'run-shell' is hard-coded to run /bin/sh. None of the example above work in /bin/sh.Grad
sh and bash don't allow for arithmetic comparison of floats. See this answer for a solution using the bench calculator bcPeri
S
4

I recently ran into this issue and my solution was to write an "tmux-older-than" script:

#! /bin/bash

TMUX_VERSION="$(tmux -V | cut -d" " -f2)"
test 1 -eq "$( echo "$TMUX_VERSION < $1" | bc)"

This makes tmux.conf much more readable:

if-shell 'tmux-older-than 3.0' \
        'bind-key ^P swap-window -t -1' \
        'bind-key ^P swap-window -d -t -1'
Sunbonnet answered 9/10, 2020 at 0:1 Comment(0)
C
2

I have this config for many years.

  • Support versions like tmux 2.4 tmux 2.4a tmux next-3.3
  • No bc command
  • Support Cygwin, macOS and Linux
# Tmux version before 2.4
if-shell -b '[ `tmux -V | cut -d" " -f2 | tr -d " |\-|.|[:alpha:]"` -lt 24 ]' \
  'bind-key -t vi-copy v begin-selection; \
    bind-key -t vi-copy Q cancel; \
    bind-key -t vi-copy Enter cancel'

# Tmux version 2.4 onwards
if-shell -b '[ `tmux -V | cut -d" " -f2 | tr -d " |\-|.|[:alpha:]"` -ge 24 ]' \
  'bind-key -T copy-mode-vi C-w   send-keys -X cancel; \
bind-key -T copy-mode-vi C-u   send-keys -X halfpage-up; \
bind-key -T copy-mode-vi C-j   send-keys -X halfpage-down; \
bind-key -T copy-mode-vi C-l   send-keys -X select-line'
Calvincalvina answered 22/4, 2021 at 4:3 Comment(0)
H
2

Newer versions of tmux support neater if conditions. The below works on tmux version 3.2a:

if-shell '[ "$(tmux -V)" = "tmux 3.2a" ]' {
    set -g status-bg red
    set -g status-fg yellow
}
Halve answered 9/1, 2022 at 12:23 Comment(0)
C
2

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

Cadence answered 22/9, 2022 at 2:41 Comment(0)
N
1

Current latest release is 2.9a, which throws off many of the direct comparisons used here.

My alternative makes use of sort -V, which is much more robust for handling version comparisons.

Edit: A commenter points out that sort -V is not available in BSD sort, for example on native OSX. However this is still an answer that accounts for versions that aren't purely numerical.

# ver >= 2.3
[ ! "$(printf "%s\n%s" "$TMUX_VERSION" "2.3" | sort -V | head -n1)" == "$TMUX_VERSION" ]' \
    "command"

# ver > 2.3
[ ! "$(printf "%s\n%s" "$TMUX_VERSION" "2.4" | sort -V | head -n1)" == "$TMUX_VERSION" ]' \
    "command"

# ver < 2.3
[ "$(printf "%s\n%s" "$TMUX_VERSION" "2.3" | sort -V | head -n1)" == "$TMUX_VERSION" ]' \
    "command"
Nesselrode answered 19/8, 2019 at 6:37 Comment(2)
careful though, sort -V does not always work, for example it does not work on macOS 10.11 which uses BSD sortTrackandfield
Drats, that's a good caveat. I usually put gnu sort on my OSX machines, so I missed that. I'll add the caveat to the answer.Nesselrode
P
0

I have combined suggested solutions to a working one (tested on tmux 1.8 and 2.7):

run-shell "tmux setenv -g TMUX_VERSION $(tmux -V | cut -c 6-)"

if-shell -b '[[ "$TMUX_VERSION" < "2.6" ]]' \
  "bind w choose-tree -u"

if-shell -b '[[ "$TMUX_VERSION" < "2.2" ]]' \
  "set -g status-utf8 on"
Pauperize answered 2/5, 2019 at 12:28 Comment(1)
your cut command isn't likely to be robust enough across different version strings. For example tmux -V at the HEAD of the repo is tmux next-3.3. tmux -V | cut -c 6- gives next-3.3. Also as others have pointed out [[ ]] test constructs are a bash feature that's not portable across systems, as the only guaranteed shell is the POSIX compliant sh.Barmen
B
0

This is not an alternative, but rather an extension to the accepted answers - (Tom Hale's answer is the most robust & complete).

For less repetition in your .tmux.conf, you can store your shell test strings in tmux env vars (available since 0.8 in 2008) & interpolate them at run-time for if-shell:

# Use which sed pattern actually works in the accepted answers
run-shell 'tmux setenv -g TMUX_VERSION $(tmux -V | sed -En "...")'

# Setup condition checks
V33_GTE='[ "$(echo "$TMUX_VERSION >= 3.3" | bc)" = 1 ]' 
V33_LT='[ "$(echo "$TMUX_VERSION < 3.3" | bc)" = 1 ]'

# So on for other versions
# ...

### Example binding
# Toggle mouse
bind m set -g mouse on  \; display 'Mouse: ON'
bind M set -g mouse off \; display 'Mouse: OFF' 

# As of 3.1 you can annotate your keybindings
# As of 3.3 you can attach a note to existing bindings without setting the binding
# If running >= 3.3 , attach a note to the binding for `list-keys -N`

if "$V33_GTE" bind -N "Enable mouse mode" m
if "$V33_GTE" bind -N "Disable mouse mode" M

Barmen answered 11/9, 2020 at 2:3 Comment(2)
set -g mouse (without on or off) toggles all by itself. Try this: bind-key c-M set-option -g mouse \; display-message 'Mouse #{?mouse,on,off}'Racoon
I can change the answer to reflect that different approach, but it's not relevant to the answer, it's an example of a binding that's conditional on an if-shell statement that evaluates an interpolated statement.Barmen
O
0

tmux 3.0a

# execute a tmux command if a shell-command succeeded
# if-shell '[[ -z "$SSH_CLIENT" ]]' \     # use test or [ , instead of [[
# if-shell "[ $HOST == 'redmi14-leo' ]"   # can't work don't know why

if-shell '[[ -z "$SSH_CLIENT" ]]' \
    'source-file ~/.tmux.remote.conf'
Ovum answered 31/12, 2021 at 2:12 Comment(1)
Comparison operator in sh is just =, not ==Furnish
B
0

Another option is to use set -gq (c.f. FAQ) to set options silently. If they are not available in older versions of tmux, they will just be silently ignored.

For example, this is one way to set the newly added allow-passthrough option, without erroring out in tmux versions prior to 3.3a.

Beguine answered 26/12, 2022 at 16:59 Comment(0)
S
0

If you want to check split-window in different tmux version to solve https://github.com/christoomey/dotfiles/issues/127

try

run-shell 'tmux setenv -g TMUX_VERSION $(tmux -V | \
                           sed -En "s/^tmux[^0-9]*([.0-9]+).*/\1/p")'

# split panes using \ and -
# https://github.com/christoomey/dotfiles/issues/127
if-shell -b '[ "$(echo "$TMUX_VERSION >= 3.0" | bc)" = 1 ]' \
    "bind \\\\ split-window -h -c '#{pane_current_path}'; \
"

if-shell -b '[ "$(echo "$TMUX_VERSION < 3.0" | bc)" = 1 ]' \
    "bind \\ split-window -h -c '#{pane_current_path}'; \
"

if-shell will re-escape \, so you need \\\\

reason: https://github.com/tmux/tmux/issues/1827#issuecomment-508985729

Stirpiculture answered 22/3 at 3:49 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.