Sync ruby wmiirc.

This commit is contained in:
Kris Maglione 2009-10-10 14:57:00 -04:00
parent 6afe9e6262
commit b26fc42fed
5 changed files with 261 additions and 534 deletions

View File

@ -19,28 +19,3 @@ WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
Portions of this software originate from wmii <http://wmii.suckless.org>:
(the MIT license)
© 2006-2007 Kris Maglione <fbsdaemon@gmail.com>
© 2003-2006 Anselm R. Garbe <garbeam at suckless dot org>
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.

View File

@ -54,13 +54,26 @@ Installation:
mv ~/.wmii-hg ~/.wmii-hg.backup
git clone git://github.com/sunaku/wmiirc.git ~/.wmii-hg
# choose
cd ~/.wmii-hg
git checkout --track -b CHOICE origin/CHOICE # choices are:
+--------+------------------------------------------------+
| CHOICE | DESCRIPTION |
+--------+------------------------------------------------+
| dvorak | sunaku's personal configuration; DSK friendly! |
| qwerty | QWERTY port of sunaku's personal configuration |
| strict | port of the default wmiirc shipped with wmii |
| master | barebones template for starting from scratch |
+--------+------------------------------------------------+
# run
~/.wmii-hg/wmiirc
Documentation:
# see list of all key bindings
grep 'Mod.*#' ~/.wmii-hg/config.yaml
egrep '^ +\$\{\w+\}' ~/.wmii-hg/config.yaml
# read the configuration file
less ~/.wmii-hg/config.yaml
@ -71,7 +84,11 @@ Configuration:
Run ~/.wmii-hg/wmiirc to apply your changes.
Contribution:
Fork this project on GitHub and send pull requests.
Questions:
Send me an e-mail; see LICENSE for my address.
Send me an e-mail (see LICENSE for my address).

View File

@ -44,7 +44,7 @@ ACTIONS = Handler.new
KEYS = Handler.new
##
# When a block is given, registers a handler
# If a block is given, registers a handler
# for the given event and returns the handler.
#
# Otherwise, executes all handlers for the given event.
@ -106,7 +106,10 @@ end
# Instruction on what the user should enter or choose.
#
def key_menu choices, prompt = nil
words = %w[dmenu -b -fn].push(CONFIG['display']['font'])
words = ['dmenu', '-fn', CONFIG['display']['font']]
# show menu at the same location as the status bar
words << '-b' if CONFIG['display']['bar'] == 'bottom'
words.concat %w[-nf -nb -sf -sb].zip(
[
@ -145,11 +148,11 @@ end
# The choice that should be initially selected.
#
# If this choice is not included in the list
# of cohices, then this item will be made
# of choices, then this item will be made
# into a makeshift title-bar for the menu.
#
def click_menu choices, initial = nil
words = %w[wmii9menu]
words = ['wmii9menu']
if initial
words << '-i'
@ -169,6 +172,36 @@ def click_menu choices, initial = nil
choice unless choice.empty?
end
##
# Shows a key_menu() containing the given
# clients and returns the chosen client.
#
# If nothing was chosen, then nil is returned.
#
# ==== Parameters
#
# [prompt]
# Instruction on what the user should enter or choose.
#
# [clients]
# List of clients to present as choices to the user.
#
# If this parameter is not specified,
# its default value will be a list of
# all currently available clients.
#
def client_menu prompt = nil, clients = Rumai.clients
choices = []
clients.each_with_index do |c, i|
choices << "%d. [%s] %s" % [i, c[:tags].read, c[:label].read.downcase]
end
if target = key_menu(choices, prompt)
clients[target.scan(/\d+/).first.to_i]
end
end
##
# Returns the basenames of executable files present in the given directories.
#
@ -269,7 +302,7 @@ def load_config config_file
# applied. but a "bad command" error is raised nevertheless!
#
warn e.inspect
warn e.backtrace
warn e.backtrace.join("\n")
end
launch 'xsetroot', '-solid', CONFIG['display']['background']
@ -343,7 +376,7 @@ def load_config config_file
@status_button_by_name.each_value {|b| b.refresh }
end.call
end
##
# Returns the status button associated with the given name.
@ -400,14 +433,106 @@ def load_config config_file
end
# control
action 'reload' do
# reload this wmii configuration
reload_config
end
action 'rehash' do
# scan for available programs and actions
@programs = find_programs(ENV['PATH'].squeeze(':').split(':'))
end
# kill all currently open clients
action 'clear' do
# firefox's restore session feature does not
# work unless the whole process is killed.
system 'killall firefox firefox-bin thunderbird thunderbird-bin'
# gnome-panel refuses to die by any other means
system 'killall -s TERM gnome-panel'
Thread.pass until clients.each do |c|
begin
c.focus # XXX: client must be on current view in order to be killed
c.kill
rescue
# ignore
end
end.empty?
end
# kill the window manager only; do not touch the clients!
action 'kill' do
fs.ctl.write 'quit'
end
# kill both clients and window manager
action 'quit' do
action 'clear'
action 'kill'
end
event 'Unresponsive' do |client_id|
client = Client.new(client_id)
IO.popen('xmessage -nearmouse -file - -buttons Kill,Wait -print', 'w+') do |f|
f.puts 'The following client is not responding.', ''
f.puts client.inspect
f.puts client.label.read
f.puts '', 'What would you like to do?'
f.close_write
if f.read.chomp == 'Kill'
client.slay
end
end
end
event 'Notice' do |*argv|
unless defined? @notice_mutex
require 'thread'
@notice_mutex = Mutex.new
end
Thread.new do
# prevent notices from overwriting each other
@notice_mutex.synchronize do
button = fs.rbar['!notice']
button.create unless button.exist?
# display the notice
message = argv.join(' ')
LOG.info message # also log it in case the user is AFK
button.write "#{CONFIG['display']['color']['notice']} #{message}"
# clear the notice
sleep [1, CONFIG['display']['notice'].to_i].max
button.remove
end
end
end
%w[key action event].each do |param|
CONFIG['control'][param].each do |name, code|
eval "#{param}(#{name.inspect}) {|*argv| #{code} }",
TOPLEVEL_BINDING, "#{config_file}:control:#{param}:#{name}"
if settings = CONFIG['control'][param]
settings.each do |name, code|
if param == 'key'
# expand ${...} expressions in shortcut key sequences
name = name.gsub(/\$\{(.+?)\}/) { CONFIG['control'][$1] }
end
eval "#{param}(#{name.inspect}) {|*argv| #{code} }",
TOPLEVEL_BINDING, "#{config_file}:control:#{param}:#{name}"
end
end
end
# script
action 'status'
action 'rehash'
eval CONFIG['script']['after'].to_s, TOPLEVEL_BINDING,
"#{config_file}:script:after"
@ -418,5 +543,5 @@ end
#
def reload_config
LOG.info 'reload'
launch $0
exec $0
end

View File

@ -11,6 +11,16 @@
#++
##
# Program preferences.
#
program:
terminal: urxvt
browser: firefox
editor: mousepad
filer: thunar
##
# Appearance settings.
#
@ -26,7 +36,7 @@ display:
##
# The font to use in all text drawn by wmii.
#
font: -*-fixed-medium-r-*-*-18-*-*-*-*-*-*-*
font: -*-fixed-medium-r-*-*-13-*-*-*-*-*-*-*
##
# Thickness of client border (measured in pixels).
@ -48,11 +58,11 @@ display:
# http://wmii.suckless.org/scripts_n_snips/themes
#
color:
normal: "#c0c0c0 #0a0a0a #202020"
focus: "#ffffff #285577 #4c7899"
error: "#8a1f11 #FBE3E4 #FBC2C4" # from http://www.blueprintcss.org
notice: "#514721 #FFF6BF #FFD324" # from http://www.blueprintcss.org
success: "#264409 #E6EFC2 #C6D880" # from http://www.blueprintcss.org
normal: "#000000 #c1c48b #81654f"
focus: "#000000 #81654f #000000"
error: "#000000 #81654f #000000"
notice: "#000000 #a1956d #413328"
success: "#000000 #c1c48b #81654f"
##
# Color of desktop background.
@ -69,7 +79,7 @@ display:
mode: default
rule: |
/gimp/ -> 17+83+41
/.*/ -> 50+50
/.*/ -> 62+38 # Golden Ratio
##
# Mapping of clients to views they must appear on.
@ -80,10 +90,7 @@ display:
# Processing stops after the first matching mapping is applied.
#
client:
- /\b(xconsole|alsamixer|XMMS|Sonata)\b/ : 1
- /^pidgin:|:WeeChat\b/ : chat
- /\b(Liferea|GMail|Thunderbird)\b/ : mail
- /:(Firefox|Shiretoko):.*\bRestore\b.*\bSession\b/ : web
- /MPlayer|VLC/ : ~
##
# Self-refreshing buttons on the status bar.
@ -103,42 +110,6 @@ display:
# bar reflects the vertical order in which they are defined below.
#
status:
- music:
refresh: 15
content: |
unless defined? @music
require 'rubygems'
gem 'librmpd', '~> 0.1'
require 'librmpd'
@music = MPD.new
end
unless @music.connected?
@music.connect
end
music_state = (@music.stopped? || @music.paused?) ? '(-)' : '(>)'
if song = @music.current_song
artist = song.artist
title = song.title || (f = song.file and File.basename(f))
song_name = [artist, title].compact.join(': ')
end
[music_state, song_name].compact
- volume:
refresh: 60
content: |
['volume', `amixer get Master`.scan(/\d+%/).first]
- disk_space:
refresh: 600 # 10 minutes
content: |
free, used, path = `df -h ~`.split.last(3)
[path, used, 'used', free, 'free']
- system_load:
refresh: 10
content: |
@ -168,374 +139,154 @@ control:
#
grab: Mod1
##
# Prefix for all shortcuts.
#
mod: Mod1
##
# Direction keys.
#
up: k
down: j
left: h
right: l
##
# Key bindings.
#
# <key sequence>: <Ruby code to execute>
#
# A key sequence may contain ${...} expressions which
# are replaced with the value corresponding to '...'
# in the 'control' section of this configuration file.
#
# For example, if the 'control' section of
# this configuration file appeared like this:
#
# control:
# foo: Mod4
# bar: y
#
# and the following key sequence was used:
#
# ${foo}-${bar},${bar}
#
# then after ${...} expression replacement,
# that key sequence would appear like this:
#
# Mod4-y,y
#
key:
#---------------------------------------------------------------------------
# focus
#---------------------------------------------------------------------------
Mod1-Control-t: | # focus above client
${mod}-${up}: | # focus above client
curr_view.select(:up) rescue nil
Mod1-Control-n: | # focus below client
${mod}-${down}: | # focus below client
curr_view.select(:down) rescue nil
Mod1-Control-h: | # focus left client
${mod}-${left}: | # focus left client
curr_view.select(:left) rescue nil
Mod1-Control-s: | # focus right client
${mod}-${right}: | # focus right client
curr_view.select(:right) rescue nil
Mod1-Control-space: | # focus floating area (toggle)
${mod}-space: | # focus floating area (toggle)
curr_view.select(:toggle)
Mod1-Control-comma: | # focus previous view
prev_view.focus
Mod1-Control-period: | # focus next view
next_view.focus
# focus the view whose index or name equals the pressed number
Mod1-Control-1: focus_view( tags[0] || 1 )
Mod1-Control-2: focus_view( tags[1] || 2 )
Mod1-Control-3: focus_view( tags[2] || 3 )
Mod1-Control-4: focus_view( tags[3] || 4 )
Mod1-Control-5: focus_view( tags[4] || 5 )
Mod1-Control-6: focus_view( tags[5] || 6 )
Mod1-Control-7: focus_view( tags[6] || 7 )
Mod1-Control-8: focus_view( tags[7] || 8 )
Mod1-Control-9: focus_view( tags[8] || 9 )
Mod1-Control-0: focus_view( tags[9] || 10 )
# focus the view whose name begins with the pressed alphabet
Mod1-Control-v,a: t = tags.grep(/^a/i).first and focus_view(t)
Mod1-Control-v,b: t = tags.grep(/^b/i).first and focus_view(t)
Mod1-Control-v,c: t = tags.grep(/^c/i).first and focus_view(t)
Mod1-Control-v,d: t = tags.grep(/^d/i).first and focus_view(t)
Mod1-Control-v,e: t = tags.grep(/^e/i).first and focus_view(t)
Mod1-Control-v,f: t = tags.grep(/^f/i).first and focus_view(t)
Mod1-Control-v,g: t = tags.grep(/^g/i).first and focus_view(t)
Mod1-Control-v,h: t = tags.grep(/^h/i).first and focus_view(t)
Mod1-Control-v,i: t = tags.grep(/^i/i).first and focus_view(t)
Mod1-Control-v,j: t = tags.grep(/^j/i).first and focus_view(t)
Mod1-Control-v,k: t = tags.grep(/^k/i).first and focus_view(t)
Mod1-Control-v,l: t = tags.grep(/^l/i).first and focus_view(t)
Mod1-Control-v,m: t = tags.grep(/^m/i).first and focus_view(t)
Mod1-Control-v,n: t = tags.grep(/^n/i).first and focus_view(t)
Mod1-Control-v,o: t = tags.grep(/^o/i).first and focus_view(t)
Mod1-Control-v,p: t = tags.grep(/^p/i).first and focus_view(t)
Mod1-Control-v,q: t = tags.grep(/^q/i).first and focus_view(t)
Mod1-Control-v,r: t = tags.grep(/^r/i).first and focus_view(t)
Mod1-Control-v,s: t = tags.grep(/^s/i).first and focus_view(t)
Mod1-Control-v,t: t = tags.grep(/^t/i).first and focus_view(t)
Mod1-Control-v,u: t = tags.grep(/^u/i).first and focus_view(t)
Mod1-Control-v,v: t = tags.grep(/^v/i).first and focus_view(t)
Mod1-Control-v,w: t = tags.grep(/^w/i).first and focus_view(t)
Mod1-Control-v,x: t = tags.grep(/^x/i).first and focus_view(t)
Mod1-Control-v,y: t = tags.grep(/^y/i).first and focus_view(t)
Mod1-Control-v,z: t = tags.grep(/^z/i).first and focus_view(t)
${mod}-1: focus_view tags[0] || 1
${mod}-2: focus_view tags[1] || 2
${mod}-3: focus_view tags[2] || 3
${mod}-4: focus_view tags[3] || 4
${mod}-5: focus_view tags[4] || 5
${mod}-6: focus_view tags[5] || 6
${mod}-7: focus_view tags[6] || 7
${mod}-8: focus_view tags[7] || 8
${mod}-9: focus_view tags[8] || 9
${mod}-0: focus_view tags[9] || 10
#---------------------------------------------------------------------------
# move
#---------------------------------------------------------------------------
Mod1-Control-m,t: | # move grouping toward the top
${mod}-Shift-${up}: | # move grouping toward the top
grouping.each {|c| c.send(:up) rescue nil }
Mod1-Control-m,n: | # move grouping toward the bottom
${mod}-Shift-${down}: | # move grouping toward the bottom
grouping.each {|c| c.send(:down) rescue nil }
Mod1-Control-m,h: | # move grouping toward the left
${mod}-Shift-${left}: | # move grouping toward the left
grouping.each {|c| c.send(:left) rescue nil }
Mod1-Control-m,s: | # move grouping toward the right
${mod}-Shift-${right}: | # move grouping toward the right
grouping.each {|c| c.send(:right) rescue nil }
Mod1-Control-m,space: | # move grouping to floating area (toggle)
${mod}-Shift-space: | # move grouping to floating area (toggle)
grouping.each {|c| c.send(:toggle) rescue nil }
Mod1-Control-m,v: | # move grouping to chosen view
#
# 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
#
choices = tags.map {|t| [t, "+#{t}", "-#{t}"] }.flatten
if target = key_menu(choices, 'tag as:')
grouping.each do |c|
case target
when /^\+/ then c.tag $'
when /^\-/ then c.untag $'
else c.tags = target
end
end
end
Mod1-Control-m,Delete: | # kill all clients in grouping
grouping.each {|c| c.kill }
# move grouping to the view whose index or name equals the pressed number
Mod1-Control-m,1: grouping.each {|c| c.tags = tags[0] || 1 }
Mod1-Control-m,2: grouping.each {|c| c.tags = tags[1] || 2 }
Mod1-Control-m,3: grouping.each {|c| c.tags = tags[2] || 3 }
Mod1-Control-m,4: grouping.each {|c| c.tags = tags[3] || 4 }
Mod1-Control-m,5: grouping.each {|c| c.tags = tags[4] || 5 }
Mod1-Control-m,6: grouping.each {|c| c.tags = tags[5] || 6 }
Mod1-Control-m,7: grouping.each {|c| c.tags = tags[6] || 7 }
Mod1-Control-m,8: grouping.each {|c| c.tags = tags[7] || 8 }
Mod1-Control-m,9: grouping.each {|c| c.tags = tags[8] || 9 }
Mod1-Control-m,0: grouping.each {|c| c.tags = tags[9] || 10 }
${mod}-Shift-1: grouping.each {|c| c.tags = tags[0] || 1 }
${mod}-Shift-2: grouping.each {|c| c.tags = tags[1] || 2 }
${mod}-Shift-3: grouping.each {|c| c.tags = tags[2] || 3 }
${mod}-Shift-4: grouping.each {|c| c.tags = tags[3] || 4 }
${mod}-Shift-5: grouping.each {|c| c.tags = tags[4] || 5 }
${mod}-Shift-6: grouping.each {|c| c.tags = tags[5] || 6 }
${mod}-Shift-7: grouping.each {|c| c.tags = tags[6] || 7 }
${mod}-Shift-8: grouping.each {|c| c.tags = tags[7] || 8 }
${mod}-Shift-9: grouping.each {|c| c.tags = tags[8] || 9 }
${mod}-Shift-0: grouping.each {|c| c.tags = tags[9] || 10 }
#---------------------------------------------------------------------------
# swap
# client
#---------------------------------------------------------------------------
Mod1-Control-w,t: | # swap with above client
curr_client.swap(:up) rescue nil
${mod}-f: | # zoom client to fullscreen (toggle)
curr_client.fullscreen!
Mod1-Control-w,n: | # swap with below client
curr_client.swap(:down) rescue nil
Mod1-Control-w,h: | # swap with left client
curr_client.swap(:left) rescue nil
Mod1-Control-w,s: | # swap with right client
curr_client.swap(:right) rescue nil
# swap current client with the column whose index equals the pressed number
Mod1-Control-w,1: curr_client.swap 1
Mod1-Control-w,2: curr_client.swap 2
Mod1-Control-w,3: curr_client.swap 3
Mod1-Control-w,4: curr_client.swap 4
Mod1-Control-w,5: curr_client.swap 5
Mod1-Control-w,6: curr_client.swap 6
Mod1-Control-w,7: curr_client.swap 7
Mod1-Control-w,8: curr_client.swap 8
Mod1-Control-w,9: curr_client.swap 9
Mod1-Control-w,0: curr_client.swap 10
${mod}-Shift-c: | # kill the current client
curr_client.kill
#---------------------------------------------------------------------------
# column
#---------------------------------------------------------------------------
Mod1-Control-z,w: | # apply equal-spacing layout to current column
curr_area.layout = :default
${mod}-d: | # apply equal-spacing layout to current column
curr_area.layout = 'default-max'
Mod1-Control-z,Shift-w: | # apply equal-spacing layout to all columns
curr_view.columns.each do |a|
a.layout = :default
end
Mod1-Control-z,v: | # apply stacked layout to current column
${mod}-v: | # apply stacked layout to current column
curr_area.layout = 'stack-max'
Mod1-Control-z,Shift-v: | # apply stacked layout to all columns
curr_view.columns.each do |a|
a.layout = 'stack-max'
end
Mod1-Control-z,m: | # apply maximized layout to current column
${mod}-m: | # apply maximized layout to current column
curr_area.layout = 'stack+max'
Mod1-Control-z,Shift-m: | # apply maximized layout to all columns
curr_view.columns.each do |a|
a.layout = 'stack+max'
end
#---------------------------------------------------------------------------
# group
#---------------------------------------------------------------------------
Mod1-Control-g,g: | # toggle current client from grouping
curr_client.group!
Mod1-Control-g,c: | # add clients in current area to grouping
curr_area.group
Mod1-Control-g,Shift-c: | # remove clients in current area from grouping
curr_area.ungroup
Mod1-Control-g,f: | # add clients in floating area to grouping
Area.floating.group
Mod1-Control-g,Shift-f: | # remove clients in floating area from grouping
Area.floating.ungroup
Mod1-Control-g,m: | # add clients in managed areas to grouping
curr_view.managed_areas.each {|a| a.group }
Mod1-Control-g,Shift-m: | # remove clients in managed areas from grouping
curr_view.managed_areas.each {|a| a.ungroup }
Mod1-Control-g,v: | # add clients in current view to grouping
curr_view.group
Mod1-Control-g,Shift-v: | # remove clients in current view from grouping
curr_view.ungroup
Mod1-Control-g,i: | # invert the grouping in the current view
curr_view.group!
Mod1-Control-g,Shift-i: | # invert the grouping in all views
Rumai.group!
Mod1-Control-g,n: | # remove all clients everywhere from grouping
Rumai.ungroup
#---------------------------------------------------------------------------
# detach
#---------------------------------------------------------------------------
Mod1-Control-d: | # detach grouping from current view
grouping.each do |c|
c.with_tags do
delete curr_tag
push DETACHED_TAG
end
end
Mod1-Control-Shift-d: | # attach most recently detached client
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
#---------------------------------------------------------------------------
# zoom
#---------------------------------------------------------------------------
Mod1-Control-f: | # zoom client to fullscreen (toggle)
curr_client.fullscreen!
Mod1-Control-b: | # copy grouping to temporary view
clients = grouping
unless clients.empty?
# determine new view
if curr_tag =~ ZOOMED_SUFFIX
src, num = $`, $1.to_i
dst = "#{src}~#{num+1}"
else
dst = "#{curr_tag}~1"
end
# add clients to new view
clients.each {|c| c.tag dst }
# focus new view
v = View.new dst
v.focus
v.arrange_in_grid
# propagate focus into new view
clients.first.focus v
end
Mod1-Control-Shift-b: | # return grouping to original view
clients = grouping
unless clients.empty?
src = curr_tag
if src =~ ZOOMED_SUFFIX
# determine new view
dst = $`
# remove clients from old view
clients.each do |c|
c.with_tags do
delete src
if empty?
push dst
else
dst = last
end
end
end
# focus new view
v = View.new dst
v.focus
# propagate focus into original view
clients.first.focus v
end
end
#---------------------------------------------------------------------------
# arrange
#---------------------------------------------------------------------------
Mod1-Control-z,t: | # arrange clients in current view like LarsWM does
curr_view.arrange_as_larswm
Mod1-Control-z,g: | # arrange clients in current view like a grid
curr_view.arrange_in_grid
Mod1-Control-z,d: | # arrange clients in current view like a diamond
curr_view.arrange_in_diamond
# apply grid layout with the pressed number of clients per column
Mod1-Control-z,1: curr_view.arrange_in_grid 1
Mod1-Control-z,2: curr_view.arrange_in_grid 2
Mod1-Control-z,3: curr_view.arrange_in_grid 3
Mod1-Control-z,4: curr_view.arrange_in_grid 4
Mod1-Control-z,5: curr_view.arrange_in_grid 5
Mod1-Control-z,6: curr_view.arrange_in_grid 6
Mod1-Control-z,7: curr_view.arrange_in_grid 7
Mod1-Control-z,8: curr_view.arrange_in_grid 8
Mod1-Control-z,9: curr_view.arrange_in_grid 9
Mod1-Control-z,0: curr_view.arrange_in_grid 9999 # make one giant column
#---------------------------------------------------------------------------
# menu
#---------------------------------------------------------------------------
Mod1-Control-i: | # run internal action chosen from a menu
${mod}-a: | # run internal action chosen from a menu
if choice = key_menu(actions, 'run action:')
action choice
end
Mod1-Control-e: | # run external program chosen from a menu
${mod}-p: | # run external program chosen from a menu
if choice = key_menu(@programs, 'run program:')
launch choice
end
Mod1-Control-u: | # focus view chosen from a menu
${mod}-t: | # focus view chosen from a menu
if choice = key_menu(tags, 'show view:')
focus_view choice
end
Mod1-Control-a: | # focus client chosen from a menu
choices = []
clients.each_with_index do |c, i|
choices << "%d. [%s] %s" % [i, c[:tags].read, c[:label].read.downcase]
end
if target = key_menu(choices, 'show client:')
i = target.scan(/\d+/).first.to_i
clients[i].focus
end
#---------------------------------------------------------------------------
# launcher
#---------------------------------------------------------------------------
Mod1-Control-x: | # launch a terminal
${mod}-Return: | # launch a terminal
#
# Launch a new terminal and set its
# working directory to be the same
@ -562,77 +313,9 @@ control:
require 'fileutils'
FileUtils.cd work do
launch 'urxvt'
launch CONFIG['program']['terminal']
end
Mod1-Control-k: | # launch a web browser
launch 'firefox'
Mod1-Control-j: | # launch a file manager
launch 'thunar'
Mod1-Control-q: | # launch a note taker
launch 'mousepad'
#---------------------------------------------------------------------------
# music
#---------------------------------------------------------------------------
Mod1-Control-Prior: | # previous song
@music.previous rescue nil
status 'music'
Mod1-Control-Next: | # next song
@music.next rescue nil
status 'music'
Mod1-Control-Return: | # pause song (toggle)
begin
if @music.stopped?
@music.play
else
@music.pause = !@music.paused?
end
rescue
# ignore
end
status 'music'
Mod1-Control-Home: | # load a playlist
if list = key_menu(@music.playlists, 'load playlist:')
@music.clear
@music.load list
@music.play
end
Mod1-Control-End: | # add current song to a playlist
if list = key_menu(@music.playlists, 'add current song to playlist:')
file = File.join(File.expand_path('~/.mpd/playlists'), list + '.m3u')
songs = File.readlines(file) rescue []
songs << @music.current_song.file
songs.uniq!
File.open(file, 'w') {|f| f.puts songs }
end
#---------------------------------------------------------------------------
# volume
#---------------------------------------------------------------------------
Mod1-Control-Shift-Prior: | # increase volume
system 'amixer set Master 3dB+'
status 'volume'
Mod1-Control-Shift-Next: | # decrease volume
system 'amixer set Master 3dB-'
status 'volume'
Mod1-Control-Shift-Return: | # mute volume (toggle)
system 'amixer set Master toggle'
status 'volume'
##
# Event handlers.
#
@ -691,47 +374,6 @@ control:
RightBarClick: |
status_click *argv.reverse
Unresponsive: |
client_id = argv[0]
client = Client.new(client_id)
IO.popen('xmessage -nearmouse -file - -buttons Kill,Wait -print', 'w+') do |f|
f.puts 'The following client is not responding.', ''
f.puts client.inspect
f.puts client.label.read
f.puts '', 'What would you like to do?'
f.close_write
if f.read.chomp == 'Kill'
client.slay
end
end
Notice: |
unless defined? @notice_mutex
require 'thread'
@notice_mutex = Mutex.new
end
Thread.new do
# prevent notices from overwriting each other
@notice_mutex.synchronize do
button = fs.rbar['!notice']
button.create unless button.exist?
# display the notice
message = argv.join(' ')
LOG.info message # also log it in case the user is AFK
button.write "#{CONFIG['display']['color']['notice']} #{message}"
# clear the notice
sleep [1, CONFIG['display']['notice'].to_i].max
button.remove
end
end
ClientMouseDown: |
client_id, mouse_button = argv
@ -753,35 +395,6 @@ control:
# <action name>: <Ruby code to execute>
#
action:
reload: | # reload this wmii configuration
reload_config
rehash: | # scan for available programs and actions
@programs = find_programs(ENV['PATH'].squeeze(':').split(':'))
clear: | # kill all clients
# firefox's restore session feature does not
# work unless the whole process is killed.
system 'killall firefox firefox-bin thunderbird thunderbird-bin'
# gnome-panel refuses to die by any other means
system 'killall -s TERM gnome-panel'
Thread.pass until clients.each do |c|
begin
c.focus # XXX: client must be on current view in order to be killed
c.kill
rescue
# ignore
end
end.empty?
kill: | # kill the window manager only; do not touch the clients!
fs.ctl.write 'quit'
quit: | # kill both clients and window manager
action 'clear'
action 'kill'
##
@ -792,13 +405,5 @@ control:
# after: <Ruby code to execute after processing this file>
#
script:
before: |
DETACHED_TAG = '|'
ZOOMED_SUFFIX = /~(\d+)$/
after: |
action 'rehash'
# desktop wallpaper
system 'sh ~/.fehbg'
before:
after:

View File

@ -1,5 +1,7 @@
#!/usr/bin/env ruby
#
# Bootloader for wmii configuration.
#
#--
# Copyright protects this work.
# See LICENSE file for details.
@ -25,11 +27,14 @@ begin
LOG.info 'birth'
# load configuration library
config_home = File.dirname(__FILE__)
config_libs = File.join(config_home, 'config.rb')
config_file = File.join(config_home, 'config.yaml')
def find_config file
base_dirs = ENV['WMII_CONFPATH'].to_s.split(/:+/)
ruby_dirs = base_dirs.map {|dir| File.join(dir, 'ruby') }
require config_libs
Dir["{#{base_dirs.zip(ruby_dirs).join(',')}}/#{file}"].first
end
require find_config('config.rb')
# terminate any existing wmiirc
fs.event.write 'Start wmiirc'
@ -39,7 +44,7 @@ begin
end
# apply user configuration
load_config config_file
load_config find_config('config.yaml')
# setup tag bar (buttons that correspond to views)
fs.lbar.clear