Skip to content

Instantly share code, notes, and snippets.

@Jcpetrucci
Last active June 19, 2024 21:53
Show Gist options
  • Save Jcpetrucci/78db4fd9fd68e362ddf9ff71377a5780 to your computer and use it in GitHub Desktop.
Save Jcpetrucci/78db4fd9fd68e362ddf9ff71377a5780 to your computer and use it in GitHub Desktop.

Advanced copy+paste from tmux via PuTTY

Introduction

Useful for copying text from vertically split panes in tmux, when normal "shift + clickdrag" copying spans across the vertical separator, or there are too many rows to fit into the pane. Video explanation of what this does and how it works @ https://www.youtube.com/watch?v=kEIpE2XpDdY

The solution

  1. In server-side tmux.conf, add:

     # Send the tmux copy buffer to a file. The file is read for ANSI printing by "t" alias in .bashrc
     bind -t vi-copy y copy-pipe 'cat > ~/.tmux-buffer' 
    
  2. In server-side .bashrc, add:

    t() {
      # Configure a PuTTY profile to send "t" as the "Remote command". This function will automatically reattach to an existing tmux session if one exists, or start a new one. This function also repeatedly sends our homemade tmux clipboard back to the PuTTY client in the form of an ANSI printer escape sequence. The contents of the homemade clipboard are populated by `bind -t vi-copy y copy-pipe 'cat > ~/.tmux-buffer'` in tmux.conf. It is expected that the PuTTY client will be configured to print to a "Microsoft XPS Document Writer" which saves the printer output to a file. The file is subsequently read by an AutoHotkey macro, and the contents are made available for paste.
      [[ "$TERM" == "xterm" ]] || return 0 # This prevents recursive runs, in case t() is called after tmux is started.
      { while :; do tput mc5; cat ~/.tmux-buffer; tput mc4; sleep 5; done } &
      tmux attach || tmux
    }
  3. On client-side (Microsoft Windows), create new printer:

  4. Add a Printer

  5. Create a new port > Local Port

  6. Enter a port name > "PuTTY_Printer_File"

  7. Driver > Microsoft XPS Document Writer

  8. Printer name > "PuTTY Printer"

  9. Optional: Print a test page and make sure it shows up in contents of file @ "%USERPROFILE%\Documents\PuTTY_Printer_File"

  10. In client-side PuTTY configuration:

  11. Set Terminal > "Printer to send ANSI printer output to:" to newly created printer named "PuTTY Printer"

  12. Set Connection > SSH > "Remote command:" to "t" (referencing the .bashrc function above)

  13. In client-side AutoHotkey configuration, create a macro to read contents from %USERPROFILE%\Documents\PuTTY_Printer_File and output it to your clipboard:

    ;### Get contents of PuTTY ANSI printer device output and paste it
    #v:: ;Winkey + v
    FileRead, Clipboard, %USERPROFILE%\Documents\PuTTY_Printer_File
    return
    
  14. Usage:

  15. Connect to host with PuTTY and get dropped into tmux by t() function.

  16. When ready to select text for copy, use tmux hotkey for copy-mode ( Ctrl + b, [ )

  17. Move cursor with arrow keys

  18. Begin selection with spacebar

  19. End selection and copy it with "y"

  20. Back on client-side running PuTTY, WindowsKey + v will paste the selection

@suprematis
Copy link

Great workaround. Thoroughly explained. I will report back once I have it up and running.

@gbajson
Copy link

gbajson commented Sep 22, 2021

After adding line from [0] my tmux complaint's with:

/home/gbajson/.tmux.conf:23: usage: bind-key [-cnr] [-T key-table] key command [arguments]

I have tmux 3.0a.

I set up the following binding instead, but it doesn't support selecting with mouse:

bind -T copy-mode-vi y send-keys -X copy-pipe-and-cancel 'cat > ~/.tmux-buffer'

@shiqf
Copy link

shiqf commented Jun 8, 2022

thanks, it's work!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment