wmii

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

commit f9a3838a8f0507574906086ef83e267bca02ce52
parent ceb97d3dd83ca8e5b9cfcf0562c22f8b550ab765
Author: Kris Maglione <jg@suckless.org>
Date:   Fri,  2 Oct 2009 21:44:50 -0400

Add help text to python key bindings.

Diffstat:
alternative_wmiircs/python/pygmi/events.py | 74++++++++++++++++++++++++++++++++++++++++++++++++++++++--------------------
alternative_wmiircs/python/pygmi/util.py | 9++++++++-
alternative_wmiircs/python/wmiirc.py | 175++++++++++++++++++++++++++++++++++++++++++++++++++-----------------------------
3 files changed, 174 insertions(+), 84 deletions(-)

diff --git a/alternative_wmiircs/python/pygmi/events.py b/alternative_wmiircs/python/pygmi/events.py @@ -6,10 +6,10 @@ import traceback import pygmi from pygmi import monitor, client, curry, call, program_list, _ -__all__ = ('keys', 'bind_events', 'event_loop', 'event', 'Match') +__all__ = ('keys', 'bind_events', 'event_loop', 'event', 'Match', + 'Desc') keydefs = {} -keys = {} events = {} eventmatchers = {} @@ -44,10 +44,6 @@ def flatten(items): for key in k: yield key, v -def bind_keys(mode='main', keys={}, import_={}): - for k, v in flatten(keys.iteritems()): - keys[k % keydefs] = v - def bind_events(items={}, **kwargs): kwargs.update(items) for k, v in flatten(kwargs.iteritems()): @@ -59,41 +55,79 @@ def bind_events(items={}, **kwargs): def event(fn): bind_events({fn.__name__: fn}) +class Desc(object): + def __init__(self, doc): + self.doc = doc + def __unicode__(self): + return self.doc + def __str__(self): + return str(self.doc) + class Keys(object): def __init__(self): self.modes = {} + self.modelist = [] self.mode = 'main' bind_events(Key=self.dispatch) def _add_mode(self, mode): if mode not in self.modes: - self.modes[mode] = { 'name': mode, 'keys': {}, 'import': {} } + self.modes[mode] = { 'name': mode, 'desc': {}, 'groups': [], + 'keys': {}, 'import': {} } + self.modelist.append(mode) def _set_mode(self, mode): self._add_mode(mode) self._mode = mode - client.write('/keys', '\n'.join(self.modes[mode]['keys'].keys() + - self.modes[mode]['import'].keys() + - [''])) + self._keys = dict((k % keydefs, v) for k, v in + self.modes[mode]['keys'].items() + + self.modes[mode]['keys'].items()); + client.write('/keys', '\n'.join(self._keys.keys()) + '\n') mode = property(lambda self: self._mode, _set_mode) - def bind(self, mode='main', keys={}, import_={}): + @property + def help(self): + return '\n\n'.join( + ('Mode %s\n' % mode['name']) + + '\n\n'.join((' %s\n' % str(group or '')) + + '\n'.join(' %- 20s %s' % (key % keydefs, + mode['desc'][key]) + for key in mode['desc'][group]) + for group in mode['groups']) + for mode in (self.modes[name] + for name in self.modelist)) + + def bind(self, mode='main', keys=(), import_={}): self._add_mode(mode) mode = self.modes[mode] - for k, v in flatten(keys.iteritems()): - mode['keys'][k % keydefs] = v + group = None + key = None + def add_desc(key, desc): + mode['desc'][key] = desc + if group not in mode['desc']: + mode['desc'][group] = [] + mode['groups'].append(group) + if key not in mode['desc'][group]: + mode['desc'][group].append(key); + + for k in keys: + if key and isinstance(k, Desc): + add_desc(key, k) + elif isinstance(k, Desc): + group = str(k) + elif key: + mode['keys'][key] = k + key = None + else: + key = k + for k, v in flatten((v, k) for k, v in import_.iteritems()): mode['import'][k % keydefs] = v def dispatch(self, key): mode = self.modes[self.mode] - seen = set() - while mode and mode['name'] not in seen: - seen.add(mode['name']) - if key in mode['keys']: - return mode['keys'][key](key) - elif key in mode['import']: - mode = modes.get(mode['import'][key], None) + if key in self._keys: + return self._keys[key](key) keys = Keys() def dispatch(event, args=''): diff --git a/alternative_wmiircs/python/pygmi/util.py b/alternative_wmiircs/python/pygmi/util.py @@ -3,7 +3,7 @@ import subprocess import pygmi -__all__ = 'call', 'program_list', 'curry', 'find_script', '_' +__all__ = 'call', 'message', 'program_list', 'curry', 'find_script', '_' def _(): pass @@ -17,6 +17,13 @@ def call(*args, **kwargs): if not background: return p.communicate(input)[0].rstrip('\n') +def message(message): + args = ['xmessage', '-file', '-']; + font = pygmi.wmii['font'] + if not font.startswith('xft:'): + args += ['-fn', font.split(',')[0]] + call(*args, input=message) + def program_list(path): names = [] for d in path: diff --git a/alternative_wmiircs/python/wmiirc.py b/alternative_wmiircs/python/wmiirc.py @@ -115,6 +115,8 @@ bind_events({ class Actions(events.Actions): def rehash(self, args=''): program_menu.choices = program_list(os.environ['PATH'].split(':')) + def showkeys(self, args=''): + message(keys.help) def quit(self, args=''): wmii.ctl('quit') def eval_(self, args=''): @@ -158,75 +160,122 @@ class Notice(Button): self.timer.start() notice = Notice() -keys.bind('main', { - '%(mod)s-%(left)s': lambda k: Tag('sel').select('left'), - '%(mod)s-%(right)s': lambda k: Tag('sel').select('right'), - '%(mod)s-%(up)s': lambda k: Tag('sel').select('up'), - '%(mod)s-%(down)s': lambda k: Tag('sel').select('down'), - - '%(mod)s-Control-%(up)s': lambda k: Tag('sel').select('up', stack=True), - '%(mod)s-Control-%(down)s': lambda k: Tag('sel').select('down', stack=True), - - '%(mod)s-space': lambda k: Tag('sel').select('toggle'), - - '%(mod)s-Shift-%(left)s': lambda k: Tag('sel').send(Client('sel'), 'left'), - '%(mod)s-Shift-%(right)s': lambda k: Tag('sel').send(Client('sel'), 'right'), - '%(mod)s-Shift-%(up)s': lambda k: Tag('sel').send(Client('sel'), 'up'), - '%(mod)s-Shift-%(down)s': lambda k: Tag('sel').send(Client('sel'), 'down'), - - '%(mod)s-Shift-space': lambda k: Tag('sel').send(Client('sel'), 'toggle'), - - '%(mod)s-d': lambda k: setattr(Tag('sel').selcol, 'mode', 'default-max'), - '%(mod)s-s': lambda k: setattr(Tag('sel').selcol, 'mode', 'stack-max'), - '%(mod)s-m': lambda k: setattr(Tag('sel').selcol, 'mode', 'stack+max'), - - '%(mod)s-f': lambda k: Client('sel').set('Fullscreen', 'toggle'), - '%(mod)s-Shift-c': lambda k: Client('sel').kill(), - - '%(mod)s-a': lambda k: action_menu.call(), - '%(mod)s-p': lambda k: program_menu.call(), - - '%(mod)s-Return': lambda k: call(*terminal, background=True), - - '%(mod)s-t': lambda k: tags.select(tag_menu.call()), - '%(mod)s-Shift-t': lambda k: setattr(Client('sel'), 'tags', tag_menu.call()), - - '%(mod)s-n': lambda k: tags.select(tags.next()), - '%(mod)s-b': lambda k: tags.select(tags.next(True)), - '%(mod)s-i': lambda k: tags.select(tags.NEXT), - '%(mod)s-o': lambda k: tags.select(tags.PREV), -}) +keys.bind('main', ( + Desc("Moving around"), + '%(mod)s-%(left)s', Desc("Select the client to the left"), + lambda k: Tag('sel').select('left'), + '%(mod)s-%(right)s', Desc("Select the client to the right"), + lambda k: Tag('sel').select('right'), + '%(mod)s-%(up)s', Desc("Select the client above"), + lambda k: Tag('sel').select('up'), + '%(mod)s-%(down)s', Desc("Select the client below"), + lambda k: Tag('sel').select('down'), + + '%(mod)s-space', Desc("Toggle between floating and managed layers"), + lambda k: Tag('sel').select('toggle'), + + Desc("Moving through stacks"), + '%(mod)s-Control-%(up)s', Desc("Select the stack above"), + lambda k: Tag('sel').select('up', stack=True), + '%(mod)s-Control-%(down)s', Desc("Select the stack below"), + lambda k: Tag('sel').select('down', stack=True), + + + Desc("Moving clients around"), + '%(mod)s-Shift-%(left)s', Desc("Move selected client to the left"), + lambda k: Tag('sel').send(Client('sel'), 'left'), + '%(mod)s-Shift-%(right)s', Desc("Move selected client to the right"), + lambda k: Tag('sel').send(Client('sel'), 'right'), + '%(mod)s-Shift-%(up)s', Desc("Move selected client up"), + lambda k: Tag('sel').send(Client('sel'), 'up'), + '%(mod)s-Shift-%(down)s', Desc("Move selected client down"), + lambda k: Tag('sel').send(Client('sel'), 'down'), + + '%(mod)s-Shift-space', Desc("Toggle selected client between floating and managed layers"), + lambda k: Tag('sel').send(Client('sel'), 'toggle'), + + Desc("Client actions"), + '%(mod)s-f', Desc("Toggle selected client's fullsceen state"), + lambda k: Client('sel').set('Fullscreen', 'toggle'), + '%(mod)s-Shift-c', Desc("Close client"), + lambda k: Client('sel').kill(), + + Desc("Changing column modes"), + '%(mod)s-d', Desc("Set column to default mode"), + lambda k: setattr(Tag('sel').selcol, 'mode', 'default-max'), + '%(mod)s-s', Desc("Set column to stack mode"), + lambda k: setattr(Tag('sel').selcol, 'mode', 'stack-max'), + '%(mod)s-m', Desc("Set column to max mode"), + lambda k: setattr(Tag('sel').selcol, 'mode', 'stack+max'), + + Desc("Running programs"), + '%(mod)s-a', Desc("Open wmii actions menu"), + lambda k: action_menu.call(), + '%(mod)s-p', Desc("Open program menu"), + lambda k: program_menu.call(), + + '%(mod)s-Return', Desc("Launch a terminal"), + lambda k: call(*terminal, background=True), + + Desc("Tag actions"), + '%(mod)s-t', Desc("Change to another tag"), + lambda k: tags.select(tag_menu.call()), + '%(mod)s-Shift-t', Desc("Retag the selected client"), + lambda k: setattr(Client('sel'), 'tags', tag_menu.call()), + + '%(mod)s-n', Desc("Move to the view to the left"), + lambda k: tags.select(tags.next()), + '%(mod)s-b', Desc("Move to the view to the right"), + lambda k: tags.select(tags.next(True)), + '%(mod)s-i', Desc("Move to the newer tag in the tag stack"), + lambda k: tags.select(tags.NEXT), + '%(mod)s-o', Desc("Move to the older tag in the tag stack"), + lambda k: tags.select(tags.PREV), +)) def bind_num(i): - keys.bind('main', { - '%%(mod)s-%d' % i: lambda k: tags.select(str(i)), - '%%(mod)s-Shift-%d' % i: lambda k: setattr(Client('sel'), 'tags', i), - }) + keys.bind('main', ( + Desc("Tag actions"), + '%%(mod)s-%d' % i, Desc("Move to view '%d'" % i), + lambda k: tags.select(str(i)), + '%%(mod)s-Shift-%d' % i, Desc("Retag selected client with tag '%d'" % i), + lambda k: setattr(Client('sel'), 'tags', i), + )) map(bind_num, range(0, 10)) -keys.bind('main', { - '%(mod)s-Control-r': lambda k: setattr(keys, 'mode', 'resize'), - '%(mod)s-Control-t': lambda k: setattr(keys, 'mode', 'passthrough'), -}); -keys.bind('passthrough', { - '%(mod)s-Control-t': lambda k: setattr(keys, 'mode', 'main'), -}); - -keys.bind('resize', { - 'Escape': lambda k: setattr(keys, 'mode', 'main'), -}, import_={'main': ('%(mod)s-%(left)s', '%(mod)s-%(right)s', +keys.bind('main', ( + Desc("Changing modes"), + '%(mod)s-Control-r', Desc("Enter resize mode"), + lambda k: setattr(keys, 'mode', 'resize'), + '%(mod)s-Control-t', Desc("Enter passthrough mode"), + lambda k: setattr(keys, 'mode', 'passthrough'), +)); +keys.bind('passthrough', ( + Desc("Changing modes"), + '%(mod)s-Control-t', Desc("Leave passthrough mode"), + lambda k: setattr(keys, 'mode', 'main'), +)); + +keys.bind('resize', ( + 'Escape', Desc("Leave resize mode"), + lambda k: setattr(keys, 'mode', 'main'), +), import_={'main': ('%(mod)s-%(left)s', '%(mod)s-%(right)s', '%(mod)s-%(up)s', '%(mod)s-%(down)s', '%(mod)s-Space')}) -def addresize(mod, cmd, *args): - keys.bind('resize', { - mod + '%(left)s': lambda k: Tag('sel').ctl(cmd, 'sel sel', 'left', *args), - mod + '%(right)s': lambda k: Tag('sel').ctl(cmd, 'sel sel', 'right', *args), - mod + '%(up)s': lambda k: Tag('sel').ctl(cmd, 'sel sel', 'up', *args), - mod + '%(down)s': lambda k: Tag('sel').ctl(cmd, 'sel sel', 'down', *args), - }); -addresize('', 'grow') -addresize('Control-', 'grow', '-1') -addresize('Shift-', 'nudge') +def addresize(mod, desc, cmd, *args): + keys.bind('resize', ( + mod + '%(left)s', Desc("%s selected client to the left" % desc), + lambda k: Tag('sel').ctl(cmd, 'sel sel', 'left', *args), + mod + '%(right)s', Desc("%s selected client to the right" % desc), + lambda k: Tag('sel').ctl(cmd, 'sel sel', 'right', *args), + mod + '%(up)s', Desc("%s selected client up" % desc), + lambda k: Tag('sel').ctl(cmd, 'sel sel', 'up', *args), + mod + '%(down)s', Desc("%s selected client down" % desc), + lambda k: Tag('sel').ctl(cmd, 'sel sel', 'down', *args), + )); +addresize('', 'Grow', 'grow') +addresize('Control-', 'Shrink', 'grow', '-1') +addresize('Shift-', 'Nudge', 'nudge') Actions.rehash()