Today I wrote a rather cool Z-Shell completion function: It will
present all words that are found in the current tmux pane in a zsh
completion menu. That means you can actually complete words from the
output of commands that you just executed. (In a way it's a little
bit like the keeper
function,
without the overhead of remembering to call keeper
in the first place.)
The code below defines two keybindings:
176.9.247.89
somewhere in the pane, try typing .9
and hitting Ctrl-X twice.
It'll complete to that IP address.Here's the code:
_tmux_pane_words() {
local expl
local -a w
if [[ -z "$TMUX_PANE" ]]; then
_message "not running inside tmux!"
return 1
fi
w=( ${(u)=$(tmux capture-pane \; show-buffer \; delete-buffer)} )
_wanted values expl 'words from current tmux pane' compadd -a w
}
zle -C tmux-pane-words-prefix complete-word _generic
zle -C tmux-pane-words-anywhere complete-word _generic
bindkey '^Xt' tmux-pane-words-prefix
bindkey '^X^X' tmux-pane-words-anywhere
zstyle ':completion:tmux-pane-words-(prefix|anywhere):*' completer _tmux_pane_words
zstyle ':completion:tmux-pane-words-(prefix|anywhere):*' ignore-line current
zstyle ':completion:tmux-pane-words-anywhere:*' matcher-list 'b:=* m:{A-Za-z}={a-zA-Z}'
How does it work? _tmux_pane_words
will just capture the current
pane's contents (capture-pane
), print out the buffer that
contains it (show-buffer
) and then delete it again
(delete-buffer
). – The rest of the magic happens via Zsh's
excellent completion mechanisms.
See it in action (after typing spm^X^X
):
Update 2013-10-06: Daniel points out that since March ’13, there
is a switch -p
for capture-pane
to print the contents to stdout;
also, using the newly introduced -J
switch, wrapped words will be
joined. See his adaption here.
Usually, I name my tmux sessions according to what project I'm working on. To
attach a specific session, I use a custom tm
function, with the appropriate
completion:
# 2011-10-19: tmux shortcut for creating/attaching named sessions
tm() {
[[ -z "$1" ]] && { echo "usage: tm <session>" >&2; return 1; }
tmux has -t $1 && tmux attach -t $1 || tmux new -s $1
}
# 2011-10-19
# stolen from completion function _tmux
function __tmux-sessions() {
local expl
local -a sessions
sessions=( ${${(f)"$(command tmux list-sessions)"}/:[ $'\t']##/:} )
_describe -t sessions 'sessions' sessions "$@"
}
compdef __tmux-sessions tm
It looks like this:
A colleague use this, but with a modification. If [[ -z "$1" ]]
, he'll simply
do a tmux attach
, which will attach the last recently used session.
Yay! My patch to tmux
was accepted yesterday. With it, tmux now supports \
as a line continuation character.
Thus, you can put statements like this in your config:
bind P run-shell \
"tmux set-b $(tmux sa - | curl -F 'sprunge=<-' http://sprunge.us) && \
tmux display-message 'sprunge: upload sucessful!'"
I had invited Nicholas Marriott to LinuxTag 2011 in Berlin to
give a talk on tmux
. I was conviced I should drop screen for tmux,
but ... Yesterday would be the day I first installed the program, and
by now I'm actively using it.
It was not without pressure, though. I had volunteered to give a talk on tmux at work, and today was the date. See the quick'n'dirty slides here (in German).
tmux
needs a fairly recent libevent
. So if you want to run a recent
tmux version (1.5) on a Debian stable system, you should consider
linking it statically like so:
$ ./configure --enable-static
$ sed -i '/^LIBS =/s/$/ -lresolv/' Makefile
$ make CC='gcc -static'
$ cp tmux ~/bin
The sed
call is needed to make the static linking work, otherwise
gcc
will fail to find the symbol __b64_ntop
, which is part of
glibc
's libresolv
.
First action to be taken is to make Ctrl-A the prefix. I mean, seriously, why would you use Ctrl-B? It's for "previous page" or previous argument!
unbind C-b
set -g prefix C-a
bind a send-prefix
bind C-a last-window
Next is the status bar. The syntax is pretty self-explanatory.
set -g status-bg yellow
set -g status-fg black
set -g status-interval 5
set -g status-left "#[fg=red]#S %H:%M "
set -g status-right "#H: #(cut -d' ' -f1-3 /proc/loadavg)"
set -w -g window-status-current-bg red
set -w -g window-status-current-fg yellow
Also, cycling through the windows becomes easier. The -r
switch to
bind
allows half a second time (set via repeat-time
) to perform
the next keystroke without pressing the prefix again. So
<prefix><space><space><space>
will move you three windows ahead:
# repeated space/backspace toggles windows forward/backwards
bind -r Space next-window
bind -r C-Space next-window
bind -r C-h previous-window
bind -r C-? previous-window
This feature is very handy for resizing or switching panes repeatedly. (Read more about sessions/windows/panes in the docs...)
bind -r h select-pane -L
bind -r j select-pane -D
bind -r k select-pane -U
bind -r l select-pane -R
Having multiple panes in one window is easy enough. Splitting panes,
however, is sort of counter-intuitive: A horizontal split (split-window
-h
) will divide the current pane into two panes that are horizontally
next to each other – i.e., a horizontal split will introduce a
vertical split line between to panes. This resource has
a nice idea to make splitting more idiomatic:
bind | split-window -h
bind - split-window -v
For a great feature, check out link-window
. If you do name your
sessions and windows in a predictable way so that you can match them
via fnmatch(3)
, you'll be able to do cool things like this:
bind M link-window -s comm:mutt*
bind I link-window -s comm:irssi*
bind K unlink-window
So with Prefix-M you'll quickly bring up the mutt instance of your communication's session, and will detach that single window with Prefix-K again. That's especially handy for things like Mail and IRC client, music player, Todo Lists ...
Side note: Sadly, it's not possible without some tricks to link a window from another session to a pane (sub-window) in the current session. (Think a ten-line-high IRC client at the bottom of your current window.) The FAQ says "[fixing this] is a big todo item but quite invasive".