2012/10/27: Tiling window managers and work spaces

With "normal" window mangers (or desktop environments) you usually have a concept of a "work space", i.e., an area, the size of a screen, where you can switch between several of them. The assumption is that when you come back, things are arranged in the way you left them.

What I found, I need more often is returning to a fixed arrangement of windows (usually two or three to compare things, or otherwise get an overview) and then quickly go to a single window (e.g., my main emacs window) to do the actual work. But it's the initial arrangement I'm returning to. At any time I only need a very small number of these configurations, certainly less than a dozen.

I recently got reminded that this is my mode of operation when I installed an old script (which I use since 2007) on yet another machine. It doesn't do a lot, since ratposion already brings all the primitives you need. fdump provides you with an opaque string describing the current arrangement of windows, frestore takes such an opaque string and brings back the arrangement of windows. So, essentially, you have to decide which keys to bind this to. Here is the script I use stripped down to this basic functionality.


#!/usr/bin/perl -w

use strict;

my $nrworkspaces=12;

my $home=$ENV{'HOME'};
defined $home && -d $home
    or die "Invalid home directory.\n";

my $display = $ENV{'DISPLAY'};
defined $display or $display = ":0.0";
$display = quote($display);

-d "$home/.rpws" 
    or mkdir "$home/.rpws", 0700
    or die "Unable to create directory `$home/.rpws` ($!)\n";

-d "$home/.rpws/$display"
    or mkdir "$home/.rpws/$display", 0700
    or die "Unable to create directory `$home/.rpws/$display` ($!)\n";

@ARGV !=0 or die "Usage: $0 (init|save|restore) ...\n";

for ($ARGV[0]) {
    /^init$/ && do {
        for (my $i=1; $i<=$nrworkspaces; $i++) {
            system("ratpoison -c fdump > \Q$home\E/.rpws/$display/$i");
            system "ratpoison", "-c", "bind F$i exec $0 restore $i";
            system "ratpoison", "-c", "bind M-F$i exec $0 save $i";
        }
        last;
    };
    /^restore$/ && do {
        @ARGV == 2 or die "$0 save needs one argument\n";
        my $ws = `cat \Q$home\E/.rpws/$display/\Q$ARGV[1]\E`;
        chomp($ws);
        system "ratpoison", "-c", "frestore " . $ws;
        system "ratpoison", "-c", "echo Workspace $ARGV[1]";
        last;
    };
    /^save$/ && do {
        @ARGV == 2 or die "$0 restore needs one argument\n";
            system("ratpoison -c fdump > \Q$home\E/.rpws/$display/\Q$ARGV[1]\E");
        system "ratpoison", "-c", "echo saved Workspace $ARGV[1]";
        last;
    };
    die "Usage: $0 (init|save|restore)\n";
}

exit 0;

sub quote
{
    my ($name) = @_;

    $name =~ s/([^-a-zA-Z0-9:])/"_" . ord ($1) . "_" /eg;
    return $name;
}


download

BTW, the good experience I had with this script was also what inspired me saving buffer configurations in emacs.