Created
September 1, 2009 14:42
-
-
Save dgfitch/179126 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# Simple helper library from generic bindings | |
module Ratpoison | |
RATPOISON="ratpoison" | |
def self.method_missing m, *args, &block | |
command m.to_s, *args | |
end | |
def self.command(command, *args) | |
puts "Running '#{command}' with '#{args.join(' ')}'" if $DEBUG | |
return `#{RATPOISON} -c "#{command} #{args.join(' ')}"` | |
end | |
def self.commands(list) | |
operations = list.map { |a| '-c "' + a.gsub('"', '\\"') + '"' } | |
cmd = RATPOISON + " " + operations.join(" ") | |
return `#{cmd}` | |
end | |
def self.mode x=nil | |
if x | |
return Ratpoison.set("topkmap main").chomp | |
else | |
return Ratpoison.set("topkmap").chomp | |
end | |
end | |
def self.getenv(*args) | |
return Ratpoison.command("getenv", *args).chomp | |
end | |
def self.select_xid xid | |
if frame = physical_screens.frames.detect {|x| x.window == xid} | |
Ratpoison.sselect frame.screen | |
Ratpoison.fselect frame.number | |
end | |
end | |
def self.window_xid xid | |
windows_array.detect {|x| x.xid.to_s == xid.to_s } | |
end | |
def self.windows_array (*args) | |
a = command("windows %f %S %n %s %l %i %c %a %t") | |
return @cached_windows if @cached_windows_string and @cached_windows_string == a | |
@cached_windows_string = a | |
@cached_windows = a.map do |line| | |
if line[/^ /] | |
rest = line.gsub(/^ /, "").chomp | |
w = Window.new(nil, *rest.split(" ", 8)) | |
else | |
rest = line.chomp | |
w = Window.new(*rest.split(" ", 9)) | |
end | |
w.screen_session = parse_screen(w.title) if w.title and w.title[/^\>/] | |
w | |
end | |
@cached_windows | |
end | |
def self.current_window | |
windows_array.detect {|x| x.active} | |
end | |
def self.current_frame | |
current_physical_screen.frames.detect {|x| x.number == current_window.frame} | |
end | |
def self.current_screen | |
screens.detect {|x| x.active} | |
end | |
def self.physical_screens | |
PhysicalScreens.new | |
end | |
def self.current_physical_screen | |
physical_screens.detect {|x| x.active} | |
end | |
def self.frames screen | |
Frames.new screen | |
end | |
# This crap has lots of edge cases I don't care about in day to day use | |
# If I have windows with standing numbers in the title, things will get wacky | |
# | |
# (note to self: this is for screen(1) sessions, not ratpoison screens... confusing) | |
def self.parse_screen string | |
s = ScreenSession.new | |
(s.host, *rest) = string.split(/\s+/) | |
screen = Screen.new | |
rest.each do |x| | |
if x[/^[0-9]+\*?$/] | |
# Screen number, hopefully | |
screen = Screen.new | |
s << screen | |
screen.number = x[/[0-9]+/] | |
if x[/\*/] | |
screen.active = true | |
s.active_screen = screen | |
end | |
else | |
# Append to the current title | |
if screen.title | |
screen.title += " " + x | |
else | |
screen.title = x | |
end | |
end | |
end | |
return s | |
end | |
class ScreenSession < Array | |
attr_accessor :host, :active_screen | |
def number | |
active_screen.number | |
end | |
def self.select number | |
# TODO: Only jump if not already selected -- not sure how to efficiently do that though | |
if Ratpoison.current_window.screen_session | |
current_number = Ratpoison.current_window.screen_session.number | |
if number.to_i != current_number.to_i | |
Ratpoison.screen_key "'meta #{number}'" | |
end | |
end | |
end | |
end | |
# This represents a screen(1) screen, not a physical screen | |
class Screen | |
attr_accessor :number, :title, :active | |
def initialize | |
@active = false | |
end | |
end | |
class PhysicalScreens < Array | |
def initialize | |
Ratpoison.sdump.chomp.split(",").each do |x| | |
self << PhysicalScreen.new(*x.split(/ +/)) | |
end | |
self | |
end | |
def frames | |
SFrames.new | |
end | |
end | |
class PhysicalScreen < Struct.new(:number, :x, :y, :width, :height, :status) | |
def active | |
status == "1" | |
end | |
def frames | |
Frames.new self.number | |
end | |
end | |
class Window < Struct.new(:frame, :screen, :number, :status, :last_access, :xid, :class, :name, :title, :screen_session) | |
def active | |
status == "*" | |
end | |
end | |
class Frames < Array | |
def initialize screen=nil | |
if screen | |
Ratpoison.fdump(screen).chomp.split(",")[0..-1].each do |f| | |
self << Frame.new(f) | |
end | |
end | |
self | |
end | |
def to_s | |
self.map {|x| x.to_s }.join(",") + "," | |
end | |
end | |
# SFrames is a collection of frames that have their screen numbers, used to | |
# do sfdump | |
class SFrames < Array | |
def initialize | |
Ratpoison.sfdump.chomp.split(",")[0..-1].each do |f| | |
d = f.sub(/\s+\d+$/, "") | |
frame = Frame.new(d) | |
frame.screen = f[/\d+$/] | |
self << frame | |
end | |
self | |
end | |
def to_s | |
sort_by {|x| x.number.to_i }.map {|x| x.to_s + " " + x.screen }.join(",") + "," | |
end | |
# Takes a frames array, the screen it originated from, and the screen it's | |
# going to, and fixes the settings | |
def move frames, from, to | |
new_frames = Ratpoison::Frames.new | |
frames.each do |f| | |
x = f.clone | |
x.screen = to.number | |
x.screenh = to.height | |
x.screenw = to.width | |
xd = from.width.to_f / to.width.to_f | |
yd = from.height.to_f / to.height.to_f | |
x.x = (x.x.to_f / xd).to_i | |
x.y = (x.y.to_f / yd).to_i | |
x.width = (x.width.to_f / xd).to_i | |
x.height = (x.height.to_f / yd).to_i | |
new_frames << x | |
end | |
return new_frames | |
end | |
end | |
class Frame < Struct.new(:screen, :number, :x, :y, :width, :height, :screenw, :screenh, :window, :last_access, :dedicated) | |
# This takes in ratpoison's sexp-style output - there's almost certainly a | |
# better way to do this | |
def initialize string=nil | |
if string | |
sexp = string.sub(/\)$/, "") | |
sexp.scan(/:([a-z\-]+) ([^ ]+)/) do |match| | |
name = $~[1].to_s | |
value = $~[2] | |
name = "last_access" if name == "last-access" | |
self[name] = value | |
end | |
end | |
end | |
def to_s | |
values = [] | |
each_pair do |name, value| | |
case name.to_s | |
when "screen" | |
# Don't print out screen, the container array will decide whether or | |
# not to do so | |
when "last_access" | |
values << ":last-access " + value.to_s | |
else | |
values << ":" + name.to_s + " " + value.to_s | |
end | |
end | |
"(frame " + values.compact.join(" ") + ")" | |
end | |
end | |
end | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment