Julius Plenz – Blog

zsh: complete words from tmux pane

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:

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.

posted 2012-01-19 tagged zsh, tmux and linux

tmux session names

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.

posted 2012-01-03 tagged tmux

tmux line continuation patch

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!'"

posted 2011-08-25 tagged tmux

switching screen for tmux

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".

posted 2011-07-21 tagged tmux