wmii

git clone git://oldgit.suckless.org/wmii/
Log | Files | Refs | README | LICENSE

commit 5f870abb2dc8663541f3399b9e83358cc2807deb
parent b986944d7a41589c542e02876fb834b355fccb4c
Author: Kris Maglione <kris@suckless.org>
Date:   Thu,  3 Jun 2010 21:38:14 -0400

[python] Sync pygmi with config changes in tip.

Diffstat:
alternative_wmiircs/python/pygmi/fs.py | 158++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-------------------
alternative_wmiircs/python/wmiirc.py | 13++++++-------
2 files changed, 127 insertions(+), 44 deletions(-)

diff --git a/alternative_wmiircs/python/pygmi/fs.py b/alternative_wmiircs/python/pygmi/fs.py @@ -1,5 +1,6 @@ import collections from datetime import datetime, timedelta +import re from pyxp import * from pyxp.client import * @@ -7,7 +8,20 @@ from pygmi import * from pygmi.util import prop __all__ = ('wmii', 'Tags', 'Tag', 'Area', 'Frame', 'Client', - 'Button', 'Colors', 'Color') + 'Button', 'Colors', 'Color', 'Toggle') + +spacere = re.compile(r'\s') + +class utf8(object): + def __str__(self): + return unicode(self).encode('utf-8') + +@apply +class Toggle(utf8): + def __unicode__(self): + return u'Toggle' + def __repr__(self): + return 'Toggle' def constrain(min, max, val): if val < min: @@ -217,8 +231,8 @@ class Client(Dir): """ base_path = '/client' - fullscreen = Dir.toggle_property('Fullscreen') - urgent = Dir.toggle_property('Urgent') + fullscreen = Dir.toggle_property('fullscreen') + urgent = Dir.toggle_property('urgent') label = Dir.file_property('label', writable=True) tags = Dir.file_property('tags', writable=True) @@ -227,6 +241,7 @@ class Client(Dir): def kill(self): """Politely asks a client to quit.""" self.ctl('kill') + def slay(self): """Forcibly severs a client's connection to the X server.""" self.ctl('slay') @@ -476,7 +491,7 @@ class Button(object): for s in client.readdir(cls.sides[side]) if s.name != 'sel') -class Colors(object): +class Colors(utf8): def __init__(self, foreground=None, background=None, border=None): vals = foreground, background, border self.vals = tuple(map(Color, vals)) @@ -497,14 +512,12 @@ class Colors(object): key = {'foreground': 0, 'background': 1, 'border': 2}[key] return self.vals[key] - def __str__(self): - return str(unicode(self)) def __unicode__(self): return ' '.join(c.hex for c in self.vals) def __repr__(self): return 'Colors(%s, %s, %s)' % tuple(repr(c.rgb) for c in self.vals) -class Color(object): +class Color(utf8): def __init__(self, colors): if isinstance(colors, Color): colors = colors.rgb @@ -527,40 +540,36 @@ class Color(object): def hex(self): return '#%02x%02x%02x' % self.rgb - def __str__(self): - return str(unicode(self)) def __unicode__(self): return 'rgb(%d, %d, %d)' % self.rgb def __repr__(self): return 'Color(%s)' % repr(self.rgb) -class Rules(collections.MutableMapping): - regex = re.compile(r'^\s*/(.*?)/\s*(?:->)?\s*(.*)$') - - def __get__(self, obj, cls): - return self - def __set__(self, obj, val): - self.setitems(val) +class Rules(collections.MutableMapping, utf8): + _items = () def __init__(self, path, rules=None): self.path = path if rules: self.setitems(rules) + _quotere = re.compile(ur'(\\(.)|/)') + @classmethod + def quoteslash(cls, str): + return cls._quotere.sub(lambda m: m.group(0) if m.group(2) else r'\/', str) + + __get__ = lambda self, obj, cls: self + def __set__(self, obj, val): + self.setitems(val) + def __getitem__(self, key): for k, v in self.iteritems(): if k == key: return v raise KeyError() def __setitem__(self, key, val): - items = [] - for k, v in self.iteritems(): - if key == k: - v = val - key = None - items.append((k, v)) - if key is not None: - items.append((key, val)) + items = [(k, v) for k, v in self.iteritems() if k != key] + items.append((key, val)) self.setitems(items) def __delitem__(self, key): self.setitems((k, v) for k, v in self.iteritems() if k != key) @@ -580,21 +589,97 @@ class Rules(collections.MutableMapping): def __add__(self, items): return tuple(self.iteritems()) + tuple(items) + def rewrite(self): + client.awrite(self.path, unicode(self)) + def setitems(self, items): + self._items = [(k, v if isinstance(v, Rule) else Rule(self, k, v)) + for (k, v) in items] + self.rewrite(); + + def __unicode__(self): + return u''.join(unicode(value) for (key, value) in self.iteritems()) or u'\n' + + def iteritems(self): + for item in self._items: + yield item + def items(self): + return list(self._items()) + +class Rule(collections.MutableMapping, utf8): + _items = () + parent = None + + @classmethod + def quotekey(cls, key): + return key.replace('_', '-') + @classmethod + def quotevalue(cls, val): + if val is True: return "on" + if val is False: return "off" + if val is Toggle: return "toggle" + return unicode(val) + + def __get__(self, obj, cls): + return self + def __set__(self, obj, val): + self.setitems(val) + + def __init__(self, parent, key, items={}): + self.key = key + self._items = [] + self.setitems(items.iteritems() if isinstance(items, dict) else items) + self.parent = parent + + def __getitem__(self, key): + for k, v in reversed(self._items): + if k == key: + return v + raise KeyError() + + def __setitem__(self, key, val): + items = [(k, v) for k, v in self.iteritems() if k != key] + items.append((key, val)) + self.setitems(items) + + def __delitem__(self, key): + self.setitems([(k, v) for k, v in self.iteritems() if k != key]) + + def __len__(self): + return len(self._items) + def __iter__(self): + for k in iter(self._items): + yield k + def __list__(self): + return list(iter(self)) + def __tuple__(self): + return tuple(iter(self)) + + def append(self, item): + self.setitems(self + (item,)) + def __add__(self, items): + return tuple(self.iteritems()) + tuple(items) + def setitems(self, items): - lines = [] - for k, v in items: - assert '/' not in k and '\n' not in v - lines.append('/%s/ -> %s' % (k, v)) - lines.append('') - client.awrite(self.path, '\n'.join(lines)) + items = list(items) + assert not any('=' in key or + spacere.search(self.quotekey(key)) or + spacere.search(self.quotevalue(val)) for (key, val) in items) + self._items = items + if self.parent: + self.parent.rewrite() + + def __unicode__(self): + return u'/%s/ %s\n' % ( + Rules.quoteslash(self.key), + u' '.join(u'%s=%s' % (self.quotekey(k), self.quotevalue(v)) + for (k, v) in self.iteritems())) def iteritems(self): - for line in client.readlines(self.path): - match = self.regex.match(line) - if match: - yield match.groups() + for i in self._items: + yield i def items(self): - return list(self.iteritems()) + return list(self._items) + @apply class wmii(Ctl): @@ -610,8 +695,7 @@ class wmii(Ctl): lbuttons = property(lambda self: Button.all('left')) rbuttons = property(lambda self: Button.all('right')) - tagrules = Rules('/tagrules') - colrules = Rules('/colrules') + rules = Rules('/rules') class Tags(object): PREV = [] diff --git a/alternative_wmiircs/python/wmiirc.py b/alternative_wmiircs/python/wmiirc.py @@ -59,13 +59,12 @@ def load(self): def time(self): return wmii.cache['focuscolors'], datetime.datetime.now().strftime('%c') -wmii.colrules = ( - ('gimp', '17+83+41'), - ('.*', '62+38 # Golden Ratio'), -) - -wmii.tagrules = ( - ('MPlayer|VLC', '~'), +wmii.rules = ( + # MPlayer and VLC don't float by default, but should. + (ur'MPlayer|VLC', dict(floating=True)), + # ROX puts all of its windows in the same group, so they open + # with the same tags. Disable grouping for ROX Filer. + (ur'^ROX-Filer:', dict(group=0)), ) def unresponsive_client(client):