commit c41e3678e0d3e0558fc56732de6b2e49e9ddea9b
parent 9052026fa3f0f0b05c66543f3cf264fed998f837
Author: Suraj N. Kurapati <sunaku@gmail.com>
Date: Thu, 26 Apr 2007 23:56:47 -0700
incorporate boroir's improvements to mini DSL and do some clean up
Diffstat:
wmiirc | | | 165 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++---------------- |
wmiirc-config.rb | | | 242 | ++++++++++++++++++++----------------------------------------------------------- |
2 files changed, 192 insertions(+), 215 deletions(-)
diff --git a/wmiirc b/wmiirc
@@ -1,55 +1,154 @@
#!/usr/bin/ruby -w
# Loader for ruby-based wmii configuration.
#--
-# Copyright 2006 Suraj N. Kurapati
+# Copyright 2006-2007 Suraj N. Kurapati
+# Copyright 2007 Nick Stenning
# See the file named LICENSE for details.
-require 'logger'
+# load the wmii-irb library
+ $: << File.join(File.dirname(__FILE__), 'wmii-irb')
+ require 'wm'
-# Provide a means by which the user can rescue themselves after an exception.
-def throw_life_saver aError
- system 'xterm &'
+ include Wmii
- IO.popen('xmessage -file - -buttons "recover from error:0,ignore this message:1"', 'w') do |f|
- f.puts aError.inspect, aError.backtrace
- end
-
- system($0 + ' &') if $?.exitstatus == 0
-end
+# create a logger to aid debugging
+ require 'logger'
+ LOG = Logger.new(__FILE__ + '.log', 5)
-LOG = Logger.new(__FILE__ + '.log', 5)
-class << LOG
- alias write <<
-end
+ # capture standard output in logger
+ class << LOG
+ alias write << # emulate IO.write
+ end
+ $stdout = $stderr = LOG
LOG.info "birth"
-# terminate existing instances of this program
- system 'wmiir xwrite /event Start wmiirc' # terminate them nicely
+begin
+ # Miniature DSL to ease configuration.
- instances = `ps -C #{File.basename $0} -o pid h`.split.map! {|s| s.to_i}
- instances.delete $$ # do not kill self!
+ class Handler < Hash
+ def handle aKey, *aArgs, &aBlock
+ if block_given?
+ self[aKey] = aBlock
+ elsif key? aKey
+ self[aKey].call(*aArgs)
+ end
+ end
+ end
- instances.each do |pid|
- LOG.info "slaying ##{pid}"
- Process.kill :SIGKILL, pid
- end
+ EVENTS = Handler.new
+ ACTIONS = Handler.new
+ KEYS = Handler.new
-# load the configuration
- Thread.abort_on_exception = true
+ def event *a, &b
+ EVENTS.handle(*a, &b)
+ end
- begin
- $stdout = $stderr = LOG
+ def action *a, &b
+ ACTIONS.handle(*a, &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(' ')
+
+ cmd << " -p #{aPrompt.to_s.inspect}" if aPrompt
+
+ IO.popen cmd, 'r+' do |menu|
+ menu.puts aChoices
+ menu.close_write
+
+ choice = menu.read
+ choice unless choice.empty?
+ end
+ end
+
+
+ require 'find'
+
+ # Returns the names of programs present in the given directories.
+ def find_programs aDirs
+ aDirs = aDirs.map {|p| File.expand_path p}
+ names = []
+
+ Find.find(*aDirs) do |f|
+ if File.file? f and File.executable? f
+ names << File.basename(f)
+ end
+ end
+
+ names.uniq.sort
+ end
+
+ # terminate existing instances of this program
+ fs.event << 'Start wmiirc'
+
+ event :Start do |arg|
+ exit if arg == 'wmiirc'
+ end
+
+ # load user's configuration file
load File.join(File.dirname(__FILE__), 'wmiirc-config.rb')
- rescue => e
- LOG.error e
- throw_life_saver e
+ # Tag bar setup
+ fs.lbar.clear
+
+ tags.each do |tag|
+ color = (tag == current_tag) ? Color::FOCUSED : Color::NORMAL
+
+ bar = fs.lbar[tag]
+ bar.create
+ bar.write "#{color} #{tag}"
+ end
+
+ # Keygrab setup
+ fs.keys = KEYS.keys.join("\n")
+
+ event :Key do |*args|
+ key(*args)
+ end
- rescue Exception => e
- LOG.fatal e
- end
+ # Event loop
+ fs.event.open do |bus|
+ loop do
+ bus.read.split("\n").each do |event|
+ type, parms = event.split(' ', 2)
+
+ args = parms.split(' ') rescue []
+ event type.to_sym, *args
+ end
+ end
+ end
+
+rescue => e
+ LOG.error e
+
+ # allow the user to rescue themselves
+ system 'xterm &'
+
+ 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
+
+rescue Exception => e
+ LOG.fatal e
+end
LOG.info "death"
diff --git a/wmiirc-config.rb b/wmiirc-config.rb
@@ -3,88 +3,6 @@
# Copyright 2006-2007 Suraj N. Kurapati
# See the file named LICENSE for details.
-
-# load the wmii-irb library
-$: << File.join(File.dirname(__FILE__), 'wmii-irb')
-require 'wm'
-include Wmii
-
-
-################################################################################
-# Miniature DSL to ease configuration.
-# Adapted from Kris Maglione and borior.
-################################################################################
-
-class HandlerHash < Hash
- def handle aKey, *aArgs, &aBlock
- if block_given?
- self[aKey] = aBlock
- elsif key? aKey
- self[aKey].call(*aArgs)
- end
- end
-end
-
-EVENTS = HandlerHash.new
-ACTIONS = HandlerHash.new
-SHORTCUTS = HandlerHash.new
-
-def event *a, &b
- EVENTS.handle(*a, &b)
-end
-
-def action *a, &b
- ACTIONS.handle(*a, &b)
-end
-
-def shortcut *a, &b
- SHORTCUTS.handle(*a, &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(' ')
-
- cmd << " -p #{aPrompt.to_s.inspect}" if aPrompt
-
- IO.popen cmd, 'r+' do |menu|
- menu.puts aChoices
- menu.close_write
-
- choice = menu.read
- choice unless choice.empty?
- end
-end
-
-
-require 'find'
-
-# Returns the names of programs present in the given directories.
-def find_programs aDirs
- aDirs = aDirs.map {|p| File.expand_path p}
- names = []
-
- Find.find(*aDirs) do |f|
- if File.file? f and File.executable? f
- names << File.basename(f)
- end
- end
-
- names.uniq!
- names.sort!
- names
-end
-
-
################################################################################
# GENERAL CONFIGURATION
################################################################################
@@ -108,11 +26,11 @@ module Key
end
module Mouse
- FIRST_CLICK = 1
- MIDDLE_CLICK = 2
- SECOND_CLICK = 3
- SCROLL_UP = 4
- SCROLL_DOWN = 5
+ PRIMARY = 1
+ MIDDLE = 2
+ SECONDARY = 3
+ SCROLL_UP = 4
+ SCROLL_DOWN = 5
end
module Color
@@ -161,17 +79,8 @@ fs.tagrules = <<EOF
/.*/ -> 1
EOF
-
# Events
- event :Start do |arg|
- exit if arg == 'wmiirc'
- end
-
- event :Key do |*args|
- shortcut(*args)
- end
-
event :CreateTag do |tag|
bar = fs.lbar[tag]
bar.create
@@ -200,16 +109,16 @@ EOF
event :LeftBarClick do |button, viewId|
case button.to_i
- when Mouse::FIRST_CLICK
+ when Mouse::PRIMARY
focus_view viewId
- when Mouse::MIDDLE_CLICK
+ when Mouse::MIDDLE
# add the grouping onto the clicked view
grouped_clients.each do |c|
c.tag viewId
end
- when Mouse::SECOND_CLICK
+ when Mouse::SECONDARY
# remove the grouping from the clicked view
grouped_clients.each do |c|
c.untag viewId
@@ -219,7 +128,7 @@ EOF
event :ClientClick do |clientId, button|
case button.to_i
- when Mouse::SECOND_CLICK
+ when Mouse::SECONDARY
# toggle the clicked client's grouping
Client.toggle_grouping clientId
end
@@ -265,146 +174,146 @@ EOF
end
-# Shortcuts
+# Key bindings
# focusing / showing
# focus client at left
- shortcut Key::FOCUS + Key::LEFT do
+ key Key::FOCUS + Key::LEFT do
current_view.ctl = 'select left'
end
# focus client at right
- shortcut Key::FOCUS + Key::RIGHT do
+ key Key::FOCUS + Key::RIGHT do
current_view.ctl = 'select right'
end
# focus client below
- shortcut Key::FOCUS + Key::DOWN do
+ key Key::FOCUS + Key::DOWN do
current_view.ctl = 'select down'
end
# focus client above
- shortcut Key::FOCUS + Key::UP do
+ key Key::FOCUS + Key::UP do
current_view.ctl = 'select up'
end
# toggle focus between floating area and the columns
- shortcut Key::FOCUS + 'space' do
+ key Key::FOCUS + 'space' do
current_view.ctl = 'select toggle'
end
# apply equal-spacing layout to current column
- shortcut Key::ARRANGE + 'w' do
+ key Key::ARRANGE + 'w' do
current_area.layout = :default
end
# apply equal-spacing layout to all columns
- shortcut Key::ARRANGE + 'Shift-w' do
+ key Key::ARRANGE + 'Shift-w' do
current_view.columns.each do |a|
a.layout = :default
end
end
# apply stacked layout to currently focused column
- shortcut Key::ARRANGE + 'v' do
+ key Key::ARRANGE + 'v' do
current_area.layout = :stack
end
# apply stacked layout to all columns in current view
- shortcut Key::ARRANGE + 'Shift-v' do
+ key Key::ARRANGE + 'Shift-v' do
current_view.columns.each do |a|
a.layout = :stack
end
end
# apply maximized layout to currently focused column
- shortcut Key::ARRANGE + 'm' do
+ key Key::ARRANGE + 'm' do
current_area.layout = :max
end
# apply maximized layout to all columns in current view
- shortcut Key::ARRANGE + 'Shift-m' do
+ key Key::ARRANGE + 'Shift-m' do
current_view.columns.each do |a|
a.layout = :max
end
end
# focus the previous view
- shortcut Key::FOCUS + 'comma' do
+ key Key::FOCUS + 'comma' do
prev_view.focus
end
# focus the next view
- shortcut Key::FOCUS + 'period' do
+ key Key::FOCUS + 'period' do
next_view.focus
end
# sending / moving
- shortcut Key::SEND + Key::LEFT do
+ key Key::SEND + Key::LEFT do
grouped_clients.each do |c|
c.send :left
end
end
- shortcut Key::SEND + Key::RIGHT do
+ key Key::SEND + Key::RIGHT do
grouped_clients.each do |c|
c.send :right
end
end
- shortcut Key::SEND + Key::DOWN do
+ key Key::SEND + Key::DOWN do
grouped_clients.each do |c|
c.send :down
end
end
- shortcut Key::SEND + Key::UP do
+ key Key::SEND + Key::UP do
grouped_clients.each do |c|
c.send :up
end
end
# send all grouped clients from managed to floating area (or vice versa)
- shortcut Key::SEND + 'space' do
+ key Key::SEND + 'space' do
grouped_clients.each do |c|
c.send :toggle
end
end
# close all grouped clients
- shortcut Key::SEND + 'Delete' do
+ key Key::SEND + 'Delete' do
grouped_clients.each do |c|
c.ctl = 'kill'
end
end
# swap the currently focused client with the one to its left
- shortcut Key::SWAP + Key::LEFT do
+ key Key::SWAP + Key::LEFT do
current_client.swap :left
end
# swap the currently focused client with the one to its right
- shortcut Key::SWAP + Key::RIGHT do
+ key Key::SWAP + Key::RIGHT do
current_client.swap :right
end
# swap the currently focused client with the one below it
- shortcut Key::SWAP + Key::DOWN do
+ key Key::SWAP + Key::DOWN do
current_client.swap :down
end
# swap the currently focused client with the one above it
- shortcut Key::SWAP + Key::UP do
+ key Key::SWAP + Key::UP do
current_client.swap :up
end
# Changes the tag (according to a menu choice) of each grouped client and
# returns the chosen tag. The +tag -tag idea is from Jonas Pfenniger:
# <http://zimbatm.oree.ch/articles/2006/06/15/wmii-3-and-ruby>
- shortcut Key::SEND + 't' do
+ key Key::SEND + 't' do
choices = tags.map {|t| [t, "+#{t}", "-#{t}"]}.flatten
if target = show_menu(choices, 'tag as:')
@@ -429,7 +338,7 @@ EOF
# zooming / sizing
# Sends grouped clients to temporary view.
- shortcut Key::PREFIX + 'b' do
+ key Key::PREFIX + 'b' do
src = current_tag
dst = src + '~' + src.object_id.abs.to_s
@@ -443,7 +352,7 @@ EOF
end
# Sends grouped clients back to their original view.
- shortcut Key::PREFIX + 'Shift-b' do
+ key Key::PREFIX + 'Shift-b' do
src = current_tag
if src =~ /~\d+$/
@@ -464,52 +373,52 @@ EOF
# client grouping
# include/exclude the currently focused client from the grouping
- shortcut Key::GROUP + 'g' do
+ key Key::GROUP + 'g' do
current_client.toggle_grouping
end
# include all clients in the currently focused view in the grouping
- shortcut Key::GROUP + 'v' do
+ key Key::GROUP + 'v' do
current_view.group
end
# exclude all clients in the currently focused view from the grouping
- shortcut Key::GROUP + 'Shift-v' do
+ key Key::GROUP + 'Shift-v' do
current_view.ungroup
end
# include all clients in the currently focused column in the grouping
- shortcut Key::GROUP + 'c' do
+ key Key::GROUP + 'c' do
current_area.group
end
# exclude all clients in the currently focused column from the grouping
- shortcut Key::GROUP + 'Shift-c' do
+ key Key::GROUP + 'Shift-c' do
current_area.ungroup
end
# invert the grouping in the currently focused view
- shortcut Key::GROUP + 'i' do
+ key Key::GROUP + 'i' do
current_view.toggle_grouping
end
# exclude all clients everywhere from the grouping
- shortcut Key::GROUP + 'n' do
+ key Key::GROUP + 'n' do
ungroup_all
end
# visual arrangement
- shortcut Key::ARRANGE + 't' do
+ key Key::ARRANGE + 't' do
current_view.arrange_as_larswm
end
- shortcut Key::ARRANGE + 'g' do
+ key Key::ARRANGE + 'g' do
current_view.arrange_in_grid
end
- shortcut Key::ARRANGE + 'd' do
+ key Key::ARRANGE + 'd' do
current_view.arrange_in_diamond
end
@@ -517,7 +426,7 @@ EOF
# interactive menu
# launch an internal action by choosing from a menu
- shortcut Key::MENU + 'i' do
+ key Key::MENU + 'i' do
if choice = show_menu(@actionMenu + ACTIONS.keys, 'run action:')
unless action choice.to_sym
system choice << '&'
@@ -526,21 +435,21 @@ EOF
end
# launch an external program by choosing from a menu
- shortcut Key::MENU + 'e' do
+ key Key::MENU + 'e' do
if choice = show_menu(@programMenu, 'run program:')
system choice << '&'
end
end
# focus any view by choosing from a menu
- shortcut Key::MENU + 'u' do
+ key Key::MENU + 'u' do
if choice = show_menu(tags, 'show view:')
focus_view choice
end
end
# focus any client by choosing from a menu
- shortcut Key::MENU + 'a' do
+ key Key::MENU + 'a' do
choices = []
clients.each_with_index do |c, i|
choices << "%d. [%s] %s" % [i, c[:tags].read, c[:props].read.downcase]
@@ -555,15 +464,15 @@ EOF
# external programs
- shortcut Key::EXECUTE + 'x' do
+ key Key::EXECUTE + 'x' do
system 'gnome-terminal &'
end
- shortcut Key::EXECUTE + 'k' do
+ key Key::EXECUTE + 'k' do
system 'firefox &'
end
- shortcut Key::EXECUTE + 'j' do
+ key Key::EXECUTE + 'j' do
system 'nautilus --no-desktop &'
end
@@ -573,7 +482,7 @@ EOF
DETACHED_TAG = '|'
# Detach the current grouping from the current view.
- shortcut Key::PREFIX + 'd' do
+ key Key::PREFIX + 'd' do
grouped_clients.each do |c|
c.with_tags do
delete current_tag
@@ -583,7 +492,7 @@ EOF
end
# Attach the most recently detached client onto the current view.
- shortcut Key::PREFIX + 'Shift-d' do
+ key Key::PREFIX + 'Shift-d' do
v = View.new DETACHED_TAG
if v.exist? and c = v.clients.last
@@ -599,19 +508,19 @@ EOF
10.times do |i|
# focus the {i}'th view
- shortcut Key::FOCUS + i.to_s do
+ key Key::FOCUS + i.to_s do
focus_view tags[i - 1] || i
end
# send current grouping to {i}'th view
- shortcut Key::SEND, i.to_s do
+ key Key::SEND + i.to_s do
grouped_clients.each do |c|
c.tags = tags[i - 1] || i
end
end
# apply grid layout with {i} clients per column
- shortcut Key::ARRANGE, i.to_s do
+ key Key::ARRANGE + i.to_s do
current_view.arrange_in_grid i
end
end
@@ -621,7 +530,7 @@ EOF
# focus the view whose name begins with an alphabet key
('a'..'z').each do |k|
- shortcut Key::VIEW + k do
+ key Key::VIEW + k do
if t = tags.grep(/^#{k}/i).first
focus_view t
end
@@ -629,38 +538,7 @@ EOF
end
-################################################################################
-# START UP
-################################################################################
-
-system "xsetroot -solid #{Color::BACKGROUND.inspect} &"
-
# Misc Setup
+system "xsetroot -solid #{Color::BACKGROUND.inspect} &"
action :status
action :rehash
-
-# Tag Bar Setup
-fs.lbar.clear
-
-tags.each do |tag|
- color = (tag == current_tag) ? Color::FOCUSED : Color::NORMAL
-
- bar = fs.lbar[tag]
- bar.create
- bar.write "#{color} #{tag}"
-end
-
-# Keygrab Setup
-fs.keys = SHORTCUTS.keys.join("\n")
-
-# Event Loop
-fs.event.open do |bus|
- loop do
- bus.read.split("\n").each do |event|
- type, parms = event.split(' ', 2)
-
- args = parms.split(' ') rescue []
- event type.to_sym, *args
- end
- end
-end