commit 0b0c2a2ba5e3d10e98de849160b97ab90275c338
parent 2d2d0d31382aefd92c30d70387e271d9ae7826f9
Author: Suraj N. Kurapati <sunaku@gmail.com>
Date: Mon, 19 Jan 2009 23:49:42 -0800
rename wmiirc-config.rb -> config.rb
Diffstat:
config.rb | | | 712 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
wmiirc | | | 2 | +- |
wmiirc-config.rb | | | 712 | ------------------------------------------------------------------------------- |
3 files changed, 713 insertions(+), 713 deletions(-)
diff --git a/config.rb b/config.rb
@@ -0,0 +1,712 @@
+# Ruby-based configuration file for wmii.
+
+################################################################################
+# GENERAL CONFIGURATION
+################################################################################
+
+module Key
+ MOD = 'Mod1'
+ UP = 't'
+ DOWN = 'n'
+ LEFT = 'h'
+ RIGHT = 's'
+
+ PREFIX = MOD + '-Control-'
+ FOCUS = PREFIX
+ SEND = PREFIX + 'm,'
+ SWAP = PREFIX + 'w,'
+ ARRANGE = PREFIX + 'z,'
+ GROUP = PREFIX + 'g,'
+ VIEW = PREFIX + 'v,'
+ MENU = PREFIX
+ EXECUTE = PREFIX
+end
+
+module Mouse
+ PRIMARY = 1
+ MIDDLE = 2
+ SECONDARY = 3
+ SCROLL_UP = 4
+ SCROLL_DOWN = 5
+end
+
+module Color
+ { # Color tuples are "<text> <background> <border>"
+ :NORMCOLORS => NORMAL = '#e0e0e0 #0a0a0a #202020',
+ :FOCUSCOLORS => FOCUSED = '#ffffff #285577 #4c7899',
+ :BACKGROUND => BACKGROUND = '#333333',
+ }.each_pair do |k, v|
+ ENV["WMII_#{k}"] = v
+ end
+end
+
+WMII_FONT = '-*-bitstream vera sans mono-medium-r-*-*-16-*-*-*-*-*-*-*'
+
+
+################################################################################
+# DETAILED CONFIGURATION
+################################################################################
+
+# WM Configuration
+fs.ctl.write <<EOF
+grabmod #{Key::MOD}
+border 2
+font #{WMII_FONT}
+focuscolors #{Color::FOCUSED}
+normcolors #{Color::NORMAL}
+EOF
+
+# Column Rules
+fs.colrules.write <<EOF
+/./ -> 50+50
+EOF
+
+# Tagging Rules
+fs.tagrules.write <<EOF
+/Gran Paradiso - Restore Previous Session/ -> web
+/.*notes.*/ -> note
+/Deluge/ -> tor
+/Buddy List.*/ -> chat
+/XChat.*/ -> chat
+/Thunderbird.*/ -> mail
+/Liferea.*/ -> mail
+/Gimp.*/ -> gimp
+/xconsole.*/ -> ~
+/alsamixer.*/ -> ~
+/QEMU.*/ -> ~
+/XMMS.*/ -> ~
+/MPlayer.*/ -> ~
+/.*/ -> !
+/.*/ -> 1
+EOF
+
+# events
+ event :CreateTag do |tag|
+ bar = fs.lbar[tag]
+ bar.create
+ bar.write "#{Color::NORMAL} #{tag}"
+ end
+
+ event :DestroyTag do |tag|
+ fs.lbar[tag].remove
+ end
+
+ event :FocusTag do |tag|
+ fs.lbar[tag].write "#{Color::FOCUSED} #{tag}"
+ end
+
+ event :UnfocusTag do |tag|
+ btn = fs.lbar[tag]
+ btn.write "#{Color::NORMAL} #{tag}" if btn.exist?
+ end
+
+ event :UrgentTag do |tag|
+ btn = fs.lbar[tag]
+ btn.write "*#{tag}" if btn.exist?
+ end
+
+ event :NotUrgentTag do |tag|
+ btn = fs.lbar[tag]
+ btn.write tag if btn.exist?
+ end
+
+ event :LeftBarClick do |button, viewId|
+ case button.to_i
+ when Mouse::PRIMARY
+ focus_view viewId
+
+ when Mouse::MIDDLE
+ # add the grouping onto the clicked view
+ grouping.each do |c|
+ c.tag viewId
+ end
+
+ when Mouse::SECONDARY
+ # remove the grouping from the clicked view
+ grouping.each do |c|
+ c.untag viewId
+ end
+ end
+ end
+
+ event :ClientClick do |clientId, button|
+ case button.to_i
+ when Mouse::SECONDARY
+ # toggle the clicked client's grouping
+ Client.toggle_group clientId
+ end
+ end
+
+ # wmii puts subsequent firefox instances on the same
+ # view as the first instance. bypass this and move
+ # the newly created firefox to the current view
+ #
+ # this "feature" applies to all programs
+ # that provide window grouping hints. so
+ # we'll just have this event handler
+ # bypass the feature for ALL programs! :-(
+ event :CreateClient do |id|
+ c = Client.new(id)
+
+ case c.label.read
+ when "Gran Paradiso - Restore Previous Session"
+ c.tags = 'web'
+ when /Firefox|Gran Paradiso|jEdit/i
+ c.tags = curr_tag
+ c.focus
+ end
+ end
+
+# actions
+ action :rehash do
+ @programMenu = find_programs ENV['PATH'].squeeze(':').split(':')
+ @actionMenu = find_programs File.dirname(__FILE__)
+ end
+
+ action :kill do
+ fs.ctl.write 'quit'
+ end
+
+ action :quit do
+ action :clear
+ action :kill
+ end
+
+ action :clear do
+ # firefox's restore session feature doesn't
+ # work unless the whole process is killed.
+ system 'killall firefox firefox-bin thunderbird thunderbird-bin deluge'
+
+ # gnome-panel refuses to die by other means
+ system 'killall -s TERM gnome-panel'
+
+ until (clients = Rumai.clients).empty?
+ clients.each do |c|
+ begin
+ c.focus
+ c.ctl.write :kill
+ rescue
+ end
+ end
+ end
+ end
+
+ class StatusBar < Thread
+ def initialize aBarNode, aRefreshRate, aBarColor = Color::NORMAL, &aBarText
+ raise ArgumentError unless block_given?
+
+ super aBarNode do |b|
+ b.create unless b.exist?
+
+ while true
+ b.write "#{aBarColor} #{aBarText.call}"
+ sleep aRefreshRate
+ end
+ end
+ end
+ end
+
+ action :status do
+ if defined? @statusBars
+ @statusBars.each {|s| s.kill }
+ end
+
+ @statusBars = [
+ StatusBar.new(fs.rbar.volume, 10) do
+ refresh_volume_display
+ end,
+
+ StatusBar.new(fs.rbar.clock, 1) do
+ Time.now
+ end,
+
+ StatusBar.new(fs.rbar.cpu_load, 5) do
+ File.read('/proc/loadavg').split[0..2].join(' ')
+ end,
+
+ StatusBar.new(fs.rbar.disk_space, 10) do
+ rem, use, dir = `df -h ~`.split[-3..-1]
+ "#{dir} #{use} used #{rem} free"
+ end,
+ ]
+ end
+
+# keyboard shortcuts
+ # focusing / showing
+ # focus client at left
+ key Key::FOCUS + Key::LEFT do
+ curr_view.ctl.write 'select left' rescue nil
+ end
+
+ # focus client at right
+ key Key::FOCUS + Key::RIGHT do
+ curr_view.ctl.write 'select right' rescue nil
+ end
+
+ # focus client below
+ key Key::FOCUS + Key::DOWN do
+ curr_view.ctl.write 'select down'
+ end
+
+ # focus client above
+ key Key::FOCUS + Key::UP do
+ curr_view.ctl.write 'select up'
+ end
+
+ # toggle focus between floating area and the columns
+ key Key::FOCUS + 'space' do
+ curr_view.ctl.write 'select toggle'
+ end
+
+ # apply equal-spacing layout to current column
+ key Key::ARRANGE + 'w' do
+ curr_area.layout = :default
+ end
+
+ # apply equal-spacing layout to all columns
+ key Key::ARRANGE + 'Shift-w' do
+ curr_view.columns.each do |a|
+ a.layout = :default
+ end
+ end
+
+ # apply stacked layout to currently focused column
+ key Key::ARRANGE + 'v' do
+ curr_area.layout = :stack
+ end
+
+ # apply stacked layout to all columns in current view
+ key Key::ARRANGE + 'Shift-v' do
+ curr_view.columns.each do |a|
+ a.layout = :stack
+ end
+ end
+
+ # apply maximized layout to currently focused column
+ key Key::ARRANGE + 'm' do
+ curr_area.layout = :max
+ end
+
+ # apply maximized layout to all columns in current view
+ key Key::ARRANGE + 'Shift-m' do
+ curr_view.columns.each do |a|
+ a.layout = :max
+ end
+ end
+
+ # focus the previous view
+ key Key::FOCUS + 'comma' do
+ prev_view.focus
+ end
+
+ # focus the next view
+ key Key::FOCUS + 'period' do
+ next_view.focus
+ end
+
+ # sending / moving
+ key Key::SEND + Key::LEFT do
+ grouping.each do |c|
+ c.send :left
+ end
+ end
+
+ key Key::SEND + Key::RIGHT do
+ grouping.each do |c|
+ c.send :right
+ end
+ end
+
+ key Key::SEND + Key::DOWN do
+ grouping.each do |c|
+ c.send :down
+ end
+ end
+
+ key Key::SEND + Key::UP do
+ 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
+ grouping.each do |c|
+ c.send :toggle
+ end
+ end
+
+ # close all grouped clients
+ key Key::SEND + 'Delete' do
+ 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
+ curr_client.swap :left
+ end
+
+ # swap the currently focused client with the one to its right
+ key Key::SWAP + Key::RIGHT do
+ curr_client.swap :right
+ end
+
+ # swap the currently focused client with the one below it
+ key Key::SWAP + Key::DOWN do
+ curr_client.swap :down
+ end
+
+ # swap the currently focused client with the one above it
+ key Key::SWAP + Key::UP do
+ curr_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>
+ key Key::SEND + 'v' do
+ choices = tags.map {|t| [t, "+#{t}", "-#{t}"]}.flatten
+
+ if target = show_menu(choices, 'tag as:')
+ grouping.each do |c|
+ case target
+ when /^\+/
+ c.tag $'
+
+ when /^\-/
+ c.untag $'
+
+ else
+ c.tags = target
+ end
+ end
+ end
+ end
+
+ # zooming / sizing
+ ZOOMED_SUFFIX = /~(\d+)$/
+
+ # Sends grouped clients to temporary view.
+ key Key::PREFIX + 'b' do
+ if curr_tag =~ ZOOMED_SUFFIX
+ src, num = $`, $1.to_i
+ dst = "#{src}~#{num+1}"
+ else
+ dst = "#{curr_tag}~1"
+ end
+
+ grouping.each do |c|
+ c.tag dst
+ end
+
+ v = View.new dst
+ v.focus
+ v.arrange_in_grid
+ #if c = grouping.shift then c.focus unless c.focus? end
+ end
+
+ # Sends grouped clients back to their original view.
+ key Key::PREFIX + 'Shift-b' do
+ src = curr_tag
+
+ if src =~ ZOOMED_SUFFIX
+ dst = $`
+
+ grouping.each do |c|
+ c.with_tags do
+ delete src
+
+ if empty?
+ push dst
+ else
+ dst = last
+ end
+ end
+ end
+
+ focus_view dst
+ end
+ end
+
+ # client grouping
+ # include/exclude the currently focused client from the grouping
+ key Key::GROUP + 'g' do
+ curr_client.toggle_group
+ end
+
+ # include all clients in the currently focused view into the grouping
+ key Key::GROUP + 'v' do
+ curr_view.group
+ end
+
+ # exclude all clients in the currently focused view from the grouping
+ key Key::GROUP + 'Shift-v' do
+ curr_view.ungroup
+ end
+
+ # include all clients in the currently focused area into the grouping
+ key Key::GROUP + 'c' do
+ curr_area.group
+ end
+
+ # exclude all clients in the currently focused column from the grouping
+ key Key::GROUP + 'Shift-c' do
+ curr_area.ungroup
+ end
+
+ # include all clients in the floating area into the grouping
+ key Key::GROUP + 'f' do
+ curr_view.floating_area.group
+ end
+
+ # exclude all clients in the currently focused column from the grouping
+ key Key::GROUP + 'Shift-f' do
+ curr_view.floating_area.ungroup
+ end
+
+ # include all clients in the managed areas into the grouping
+ key Key::GROUP + 'a' do
+ 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
+ curr_view.columns.each do |c|
+ c.ungroup
+ end
+ end
+
+ # invert the grouping in the currently focused view
+ key Key::GROUP + 'i' do
+ curr_view.toggle_group
+ end
+
+ # exclude all clients everywhere from the grouping
+ key Key::GROUP + 'n' do
+ Rumai.ungroup
+ end
+
+ # visual arrangement
+ key Key::ARRANGE + 't' do
+ curr_view.arrange_as_larswm
+ end
+
+ key Key::ARRANGE + 'g' do
+ curr_view.arrange_in_grid
+ end
+
+ key Key::ARRANGE + 'd' do
+ curr_view.arrange_in_diamond
+ end
+
+ # interactive menu
+ # launch an internal action by choosing from a menu
+ key Key::MENU + 'i' do
+ if choice = show_menu(@actionMenu + ACTIONS.keys, 'run action:')
+ unless action choice.to_sym
+ system choice << '&'
+ end
+ end
+ end
+
+ # launch an external program by choosing from a menu
+ key Key::MENU + 'e' do
+ if choice = show_menu(@programMenu, 'run program:')
+ system choice << '&'
+ end
+ end
+
+ # focus any view by choosing from a menu
+ 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
+ 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]
+ end
+
+ if target = show_menu(choices, 'show client:')
+ i = target.scan(/\d+/).first.to_i
+ clients[i].focus
+ end
+ end
+
+ # external programs
+ require 'fileutils'
+
+ # Open a new terminal and set its working directory
+ # to be the same as the currently focused terminal.
+ key Key::EXECUTE + 'x' do
+ c = curr_client
+ d = File.expand_path(c.label.read.split(' ', 2).last) rescue nil
+ d = ENV['HOME'] unless File.directory? d.to_s
+
+ FileUtils.cd(d) do
+ system 'terminal &'
+ end
+ end
+
+ key Key::EXECUTE + 'k' do
+ system 'firefox &'
+ end
+
+ key Key::EXECUTE + 'j' do
+ system 'thunar &'
+ end
+
+ # volume controls
+ def refresh_volume_display
+ level = `amixer get Master`.scan(/\d+%/).first
+ label = "volume #{level}"
+
+ b = Rumai.fs.rbar.volume
+ b.create unless b.exist?
+ b.write "#{Color::NORMAL} #{label}"
+
+ label
+ end
+
+ key(Key::PREFIX + 'Shift-Prior') do
+ system 'amixer set Master 3dB+'
+ refresh_volume_display
+ end
+
+ key(Key::PREFIX + 'Shift-Next') do
+ system 'amixer set Master 3dB-'
+ refresh_volume_display
+ end
+
+ key(Key::PREFIX + 'Shift-Return') do
+ system 'amixer set Master toggle'
+ refresh_volume_display
+ end
+
+ # music controls
+ print 'connecting to MPD... ',
+ begin
+ require 'rubygems'
+ require 'librmpd'
+
+ @mpd = MPD.new
+ @mpd.connect(true) # true keeps connection alive
+ rescue => e
+ puts e # ignore
+ end
+
+ key(Key::PREFIX + 'Prior') { @mpd.previous }
+ key(Key::PREFIX + 'Next') { @mpd.next }
+
+ key Key::PREFIX + 'Return' do # play / pause
+ if @mpd.stopped?
+ @mpd.play
+ else
+ # toggle play/pause
+ @mpd.pause = !@mpd.paused?
+ end
+ end
+
+ # load an MPD playlist
+ key(Key::PREFIX + 'Home') do
+ choices = @mpd.playlists
+
+ if target = show_menu(choices, 'load MPD playlist:')
+ @mpd.clear
+ @mpd.load target
+ @mpd.play
+ end
+ end
+
+ # add current song to an MPD playlist
+ key(Key::PREFIX + 'End') do
+ choices = @mpd.playlists
+
+ if target = show_menu(choices, 'add current song to MPD playlist:')
+ song = @mpd.current_song
+
+ file = File.join(File.expand_path('~/.mpd/playlists'), target + '.m3u')
+ list = File.read(file).split(/\r?\n/) rescue []
+
+ list.push song.file
+ list.uniq!
+
+ File.open(file, 'w') {|f| f.puts list }
+ end
+ end
+
+
+ # wmii-2 style client detaching
+ DETACHED_TAG = '|'
+
+ # Detach the current grouping from the current view.
+ key Key::PREFIX + 'd' do
+ grouping.each do |c|
+ c.with_tags do
+ delete curr_tag
+ push DETACHED_TAG
+ end
+ end
+ end
+
+ # Attach the most recently detached client onto the current view.
+ key Key::PREFIX + 'Shift-d' do
+ v = View.new DETACHED_TAG
+
+ if v.exist? and c = v.clients.last
+ c.with_tags do
+ delete DETACHED_TAG
+ push curr_tag
+ end
+ end
+ end
+
+ # number keys
+ 10.times do |i|
+ # focus the {i}'th view
+ key Key::FOCUS + i.to_s do
+ focus_view tags[i - 1] || i
+ end
+
+ # send current grouping to {i}'th view
+ key Key::SEND + i.to_s do
+ 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
+ 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
+ curr_view.arrange_in_grid i
+ end
+ end
+
+ # alphabet keys
+ # focus the view whose name begins with an alphabet key
+ ('a'..'z').each do |k|
+ key Key::VIEW + k do
+ if t = tags.grep(/^#{k}/i).first
+ focus_view t
+ end
+ end
+ end
+
+# wallpaper
+ system "xsetroot -solid #{Color::BACKGROUND.inspect} &"
+ system 'sh ~/.fehbg &' # set desktop wallpaper
+
+# bootstrap
+ action :status
+ action :rehash
diff --git a/wmiirc b/wmiirc
@@ -116,7 +116,7 @@ begin
end
# load user's configuration file
- load File.join(File.dirname(__FILE__), 'wmiirc-config.rb')
+ load File.join(File.dirname(__FILE__), 'config.rb')
# populate lbar with buttons for every tag
bar = fs.lbar
diff --git a/wmiirc-config.rb b/wmiirc-config.rb
@@ -1,712 +0,0 @@
-# Ruby-based configuration file for wmii.
-
-################################################################################
-# GENERAL CONFIGURATION
-################################################################################
-
-module Key
- MOD = 'Mod1'
- UP = 't'
- DOWN = 'n'
- LEFT = 'h'
- RIGHT = 's'
-
- PREFIX = MOD + '-Control-'
- FOCUS = PREFIX
- SEND = PREFIX + 'm,'
- SWAP = PREFIX + 'w,'
- ARRANGE = PREFIX + 'z,'
- GROUP = PREFIX + 'g,'
- VIEW = PREFIX + 'v,'
- MENU = PREFIX
- EXECUTE = PREFIX
-end
-
-module Mouse
- PRIMARY = 1
- MIDDLE = 2
- SECONDARY = 3
- SCROLL_UP = 4
- SCROLL_DOWN = 5
-end
-
-module Color
- { # Color tuples are "<text> <background> <border>"
- :NORMCOLORS => NORMAL = '#e0e0e0 #0a0a0a #202020',
- :FOCUSCOLORS => FOCUSED = '#ffffff #285577 #4c7899',
- :BACKGROUND => BACKGROUND = '#333333',
- }.each_pair do |k, v|
- ENV["WMII_#{k}"] = v
- end
-end
-
-WMII_FONT = '-*-bitstream vera sans mono-medium-r-*-*-16-*-*-*-*-*-*-*'
-
-
-################################################################################
-# DETAILED CONFIGURATION
-################################################################################
-
-# WM Configuration
-fs.ctl.write <<EOF
-grabmod #{Key::MOD}
-border 2
-font #{WMII_FONT}
-focuscolors #{Color::FOCUSED}
-normcolors #{Color::NORMAL}
-EOF
-
-# Column Rules
-fs.colrules.write <<EOF
-/./ -> 50+50
-EOF
-
-# Tagging Rules
-fs.tagrules.write <<EOF
-/Gran Paradiso - Restore Previous Session/ -> web
-/.*notes.*/ -> note
-/Deluge/ -> tor
-/Buddy List.*/ -> chat
-/XChat.*/ -> chat
-/Thunderbird.*/ -> mail
-/Liferea.*/ -> mail
-/Gimp.*/ -> gimp
-/xconsole.*/ -> ~
-/alsamixer.*/ -> ~
-/QEMU.*/ -> ~
-/XMMS.*/ -> ~
-/MPlayer.*/ -> ~
-/.*/ -> !
-/.*/ -> 1
-EOF
-
-# events
- event :CreateTag do |tag|
- bar = fs.lbar[tag]
- bar.create
- bar.write "#{Color::NORMAL} #{tag}"
- end
-
- event :DestroyTag do |tag|
- fs.lbar[tag].remove
- end
-
- event :FocusTag do |tag|
- fs.lbar[tag].write "#{Color::FOCUSED} #{tag}"
- end
-
- event :UnfocusTag do |tag|
- btn = fs.lbar[tag]
- btn.write "#{Color::NORMAL} #{tag}" if btn.exist?
- end
-
- event :UrgentTag do |tag|
- btn = fs.lbar[tag]
- btn.write "*#{tag}" if btn.exist?
- end
-
- event :NotUrgentTag do |tag|
- btn = fs.lbar[tag]
- btn.write tag if btn.exist?
- end
-
- event :LeftBarClick do |button, viewId|
- case button.to_i
- when Mouse::PRIMARY
- focus_view viewId
-
- when Mouse::MIDDLE
- # add the grouping onto the clicked view
- grouping.each do |c|
- c.tag viewId
- end
-
- when Mouse::SECONDARY
- # remove the grouping from the clicked view
- grouping.each do |c|
- c.untag viewId
- end
- end
- end
-
- event :ClientClick do |clientId, button|
- case button.to_i
- when Mouse::SECONDARY
- # toggle the clicked client's grouping
- Client.toggle_group clientId
- end
- end
-
- # wmii puts subsequent firefox instances on the same
- # view as the first instance. bypass this and move
- # the newly created firefox to the current view
- #
- # this "feature" applies to all programs
- # that provide window grouping hints. so
- # we'll just have this event handler
- # bypass the feature for ALL programs! :-(
- event :CreateClient do |id|
- c = Client.new(id)
-
- case c.label.read
- when "Gran Paradiso - Restore Previous Session"
- c.tags = 'web'
- when /Firefox|Gran Paradiso|jEdit/i
- c.tags = curr_tag
- c.focus
- end
- end
-
-# actions
- action :rehash do
- @programMenu = find_programs ENV['PATH'].squeeze(':').split(':')
- @actionMenu = find_programs File.dirname(__FILE__)
- end
-
- action :kill do
- fs.ctl.write 'quit'
- end
-
- action :quit do
- action :clear
- action :kill
- end
-
- action :clear do
- # firefox's restore session feature doesn't
- # work unless the whole process is killed.
- system 'killall firefox firefox-bin thunderbird thunderbird-bin deluge'
-
- # gnome-panel refuses to die by other means
- system 'killall -s TERM gnome-panel'
-
- until (clients = Rumai.clients).empty?
- clients.each do |c|
- begin
- c.focus
- c.ctl.write :kill
- rescue
- end
- end
- end
- end
-
- class StatusBar < Thread
- def initialize aBarNode, aRefreshRate, aBarColor = Color::NORMAL, &aBarText
- raise ArgumentError unless block_given?
-
- super aBarNode do |b|
- b.create unless b.exist?
-
- while true
- b.write "#{aBarColor} #{aBarText.call}"
- sleep aRefreshRate
- end
- end
- end
- end
-
- action :status do
- if defined? @statusBars
- @statusBars.each {|s| s.kill }
- end
-
- @statusBars = [
- StatusBar.new(fs.rbar.volume, 10) do
- refresh_volume_display
- end,
-
- StatusBar.new(fs.rbar.clock, 1) do
- Time.now
- end,
-
- StatusBar.new(fs.rbar.cpu_load, 5) do
- File.read('/proc/loadavg').split[0..2].join(' ')
- end,
-
- StatusBar.new(fs.rbar.disk_space, 10) do
- rem, use, dir = `df -h ~`.split[-3..-1]
- "#{dir} #{use} used #{rem} free"
- end,
- ]
- end
-
-# keyboard shortcuts
- # focusing / showing
- # focus client at left
- key Key::FOCUS + Key::LEFT do
- curr_view.ctl.write 'select left' rescue nil
- end
-
- # focus client at right
- key Key::FOCUS + Key::RIGHT do
- curr_view.ctl.write 'select right' rescue nil
- end
-
- # focus client below
- key Key::FOCUS + Key::DOWN do
- curr_view.ctl.write 'select down'
- end
-
- # focus client above
- key Key::FOCUS + Key::UP do
- curr_view.ctl.write 'select up'
- end
-
- # toggle focus between floating area and the columns
- key Key::FOCUS + 'space' do
- curr_view.ctl.write 'select toggle'
- end
-
- # apply equal-spacing layout to current column
- key Key::ARRANGE + 'w' do
- curr_area.layout = :default
- end
-
- # apply equal-spacing layout to all columns
- key Key::ARRANGE + 'Shift-w' do
- curr_view.columns.each do |a|
- a.layout = :default
- end
- end
-
- # apply stacked layout to currently focused column
- key Key::ARRANGE + 'v' do
- curr_area.layout = :stack
- end
-
- # apply stacked layout to all columns in current view
- key Key::ARRANGE + 'Shift-v' do
- curr_view.columns.each do |a|
- a.layout = :stack
- end
- end
-
- # apply maximized layout to currently focused column
- key Key::ARRANGE + 'm' do
- curr_area.layout = :max
- end
-
- # apply maximized layout to all columns in current view
- key Key::ARRANGE + 'Shift-m' do
- curr_view.columns.each do |a|
- a.layout = :max
- end
- end
-
- # focus the previous view
- key Key::FOCUS + 'comma' do
- prev_view.focus
- end
-
- # focus the next view
- key Key::FOCUS + 'period' do
- next_view.focus
- end
-
- # sending / moving
- key Key::SEND + Key::LEFT do
- grouping.each do |c|
- c.send :left
- end
- end
-
- key Key::SEND + Key::RIGHT do
- grouping.each do |c|
- c.send :right
- end
- end
-
- key Key::SEND + Key::DOWN do
- grouping.each do |c|
- c.send :down
- end
- end
-
- key Key::SEND + Key::UP do
- 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
- grouping.each do |c|
- c.send :toggle
- end
- end
-
- # close all grouped clients
- key Key::SEND + 'Delete' do
- 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
- curr_client.swap :left
- end
-
- # swap the currently focused client with the one to its right
- key Key::SWAP + Key::RIGHT do
- curr_client.swap :right
- end
-
- # swap the currently focused client with the one below it
- key Key::SWAP + Key::DOWN do
- curr_client.swap :down
- end
-
- # swap the currently focused client with the one above it
- key Key::SWAP + Key::UP do
- curr_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>
- key Key::SEND + 'v' do
- choices = tags.map {|t| [t, "+#{t}", "-#{t}"]}.flatten
-
- if target = show_menu(choices, 'tag as:')
- grouping.each do |c|
- case target
- when /^\+/
- c.tag $'
-
- when /^\-/
- c.untag $'
-
- else
- c.tags = target
- end
- end
- end
- end
-
- # zooming / sizing
- ZOOMED_SUFFIX = /~(\d+)$/
-
- # Sends grouped clients to temporary view.
- key Key::PREFIX + 'b' do
- if curr_tag =~ ZOOMED_SUFFIX
- src, num = $`, $1.to_i
- dst = "#{src}~#{num+1}"
- else
- dst = "#{curr_tag}~1"
- end
-
- grouping.each do |c|
- c.tag dst
- end
-
- v = View.new dst
- v.focus
- v.arrange_in_grid
- #if c = grouping.shift then c.focus unless c.focus? end
- end
-
- # Sends grouped clients back to their original view.
- key Key::PREFIX + 'Shift-b' do
- src = curr_tag
-
- if src =~ ZOOMED_SUFFIX
- dst = $`
-
- grouping.each do |c|
- c.with_tags do
- delete src
-
- if empty?
- push dst
- else
- dst = last
- end
- end
- end
-
- focus_view dst
- end
- end
-
- # client grouping
- # include/exclude the currently focused client from the grouping
- key Key::GROUP + 'g' do
- curr_client.toggle_group
- end
-
- # include all clients in the currently focused view into the grouping
- key Key::GROUP + 'v' do
- curr_view.group
- end
-
- # exclude all clients in the currently focused view from the grouping
- key Key::GROUP + 'Shift-v' do
- curr_view.ungroup
- end
-
- # include all clients in the currently focused area into the grouping
- key Key::GROUP + 'c' do
- curr_area.group
- end
-
- # exclude all clients in the currently focused column from the grouping
- key Key::GROUP + 'Shift-c' do
- curr_area.ungroup
- end
-
- # include all clients in the floating area into the grouping
- key Key::GROUP + 'f' do
- curr_view.floating_area.group
- end
-
- # exclude all clients in the currently focused column from the grouping
- key Key::GROUP + 'Shift-f' do
- curr_view.floating_area.ungroup
- end
-
- # include all clients in the managed areas into the grouping
- key Key::GROUP + 'a' do
- 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
- curr_view.columns.each do |c|
- c.ungroup
- end
- end
-
- # invert the grouping in the currently focused view
- key Key::GROUP + 'i' do
- curr_view.toggle_group
- end
-
- # exclude all clients everywhere from the grouping
- key Key::GROUP + 'n' do
- Rumai.ungroup
- end
-
- # visual arrangement
- key Key::ARRANGE + 't' do
- curr_view.arrange_as_larswm
- end
-
- key Key::ARRANGE + 'g' do
- curr_view.arrange_in_grid
- end
-
- key Key::ARRANGE + 'd' do
- curr_view.arrange_in_diamond
- end
-
- # interactive menu
- # launch an internal action by choosing from a menu
- key Key::MENU + 'i' do
- if choice = show_menu(@actionMenu + ACTIONS.keys, 'run action:')
- unless action choice.to_sym
- system choice << '&'
- end
- end
- end
-
- # launch an external program by choosing from a menu
- key Key::MENU + 'e' do
- if choice = show_menu(@programMenu, 'run program:')
- system choice << '&'
- end
- end
-
- # focus any view by choosing from a menu
- 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
- 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]
- end
-
- if target = show_menu(choices, 'show client:')
- i = target.scan(/\d+/).first.to_i
- clients[i].focus
- end
- end
-
- # external programs
- require 'fileutils'
-
- # Open a new terminal and set its working directory
- # to be the same as the currently focused terminal.
- key Key::EXECUTE + 'x' do
- c = curr_client
- d = File.expand_path(c.label.read.split(' ', 2).last) rescue nil
- d = ENV['HOME'] unless File.directory? d.to_s
-
- FileUtils.cd(d) do
- system 'terminal &'
- end
- end
-
- key Key::EXECUTE + 'k' do
- system 'firefox &'
- end
-
- key Key::EXECUTE + 'j' do
- system 'thunar &'
- end
-
- # volume controls
- def refresh_volume_display
- level = `amixer get Master`.scan(/\d+%/).first
- label = "volume #{level}"
-
- b = Rumai.fs.rbar.volume
- b.create unless b.exist?
- b.write "#{Color::NORMAL} #{label}"
-
- label
- end
-
- key(Key::PREFIX + 'Shift-Prior') do
- system 'amixer set Master 3dB+'
- refresh_volume_display
- end
-
- key(Key::PREFIX + 'Shift-Next') do
- system 'amixer set Master 3dB-'
- refresh_volume_display
- end
-
- key(Key::PREFIX + 'Shift-Return') do
- system 'amixer set Master toggle'
- refresh_volume_display
- end
-
- # music controls
- print 'connecting to MPD... ',
- begin
- require 'rubygems'
- require 'librmpd'
-
- @mpd = MPD.new
- @mpd.connect(true) # true keeps connection alive
- rescue => e
- puts e # ignore
- end
-
- key(Key::PREFIX + 'Prior') { @mpd.previous }
- key(Key::PREFIX + 'Next') { @mpd.next }
-
- key Key::PREFIX + 'Return' do # play / pause
- if @mpd.stopped?
- @mpd.play
- else
- # toggle play/pause
- @mpd.pause = !@mpd.paused?
- end
- end
-
- # load an MPD playlist
- key(Key::PREFIX + 'Home') do
- choices = @mpd.playlists
-
- if target = show_menu(choices, 'load MPD playlist:')
- @mpd.clear
- @mpd.load target
- @mpd.play
- end
- end
-
- # add current song to an MPD playlist
- key(Key::PREFIX + 'End') do
- choices = @mpd.playlists
-
- if target = show_menu(choices, 'add current song to MPD playlist:')
- song = @mpd.current_song
-
- file = File.join(File.expand_path('~/.mpd/playlists'), target + '.m3u')
- list = File.read(file).split(/\r?\n/) rescue []
-
- list.push song.file
- list.uniq!
-
- File.open(file, 'w') {|f| f.puts list }
- end
- end
-
-
- # wmii-2 style client detaching
- DETACHED_TAG = '|'
-
- # Detach the current grouping from the current view.
- key Key::PREFIX + 'd' do
- grouping.each do |c|
- c.with_tags do
- delete curr_tag
- push DETACHED_TAG
- end
- end
- end
-
- # Attach the most recently detached client onto the current view.
- key Key::PREFIX + 'Shift-d' do
- v = View.new DETACHED_TAG
-
- if v.exist? and c = v.clients.last
- c.with_tags do
- delete DETACHED_TAG
- push curr_tag
- end
- end
- end
-
- # number keys
- 10.times do |i|
- # focus the {i}'th view
- key Key::FOCUS + i.to_s do
- focus_view tags[i - 1] || i
- end
-
- # send current grouping to {i}'th view
- key Key::SEND + i.to_s do
- 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
- 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
- curr_view.arrange_in_grid i
- end
- end
-
- # alphabet keys
- # focus the view whose name begins with an alphabet key
- ('a'..'z').each do |k|
- key Key::VIEW + k do
- if t = tags.grep(/^#{k}/i).first
- focus_view t
- end
- end
- end
-
-# wallpaper
- system "xsetroot -solid #{Color::BACKGROUND.inspect} &"
- system 'sh ~/.fehbg &' # set desktop wallpaper
-
-# bootstrap
- action :status
- action :rehash