-
-
Save mikeboiko/b6e50210b4fb351b036f1103ea3c18a9 to your computer and use it in GitHub Desktop.
set-hook -g client-attached 'run-shell /bin/update_display.sh' |
#!/usr/bin/env bash | |
# The problem: | |
# When you `ssh -X` into a machine and attach to an existing tmux session, the session | |
# contains the old $DISPLAY env variable. In order the x-server/client to work properly, | |
# you have to update $DISPLAY after connection. For example, the old $DISPLAY=:0 and | |
# you need to change to DISPLAY=localhost:10.0 for the ssh session to | |
# perform x-forwarding properly. | |
# The solution: | |
# When attaching to tmux session, update $DISPLAY for each tmux pane in that session | |
# This is performed by using tmux send-keys to the shell. | |
# This script handles updating $DISPLAY within vim also | |
NEW_DISPLAY=$DISPLAY | |
# NEW_DISPLAY=$(tmux show-env | sed -n 's/^DISPLAY=//p') | |
# Update $DISPLAY in bash, zsh and vim/nvim | |
tmux list-panes -s -F "#{session_name}:#{window_index}.#{pane_index} #{pane_current_command}" | \ | |
while read pane_process | |
do | |
IFS=' ' read -ra pane_process <<< "$pane_process" | |
if [[ "${pane_process[1]}" == "zsh" || "${pane_process[1]}" == "bash" ]]; then | |
tmux send-keys -t ${pane_process[0]} "export DISPLAY=$NEW_DISPLAY" Enter | |
elif [[ "${pane_process[1]}" == *"vi"* ]]; then | |
tmux send-keys -t ${pane_process[0]} Escape | |
tmux send-keys -t ${pane_process[0]} ":let \$DISPLAY = \"$NEW_DISPLAY\"" Enter | |
tmux send-keys -t ${pane_process[0]} ":silent! xrestore" Enter | |
fi | |
done |
@mikeboiko : I found VcXsrv works the best.
Take a look at my zsh/vim/tmux setup in my linux_config repo. You can customize linux_config. My personal customizations are in the linux_config_custom repo. Here is my Vim clipboard configuration:
https://github.com/rjmccabe3701/linux_config_custom/blob/master/dot_files/myvimrc#L5-L44
I also have clipboard integration with tmux. In a perfect world the tmux-yank plugin would do this, but it doesn't seem to work for me. So I run this tmux_fixups.sh script.
@rjmccabe3701, thanks for sharing your config.
I saw that you're using neovim, while I'm using 8.2. After doing some more research, I ended up finding https://gist.github.com/antonkratz/ebfcefdb5fdf266631e4985d65535322#solution-2
It seems that vim doesn't automatically restore x-connections once they are dropped. You have to run :xrestore
. I haven't done any thorough testing on neovim, but judging from your rc and the fact that the xrestore
command doesn't exist, it seems this is done automatically.
I'm glad to get the vim portion of this script finally working!
Neat script, thanks for sharing!
The command set-hook -g client-attached 'run-shell /bin/update_display.sh'
was ignored by tmux in my case, but changing it to set-hook -g client-attached 'run-shell "sh /bin/update_display.sh"'
made it work.
Neat script, thanks for sharing!
The command
set-hook -g client-attached 'run-shell /bin/update_display.sh'
was ignored by tmux in my case, but changing it toset-hook -g client-attached 'run-shell "sh /bin/update_display.sh"'
made it work.
No problem!
Was update_display.sh
executable? Perhaps running sudo chmod +x update_display.sh
would have fixed it too. Either way, glad it works for you :)
You're right, that makes sense. Just double checked and this works also. Thanks for pointing that out.
hi mikeboiko. I have the same trouble with you. Thx for shaing! But it doesn't work for me. I add "echo $NEW_DISPLAY > ~/1.log" in update_display.sh to debug it. The file 1.log created by update_display.sh is blank or with a blank line. It seems that tmux command in update_display.sh means nothing in run-shell env. I found other command in linux works, for example, "ls ./" can echo to 1.log normally
Probably related to the shell that tmux is using.
Try running which tmux
in your regular shell.
Mine outputs: /usr/bin/tmux
.
You could hard-code this path in update_display.sh
hi mikeboiko, you're right, my tmux is in my $HOME path. It does not work, although i add it to $PATH. As you've said, it works when I use the abs path. Thank you.
But I found a small bug: when i detach tmux from a foreground vim, and i attach tmux session again, the vim will xrestore the right $DISPLAY. After quit vim, the bash terminal would not update $DISPLAY automatically
@qjzh0603, glad you got it working.
You're right, I experience the same annoyance. There isn't a good automated solution to this problem that I know of, so I just created an alias to update my display manually after I quit vim:
alias ud='export DISPLAY="`tmux show-env | sed -n \"s/^DISPLAY=//p\"`"'
Thanks for the script!. BTW: I added hook to session switching:
set-hook -g client-session-changed 'run-shell /bin/update_display.sh'
It works. However, DISPLAY is updated every time I switch session event if it's not necessary. Tried to guard the update script with
if [[ $NEW_DISPLAY != $DISPLAY ]]; then
It seems that this condition always satisfies even if DISPLAY really needs update. $DISPLAY
gives the value of the shell before attaching to tmux session. So the condition is matched.
Thanks for the script!. BTW: I added hook to session switching:
set-hook -g client-session-changed 'run-shell /bin/update_display.sh'
It works. However, DISPLAY is updated every time I switch session event if it's not necessary. Tried to guard the update script withif [[ $NEW_DISPLAY != $DISPLAY ]]; then
It seems that this condition always satisfies even if DISPLAY really needs update.$DISPLAY
gives the value of the shell before attaching to tmux session. So the condition is matched.
@robertbu, I like it! I have updated my script with this logic.
@robertbu, actually that new logic didn't work. When update-display.sh
evaluated $DISPLAY, it was already seeing the new DISPLAY value.
In fact, I simplified the script to use: NEW_DISPLAY=$DISPLAY
I'm not sure if you had to do anything else to make this conditional logic work on your side. Would love to get it working too.
Thanks for this. I made a version which updates WAYLAND_DISPLAY based on this: https://github.com/graham33/scripts/blob/master/update_wayland_display.sh. It's just a search and replace on your script, ideally it would be great to have one script that handled both, or maybe any env var in the tmux update-environment
list.
@rjmccabe3701, I like your additions to it!
Question for you about the vim part of it. I also attempted to do a very similar thing for vim, but neither my method or your method yielded the results I was looking for. The main reason I wanted to get the x-server working properly on tmux sessions was to get clipboard sharing between remote ssh sessions and my local machine.
When I simply set DISPLAY from within vim, my vim still uses a different clipboard from my main system. I still seem to have to exit vim and update DISPLAY in my shell in order to fix the vim clipboard.
Does vim behave in the same way for you?