hoodwink.d enhanced


A Few Wmii-3 Hacks #

by why in inspect

mfp: I guess this makes me a weirdo (maybe even more so amongst Rubyists, which would often kill for a Mac — their third or fourth one) but I much prefer this to Exposé+Dock+Dashboard and all that eye candy (not that I’ve used it that much, but more than it took me to like wmii — maybe the learning curve is too steep? :-P).

I’m all hot in the collar over this as well. Totally lovestruck. They took all the right cues from Plan 9. I’ve been enjoying Mauricio’s script. Here’s a couple minor hacks.

PLEASE NOTE: Mauricio’s hacks (and mine) only work with the stable wmii-3 just released.

Mmmnn. Tailing in default mode.

Resizing Hotkeys

I don’t ever swap two windows. So I used those hotkeys for pushing the edges of a window wider. For example, Alt+Control+k adds 48 pixels to the right side of a window. Now, if that window is up against the right-hand side of the screen, this’ll have no affect.

  on_key("#{MODKEY}-Control-#{UP}") { 
    write "/view/sel/sel/geom", "+0 -48 +0 +48" }
  on_key("#{MODKEY}-Control-#{DOWN}") { 
    write "/view/sel/sel/geom", "+0 +0 +0 +48" }
  on_key("#{MODKEY}-Control-#{RIGHT}") { 
    write "/view/sel/sel/geom", "+0 +0 +48 +0" }
  on_key("#{MODKEY}-Control-#{LEFT}") { 
    write "/view/sel/sel/geom", "-48 +0 +48 +0" }

No Numbers

Tags correspond to Alt+num

I don’t use the numeric tags. I use about ten verbose tags regularly and wmii-3 displays them in order in the bar. So I use the numeric keys to tab quickly between them. (Alt+1 is the first tag, Alt+2 is the second…) I got this from Suraj N. Kurapati (who also posted his Ruby wmiirc.

I’ve also added Alt+Shift+num which adds the tag at num position to the current window’s set of tags. And Alt+Control+num removes the tag at num position from the current window’s set.

  (0..9).each do |i|
    k = (i - 1) % 10
    on_key("#{MODKEY}-#{i}") do
       view(read('/tags').split[k] || i)
    on_key("#{MODKEY}-Shift-#{i}") do
      key = read('/tags').split[k] || i
      oldtags = read("/view/sel/sel/tags").split(/\+/)
      write "/view/sel/sel/tags", (oldtags + [key]).uniq.join("+")
    on_key("#{MODKEY}-Control-#{i}") do
      key = read('/tags').split[k] || i
      oldtags = read("/view/sel/sel/tags").split(/\+/)
      write "/view/sel/sel/tags", (oldtags - [key]).uniq.join("+")

Action Commands

Mauricio lets you setup some commands in your Ruby script which you can get to from the menu. For example, Alt+a google launches a search in your browser using the current cursor selection as the search terms. I’ve just extended this a bit by allowing the search terms right on the bar. So: Alt+a google houyhnhnms.

  on_key("#{MODKEY}-a") do
    internal_actions = {
      "browser" => lambda do |selection|
        selection ||= `wmiipsel`.strip
        case browser = ENV["BROWSER"]
        when nil: system "/etc/alternatives/x-www-browser '#{selection}' &" 
        else system "#{browser} '#{selection}' &" 
      "google" => lambda do |*selection|
        require 'cgi'
        if selection
          selection = CGI.escape(selection.join(" "))
          selection = CGI.escape(%!"#{`wmiipsel`.strip}"!)
        url = "http://www.google.com/search?q=#{selection}" 
        case browser = ENV["BROWSER"]
        when nil: system "/etc/alternatives/x-www-browser '#{url}' &" 
        else system "#{browser} '#{url}' &" 
    wmiimenu((action_list + internal_actions.keys).sort) do |choice|
      if internal_actions[choice]
        choices = choice.split(/\s+/)
        if internal_actions[choices.first]
        system("$HOME/.wmii-3/#{choice} &") if /^\s*$/ !~ choice

For some other shell snippets: snippets. And, for more about tagging: tagging.

said on 13 Jun 2006 at 12:00

I don’t get it. Is Wmii a very basic but exceptionally scriptable window manager, and these are customified ruby scripts for making it dance a productive jig?

said on 13 Jun 2006 at 12:46

why, you are making me nostalgic for my wmii. Although I am enjoying expose on my macbook =)

said on 13 Jun 2006 at 13:23

wmii-3 definitively rocks … althugh a little bit slow on Cygwin.

said on 13 Jun 2006 at 13:37

Do you often use floating windows? (I’m in managed mode 97% of the time).

I’ve been thinking about numeric tags for a while; my problem is that I have too many tags to use ALT +NUM effectively - counting takes too much time. Some views are fairly static and I’ve just learned that 2 = browser, 3 = mail, etc. I’ve tried to change the labels in the bar to have the num along the tag, but wmii removes it as soon as you add/remove a tag. (I read that this has been externalized in the devel version, so it’d do nicely there). My bar looks like this atm.:

A few other things I’m quite fond of:
  • namespaces&quick switching between tags within a namespace
  • retag&jump to new tag

I also have a basic IXP extension more or less working.

said on 13 Jun 2006 at 15:08

That’s a funny coincidence; I chose today to switch over to stumpwm, a WM written entirely in Common Lisp. If your window manager doesn’t have a REPL , that’s weak sauce!

said on 13 Jun 2006 at 18:29

I think I’ll keep my 8-1/2 thank you.

said on 13 Jun 2006 at 20:26

I use a mac (quite happily) and I find that using quicksilver triggers (both mouse and keyboard) I am able to accomplish all of my highly trafficked gui navigation pathways.

I stopped using expose shortly after getting the mac, too much graphics, not enough response. It would be nice to have something like quicksilver more tightly integrated however.

said on 14 Jun 2006 at 16:57

Enhanced client tagging ; `+tag` appends tag, `-tag` removes tag, `tag` sets the tag :

  on_key("#{MODKEY}-Shift-t") do
    old_tags = read('/view/sel/sel/tags').split(/\+/)
    wmiimenu(read("/tags")) do |new_tag|
      write '/view/sel/sel/tags', case new_tag
      when /^\+/ : old_tags.push(new_tag.sub(/^\+/,'')).join('+')
      when /^-/  : old_tags.reject{|t| t == new_tag.sub(/^-/,'')}.join('+')
      when /^$/  : old_tags.join('+')
      else; new_tag; end
said on 14 Jun 2006 at 21:50

This is pretty ugly, but it emulates ion’s fullscreen functionality.

Hit Mod-f to make the current window fullscreen. Hit it again to go back to where you were.

  on_key("#{MODKEY}-f") do
      oldtags = read("/view/sel/sel/tags").split(/\+/)
      if oldtags.include? "buffer" 
          write "/view/sel/sel/tags", (oldtags - ["buffer"]).uniq.join("+")
          current = read("/view/name")
          oldtags = [current] + (oldtags - [current]) # stick the current tag on the beginning, for later retrieval
          write "/view/sel/sel/tags", (oldtags + ["buffer"]).uniq.join("+")

said on 16 Jun 2006 at 09:55

Please share your color scheme? I like it very much!

said on 16 Jun 2006 at 11:41

I am in the middle of a re-write of this Ruby script to make it modular and add many new helper methods to make things-especially bar-handling-much easier. I am using WMII -3 full time BECAUSE of this script!

said on 16 Jun 2006 at 12:34


 WMII_SELCOLORS='#FFFFFF #248047 #147027'
said on 16 Jun 2006 at 23:01

Thanks! :)

said on 17 Jun 2006 at 06:22

I’ve been playing with this for a few days myself. I’m using mfp’s script with _why’s changes, and I’m quite happy with it. Now, I’m trying to figure out how to emulate something similar to Windows’ Startup folder—automatically starting up a few programs in their appropriate views when wmii is first loaded. For example, when I first log in, I always open up two SSH sessions to my home server to run pine and pork. So here’s what I’ve got so far:

personal_view_name = 'personal'
if read("/tags").grep(/^#{personal_view_name}$/).size == 0
   real_rules = read "/def/rules" 
   write "/def/rules", "/.*/ -> #{personal_view_name}\n" 
   system "/etc/alternatives/x-terminal-emulator -e /usr/bin/ssh username@myserver.net &" 
   system "/etc/alternatives/x-terminal-emulator -e /usr/bin/ssh username@myserver.net &" 
   write "/def/rules", real_rules

(Note: I’m relatively new to Ruby and haven’t yet picked up the coding style—if there’s a better, shorter, or more fun way to code the above, please feel free to share.)

Anyway, the problem, of course, is that this code comes before the call to reactor.main_loop, so by the time wmii gets around to spotting the new clients, the stock /def/rules file is back in place, and the clients get opened up in the current view.

Does anyone have any ideas? Perhaps a way to “hand-crank” the loop for one iteration to get it to handle the newly-created clients?

Maybe this would be better discussed on the wmii mailing list.

said on 17 Jun 2006 at 07:25

OK, it turns out that konsole (which I’m using as my shell) lets you set a window title with -T, so I can give it a particular title and use regular rules to catch it. I’d still like to figure out how to launch a program with a particular tag in general, though.

said on 17 Jun 2006 at 14:11

I have an IXP extension (it’s around 5 times faster than calling wmiir) & an improved script. Coming soon.

said on 20 Jun 2006 at 20:23

I’ve got a wmii control script in elisp with emacs-ish key bindings, if anyone is into that sort of thing. (Sorry, not ruby-related.)


Thanks for the tip, _why. I’ve ditched the whole CL window manager, and wmii-3 makes me gleeful.

said on 21 Jun 2006 at 04:05

New, much improved version available


technomancy: as for running programs in a given view at startup -> wmii will retag them, no matter whether the main_loop is running or not. You can just set a default rule

/.*/ -> mytag
sleep for a second or two, and then set the actual rules.

said on 21 Jun 2006 at 12:57

mfp: Please do not hesitate to post your IXP bindings, even if you think it’s not perfect (although I’m sure it is!)

said on 22 Jun 2006 at 15:15

Alright, my wmiirc is running using IXP .so right now. I’ll be testing it for a while before the release.

Just a couple figures to summarize the difference: the response time for ALT +j has gone from 0.06 seconds to about 0.0015s, a 40X speedup (the standard deviation seems very small, but I haven’t measured it precisely yet). View switching is sub-millisecond (around 0.2ms on my box).

said on 23 Jun 2006 at 08:50

I’m interested in testing it under Cygwin, as it seems that process fork is quite long under Cygwin, and thus spawning a wmiir each time is quite heavy ;)

said on 26 Jun 2006 at 04:49

I had some problems with rb_thread_select and rewrote part of libixp to use Ruby’s socket extension. Unfortunately I’m running into some weird crashes (deadlocks), so I’ll need some more time.

Meanwhile, I’ve been working on a new configuration scheme which allows for easy distribution of plugins and simpler upgrades that preserve your settings. ruby-wmii 0.3.0 should be out in short.

said on 29 Jun 2006 at 12:28

sweetness! this is a totally unexpected way for me to learn ruby, as well as a relatively easy way to add some features i’ve been wanting in wmii.

although i do want to point out that the font in your screenshot is “fixed”, not “glispbold”, so maybe your font config is messed up?

12 Jul 2010 at 22:15

* do fancy stuff in your comment.