#!/usr/bin/env perl # # Copyright (c) 2009 Hatem Nassrat # All rights reserved. Modifications under same license as original script. # ChangeLog: # # Added C-M-Right and C-M-Left for next and prev workspace # Added move window to next prev workspace # Added dump/restore workspaces # # Copyright (c) 2005 Mike O'Connor # All rights reserved. # Author Mike O'Connor # # Modified by Shawn Betts. # # code was adapeted from rpws that comes from ratpoison containing the follwing copyright: # Copyright (C) 2003 Shawn Betts # Author: Shawn Betts # use strict; use warnings; use Fcntl qw (:flock); use Getopt::Std; my $ratpoison = $ENV{ "RATPOISON" } || "ratpoison"; my $tmp=$ENV{ "TMP" } || "/tmp"; my $lockfile = $ENV{ "RPWS_LOCKFILE" } || "$tmp/rpws.$<.lock"; sub help { system("pod2usage", $0); print( "for more detailed documentation run \"perldoc $0\"\n" ); } sub rp_call { my $result = `$ratpoison -c "@_"`; chomp( $result ); chomp( $result ); return $result; } sub ws_init_ws { my $num = shift; rp_call( "gnew wspl$num" ); my $fd = fdump(); rp_call( "setenv fspl$num $fd" ); } sub fdump { return rp_call( "fdump" ); } sub ws_init { my $num = shift; $num >= 2 || die "You must create at least 2 workspaces."; # Backup the frames my $fd = fdump(); rp_call( "select -" ); rp_call( "only" ); my $i; for my $i (2..$num) { ws_init_ws( $i ); } # Workspace 1 uses the 'default' group. # Start in workspace 1. $fd = fdump(); rp_call( "gselect default" ); rp_call( "setenv fspl1 $fd" ); rp_call( "setenv wspl 1" ); # Keep track of workspace count rp_call( "setenv wspc $num" ); # restore the frames rp_call( "frestore $fd" ); if( -e "$lockfile" ) { unlink ("$lockfile" ); } } sub ws_save { my $ws = rp_call( "getenv wspl" ); my $fd = fdump(); rp_call( "setenv fspl$ws $fd" ); } sub ws_restore { my $which = shift; my $which_name; my $move; # Step1: determine which workspace to move to if ( $which =~ /^move/ ) { $move = 1; $which = substr($which, 4); } if ( $which =~ /^(?:next|prev)$/ ) { my $ws = rp_call( "getenv wspl" ); my $wspc = rp_call( "getenv wspc" ); if ( $which eq 'next' ) { $ws++; } else { $ws--; } $which = ( ( $ws - 1 ) % $wspc ) + 1; } if ( $which == 1 ) { $which_name = "default"; } else { $which_name = "wspl$which"; } # Step 2a: Moving Window if necessary if ( $move ) { rp_call( "gmove $which_name" ); rp_call( "select -" ); rp_call( "prev" ); } # Step2: Process the workspace switch ws_save(); rp_call( "gselect $which_name"); my $last = rp_call( "getenv fspl$which" ); rp_call( "frestore $last" ); rp_call( "setenv wspl $which" ); # Step 2x: Display the moved Window if ( $move ) { rp_call( "next" ); } rp_call( "echo Workspace $which" ); } sub ws_dump { my $ws_dumpf = shift; my $wspc = rp_call( "getenv wspc" ); open WSDUMP, ">$ws_dumpf" or die $!; ws_save(); for my $i (1..$wspc) { print WSDUMP rp_call( "getenv fspl$i" )."\n"; } close WSDUMP; rp_call( "echo Workspaces dumped to $ws_dumpf" ); } sub ws_dumprestore { my $ws_dumpf = shift; my $ws = rp_call( "getenv wspl" ); my $wspc = rp_call( "getenv wspc" ); # Get dumped frame info open WSDUMP, "$ws_dumpf" or die $!; my @wsdata=; close WSDUMP; my $wspc_dump = scalar @wsdata; if ($wspc < $wspc_dump) { # Number of workspaces to restore more than available die "Cannot restore all workspaces (dump_count = " . $wspc_dump . ", rp_count = " . $wspc . ")"; } # Restoring all workspaces for my $i (1..$wspc_dump) { # calculating previous workspace number my $j = ( $wspc + $i - 2 ) % $wspc + 1; # moving to workspace $i -1 ws_restore( $j ); # restoring workspace $i rp_call( "setenv fspl$i $wsdata[$i-1]" ); } # goto the originally visible workspace ws_restore( $ws ); rp_call( "echo Workspaces loaded from $ws_dumpf" ); } sub add_aliases { my $n = shift; foreach my $i (1..$n) { # Switch Workspace rp_call ( "alias rpws$i exec $0 $i" ); # Move Window to wrokspace rp_call ( "alias rpwsm$i exec $0 move$i" ); } rp_call ( "alias rpwsn exec $0 next" ); rp_call ( "alias rpwsp exec $0 prev" ); rp_call ( "alias rpwsmn exec $0 movenext" ); rp_call ( "alias rpwsmp exec $0 moveprev" ); } sub add_keys { my $n = shift; foreach my $i (1..$n) { # Switch Workspace rp_call ( "definekey top M-F$i rpws$i" ); # Move Window to wrokspace rp_call ( "definekey top C-M-S-F$i rpwsm$i" ); } rp_call ( "definekey top C-M-Right rpwsn" ); rp_call ( "definekey top C-M-Left rpwsp" ); rp_call ( "definekey top C-M-greater rpwsmn" ); rp_call ( "definekey top C-M-less rpwsmp" ); } my $arg = shift @ARGV || 'help'; if( $arg eq "help" ) { help(); } elsif( $arg eq "init" ) { my $num = shift @ARGV; my %opts; ws_init( $num ); getopts('ka', \%opts); add_aliases( $num ) if $opts{'a'} || $opts{'k'}; add_keys ( $num ) if $opts{'k'}; } elsif( $arg eq "dump" ) { my $filename = shift @ARGV; ws_dump($filename); } elsif( $arg eq "restore" ) { my $filename = shift @ARGV; ws_dumprestore($filename); } else { open LOCK, ">>$lockfile" or die "Cannot open lockfile: $lockfile"; flock(LOCK, LOCK_EX); ws_restore( $arg ); } __END__ =head1 NAME rpws - Implements multiple workspaces in ratpoison =head1 SYNOPSIS rpws init n [-k] [-a] - setup rpws with n workspaces. -a sets up command aliases; -k sets up key bindings and aliases. rpws dump - dumps the current layout to rpws restore - restores rpws workspaces from rpws help - this documentation rpws n - switch to this workspace =head1 DESCRIPTION B implements multiple workspaces in ratpoison by making calls to fdump, freestore. It was adapted from rpws which comes with ratpoison in the contrib directory. =head1 USAGE Add the following line in ~/.ratpoisonrc exec /path/to/rpws init 6 -k This creates 6 aliases rpws1, rpws2, etc. It also binds the keys M-F1, M-F2, etc to each rpwsN alias. Moreover, rpwsn (Next) and rpwsp (Prev) are created, and C-M-{Right,Left} are bound to rpws{n,p}. Full list of keybindings created are: M-F$i Goto workspace $i C-M-Right Goto Next workspace C-M-Left Goto Prev workspace C-M-S-F$i Move window to workspace $i C-M-greater Move current window to next workspace C-M-less Move current window to prev workspace =head1 FILES rpws requires use of a lockfile. It defaults to using /tmp/rpws..lock but this can be changed by setting the environment variable RPWS_LOCKFILE to your desired lockfile. =head1 AUTHOR Mike O'Connor =head1 COPYRIGHT Copyright (c) 2005 Mike O'Connor All rights reserved. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.