Way to ignore this script if not on OS X? #8

Closed
tylerball opened this Issue Feb 21, 2012 · 29 comments

Comments

Projects
None yet
@tylerball

I like to keep my ~/.tmux.conf consistent across OS X and Linux. Currently the script is not present on my Linux machines and so tmux crashes if the reattach-to-user-namespace command is added. Are you aware of any solution to this problem?

@ChrisJohnsen

This comment has been minimized.

Show comment
Hide comment
@ChrisJohnsen

ChrisJohnsen Feb 22, 2012

Owner

Here are two alternatives that should work:

Conditional Configuration

Use the if-shell command of tmux to conditionally include the OS X–specific bits of configuration.

Update: There is a race condition inherent in using if-shell to make configuration changes. See my later comment.

Update (much later): The race condition that I described was fixed in tmux 1.9, so this kind of conditional configuration works fine there.

In a new ~/.tmux-osx.conf file:

set-option -g default-command "reattach-to-user-namespace -l zsh"

Use whatever bit of configuration you have been using on OS X: include the path to the wrapper if it is not normally in your PATH, and/or specify a different (path to the) shell.

Then, in your main ~/.tmux.conf file, remove the references to reattach-to-user-namespace (i.e. the bits of configuration moved to the new file described above) and include this line instead:

if-shell 'test "$(uname)" = "Darwin"' 'source ~/.tmux-osx.conf'

Actually, if you can arrange to not have the ~/.tmux-osx.conf file present at all on your non–OS X systems, then you can probably get away without the if-shell, just use source ~/.tmux-osx.conf; tmux seems to ignore missing files (though this could reasonably change in future versions of tmux).

Provide reattach-to-user-namespace as a Script

Drop a Bash script named reattach-to-user-namespace into a directory in the PATH on your non–OS X systems:

#!/bin/bash
# For non-OS X systems, a placeholder for the program from
# https://github.com/ChrisJohnsen/tmux-MacOSX-pasteboard
exec "$@"

(Be sure to chmod +x the file.)

Owner

ChrisJohnsen commented Feb 22, 2012

Here are two alternatives that should work:

Conditional Configuration

Use the if-shell command of tmux to conditionally include the OS X–specific bits of configuration.

Update: There is a race condition inherent in using if-shell to make configuration changes. See my later comment.

Update (much later): The race condition that I described was fixed in tmux 1.9, so this kind of conditional configuration works fine there.

In a new ~/.tmux-osx.conf file:

set-option -g default-command "reattach-to-user-namespace -l zsh"

Use whatever bit of configuration you have been using on OS X: include the path to the wrapper if it is not normally in your PATH, and/or specify a different (path to the) shell.

Then, in your main ~/.tmux.conf file, remove the references to reattach-to-user-namespace (i.e. the bits of configuration moved to the new file described above) and include this line instead:

if-shell 'test "$(uname)" = "Darwin"' 'source ~/.tmux-osx.conf'

Actually, if you can arrange to not have the ~/.tmux-osx.conf file present at all on your non–OS X systems, then you can probably get away without the if-shell, just use source ~/.tmux-osx.conf; tmux seems to ignore missing files (though this could reasonably change in future versions of tmux).

Provide reattach-to-user-namespace as a Script

Drop a Bash script named reattach-to-user-namespace into a directory in the PATH on your non–OS X systems:

#!/bin/bash
# For non-OS X systems, a placeholder for the program from
# https://github.com/ChrisJohnsen/tmux-MacOSX-pasteboard
exec "$@"

(Be sure to chmod +x the file.)

@tylerball

This comment has been minimized.

Show comment
Hide comment
@tylerball

tylerball Feb 22, 2012

Thanks a lot, the first option worked perfect for me.

Thanks a lot, the first option worked perfect for me.

@tylerball tylerball closed this Feb 22, 2012

@ChrisJohnsen

This comment has been minimized.

Show comment
Hide comment
@ChrisJohnsen

ChrisJohnsen Feb 23, 2012

Owner

I have noticed that there is a race condition when using if-shell to make configuration changes. tmux runs the shell command (and the resulting tmux command) “in the background”. This means that the rest of the startup process proceeds while the platform check (et cetera) happens.

It is entirely possible that tmux will create the first pane (possibly several panes/windows/sessions if you use split-window/new-window/new-session in your .tmux.conf) before the conditional is evaluated and/or before the default-command option is assigned its desired value.

Workarounds

As described in my earlier reply, you could use the unconditional source-file ~/.tmux-osx.conf technique (where ~/.tmux-osx.conf is missing on non–OS X systems) or arrange for the “dummy” wrapper on non–OS X systems. Unfortunately, both of these alternatives prevent you from keeping a full set of identical sets of files in your home directory on both kinds of systems (assuming you put the dummy wrapper in ~/bin or similar).

Here is yet another method:

  1. Use this ~/.tmux-osx.conf:

    source-file ~/.tmux.conf
    set-option -g default-command "reattach-to-user-namespace -l zsh"
    
  2. Eliminate any mentions of ~/.tmux-osx.conf or reattach-to-user-namespace from your ~/.tmux.conf.

  3. In a directory early in your PATH (e.g. $HOME/bin) make a tmux script:

    #!/bin/sh
    unset cfg
    test "$(uname)" = "Darwin" && cfg=$HOME/.tmux-osx.conf
    exec /path/to/actual/tmux ${cfg+-f "$cfg"} "$@"
    

Instead of the last step, you could arrange to conditionally define an alias for your shell that does something similar. Personally, I like the script better since it will work correctly from any process that does an exec(2)-family syscall as long as you have preconfigured the PATH environment variable.

Owner

ChrisJohnsen commented Feb 23, 2012

I have noticed that there is a race condition when using if-shell to make configuration changes. tmux runs the shell command (and the resulting tmux command) “in the background”. This means that the rest of the startup process proceeds while the platform check (et cetera) happens.

It is entirely possible that tmux will create the first pane (possibly several panes/windows/sessions if you use split-window/new-window/new-session in your .tmux.conf) before the conditional is evaluated and/or before the default-command option is assigned its desired value.

Workarounds

As described in my earlier reply, you could use the unconditional source-file ~/.tmux-osx.conf technique (where ~/.tmux-osx.conf is missing on non–OS X systems) or arrange for the “dummy” wrapper on non–OS X systems. Unfortunately, both of these alternatives prevent you from keeping a full set of identical sets of files in your home directory on both kinds of systems (assuming you put the dummy wrapper in ~/bin or similar).

Here is yet another method:

  1. Use this ~/.tmux-osx.conf:

    source-file ~/.tmux.conf
    set-option -g default-command "reattach-to-user-namespace -l zsh"
    
  2. Eliminate any mentions of ~/.tmux-osx.conf or reattach-to-user-namespace from your ~/.tmux.conf.

  3. In a directory early in your PATH (e.g. $HOME/bin) make a tmux script:

    #!/bin/sh
    unset cfg
    test "$(uname)" = "Darwin" && cfg=$HOME/.tmux-osx.conf
    exec /path/to/actual/tmux ${cfg+-f "$cfg"} "$@"
    

Instead of the last step, you could arrange to conditionally define an alias for your shell that does something similar. Personally, I like the script better since it will work correctly from any process that does an exec(2)-family syscall as long as you have preconfigured the PATH environment variable.

@tylerball

This comment has been minimized.

Show comment
Hide comment
@tylerball

tylerball Feb 23, 2012

I don't have tmux set up a default set of panes or anything on startup, I use teamocil for that, so I think I can stick with that solution for now. Having different files on different OSes makes it hard to keep a consistent set of dotfiles.

Creating a simple bash/zsh alias does indeed work.

if [[ "$(uname)" = "Darwin" ]]; then
    alias tmux='tmux -2 -f ~/.tmux-osx.conf'
else
    alias tmux='tmux -2'
fi

But yeah, that script is nicer.

I don't have tmux set up a default set of panes or anything on startup, I use teamocil for that, so I think I can stick with that solution for now. Having different files on different OSes makes it hard to keep a consistent set of dotfiles.

Creating a simple bash/zsh alias does indeed work.

if [[ "$(uname)" = "Darwin" ]]; then
    alias tmux='tmux -2 -f ~/.tmux-osx.conf'
else
    alias tmux='tmux -2'
fi

But yeah, that script is nicer.

@ChrisJohnsen

This comment has been minimized.

Show comment
Hide comment
@ChrisJohnsen

ChrisJohnsen Feb 24, 2012

Owner

Just one clarification: The conditional-configuration-via-if-shell race condition can affect the initial window even if you are not creating multiple panes/windows/sessions in your ~/.tmux.conf.

The “possibly several panes/windows/sessions” parenthetical in my previous comment was meant to indicate that more than just the initial window could be affected, not to imply that you would only be affected if you were creating extra panes/windows in the configuration file.

I have not used teamocil, but (after a cursory look at the code) it seems like you could end up reusing the initial window if you use the --here option, or if you later switch back to the initial window after loading your teamocil-based window/pane arrangement.

teamocil is probably slow enough to start that the proposed if-shell-based conditional configuration should be in place by the time it creates any new panes/windows. However, due to the race condition, the shell in the initial window (whether reused via --here or left in place and later manually reused) may not always have been started under the reattach-to-user-namespace wrapper.

Anyway, this all applies only to the if-shell-based conditional configuration. If you use the previously described tmux wrapper script (or your alias variation) you will not be subject to this race condition that could affect “early” panes/windows.


tmux does an implicit new-session if you run tmux without any command arguments when starting the server.

Not that I expect teamocil to be particularly slow, just that starting its Ruby instance and evaluating its code is probably much slower than starting a shell, evaluating the condition, and tmux finishing its source-file command.

Owner

ChrisJohnsen commented Feb 24, 2012

Just one clarification: The conditional-configuration-via-if-shell race condition can affect the initial window even if you are not creating multiple panes/windows/sessions in your ~/.tmux.conf.

The “possibly several panes/windows/sessions” parenthetical in my previous comment was meant to indicate that more than just the initial window could be affected, not to imply that you would only be affected if you were creating extra panes/windows in the configuration file.

I have not used teamocil, but (after a cursory look at the code) it seems like you could end up reusing the initial window if you use the --here option, or if you later switch back to the initial window after loading your teamocil-based window/pane arrangement.

teamocil is probably slow enough to start that the proposed if-shell-based conditional configuration should be in place by the time it creates any new panes/windows. However, due to the race condition, the shell in the initial window (whether reused via --here or left in place and later manually reused) may not always have been started under the reattach-to-user-namespace wrapper.

Anyway, this all applies only to the if-shell-based conditional configuration. If you use the previously described tmux wrapper script (or your alias variation) you will not be subject to this race condition that could affect “early” panes/windows.


tmux does an implicit new-session if you run tmux without any command arguments when starting the server.

Not that I expect teamocil to be particularly slow, just that starting its Ruby instance and evaluating its code is probably much slower than starting a shell, evaluating the condition, and tmux finishing its source-file command.

@AnthonyDiSanti

This comment has been minimized.

Show comment
Hide comment
@AnthonyDiSanti

AnthonyDiSanti Oct 18, 2012

I sync my tmux.conf down via a dot files repo and then symlink it into my home directory, so I was looking for an option that would be portable but wouldn't require any manual setup on non-osx machines. For that reason, I opted for your "Provide reattach-to-user-namespace as a Script" option. However, I use the script on all systems and embed the logic for determining the system there. I create another script in my path (in this case a directory that comes down with my dot files repo) called reattach-to-user-namespace-tmux:

#!/usr/bin/env bash

if [[ "$(uname)" = "Darwin" ]]; then
  reattach-to-user-namespace $@
else
  exec "$@"
fi

And then I change the command in my tmux.conf to:

set-option -g default-command 'reattach-to-user-namespace-tmux -l "$SHELL"'

Works like a charm! Thanks for all the time you put into addressing this issue.

I sync my tmux.conf down via a dot files repo and then symlink it into my home directory, so I was looking for an option that would be portable but wouldn't require any manual setup on non-osx machines. For that reason, I opted for your "Provide reattach-to-user-namespace as a Script" option. However, I use the script on all systems and embed the logic for determining the system there. I create another script in my path (in this case a directory that comes down with my dot files repo) called reattach-to-user-namespace-tmux:

#!/usr/bin/env bash

if [[ "$(uname)" = "Darwin" ]]; then
  reattach-to-user-namespace $@
else
  exec "$@"
fi

And then I change the command in my tmux.conf to:

set-option -g default-command 'reattach-to-user-namespace-tmux -l "$SHELL"'

Works like a charm! Thanks for all the time you put into addressing this issue.

@simonszu

This comment has been minimized.

Show comment
Hide comment
@simonszu

simonszu Nov 13, 2012

What about copying text out of tmux? As the internet considers, i have a key binding called bind y run "tmux save-buffer - | reattach-to-user-namespace pbcopy" What about keeping this .tmux.conf synchronized between my linux and mac os machines?

What about copying text out of tmux? As the internet considers, i have a key binding called bind y run "tmux save-buffer - | reattach-to-user-namespace pbcopy" What about keeping this .tmux.conf synchronized between my linux and mac os machines?

@AnthonyDiSanti

This comment has been minimized.

Show comment
Hide comment
@AnthonyDiSanti

AnthonyDiSanti Nov 13, 2012

I use the same binding for copy. What I've been meaning to get around to is creating a pbcopy script that will dispatch to the remote clipboard utility or just silently fail on systems where that utility doesn't exist.

Currently, I just deal with not having tmux's copy functionality on non-osx machines. As a workaround, I use the local system clipboard (in iTerm2 hold option, then click and drag to do a standard selection then hit command+c to copy to your local box's clipboard).

I use the same binding for copy. What I've been meaning to get around to is creating a pbcopy script that will dispatch to the remote clipboard utility or just silently fail on systems where that utility doesn't exist.

Currently, I just deal with not having tmux's copy functionality on non-osx machines. As a workaround, I use the local system clipboard (in iTerm2 hold option, then click and drag to do a standard selection then hit command+c to copy to your local box's clipboard).

@simonszu

This comment has been minimized.

Show comment
Hide comment
@simonszu

simonszu Nov 13, 2012

Yes, this would be the deal for me too. But this will fail when i want to copy text which extends out of my iTerm window and i have to use the tmux copy mode. :(

Yes, this would be the deal for me too. But this will fail when i want to copy text which extends out of my iTerm window and i have to use the tmux copy mode. :(

@AnthonyDiSanti

This comment has been minimized.

Show comment
Hide comment
@AnthonyDiSanti

AnthonyDiSanti Nov 13, 2012

Yeah, it's not a good solution. I'm assuming you're talking about when you have multiple panes in a single window (like vim's windows in a tab). You can break-pane for a minute and then join-pane it back in. If it's a common enough procedure for you, you could implement these "maximize a pane" bindings (in the second answer):

http://superuser.com/questions/238702/maximizing-a-pane-in-tmux

I haven't done this myself, so ymmv

Yeah, it's not a good solution. I'm assuming you're talking about when you have multiple panes in a single window (like vim's windows in a tab). You can break-pane for a minute and then join-pane it back in. If it's a common enough procedure for you, you could implement these "maximize a pane" bindings (in the second answer):

http://superuser.com/questions/238702/maximizing-a-pane-in-tmux

I haven't done this myself, so ymmv

@ChrisJohnsen

This comment has been minimized.

Show comment
Hide comment
@ChrisJohnsen

ChrisJohnsen Nov 13, 2012

Owner

@simonszu, below is an example of a script similar to the one that @AnthonyDiSanti described (though someone else will need to fill in the non–OS X bits). If you can deploy it to all your platforms under the same name, then you can use it in your binding and have an identical .tmux.conf (and script) on all your systems.

For example:

#!/bin/sh

# tmux-osdep-copy-buffer
#  Use an OS-dependent method to place the contents of the current
#  tmux paste buffer into the "system clipboard".

#exec 2>&1 # helpful for capturing stderr while debugging

n=${0##*/}

die() {
    # If this was run via run-shell, stdout will be captured and
    # displayed in a temporary copy-mode in the current pane.
    printf "$n"': %s\n' "$*"
    exit 1
}

case "$(uname -s)" in
Darwin)
    # If reattach-to-user-namespace is not in your PATH, you may
    # set the RATUNS environment variable (e.g. before your start
    # your tmux server, or in your .tmux.conf file).
    tmux save-buffer - | "${RATUNS:-reattach-to-user-namespace}" pbcopy ||
        die 'unable to use pbcopy'
    ;;
#Linux|*BSD|SunOS)
#    # Check for DISPLAY and xsel/xclip, and use them (or whatever is appropriate).
#    ;;
*) 
    die 'unknown platform'
    ;;
esac
Owner

ChrisJohnsen commented Nov 13, 2012

@simonszu, below is an example of a script similar to the one that @AnthonyDiSanti described (though someone else will need to fill in the non–OS X bits). If you can deploy it to all your platforms under the same name, then you can use it in your binding and have an identical .tmux.conf (and script) on all your systems.

For example:

#!/bin/sh

# tmux-osdep-copy-buffer
#  Use an OS-dependent method to place the contents of the current
#  tmux paste buffer into the "system clipboard".

#exec 2>&1 # helpful for capturing stderr while debugging

n=${0##*/}

die() {
    # If this was run via run-shell, stdout will be captured and
    # displayed in a temporary copy-mode in the current pane.
    printf "$n"': %s\n' "$*"
    exit 1
}

case "$(uname -s)" in
Darwin)
    # If reattach-to-user-namespace is not in your PATH, you may
    # set the RATUNS environment variable (e.g. before your start
    # your tmux server, or in your .tmux.conf file).
    tmux save-buffer - | "${RATUNS:-reattach-to-user-namespace}" pbcopy ||
        die 'unable to use pbcopy'
    ;;
#Linux|*BSD|SunOS)
#    # Check for DISPLAY and xsel/xclip, and use them (or whatever is appropriate).
#    ;;
*) 
    die 'unknown platform'
    ;;
esac
@jeffpeterson

This comment has been minimized.

Show comment
Hide comment
@jeffpeterson

jeffpeterson Apr 11, 2013

A fairly old issue, but I stumbled across it in a Google search.
How about:

set-option -g default-command "reattach-to-user-namespace -l zsh 2> /dev/null || zsh"

A fairly old issue, but I stumbled across it in a Google search.
How about:

set-option -g default-command "reattach-to-user-namespace -l zsh 2> /dev/null || zsh"
@MarioRicalde

This comment has been minimized.

Show comment
Hide comment
@MarioRicalde

MarioRicalde Apr 14, 2013

@jeffpeterson excellent! Thanks for sharing this!

@jeffpeterson excellent! Thanks for sharing this!

@AnthonyDiSanti

This comment has been minimized.

Show comment
Hide comment
@AnthonyDiSanti

AnthonyDiSanti Apr 14, 2013

@jeffpeterson That's a very direct solution, thank you. My only concern is that waiting for a command to fail every time you open a new pane or window would slow down your general use of tmux. Have you found that to be an issue?

@jeffpeterson That's a very direct solution, thank you. My only concern is that waiting for a command to fail every time you open a new pane or window would slow down your general use of tmux. Have you found that to be an issue?

@jeffpeterson

This comment has been minimized.

Show comment
Hide comment
@jeffpeterson

jeffpeterson Apr 14, 2013

@AnthonyDiSanti It shouldn't take any longer to fail than it does to run.

@AnthonyDiSanti It shouldn't take any longer to fail than it does to run.

@gnapse

This comment has been minimized.

Show comment
Hide comment
@gnapse

gnapse Jun 17, 2013

@jeffpeterson your suggestion seemed great at first, but I've been noticing recently that many commands in my shell have been omitting some of their output.

Today I decided to find out what the reason was, and after noticing that this only happened while inside tmux, it took me little time to detect that your suggestion has the culprit. Is it just me? For instance, I get no output from wget, curl, git clone, git push, git pull. They work fine, but I get no feedback on the shell as to how they did. I'm also not getting any errors when I invoke invalid commands.

After I rolled back that change, they all started to give me the usual output. Too bad :( because this was the ideal solution!

gnapse commented Jun 17, 2013

@jeffpeterson your suggestion seemed great at first, but I've been noticing recently that many commands in my shell have been omitting some of their output.

Today I decided to find out what the reason was, and after noticing that this only happened while inside tmux, it took me little time to detect that your suggestion has the culprit. Is it just me? For instance, I get no output from wget, curl, git clone, git push, git pull. They work fine, but I get no feedback on the shell as to how they did. I'm also not getting any errors when I invoke invalid commands.

After I rolled back that change, they all started to give me the usual output. Too bad :( because this was the ideal solution!

@jeffpeterson

This comment has been minimized.

Show comment
Hide comment
@jeffpeterson

jeffpeterson Jun 17, 2013

@gnapse Yeah, I noticed the same thing soon after posting it. The missing output is because standard error is redirected to /dev/null. You can use:

set-option -g default-command "reattach-to-user-namespace -l zsh || zsh"

But, if the first zsh session doesn't exit with exit code 0, it will run the second zsh command.

@gnapse Yeah, I noticed the same thing soon after posting it. The missing output is because standard error is redirected to /dev/null. You can use:

set-option -g default-command "reattach-to-user-namespace -l zsh || zsh"

But, if the first zsh session doesn't exit with exit code 0, it will run the second zsh command.

@jimeh

This comment has been minimized.

Show comment
Hide comment
@jimeh

jimeh Aug 18, 2013

@jeffpeterson The issue with not directing STDERR to /dev/null is that you get command missing error on each new window/pane created when reattach-to-user-namespace is not available.

Personally I opted for a slight variation of @AnthonyDiSanti's solution by using a proxy-command. But instead of checking for the OS type, I simply check if the reattach-to-user-namespace command is available.

Details are here: jimeh/dotfiles@3838db8

jimeh commented Aug 18, 2013

@jeffpeterson The issue with not directing STDERR to /dev/null is that you get command missing error on each new window/pane created when reattach-to-user-namespace is not available.

Personally I opted for a slight variation of @AnthonyDiSanti's solution by using a proxy-command. But instead of checking for the OS type, I simply check if the reattach-to-user-namespace command is available.

Details are here: jimeh/dotfiles@3838db8

@gkb

This comment has been minimized.

Show comment
Hide comment
@gkb

gkb Aug 30, 2013

I'm using a script based on what @ChrisJohnsen provided earlier. It assumes that the xclip utility is present on Linux.

#!/bin/sh

#  Use an OS-dependent method to place the contents of the current
#  tmux paste buffer into the "system clipboard".

#exec 2>&1 # helpful for capturing stderr while debugging

n=${0##*/}

die() {
        # If this was run via run-shell, stdout will be captured and
        # displayed in a temporary copy-mode in the current pane.
        printf "$n"': %s\n' "$*"
        exit 1
}

case "$(uname -s)" in
Darwin)
        # If reattach-to-user-namespace is not in your PATH, you may
        # set the RATUNS environment variable (e.g. before your start
        # your tmux server, or in your .tmux.conf file).
        case "$1" in
        copy)
                tmux save-buffer - | "${RATUNS:-reattach-to-user-namespace}" pbcopy ||
                        die 'unable to use pbcopy'
                ;;
        paste)
                tmux set-buffer $(reattach-to-user-namespace pbpaste)
        tmux paste-buffer
                ;;
        *)
                die 'unknown command: must be copy or paste'
                ;;
        esac
        ;;
Linux|*BSD|SunOS)
        # Check for DISPLAY and xsel/xclip, and use them (or whatever is appropriate).
        case "$1" in
        copy)
                tmux save-buffer - | xclip -i -sel clipboard
                ;;
        paste)
                tmux set-buffer "$(xclip -o -sel clipboard)"; tmux paste-buffer
                ;;
        *)
                die 'unknown command: must be copy or paste'
        esac
        ;;
*)
        die 'unknown platform'
        ;;
esac

In my .tmux.conf file, I've included these lines.

bind C-c run "tmux-osdep-copy-buffer copy"
bind C-v run "tmux-osdep-copy-buffer paste"

This works really well for me.

gkb commented Aug 30, 2013

I'm using a script based on what @ChrisJohnsen provided earlier. It assumes that the xclip utility is present on Linux.

#!/bin/sh

#  Use an OS-dependent method to place the contents of the current
#  tmux paste buffer into the "system clipboard".

#exec 2>&1 # helpful for capturing stderr while debugging

n=${0##*/}

die() {
        # If this was run via run-shell, stdout will be captured and
        # displayed in a temporary copy-mode in the current pane.
        printf "$n"': %s\n' "$*"
        exit 1
}

case "$(uname -s)" in
Darwin)
        # If reattach-to-user-namespace is not in your PATH, you may
        # set the RATUNS environment variable (e.g. before your start
        # your tmux server, or in your .tmux.conf file).
        case "$1" in
        copy)
                tmux save-buffer - | "${RATUNS:-reattach-to-user-namespace}" pbcopy ||
                        die 'unable to use pbcopy'
                ;;
        paste)
                tmux set-buffer $(reattach-to-user-namespace pbpaste)
        tmux paste-buffer
                ;;
        *)
                die 'unknown command: must be copy or paste'
                ;;
        esac
        ;;
Linux|*BSD|SunOS)
        # Check for DISPLAY and xsel/xclip, and use them (or whatever is appropriate).
        case "$1" in
        copy)
                tmux save-buffer - | xclip -i -sel clipboard
                ;;
        paste)
                tmux set-buffer "$(xclip -o -sel clipboard)"; tmux paste-buffer
                ;;
        *)
                die 'unknown command: must be copy or paste'
        esac
        ;;
*)
        die 'unknown platform'
        ;;
esac

In my .tmux.conf file, I've included these lines.

bind C-c run "tmux-osdep-copy-buffer copy"
bind C-v run "tmux-osdep-copy-buffer paste"

This works really well for me.

@johnae

This comment has been minimized.

Show comment
Hide comment
@johnae

johnae Oct 23, 2013

I just do this:

set-option -g default-command "which reattach-to-user-namespace >/dev/null && reattach-to-user-namespace -l bash || bash"

johnae commented Oct 23, 2013

I just do this:

set-option -g default-command "which reattach-to-user-namespace >/dev/null && reattach-to-user-namespace -l bash || bash"
@trevor

This comment has been minimized.

Show comment
Hide comment
@trevor

trevor Oct 23, 2013

Contributor

@johnae nice

Contributor

trevor commented Oct 23, 2013

@johnae nice

@AnthonyDiSanti

This comment has been minimized.

Show comment
Hide comment
@AnthonyDiSanti

AnthonyDiSanti Oct 25, 2013

@johnae That's a great solution as long as your interactive sessions always exit with code 0. I'm not sure why an interactive session would ever exit with anything other than 0 unless done intentionally, so I think that's perfect.

@johnae That's a great solution as long as your interactive sessions always exit with code 0. I'm not sure why an interactive session would ever exit with anything other than 0 unless done intentionally, so I think that's perfect.

@behrangsa

This comment has been minimized.

Show comment
Hide comment
@behrangsa

behrangsa Mar 10, 2014

It should be possible to use if-shell now: http://sourceforge.net/p/tmux/tickets/65/

It should be possible to use if-shell now: http://sourceforge.net/p/tmux/tickets/65/

@ChrisJohnsen

This comment has been minimized.

Show comment
Hide comment
@ChrisJohnsen

ChrisJohnsen Mar 10, 2014

Owner

Yes, the if-shell configuration that I originally described in my first comment on this issue now works race-free in tmux 1.9:

In .tmux.conf:

if-shell 'test "$(uname)" = "Darwin"' 'source ~/.tmux-osx.conf'

In .tmux-osx.conf:

set-option -g default-command "reattach-to-user-namespace -l zsh"
Owner

ChrisJohnsen commented Mar 10, 2014

Yes, the if-shell configuration that I originally described in my first comment on this issue now works race-free in tmux 1.9:

In .tmux.conf:

if-shell 'test "$(uname)" = "Darwin"' 'source ~/.tmux-osx.conf'

In .tmux-osx.conf:

set-option -g default-command "reattach-to-user-namespace -l zsh"
@jimeh

This comment has been minimized.

Show comment
Hide comment
@jimeh

jimeh Mar 10, 2014

@ChrisJohnsen I still prefer the solution I already have in place: jimeh/dotfiles@3838db8

No extra OSX-specific config files, and backwards compatible with Tmux 1.8. It does require that you distribute your .tmux.conf along with the wrapper command though, but obviously I keep all my dotfiles in a git repo, so not really an issue me at least :)

jimeh commented Mar 10, 2014

@ChrisJohnsen I still prefer the solution I already have in place: jimeh/dotfiles@3838db8

No extra OSX-specific config files, and backwards compatible with Tmux 1.8. It does require that you distribute your .tmux.conf along with the wrapper command though, but obviously I keep all my dotfiles in a git repo, so not really an issue me at least :)

@rkrdo rkrdo referenced this issue in rkrdo/vimfiles Sep 8, 2014

Closed

tmux conf file #7

@blandinw

This comment has been minimized.

Show comment
Hide comment
@blandinw

blandinw Apr 23, 2015

To avoid having an external file, I ended up doing:

set -g default-command "which reattach-to-user-namespace 2>/dev/null && reattach-to-user-namespace -l zsh || zsh"

This seems to combine the best of both worlds, did I miss something?

To avoid having an external file, I ended up doing:

set -g default-command "which reattach-to-user-namespace 2>/dev/null && reattach-to-user-namespace -l zsh || zsh"

This seems to combine the best of both worlds, did I miss something?

@ChrisJohnsen

This comment has been minimized.

Show comment
Hide comment
@ChrisJohnsen

ChrisJohnsen Apr 23, 2015

Owner

@blandinw That is almost the same construction as one of the comments above, so it has the same minor issue. The middle part could be written as && { … ; true ; } || to avoid that issue (at least in this context, since the interactive shell’s exit code is otherwise mostly ignored anyway).

Otherwise, it is a reasonable solution. But, if all your OS X systems are running Yosemite, you may not even need the wrapper anymore: Apple seems to have integrated its own workaround so that the pasteboard remains accessible inside tmux sessions.

Owner

ChrisJohnsen commented Apr 23, 2015

@blandinw That is almost the same construction as one of the comments above, so it has the same minor issue. The middle part could be written as && { … ; true ; } || to avoid that issue (at least in this context, since the interactive shell’s exit code is otherwise mostly ignored anyway).

Otherwise, it is a reasonable solution. But, if all your OS X systems are running Yosemite, you may not even need the wrapper anymore: Apple seems to have integrated its own workaround so that the pasteboard remains accessible inside tmux sessions.

@supermarin

This comment has been minimized.

Show comment
Hide comment
@supermarin

supermarin Jan 4, 2017

There's a way that should work without if-shell with pure bash:

run '[ "$(uname)" = "Darwin" ] && tmux source ~/.tmux-osx.conf`

Writing this because I've found the solution with if-shell wasn't working for me in tmux HEAD (2.4)

supermarin commented Jan 4, 2017

There's a way that should work without if-shell with pure bash:

run '[ "$(uname)" = "Darwin" ] && tmux source ~/.tmux-osx.conf`

Writing this because I've found the solution with if-shell wasn't working for me in tmux HEAD (2.4)

XadillaX added a commit to XadillaX/tmuxrc that referenced this issue Mar 23, 2017

bboykov added a commit to bboykov/dotfiles that referenced this issue Nov 6, 2017

Fix tmux exited on linux because of clipboard
Before this fix the tmux was failing on linux system due to MacOS
specific configuration inside tmux.conf.
More information about the issue could be found here:
ChrisJohnsen/tmux-MacOSX-pasteboard#8 (comment)

Checks if reattach-to-user-namespace  existing before using it.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment