Scripting wmii column widths with Python
I mentioned in my previous post on using wmii with Gnome that I had written a script for resizing the column widths in wmii. This is the followup post. Note, I am using the 20080520 snapshot of wmii. This doesn't work with wmii 3.6 (as Marco commented below).
To incrementally change window sizes, I use the following in my ~/.wmii-3.5/wmiirc
file:
Key $MODKEY-y # shrink horizontally wmiir xwrite /tag/sel/ctl grow sel sel right -10 wmiir xwrite /tag/sel/ctl grow sel sel left -10 Key $MODKEY-u # grow horizontally wmiir xwrite /tag/sel/ctl grow sel sel right 10 wmiir xwrite /tag/sel/ctl grow sel sel left 10 Key $MODKEY-i # shrink vertically wmiir xwrite /tag/sel/ctl grow sel sel down -10 wmiir xwrite /tag/sel/ctl grow sel sel up -10 Key $MODKEY-o # grow vertically wmiir xwrite /tag/sel/ctl grow sel sel down 10 wmiir xwrite /tag/sel/ctl grow sel sel up 10 Key $MODKEY-Shift-y # shrink horizontally wmiir xwrite /tag/sel/ctl grow sel sel right -2 wmiir xwrite /tag/sel/ctl grow sel sel left -2 Key $MODKEY-Shift-u # grow horizontally wmiir xwrite /tag/sel/ctl grow sel sel right 2 wmiir xwrite /tag/sel/ctl grow sel sel left 2 Key $MODKEY-Shift-i # shrink vertically wmiir xwrite /tag/sel/ctl grow sel sel down -2 wmiir xwrite /tag/sel/ctl grow sel sel up -2 Key $MODKEY-Shift-o # grow vertically wmiir xwrite /tag/sel/ctl grow sel sel down 2 wmiir xwrite /tag/sel/ctl grow sel sel up 2
In addition to incrementally changing column widths, I wanted to be able to switch to predetermined column width ratios with a keyboard shortcut. For example, I wanted to be able to set the column widths at a 20/80 ratio, a 40/60 ratio, a 50/50 ratio, a 60/40 ratio, and so on. So I hacked a Python script to do this. It is pretty ugly because I first grow the window by a set amount, measure the change in size, then grow it again to the correct width. If anyone knows of a better way to do this, please let me know. I'm posting my solution here in case anyone else wanted to do the same thing and got stuck. (Note, this script only works with two columns)
UPDATE 2009-12-21: I just learned from the new wmii documentation that I can specify a grow amount in pixels by suffixing it with "px". This means I no longer have to perform the ugly, extra grow-then-measure step in my script. I'm not sure if this is a newly added change or if it is just newly documented. I am now using wmii 3.9b1. I have updated the script below to use the new method. Also, the script now works with more than two columns. I kept the old method for reference.
#!/usr/bin/env python
import os
import re
import sys
class Wmii:
"""
wmiir xwrite /tag/sel/ctl grow col row side increment
col: column number of the window to grow
row: row number of the window to grow
side: the side to grow. one of left, right, up, or down
increment: the number of pixels to grow. use a positive number to grow larger
and a negative number to grow smaller
"""
def set_column_widths(self, width_list):
"""Use the 'grow' command to set the column widths to those specified.
Widths are specified in percentages.
"""
total_width_perc = sum([float(width) for width in width_list])
for i, width_perc in enumerate(width_list[:-1]):
self.read_current_col_widths()
total_width_px = float(sum(self.curr_colwidths))
new_width_px = float(width_perc) / total_width_perc * total_width_px
grow_amount_px = int(round(new_width_px - self.curr_colwidths[i]))
self.xwrite("/tag/sel/ctl grow %d 1 right %dpx" % (i+1, grow_amount_px))
def read_current_col_widths(self):
"""'wmiir read /tag/sel/index' and set the attribute, self.curr_colwidths.
self.curr_colwidths is a list of the width (ints) (in pixels) of each
column in the view.
"""
lines = self.read("/tag/sel/index")
self.curr_colwidths = []
for line in lines:
match = re.search(r"# [^~]+ \d+ (\d+)", line)
if match:
self.curr_colwidths.append(int(match.group(1)))
print self.curr_colwidths
def xwrite(self, path_and_value):
"""Use the xwrite form."""
cmd = "wmiir xwrite %s" % path_and_value
print cmd
os.system(cmd)
def read(self, path):
"""Return a list of the lines returned by "wmii read path" """
return os.popen4("wmiir read " + path)[1].readlines()
if __name__ == "__main__":
w = Wmii()
w.set_column_widths(sys.argv[1:])
#!/usr/bin/env python
import os
import re
import sys
class Wmii:
"""
wmiir xwrite /tag/sel/ctl grow col row side increment
col: column number of the window to grow
row: row number of the window to grow
side: the side to grow. one of left, right, up, or down
increment: the number of pixels to grow. use a positive number to grow larger
and a negative number to grow smaller
"""
def __init__(self):
pass
def set_column_widths(self, width0, width1):
"""Use the 'grow' command to set the column widths to those specified.
Widths are specified in percentages.
Currently only works with 2 columns.
"""
self.determine_pixels_per_grow_horiz()
new_width0 = sum(self.curr_colwidths) * (float(width0) /
(float(width0)+float(width1)))
grow_amount = int(round((new_width0-self.curr_colwidths[0]) /
self.pixels_per_grow_increment))
self.xwrite("/tag/sel/ctl grow 1 1 right %d" % grow_amount)
def determine_pixels_per_grow_horiz(self):
"""Try growing by an increment of 1 and record the number of pixels changed.
"""
self.read_current_col_widths()
prev_colwidth0 = self.curr_colwidths[0]
self.xwrite("/tag/sel/ctl grow 1 1 right 1")
self.read_current_col_widths()
self.pixels_per_grow_increment = self.curr_colwidths[0] - prev_colwidth0
def read_current_col_widths(self):
"""'wmiir read /tag/sel/index' and set the attribute, self.curr_colwidths.
self.curr_colwidths is a list of the width (ints) (in pixels) of each
column in the view.
"""
lines = self.read("/tag/sel/index")
self.curr_colwidths = []
for line in lines:
match = re.search(r"# [^~]+ \d+ (\d+)", line)
if match:
self.curr_colwidths.append(int(match.group(1)))
print self.curr_colwidths
def read_current_column_number(self):
"""'wmiir read /tag/sel/ctl' and set the attribute, self.curr_col."""
lines = self.read("/tag/sel/ctl")
self.curr_col = re.split(" ", lines[1])[1]
print "curr_col = %s" % self.curr_col
def xwrite(self, path_and_value):
"""Use the xwrite form."""
cmd = "wmiir xwrite %s" % path_and_value
print cmd
os.system(cmd)
def read(self, path):
"""Return a list of the lines returned by "wmii read path" """
return os.popen4("wmiir read " + path)[1].readlines()
if __name__ == "__main__":
w = Wmii()
w.set_column_widths(sys.argv[1], sys.argv[2])
I named the script wmii.py
, made it executable, and put it on my path. Then I modified my wmiirc
:
Key $MODKEY-q wmii.py 20 80 Key $MODKEY-w wmii.py 40 60 Key $MODKEY-e wmii.py 50 50 Key $MODKEY-r wmii.py 60 40 Key $MODKEY-t wmii.py 80 20
Hope that's helpful to someone. Let me know if you've written some cool python wmii scripts.
Related posts
- Wmii Python script to monitor remote machines — posted 2009-12-22
- Install wmii snapshot 20090703 on Ubuntu Jaunty — posted 2009-07-13
- Using wmii with Gnome — posted 2009-03-19
- Install wmii snapshot — posted 2008-07-29
- Install coLinux (and Ubuntu Hardy) on Win XP using Slirp to internet and TAP to host behind a corporate firewall/proxy server — posted 2008-04-14
Comments
Hi sofeng, thanks for the post! Unfortunately the stable wmii-3.6 (dated 2007-11-16) doesn't have the grow command, as confirmed here.
The idea of fixed column width ratios is good, but I would have used just one key shortcut to cycle between the predefined widths. I will experiment with that code after a wmii upgrade...
Bye, Marco
Hi Marco, OK, thanks for the information-- I'll update my post. Good luck with upgrading wmii. I recommend the 20080520 snapshot over 3.6. Here are my install notes for wmii snapshot: http://www.saltycrane.com/blog/2008/07/install-wmii-snapshot/
This is exactly what I was looking for! Thanks :)