wmiirc-rumai

git clone git://oldgit.suckless.org/wmiirc-rumai/
Log | Files | Refs | README | LICENSE

commit 12086db40e2a7c528a03ed5990a79f065193d325
parent 2c0eb8e1439d1a6af7ffdeaaedb60fd5a1dffd45
Author: Suraj N. Kurapati <sunaku@gmail.com>
Date:   Sat, 26 Jan 2008 19:18:47 -0800

upgrade to Rumai

Diffstat:
README | 29+++--------------------------
wmiirc | 200++++++++++++++++++++++++++++++++++++++++++-------------------------------------
wmiirc-config.rb | 135++++++++++++++++++++++++++++++++++++++++---------------------------------------
3 files changed, 178 insertions(+), 186 deletions(-)

diff --git a/README b/README @@ -2,7 +2,7 @@ wmiirc: wmii configuration in Ruby ================================== This is my wmii configuration in Ruby [1]. It currently only works with -wmii-snap20070516, and I will work on upgrading it to wmii-3.6 soon. +wmii-snap20070516, but I will work on upgrading it to wmii-3.6 soon. If you have any questions or suggestions, e-mail me at <SNK at GNA dot ORG>. @@ -14,30 +14,7 @@ Cheers. Setup instructions ------------------ -# obtain my wmii configuration +1. Install the Rumai library: http://rumai.rubyforge.org - darcs get http://rassmalog.rubyforge.org/blog/pub/code/wmiirc/ - chmod +x wmiirc +2. Adjust the $: (load path) variable at the top of the wmiirc file. -# obtain wmii-irb (which is a requirement for my wmii configuration) - - darcs get http://rassmalog.rubyforge.org/blog/pub/code/wmii-irb/ - cd wmii-irb - -# satisfy dependencies for wmii-irb - - svn co svn://svn.gna.org/svn/rubyixp/trunk ruby-ixp - -# view API reference for wmii-irb - - rdoc *.rb - firefox doc/index.html & - -# customize my wmii configuration - - cd .. - vim wmiirc-config.rb - -# apply the new configuration - - wmiirc diff --git a/wmiirc b/wmiirc @@ -6,148 +6,162 @@ # See the file named LICENSE for details. # load the wmii-irb library - $: << File.join(File.dirname(__FILE__), 'wmii-irb') - require 'wm' +$: << '/home/sun/src/rumai/lib' +require 'rumai' +include Rumai - include Wmii # create a logger to aid debugging - require 'logger' +require 'logger' +LOG = Logger.new(__FILE__ + '.log', 5) - LOG = Logger.new(__FILE__ + '.log', 5) +unless $DEBUG + class << LOG + alias write << # emulate IO.write + end # capture standard output in logger - unless $DEBUG - class << LOG - alias write << # emulate IO.write - end + $stdout = $stderr = LOG +end - $stdout = $stderr = LOG - end LOG.info "birth" begin + ## + # # Miniature DSL to ease configuration. + # + ## - class Handler < Hash - # When a block is given, registers a handler for the given key. - # Otherwise, executes all registered handlers for the given key. - def handle aKey, *aArgs, &aBlock - if block_given? - (self[aKey] ||= []) << aBlock - - elsif key? aKey - self[aKey].each do |block| - block.call(*aArgs) - end + class Handler < Hash + def initialize + super {|h,k| h[k] = [] } + end + + # When a block is given, registers a handler for the given key. + # Otherwise, executes all registered handlers for the given key. + def handle aKey, *aArgs, &aBlock + if block_given? + self[aKey] << aBlock + + elsif key? aKey + self[aKey].each do |block| + block.call(*aArgs) end end end + end - EVENTS = Handler.new - ACTIONS = Handler.new - KEYS = Handler.new + EVENTS = Handler.new + ACTIONS = Handler.new + KEYS = Handler.new - def event *a, &b - EVENTS.handle(*a, &b) - end + def event *a, &b + EVENTS.handle(*a, &b) + end - def action *a, &b - ACTIONS.handle(*a, &b) - end + def action *a, &b + ACTIONS.handle(*a, &b) + end + + def key *a, &b + KEYS.handle a.map {|k| k.flatten.join('-') rescue k }.join(','), &b + end - def key *a, &b - a.map! { |x| x.respond_to?(:flatten) ? x.flatten.join('-') : x } - KEYS.handle a.join(','), &b - end + ## + # # Utility functions + # + ## - # Shows a menu with the given items and returns the chosen - # item. If nothing was chosen, then *nil* is returned. - def show_menu aChoices, aPrompt = nil - cmd = "dmenu -b -fn #{WMII_FONT.inspect} " << - %w[-nf -nb -sf -sb].zip( - Color::NORMAL.split[0,2] + Color::FOCUSED.split[0,2] - ).flatten.map {|s| s.inspect}.join(' ') + # Shows a menu with the given items and returns the chosen + # item. If nothing was chosen, then *nil* is returned. + def show_menu aChoices, aPrompt = nil + cmd = "dmenu -b -fn #{WMII_FONT.inspect} " << + %w[-nf -nb -sf -sb].zip( + Color::NORMAL.split[0,2] + Color::FOCUSED.split[0,2] + ).flatten.map {|s| s.inspect}.join(' ') - cmd << " -p #{aPrompt.to_s.inspect}" if aPrompt + cmd << " -p #{aPrompt.to_s.inspect}" if aPrompt - IO.popen cmd, 'r+' do |menu| - menu.puts aChoices - menu.close_write + IO.popen cmd, 'r+' do |menu| + menu.puts aChoices + menu.close_write - choice = menu.read - choice unless choice.empty? - end + choice = menu.read + choice unless choice.empty? end + end - require 'pathname' + require 'pathname' - # Returns the names of programs present in the given directories. - def find_programs *aDirs - aDirs.flatten.map do |d| - Pathname.new(d).expand_path.children rescue [] - end.flatten.map do |f| - f.basename.to_s if f.file? and f.executable? - end.compact.uniq.sort - end + # Returns the names of programs present in the given directories. + def find_programs *aDirs + aDirs.flatten.map do |d| + Pathname.new(d).expand_path.children rescue [] + end.flatten.map do |f| + f.basename.to_s if f.file? and f.executable? + end.compact.uniq.sort + end # terminate existing instances of this program - fs.event << 'Start wmiirc' + fs.event.write 'Start wmiirc' - event :Start do |arg| - exit if arg == 'wmiirc' - end + event :Start do |arg| + exit if arg == 'wmiirc' + end # load user's configuration file - load File.join(File.dirname(__FILE__), 'wmiirc-config.rb') + load File.join(File.dirname(__FILE__), 'wmiirc-config.rb') - # Tag bar setup - fs.lbar.clear + # populate lbar with buttons for every tag + bar = fs.lbar + bar.clear - tags.each do |tag| - color = (tag == current_tag) ? Color::FOCUSED : Color::NORMAL + tags.each do |tag| + color = (tag == curr_tag) ? Color::FOCUSED : Color::NORMAL - bar = fs.lbar[tag] - bar.create - bar.write "#{color} #{tag}" - end + btn = bar[tag] + btn.create + btn.write "#{color} #{tag}" + end - # Keygrab setup - fs.keys = KEYS.keys.join("\n") + # enable keyboard shortcuts + fs.keys.write KEYS.keys.join("\n") - event :Key do |*args| - key(*args) - end + event :Key do |*args| + key(*args) + end - # Event loop - fs.event.open do |bus| - loop do - bus.read.split("\n").each do |event| - type, parms = event.split(' ', 2) + # the main event loop + fs.event.each_line do |line| + line.split("\n").each do |event| + type, parms = event.split(' ', 2) - args = parms.split(' ') rescue [] - event type.to_sym, *args - end - end - end + args = parms.split(' ') rescue [] + event type.to_sym, *args + end + end rescue => e LOG.error e # allow the user to rescue themselves - system 'xterm &' + system 'xterm &' - IO.popen('xmessage -file - -buttons recover:0,ignore:1', 'w') do |f| - f.puts e.inspect, e.backtrace - end + IO.popen('xmessage -file - -buttons recover:0,ignore:1', 'w') do |f| + f.puts e.inspect, e.backtrace + end - if $?.exitstatus == 0 - system $0 + ' &' - end + if $?.exitstatus == 0 + system $0 + ' &' + end + +rescue SystemExit + # ignore it rescue Exception => e LOG.fatal e diff --git a/wmiirc-config.rb b/wmiirc-config.rb @@ -51,7 +51,7 @@ WMII_FONT = '-*-bitstream vera sans mono-medium-r-*-*-16-*-*-*-*-*-*-*' ################################################################################ # WM Configuration -fs.ctl = <<EOF +fs.ctl.write <<EOF grabmod #{Key::MOD} border 2 font #{WMII_FONT} @@ -60,12 +60,12 @@ normcolors #{Color::NORMAL} EOF # Column Rules -fs.colrules = <<EOF +fs.colrules.write <<EOF /./ -> 50+50 EOF # Tagging Rules -fs.tagrules = <<EOF +fs.tagrules.write <<EOF /.*notes.*/ -> note /Buddy List.*/ -> chat /XChat.*/ -> chat @@ -94,19 +94,22 @@ EOF end event :FocusTag do |tag| - fs.lbar[tag] << "#{Color::FOCUSED} #{tag}" + fs.lbar[tag].write "#{Color::FOCUSED} #{tag}" end event :UnfocusTag do |tag| - fs.lbar[tag] << "#{Color::NORMAL} #{tag}" + btn = fs.lbar[tag] + btn.write "#{Color::NORMAL} #{tag}" if btn.exist? end event :UrgentTag do |tag| - fs.lbar[tag] << "*#{tag}" + btn = fs.lbar[tag] + btn.write "*#{tag}" if btn.exist? end event :NotUrgentTag do |tag| - fs.lbar[tag] << tag + btn = fs.lbar[tag] + btn.write tag if btn.exist? end event :LeftBarClick do |button, viewId| @@ -116,13 +119,13 @@ EOF when Mouse::MIDDLE # add the grouping onto the clicked view - grouped_clients.each do |c| + grouping.each do |c| c.tag viewId end when Mouse::SECONDARY # remove the grouping from the clicked view - grouped_clients.each do |c| + grouping.each do |c| c.untag viewId end end @@ -132,7 +135,7 @@ EOF case button.to_i when Mouse::SECONDARY # toggle the clicked client's grouping - Client.toggle_grouping clientId + Client.toggle_group clientId end end @@ -145,7 +148,7 @@ EOF end action :kill do - fs.ctl = 'quit' + fs.ctl.write 'quit' end action :quit do @@ -161,15 +164,13 @@ EOF # gnome-panel refuses to die by other means system 'killall -s TERM gnome-panel' - fs.event.open do |f| - clients.each do |c| - if c.exist? + clients.each do |c| + while c.exist? + begin c.focus - c.ctl = :kill - - # wait until the client is dead - until f.read =~ /DestroyClient #{c.id}/ - end + c.ctl.write :kill + rescue IXP::Error + # ignore and retry end end end @@ -209,61 +210,61 @@ EOF # focus client at left key Key::FOCUS + Key::LEFT do - current_view.ctl = 'select left' + curr_view.ctl.write 'select left' rescue nil end # focus client at right key Key::FOCUS + Key::RIGHT do - current_view.ctl = 'select right' + curr_view.ctl.write 'select right' rescue nil end # focus client below key Key::FOCUS + Key::DOWN do - current_view.ctl = 'select down' + curr_view.ctl.write 'select down' end # focus client above key Key::FOCUS + Key::UP do - current_view.ctl = 'select up' + curr_view.ctl.write 'select up' end # toggle focus between floating area and the columns key Key::FOCUS + 'space' do - current_view.ctl = 'select toggle' + curr_view.ctl.write 'select toggle' end # apply equal-spacing layout to current column key Key::ARRANGE + 'w' do - current_area.layout = :default + curr_area.layout = :default end # apply equal-spacing layout to all columns key Key::ARRANGE + 'Shift-w' do - current_view.columns.each do |a| + curr_view.columns.each do |a| a.layout = :default end end # apply stacked layout to currently focused column key Key::ARRANGE + 'v' do - current_area.layout = :stack + curr_area.layout = :stack end # apply stacked layout to all columns in current view key Key::ARRANGE + 'Shift-v' do - current_view.columns.each do |a| + curr_view.columns.each do |a| a.layout = :stack end end # apply maximized layout to currently focused column key Key::ARRANGE + 'm' do - current_area.layout = :max + curr_area.layout = :max end # apply maximized layout to all columns in current view key Key::ARRANGE + 'Shift-m' do - current_view.columns.each do |a| + curr_view.columns.each do |a| a.layout = :max end end @@ -282,61 +283,61 @@ EOF # sending / moving key Key::SEND + Key::LEFT do - grouped_clients.each do |c| + grouping.each do |c| c.send :left end end key Key::SEND + Key::RIGHT do - grouped_clients.each do |c| + grouping.each do |c| c.send :right end end key Key::SEND + Key::DOWN do - grouped_clients.each do |c| + grouping.each do |c| c.send :down end end key Key::SEND + Key::UP do - grouped_clients.each do |c| + grouping.each do |c| c.send :up end end # send all grouped clients from managed to floating area (or vice versa) key Key::SEND + 'space' do - grouped_clients.each do |c| + grouping.each do |c| c.send :toggle end end # close all grouped clients key Key::SEND + 'Delete' do - grouped_clients.each do |c| - c.ctl = 'kill' + grouping.each do |c| + c.ctl.write 'kill' end end # swap the currently focused client with the one to its left key Key::SWAP + Key::LEFT do - current_client.swap :left + curr_client.swap :left end # swap the currently focused client with the one to its right key Key::SWAP + Key::RIGHT do - current_client.swap :right + curr_client.swap :right end # swap the currently focused client with the one below it key Key::SWAP + Key::DOWN do - current_client.swap :down + curr_client.swap :down end # swap the currently focused client with the one above it key Key::SWAP + Key::UP do - current_client.swap :up + curr_client.swap :up end # Changes the tag (according to a menu choice) of each grouped client and @@ -346,7 +347,7 @@ EOF choices = tags.map {|t| [t, "+#{t}", "-#{t}"]}.flatten if target = show_menu(choices, 'tag as:') - grouped_clients.each do |c| + grouping.each do |c| case target when /^\+/ c.tag $' @@ -366,10 +367,10 @@ EOF # Sends grouped clients to temporary view. key Key::PREFIX + 'b' do - src = current_tag + src = curr_tag dst = src + '~' + src.object_id.abs.to_s - grouped_clients.each do |c| + grouping.each do |c| c.tag dst end @@ -380,12 +381,12 @@ EOF # Sends grouped clients back to their original view. key Key::PREFIX + 'Shift-b' do - src = current_tag + src = curr_tag if src =~ /~\d+$/ dst = $` - grouped_clients.each do |c| + grouping.each do |c| c.with_tags do delete src push dst if empty? @@ -401,76 +402,76 @@ EOF # include/exclude the currently focused client from the grouping key Key::GROUP + 'g' do - current_client.toggle_grouping + curr_client.toggle_group end # include all clients in the currently focused view into the grouping key Key::GROUP + 'v' do - current_view.group + curr_view.group end # exclude all clients in the currently focused view from the grouping key Key::GROUP + 'Shift-v' do - current_view.ungroup + curr_view.ungroup end # include all clients in the currently focused area into the grouping key Key::GROUP + 'c' do - current_area.group + curr_area.group end # exclude all clients in the currently focused column from the grouping key Key::GROUP + 'Shift-c' do - current_area.ungroup + curr_area.ungroup end # include all clients in the floating area into the grouping key Key::GROUP + 'f' do - current_view.floating_area.group + curr_view.floating_area.group end # exclude all clients in the currently focused column from the grouping key Key::GROUP + 'Shift-f' do - current_view.floating_area.ungroup + curr_view.floating_area.ungroup end # include all clients in the managed areas into the grouping key Key::GROUP + 'a' do - current_view.columns.each do |c| + curr_view.columns.each do |c| c.group end end # exclude all clients in the managed areas from the grouping key Key::GROUP + 'Shift-a' do - current_view.columns.each do |c| + curr_view.columns.each do |c| c.ungroup end end # invert the grouping in the currently focused view key Key::GROUP + 'i' do - current_view.toggle_grouping + curr_view.toggle_group end # exclude all clients everywhere from the grouping key Key::GROUP + 'n' do - ungroup_all + Rumai.ungroup end # visual arrangement key Key::ARRANGE + 't' do - current_view.arrange_as_larswm + curr_view.arrange_as_larswm end key Key::ARRANGE + 'g' do - current_view.arrange_in_grid + curr_view.arrange_in_grid end key Key::ARRANGE + 'd' do - current_view.arrange_in_diamond + curr_view.arrange_in_diamond end @@ -520,7 +521,7 @@ EOF # Open a new terminal and set its working directory # to be the same as the currently focused terminal. key Key::EXECUTE + 'x' do - c = current_client + c = curr_client d = File.expand_path(c.label.read.sub(/^.*?:\s+/, '')) rescue nil d = ENV['HOME'] unless File.directory? d.to_s @@ -572,9 +573,9 @@ EOF # Detach the current grouping from the current view. key Key::PREFIX + 'd' do - grouped_clients.each do |c| + grouping.each do |c| c.with_tags do - delete current_tag + delete curr_tag push DETACHED_TAG end end @@ -587,7 +588,7 @@ EOF if v.exist? and c = v.clients.last c.with_tags do delete DETACHED_TAG - push current_tag + push curr_tag end end end @@ -603,19 +604,19 @@ EOF # send current grouping to {i}'th view key Key::SEND + i.to_s do - grouped_clients.each do |c| + grouping.each do |c| c.tags = tags[i - 1] || i end end # swap current client with the primary client in {i}'th column key Key::SWAP + i.to_s do - current_view.ctl = "swap sel #{i+1}" # XXX: +1 b/c floating area is column 1: until John-Galt fixes this! + curr_view.ctl.write "swap sel #{i+1}" # XXX: +1 b/c floating area is column 1: until John-Galt fixes this! end # apply grid layout with {i} clients per column key Key::ARRANGE + i.to_s do - current_view.arrange_in_grid i + curr_view.arrange_in_grid i end end