Window manager changed to i3: scratchpad tricks

Sticking to what seems to be my two-year window manager changing schedule, I switched again and ended up with i3. Xmonad was ok, performance- and feature-wise, but I didn't find the time to learn Haskell to be really able to configure it properly.

i3 has some properties I particularly like:

I use the scratchpad as a more powerful replacement for dmenu_run, which under high IO load can take long time to fire up: I keep a terminal with tmux ready at the scratchpad, which is configured to hide itself again as soon as a command is executed, and to spawn another tmux window to be ready for the next input.

Usability-wise, it's like running dmenu or gmrun (which I used some time ago): You press Super-p, a window shows up, you enter your command, press Return, the window vanishes and the command gets executed. In addition, it offers

The code for that is pretty short, and most of it is to cover corner cases. This file is ~/.config/i3/scratchpad/perpetual_terminal.sh and is best executed from i3 under a flock guard:

(download)

#!/bin/sh

run_inside="'ZDOTDIR=${HOME}/.config/i3/scratchpad zsh'"

while true; do
    # not using urxvtc here, as we're relying on the process to run
    # until either
    #
    # * it gets detached (eg by ^Ad)
    # * it terminates (because someone killed all windows)
    #
    # in any case, we try to reattach to the session, or, if that fails,
    # create a new one.
    urxvt -name scratchpad -e sh -c "tmux attach -t scratchpad || tmux new-session -s scratchpad $run_inside ';' set-option -t scratchpad default-command $run_inside"
done

And this file, ~/.config/i3/scratchpad/.zshrc, configures the shell that gets executed:

(download)

source ~/.zshrc

# reset again what was set outside
export ZDOTDIR=${HOME}

PS1="(scratchpad)$PS1"

preexec() {
    i3-msg '[instance="^scratchpad$"]' move scratchpad
    tmux new-window

    precmd() {
            echo "=============================="
            echo "exited with $?"
            exec sleep 10m
    }
}

zshexit() {
    # user pressed ^D or window got killed, will not be executed when the
    # shell gets "killed" by the final exec in the regular workflow
    i3-msg '[instance="^scratchpad$"]' move scratchpad
    tmux new-window
}

TRAPHUP() {
    # when the window gets killed, just die
    zshexit() {}
}

To activate this from i3, the following lines are placed in the i3 config:

bindsym $mod+p [instance="^scratchpad$"] scratchpad show
exec_always flock -w1 ~/.config/i3/scratchpad/lockfile ~/.config/i3/scratchpad/perpetual_terminal.sh
for_window [instance="^scratchpad$"] move scratchpad

All of the above requires zsh, tmux and urxvt to be installed, zsh to be configure as login shell and possibly other things I might have forgotten (please let me know if you have trouble reproducing this setup).


Other i3 features that look good and I plan to discover:

An issue I yet have to find a solution for is the status bar: I want nice graphs of CPU usage etc, so the tiling window manager typical solutions like dzen2 or i3's i3status/i3bar won't do the trick. I'm using conky for the moment, but I still need i3bar because it has a realtime display of the active workspace and of urgency notifications. Ideally, I'd want i3bar to provide an X window to conky where it can draw, but for the moment, I'm keeping a single statusline worth of visual information in two distinct panels.