diff options
Diffstat (limited to 'examples/data/uzbl/plugins/bind.py')
-rw-r--r-- | examples/data/uzbl/plugins/bind.py | 143 |
1 files changed, 84 insertions, 59 deletions
diff --git a/examples/data/uzbl/plugins/bind.py b/examples/data/uzbl/plugins/bind.py index 3169b15..9702434 100644 --- a/examples/data/uzbl/plugins/bind.py +++ b/examples/data/uzbl/plugins/bind.py @@ -11,13 +11,15 @@ And it is also possible to execute a function on activation: import sys import re +import pprint # Export these functions to uzbl.<name> __export__ = ['bind', 'del_bind', 'del_bind_by_glob', 'get_binds'] # Hold the bind dicts for each uzbl instance. UZBLS = {} -DEFAULTS = {'binds': [], 'depth': 0, 'stack': [], 'args': [], 'last_mode': ''} +DEFAULTS = {'binds': [], 'depth': 0, 'stack': [], 'args': [], + 'last_mode': '', 'after': None} # Commonly used regular expressions. starts_with_mod = re.compile('^<([A-Z][A-Za-z0-9-_]*)>') @@ -27,6 +29,10 @@ find_prompts = re.compile('<([^:>]*):(\"[^\"]*\"|\'[^\']*\'|[^>]*)>').split ON_EXEC, HAS_ARGS, MOD_CMD, GLOB, MORE = range(5) +class ArgumentError(Exception): + pass + + def ismodbind(glob): '''Return True if the glob specifies a modbind.''' @@ -74,21 +80,11 @@ def get_binds(uzbl): return get_bind_dict(uzbl)['binds'] -def get_stack_depth(uzbl): - '''Return the stack for the uzbl instance.''' - - return get_bind_dict(uzbl)['depth'] - - -def get_filtered_binds(uzbl): +def get_filtered_binds(uzbl, bd): '''Return the bind list for the uzbl instance or return the filtered bind list thats on the current stack.''' - bind_dict = get_bind_dict(uzbl) - if bind_dict['depth']: - return list(bind_dict['stack']) - - return list(bind_dict['binds']) + return bd['stack'] if bd['depth'] else bd['binds'] def del_bind(uzbl, bind): @@ -220,6 +216,20 @@ class Bind(object): return self._repr_cache +def expand(cmd, args): + '''Replaces "%s %1 %2 %3..." with "<all args> <arg 0> <arg 1>...".''' + + if '%s' in cmd: + cmd = cmd.replace('%s', ' '.join(map(unicode, args))) + + for (index, arg) in enumerate(args): + index += 1 + if '%%%d' % index in cmd: + cmd = cmd.replace('%%%d' % index, unicode(arg)) + + return cmd + + def exec_bind(uzbl, bind, *args, **kargs): '''Execute bind objects.''' @@ -236,14 +246,7 @@ def exec_bind(uzbl, bind, *args, **kargs): commands = [] for cmd in bind.commands: - if '%s' in cmd: - if len(args) > 1: - for arg in args: - cmd = cmd.replace('%s', arg, 1) - - elif len(args) == 1: - cmd = cmd.replace('%s', args[0]) - + cmd = expand(cmd, args) uzbl.send(cmd) @@ -283,43 +286,51 @@ def mode_changed(uzbl, mode): clear_stack(uzbl) -def clear_stack(uzbl): +def clear_stack(uzbl, bd=None): '''Clear everything related to stacked binds.''' - bind_dict = get_bind_dict(uzbl) - bind_dict['stack'] = [] - bind_dict['depth'] = 0 - bind_dict['args'] = [] - if bind_dict['last_mode']: - uzbl.set_mode(bind_dict['last_mode']) - bind_dict['last_mode'] = '' + if bd is None: + bd = get_bind_dict(uzbl) + + bd['stack'] = [] + bd['depth'] = 0 + bd['args'] = [] + bd['after'] = None + if bd['last_mode']: + mode, bd['last_mode'] = bd['last_mode'], '' + uzbl.set_mode(mode) - uzbl.set('keycmd_prompt', force=False) + uzbl.set('keycmd_prompt') -def stack_bind(uzbl, bind, args, depth): +def stack_bind(uzbl, bind, args, depth, bd): '''Increment the stack depth in the bind dict, generate filtered bind list for stack mode and set keycmd prompt.''' - bind_dict = get_bind_dict(uzbl) - if bind_dict['depth'] != depth: - if bind not in bind_dict['stack']: - bind_dict['stack'].append(bind) + if bd['depth'] != depth: + if bind not in bd['stack']: + bd['stack'].append(bind) return if uzbl.get_mode() != 'stack': - bind_dict['last_mode'] = uzbl.get_mode() + bd['last_mode'] = uzbl.get_mode() uzbl.set_mode('stack') - globalcmds = [cmd for cmd in bind_dict['binds'] if cmd.is_global] - bind_dict['stack'] = [bind,] + globalcmds - bind_dict['args'] += args - bind_dict['depth'] = depth + 1 + globalcmds = [cmd for cmd in bd['binds'] if cmd.is_global] + bd['stack'] = [bind,] + globalcmds + bd['args'] += args + bd['depth'] = depth + 1 + bd['after'] = bind.prompts[depth] + - uzbl.send('event BIND_STACK_LEVEL %d' % bind_dict['depth']) +def after_bind(uzbl, bd): + '''Check if there are afte-actions to perform.''' - (prompt, set) = bind.prompts[depth] + if bd['after'] is None: + return + + (prompt, set), bd['after'] = bd['after'], None if prompt: uzbl.set('keycmd_prompt', '%s:' % prompt) @@ -332,9 +343,11 @@ def stack_bind(uzbl, bind, args, depth): else: uzbl.clear_keycmd() + uzbl.send('event BIND_STACK_LEVEL %d' % bd['depth']) + + +def match_and_exec(uzbl, bind, depth, keylet, bd): -def match_and_exec(uzbl, bind, depth, keylet): - bind_dict = get_bind_dict(uzbl) (on_exec, has_args, mod_cmd, glob, more) = bind[depth] held = keylet.held @@ -363,62 +376,74 @@ def match_and_exec(uzbl, bind, depth, keylet): return True elif more: - stack_bind(uzbl, bind, args, depth) + stack_bind(uzbl, bind, args, depth, bd) return False - args = bind_dict['args'] + args + args = bd['args'] + args exec_bind(uzbl, bind, *args) uzbl.set_mode() if not has_args: - clear_stack(uzbl) + clear_stack(uzbl, bd) uzbl.clear_current() return True def keycmd_update(uzbl, keylet): - depth = get_stack_depth(uzbl) - for bind in get_filtered_binds(uzbl): + bd = get_bind_dict(uzbl) + depth = bd['depth'] + for bind in get_filtered_binds(uzbl, bd): t = bind[depth] if t[MOD_CMD] or t[ON_EXEC]: continue - if match_and_exec(uzbl, bind, depth, keylet): + if match_and_exec(uzbl, bind, depth, keylet, bd): return + after_bind(uzbl, bd) + def keycmd_exec(uzbl, keylet): - depth = get_stack_depth(uzbl) - for bind in get_filtered_binds(uzbl): + bd = get_bind_dict(uzbl) + depth = bd['depth'] + for bind in get_filtered_binds(uzbl, bd): t = bind[depth] if t[MOD_CMD] or not t[ON_EXEC]: continue - if match_and_exec(uzbl, bind, depth, keylet): + if match_and_exec(uzbl, bind, depth, keylet, bd): return uzbl.clear_keycmd() + after_bind(uzbl, bd) + def modcmd_update(uzbl, keylet): - depth = get_stack_depth(uzbl) - for bind in get_filtered_binds(uzbl): + bd = get_bind_dict(uzbl) + depth = bd['depth'] + for bind in get_filtered_binds(uzbl, bd): t = bind[depth] if not t[MOD_CMD] or t[ON_EXEC]: continue - if match_and_exec(uzbl, bind, depth, keylet): + if match_and_exec(uzbl, bind, depth, keylet, bd): return + after_bind(uzbl, bd) + def modcmd_exec(uzbl, keylet): - depth = get_stack_depth(uzbl) - for bind in get_filtered_binds(uzbl): + bd = get_bind_dict(uzbl) + depth = bd['depth'] + for bind in get_filtered_binds(uzbl, bd): t = bind[depth] if not t[MOD_CMD] or not t[ON_EXEC]: continue - if match_and_exec(uzbl, bind, depth, keylet): + if match_and_exec(uzbl, bind, depth, keylet, bd): return uzbl.clear_modcmd() + after_bind(uzbl, bd) + def init(uzbl): connects = {'BIND': parse_bind_event, |