DEV Community

Igor Irianto
Igor Irianto

Posted on

The Easy Way to Copy Text in Tmux

How to Easily Copy Texts in Tmux

If you've used tmux for a while, you will realize that highlighting a text with a mouse in tmux to copy them is a painful experience. That's because it's now how tmux is designed. Having used text editing softwares like Microsoft Word / Google Docs and to some extent, Atom / VSCode / IntelliJ, it may feel natural to grab your mouse, highlight the body of texts, and press Ctrl + C.

Not so with tmux. Copying with tmux is more like copying in Vim, where it's best done with a keyboard rather than a mouse. This is done in tmux copy mode. In this article, I will show you how to utilize tmux copy mode to easily copy text.

Vi Copy Mode

Tmux is similar to vim in many ways. One of them is that they are modal programs. What that means is that to accomplish a specific task, you need to switch to a mode that's optimized for that task. In Vim, we have a normal mode where you can move around with your keyboard. Vim's normal mode is designed for moving (and to a certain extent, modifying) within your file. If you need to insert texts, you need to switch to vim insert mode.

To navigate your terminal history and to copy text, you need to switch to tmux copy mode (technically it is vi-copy-mode, but to keep it simple, let's call it copy mode).

So what exactly is a copy mode?

If you try to copy a text from a tmux window with your mouse, you may have seen a warning saying that you can't simply copy the text. The correct way to copy a text from tmux is to first switch to copy mode, then copy it, then paste it.

To enable this copy mode, in you tmux config file, add:

setw -g mode-keys vi
Enter fullscreen mode Exit fullscreen mode

Then save and source the tmux config. This will enable vi mode-keys. If you are unsure about tmux config, check out my previous article on tmux config.

To enter the copy mode, use Ctrl + [. You should be able to see a yellow visual indicator on the top right of your tmux window. With this, you can now move around using vim navigation keys.

Although tmux copy mode doesn't translate to 100% vim navigation keys - overall they are good enough to feel natural. Some navigation keys that you can use:

  • h / j / k / l to move left/down/up/right
  • w / W / e / E / b / B to move forward to the start / to the end / backward a word or WORD
  • { / } to move backward / forward a paragraph
  • Ctrl + e / d / f to scroll down a line / half screen / whole screen
  • Ctrl + y / u / b to scroll up a line / half screen / whole screen
  • / / ? to search forward / backward
  • n / N to repeat the previous search forward / backward
  • etc

There are a lot more navigation keys. Check out inside man tmux and search for the mode-keys keyword.

In this mode, you can move around the terminal like you move around vim. To exit this mode, press q or Enter.

To begin highlighting, press Space. Note that your cursor will highlight the letter under it. It will expand the highlight as you move around your cursor.

Once you highlight all the text you want to copy, press Enter. You should automatically exit the copy mode. The text that you copied are stored inside a tmux buffer. It is an allocated space in the memory where tmux temporarily stores data.

To paste from the tmux buffer, press Ctrl + ]. Woot! Congratulations, you've copied a text with tmux - stress-free!

To recap:

  • Add setw -g mode-keys vi in your tmux config
  • Ctrl + [ to enter tmux vi copy mode
  • Move around with vim navigation keys
  • Begin highlight with Space
  • Copy with Enter
  • Paste with Ctrl + ]

Making Copy-Paste More Intuitive

I find a number of the copy-pasting keys unintuitive. Let's modify them to mimic vim keybindings.

Recall that vim has a visual mode (v) that allows you to highlight a body of text. You can also "yank" text with y. Finally, you can paste the yanked text with p or P.

Let's use similar keymaps. Add these lines in the tmux config:

bind -T copy-mode-vi v send -X begin-selection
bind -T copy-mode-vi y send-keys -X copy-pipe-and-cancel "pbcopy"
bind P paste-buffer
bind -T copy-mode-vi MouseDragEnd1Pane send-keys -X copy-pipe-and-cancel "pbcopy"
Enter fullscreen mode Exit fullscreen mode

The first line, bind -T copy-mode-vi v send -X begin-selection, lets you begin selection (highlight) by pressing v while in copy mode (copy-mode-vi). The second line allows you to yank the text with y. The third line allows us to paste from the tmux buffer (where our text is saved) with Ctrl + P. The last line is a bonus. It lets you copy the text that you highlight with the mouse (note that it has the same effect as the second line).

Notice that on the second and fourth line, I use pbcopy. I need to use it to pipe the copied text into the clipboard on my Mac. If you're on linux, omit pbcopy:

bind-key -T copy-mode-vi y send -X copy-selection-and-cancel
bind-key -T copy-mode-vi MouseDragEnd1Pane send-keys -X copy-pipe-and-cancel
Enter fullscreen mode Exit fullscreen mode

As always, don't forget to save and source the config file. With this new setting, the workflow is:

  1. Enter the copy-mode with Ctrl + [
  2. Position yourself to the start of the text you want to copy with vim navigation
  3. Start highlight with v (similar to vim visual mode)
  4. Yank the highlighted text with y
  5. Paste with Prefix + P

I use an uppercase P instead of lowercase p because Prefix + p is how tmux goes to the previous window (recall: Prefix + p to go to the previous window and Prefix + n to go to the next window. If you are not familiar with this, I'd highly recommend you to read my first tmux article).

Taking Advantage of the Vi Mode

The vi-copy-mode is not only useful for copying texts. You can use it to quickly search through your terminal.

For example, in the terminal, if you are looking for a text, you would press Cmd + f (or Ctrl + f) and type in the string that you want to search. This method has limitations. First, you can only search for that exact string (what if instead of searching for the string "mux", you want to search for "mux", "mix", and "max" simultaneously?). Second, if you have multiple panes in a window, this method will search for the text in all panes (what if you need to constrain your search only to the current pane?). Third, it is limited to what is currently displayed on tmux at the moment. Due to the nature of tmux's scrolling, it can't search for texts that are above the displayed window.

A better way to search is to leverage the vi-copy-mode. Recall that in Vim, you can search forward with / and backward with ?. With vi mode, you can do that too.

Suppose that I need to search for "redis_1" in my terminal. Here's how I would do it.

From inside a tmux session, enter the vi mode:

Prefix + [
Enter fullscreen mode Exit fullscreen mode

Then search backward with:

? + KEYWORD
Enter fullscreen mode Exit fullscreen mode

In this case, KEYWORD is "redis_1". I find myself using ? much more than /, because 80% of the time I would be searching backwards. Tmux should highlight all "redis_1" texts. To keep jumping to the subsequent or preceding matches, use either n or N. Sweet!

But wait, there's more! Just like you can use regular expressions in Vim while searching, you can with tmux too!

Suppose that I want to search for words like "redis_1" OR "node_1", OR "rails_1", I can search for all of them with [a-z]+_1:

? + [a-z]+_1
Enter fullscreen mode Exit fullscreen mode

Regex breakdown:

  • [a-z] is the lowercase a-z
  • + means one or more subsequent characters (which was a-z). [a-z]+ means one or more any lowercase alphabet character
  • _1 is a literal underscore followed by a literal one.

This will match "redis_1", "node_1", and "rails_1" (it will also match strings like "java_1", "sidekiq_1", etc.

If you want to match ONLY "redis_1", "node_1", or "rails_1", you can use a group match:

? + (redis|node|rails)_1
Enter fullscreen mode Exit fullscreen mode

Pretty cool! I won't go through regex here because it's outside the scope of this article. The point is, searching in tmux using vi mode is a powerful tool especially if you're proficient with regex (even if you don't, you can get pretty far with just a little regex knowledge).

Emacs Copy Mode

If you look at the man tmux page, in addition to the vi-copy-mode, tmux also has an emacs-copy mode. It is similar to vi-copy-mode, but instead of using vi key bindings, it uses emacs key bindings.

If you're more of an emacs guy (don't worry, we can still be friends) and want to set it up to use emacs keybindings instead, check out inside the man tmux page under mode-keys section. There you will find instructions on how to set it up, including a list of keymaps.

Conclusion

In this article, we learned how to leverage the copy mode to make it easier to copy-paste from your tmux terminal. We also learned how to configure it to mimic vim copy-pasting behavior. This copy mode can be leveraged to be an effective search tool.

Tmux is a powerful tool. It complements with vim well. To make it even more powerful, you can configure it to behave like vim behaves.

Happy hacking!

Top comments (5)

Collapse
 
pbnj profile image
Peter Benjamin (they/them)

I have not experienced any problems selecting and copying text in tmux with a mouse after setting set -g mouse on.

If you want to emulate some terminal features like "auto copy selected text", you can set the additional tmux setting:

bind-key -T copy-mode-vi MouseDragEnd1Pane send-keys -X copy-pipe-and-cancel "<clipboard_program>"
Enter fullscreen mode Exit fullscreen mode

Where <clipboard_program> on linux can be something like xclip and on mac would be pbcopy.

From this point on, you can use the mouse to click-and-drag selection over text and once you let go, tmux will automatically copy to system clipboard.

Collapse
 
vophanlee profile image
v0phan1ee

Thanks for sharing ;)

Collapse
 
radix profile image
aka_radix

Thanks a lot, much appreciated!

Collapse
 
bngcebetsha profile image
Buntu Ngcebetsha

finally...thank you for this

Collapse
 
leonid-charey profile image
Leonid • Edited

Igor, thank you for post! Could you also show how to transfer data from tmux' buffer to system buffer (to another application) and vice versa?