In my ~/.tmux.conf I have this which works great:
bind-key -t vi-copy n cursor-down
It allows me to move my cursor in history / copy mode.
I want to jump more rapidly (like I do in vim).
I want to jump 5 lines, but this doesn't work:
bind-key -t vi-copy E 5 cursor-up
How can I add a keybinding that will jump several lines?
Originally, tmux has only a restricted support for commands in copy-mode.
You can't assign multiple commands, you can't repeat them.
The only option is only assign a single command to a keystroke.
However, there's a mod for tmux that allows the full-fledged support for scripting in tmux: http://ershov.github.io/tmux/ (I'm the author)
Using this mod, you can do it this way:
bind-key -t vi-copy K tcl {
for {set i 0} {$i < 5} {incr i} {
cursor-up
}
}
Also, you'd be able to use variables, loops, define your own procedures and also have more control on tmux internals.
Related
Tmux is excellent, but there is one quirk that is proving to be a pane. If I hit ctrl+b then go too fast to the arrow key in order to switch panes I end up just resizing the current pane. It would be very nice to get rid of that behaviour. Is this a problem solvable in tmux or is in some kind of lag in my OS?
tmux is fully configurable so, yes, it's possible to solve this issue.
I suggest that you take a look at the tmux man pages or at other resources like Pragmatic Bookshelf's "tmux 2" book.
As an example, you can fully remap the keys to use to split, move around and resize windows adding something like this to your ~/.tmux.conf file:
# Splitting panes
bind | split-window -h # Uses "|" to split pane horizontally
bind - split-window -v # Uses "-" to split pane vertically
# Remapping movement keys
bind h select-pane -L # Move focus to pane on the left
bind j select-pane -D # Move focus to pane above the current one
bind k select-pane -U # Move focus to pane below the current one
bind l select-pane -R # Move focus to pane on the right
bind -r C-h select-window -t :- # Move to previous window
bind -r C-l select-window -t :+ # Move to next window
# Resizing panes (notes that is using the uppercase here and resize by 5 chars)
bind -r H resize-pane -L 5
bind -r J resize-pane -D 5
bind -r K resize-pane -U 5
bind -r L resize-pane -R 5
I was wondering what the possible options are for tmux vi-copy bindings. I have the following in my .tmux.conf:
bind -t vi-copy e start-of-line
bind -t vi-copy r end-of-line
bind -t vi-copy v begin-selection
bind -t vi-copy V rectangle-toggle
bind -t vi-copy K page-up
bind -t vi-copy J page-down
bind -t vi-copy h cursor-left
bind -t vi-copy j cursor-down
bind -t vi-copy k cursor-up
bind -t vi-copy l cursor-right
bind -t vi-copy C-f cancel
Q1: I've had this in my config file for a while and have no idea where the options in the last column come from. A google search only showed me other forums that have code snippets like this. I can't find the documentation on these keywords. Any ideas? nope, not the manpage :)
Q2: If possible I would like to change K to (the tried and failed) half-page-up, or even to something like "go up 5 lines", to preserve context.
Tried and failed:
1) bind -t vi-copy K half-page-up
2) bind -t vi-copy K M-Up
3) bind -t vi-copy K C-u // already configured half page-up
Thx!
You can use tmux list-keys -t vi-copy to see a list of all the functions that are mapped in vi-copy mode. If you wish to see all possible commands you can look at the source code, specifically mode-key.c. I don't think there are any docs that list them all.
The mappings you are looking for are:
bind-key -t vi-copy 'K' halfpage-up
bind-key -t vi-copy 'J' halfpage-down
Unfortunately, this part is not documented well in tmux.
This is the full list of 'copy mode' commands in version 2.2 ripped out from the source code:
append-selection
back-to-indentation
begin-selection
bottom-line
cancel
clear-selection
copy-end-of-line
copy-line
copy-pipe
copy-selection
cursor-down
cursor-left
cursor-right
cursor-up
end-of-line
goto-line
halfpage-down
halfpage-up
history-bottom
history-top
jump-again
jump-backward
jump-forward
jump-reverse
jump-to-backward
jump-to-forward
middle-line
next-space
next-space-end
next-word
next-word-end
other-end
page-down
page-up
previous-space
previous-word
rectangle-toggle
scroll-down
scroll-up
search-again
search-backward
search-forward
search-reverse
select-line
start-named-buffer
start-number-prefix
start-of-line
top-line
All these commands apply to both vi-copy and emacs-copy modes but behavior might differ making it consistent with vi or emacs, though.
There are some shortcomings when tmux is 'in mode':
No sensible commands list or tab-completion for 'mode' commands
No way to combine commands in 'mode': you can only bind one action to a keypress and the set of actions is limited.
There's also a patch addressing these problems: http://ershov.github.io/tmux/
It adds full-fledged scripting support into tmux.
Using that, you can list all available commands:
info commands ::tmux::*
List all 'mode' commands:
info commands ::tmux::mode::*
List all 'copy mode' commands:
info commands ::tmux::mode::copy::*
Bind multiple actions in copy-mode:
bind-key -t vi-copy K tcl { scroll-up ; scroll-up }
Does Tmux supports key-bindings with key sequences like Vim does (e.g. bind-key ab kill-pane)? Or how can i emulate that?
I'm using tmux 2.3.
You can emulate key sequences by defining your own key tables and chaining them together.
For example, if I want <C-q>x to do something, I put the binding for 'x' into a key table "my-keys", then bind the key that activates that key table with switch-client (C-q):
bind-key -Tmy-keys x send-keys "my binding"
# Multi-key prefix for custom bindings
bind-key -Troot C-q switch-client -Tmy-keys
NOTE: I started with C-q, because it seems to conflict the least with the command line and Vim.
So, now you have every key at your disposal with a C-q prefix.
If you want more keys in your sequence, add another level of indirection:
bind-key -Tmy-keys x send-keys "my binding"
# Pane (i.e. 'W'indow commands like Vim with C-w)
bind-key -Tmy-keys-window-ctl s swap-pane
bind-key -Tmy-keys C-w switch-client -T my-keys-window-ctl
# Multi-key prefix for custom bindings
bind-key -Troot C-q switch-client -Tmy-keys
So, now I have swap-pane bound to <C-q><C-w>s.
This works because
<C-q> activates "my-keys" key table,
which has the binding <C-w>,
which activates "my-keys-window-ctl" key table
which has the binding s to call swap-pane
Tmux supports only single character key bindings (unfortunately).
So, only this:
bind-key a kill-pane
or this:
bind-key b kill-pane
Please note this is different from for example C-a (Ctrl-a) or M-a (Alt-a).
Even though we users write those with multiple characters and even have to press 2 keys to invoke them, both Ctrl-a and Alt-a are actually a single character for tmux (and in general to my knowledge).
Alternative
...might not be what you expect, but here it is:
# in .tmux.conf
bind a command-prompt -p "pressed a" "run '~/my_script %%'"
And the example my_script file:
#!/bin/bash
case "$1" in
b)
tmux kill-pane
;;
c)
tmux kill-window
;;
esac
Now after you reload your tmux.conf and press prefix + a you'll get a tmux prompt saying 'pressed a'.
Go ahead and press b and Enter. tmux kill-pane from the script will execute.
Similarly if you press prefix + a + c and Enter you'll execute another option from the script.
This kind-of mimics what you want with the addition of Enter key at the end.
Also, the provided script is extendable so you can add more "bindings" to get prefix + a + d + Enter etc..
I've been a happy tmux user for a while now but there's one behaviour that's bugging me. When I switch panes using ^b-arrow, and then immediately press arrow-up (to get a command from history, for example), the window pane switches again. I understand this can be useful if you want to move through multiple panes quickly, but for me it's a pain in the backside since I keep ending up in panes I never meant to be in.
So, is there a way to set tmux so that the ^b-arrow command only switches pane once and ignores any following arrow key presses?
That happens because the default bindings for the arrow keys are setup with bind-key -r, specifying that they may be repeated. There are two ways that you can disable this.
First, you can use set-option repeat-time 0 to disable repeating entirely. This will affect all bindings. I find that to be very annoying when resizing panes.
Secondly, you can change the bindings for the arrow keys to use bind-key without the -r option:
bind-key Up select-pane -U
bind-key Down select-pane -D
bind-key Left select-pane -L
bind-key Right select-pane -R
If you spend a lot of times navigating panes, why not set up global mappings so you don't have to use prefixes at all, e.g. bind -n C-h select-pane -L to map ctrl-h to switching left, same as Vim.
See http://robots.thoughtbot.com/seamlessly-navigate-vim-and-tmux-splits for an even better solution that also navigates across Vim windows.
Another option is to make a binding to jump to the previous pane, if you are flicking back and forth between the same two panes.
bind-key C-a last-pane
If I'm working in a widescreen monitor I like to primarily use two panes and switch between them with C-a Ca.
If I'm working on a square monitor I'll use two windows. I'd like to be able to switch between them with C-a C-a as well without changing my tmux.conf.
If you always want C-a to
switch between panes when the active window has more than one pane, and
switch between windows when the active window has only one pane,
then you can use an if-shell that counts the number of panes in the active window to decide between last-pane and last-window:
bind-key C-a if-shell 'test $(tmux list-panes | wc -l) -gt 1' 'last-pane' 'last-window'
It will still be “up to you” to rearrange your panes when switching between “wide” and “square” configurations (e.g. via break-pane and join-pane).
In tmux 1.8 if-shell and run-shell do format expansion, so you can simply the shell command a bit:
bind-key C-a if-shell 'test #{window_panes} -gt 1' 'last-pane' 'last-window'
I'd like to suggest the following (adjust 80 to distinguish between your two terminal widths)
if-shell '[ "$COLUMNS" -gt 80 ]' 'bind-key C-a "select-window -t :.+"' 'bind-key C-a "next-window"'
but I'm either messing up the syntax, or COLUMNS isn't set in the relevant tmux environment, as the above shell expression always evaluates false for me.