aboutsummaryrefslogtreecommitdiffhomepage
path: root/examples/data/uzbl/plugins/bind.py
diff options
context:
space:
mode:
authorGravatar Mason Larobina <mason.larobina@gmail.com>2009-11-19 20:39:18 +0800
committerGravatar Mason Larobina <mason.larobina@gmail.com>2009-11-19 20:39:18 +0800
commitd23d26b84d76dcd0839d55602345e72a297d0049 (patch)
treeb77b6cdc9e722c46b6909324d7354bebf411f376 /examples/data/uzbl/plugins/bind.py
parent00f7036a0134792e83bb7ebce0724be0ac1175a3 (diff)
General bugfixes in the bind plugin.
1. Use sets in the keycmd plugin for the held list. 2. Remove the bind filter function in the bind plugin. 3. Compare the mod_cmd and keylet.held sets instead of using a string comparison to determine if the user is holding down the correct modkeys for any given bind. 4. Raise exceptions instead of printing errors in the bind plugin. 5. Raise the builtin SyntaxError exception for parsing failures.
Diffstat (limited to 'examples/data/uzbl/plugins/bind.py')
-rw-r--r--examples/data/uzbl/plugins/bind.py92
1 files changed, 35 insertions, 57 deletions
diff --git a/examples/data/uzbl/plugins/bind.py b/examples/data/uzbl/plugins/bind.py
index 89b0831..ea04af6 100644
--- a/examples/data/uzbl/plugins/bind.py
+++ b/examples/data/uzbl/plugins/bind.py
@@ -12,10 +12,10 @@ And it is also possible to execute a function on activation:
import sys
import re
-# Export these variables/functions to uzbl.<name>
+# Export these functions to uzbl.<name>
__export__ = ['bind', 'del_bind', 'del_bind_by_glob', 'get_binds']
-# Hold the bind lists per uzbl instance.
+# Hold the bind dicts for each uzbl instance.
UZBLS = {}
# Commonly used regular expressions.
@@ -23,15 +23,7 @@ starts_with_mod = re.compile('^<([A-Z][A-Za-z0-9-_]*)>')
find_prompts = re.compile('<([^:>]*):(\"[^\"]*\"|\'[^\']*\'|[^>]*)>').split
# For accessing a bind glob stack.
-MOD_CMD, ON_EXEC, HAS_ARGS, GLOB, MORE = range(5)
-
-
-class BindParseError(Exception):
- pass
-
-
-def error(msg):
- sys.stderr.write('bind plugin: error: %s\n' % msg)
+ON_EXEC, HAS_ARGS, MOD_CMD, GLOB, MORE = range(5)
def ismodbind(glob):
@@ -40,25 +32,25 @@ def ismodbind(glob):
return bool(starts_with_mod.match(glob))
-def sort_mods(glob):
- '''Mods are sorted in the keylet.to_string() result so make sure that
- bind commands also have their mod keys sorted.'''
+def split_glob(glob):
+ '''Take a string of the form "<Mod1><Mod2>cmd _" and return a list of the
+ modkeys in the glob and the command.'''
- mods = []
+ mods = set()
while True:
match = starts_with_mod.match(glob)
if not match:
break
end = match.span()[1]
- mods.append(glob[:end])
+ mods.add(glob[:end].strip("<>"))
glob = glob[end:]
- return '%s%s' % (''.join(sorted(mods)), glob)
+ return (mods, glob)
def add_instance(uzbl, *args):
- UZBLS[uzbl] = {'binds': [], 'depth': 0, 'filter': [],
+ UZBLS[uzbl] = {'binds': [], 'depth': 0, 'stack': [],
'args': [], 'last_mode': ''}
@@ -94,7 +86,7 @@ def get_filtered_binds(uzbl):
bind_dict = get_bind_dict(uzbl)
if bind_dict['depth']:
- return list(bind_dict['filter'])
+ return list(bind_dict['stack'])
return list(bind_dict['binds'])
@@ -169,13 +161,13 @@ class Bind(object):
for glob in split[:-1:3]:
if glob.endswith('*'):
msg = "token '*' not at the end of a prompt bind: %r" % split
- raise BindParseError(msg)
+ raise SyntaxError(msg)
# Check that there is nothing like: fl<prompt1:><prompt2:>_
for glob in split[3::3]:
if not glob:
msg = 'found null segment after first prompt: %r' % split
- raise BindParseError(msg)
+ raise SyntaxError(msg)
stack = []
for (index, glob) in enumerate(reversed(split[::3])):
@@ -189,7 +181,8 @@ class Bind(object):
has_args = True if glob[-1] in ['*', '_'] else False
glob = glob[:-1] if has_args else glob
- stack.append((mod_cmd, on_exec, has_args, glob, index))
+ mods, glob = split_glob(glob)
+ stack.append((on_exec, has_args, mods, glob, index))
self.stack = list(reversed(stack))
self.is_global = (len(self.stack) == 1 and self.stack[0][MOD_CMD])
@@ -259,7 +252,6 @@ def bind(uzbl, glob, handler, *args, **kargs):
# Mods come from the keycmd sorted so make sure the modkeys in the bind
# command are sorted too.
- glob = sort_mods(glob)
del_bind_by_glob(uzbl, glob)
binds = get_binds(uzbl)
@@ -275,11 +267,11 @@ def parse_bind_event(uzbl, args):
'''Break "event BIND fl* = js follownums.js" into (glob, command).'''
if not args:
- return error('missing bind arguments')
+ raise ArgumentError('missing bind arguments')
split = map(unicode.strip, args.split('=', 1))
if len(split) != 2:
- return error('missing "=" in bind definition: %r' % args)
+ raise ArgumentError('missing delimiter in bind: %r' % args)
glob, command = split
bind(uzbl, glob, command)
@@ -307,40 +299,30 @@ def clear_stack(uzbl, mode):
if mode != "stack":
bind_dict = get_bind_dict(uzbl)
- bind_dict['filter'] = []
+ bind_dict['stack'] = []
bind_dict['depth'] = 0
bind_dict['args'] = []
bind_dict['last_mode'] = mode
-def filter_bind(uzbl, bind_dict, bind):
- '''Remove a bind from the stack filter list.'''
-
- if bind in bind_dict['filter']:
- bind_dict['filter'].remove(bind)
-
- if not bind_dict['filter']:
- uzbl.set_mode()
+def match_and_exec(uzbl, bind, depth, keylet, mod_event=False):
+ bind_dict = get_bind_dict(uzbl)
+ (on_exec, has_args, mod_cmd, glob, more) = bind[depth]
+ held = keylet.held
+ cmd = keylet.modcmd if mod_cmd else keylet.keycmd
-def match_and_exec(uzbl, bind, depth, keycmd):
- bind_dict = get_bind_dict(uzbl)
- (mod_cmd, on_exec, has_args, glob, more) = bind[depth]
+ if mod_cmd and held != mod_cmd:
+ return False
if has_args:
- if not keycmd.startswith(glob):
- if not mod_cmd:
- filter_bind(uzbl, bind_dict, bind)
-
+ if not cmd.startswith(glob):
return False
- args = [keycmd[len(glob):],]
-
- elif keycmd != glob:
- if not mod_cmd:
- filter_bind(uzbl, bind_dict, bind)
+ args = [cmd[len(glob):],]
+ elif cmd != glob:
return False
else:
@@ -356,12 +338,12 @@ def match_and_exec(uzbl, bind, depth, keycmd):
elif more:
if bind_dict['depth'] == depth:
globalcmds = [cmd for cmd in bind_dict['binds'] if cmd.is_global]
- bind_dict['filter'] = [bind,] + globalcmds
+ bind_dict['stack'] = [bind,] + globalcmds
bind_dict['args'] += args
bind_dict['depth'] = depth + 1
- elif bind not in bind_dict['filter']:
- bind_dict['filter'].append(bind)
+ elif bind not in bind_dict['stack']:
+ bind_dict['stack'].append(bind)
set_stack_mode(uzbl, bind.prompts[depth])
return False
@@ -377,49 +359,45 @@ def match_and_exec(uzbl, bind, depth, keycmd):
def keycmd_update(uzbl, keylet):
depth = get_stack_depth(uzbl)
- keycmd = keylet.get_keycmd()
for bind in get_filtered_binds(uzbl):
t = bind[depth]
if t[MOD_CMD] or t[ON_EXEC]:
continue
- if match_and_exec(uzbl, bind, depth, keycmd):
+ if match_and_exec(uzbl, bind, depth, keylet):
return
def keycmd_exec(uzbl, keylet):
depth = get_stack_depth(uzbl)
- keycmd = keylet.get_keycmd()
for bind in get_filtered_binds(uzbl):
t = bind[depth]
if t[MOD_CMD] or not t[ON_EXEC]:
continue
- if match_and_exec(uzbl, bind, depth, keycmd):
+ if match_and_exec(uzbl, bind, depth, keylet):
return uzbl.clear_keycmd()
def modcmd_update(uzbl, keylet):
depth = get_stack_depth(uzbl)
- keycmd = keylet.get_modcmd()
for bind in get_filtered_binds(uzbl):
t = bind[depth]
if not t[MOD_CMD] or t[ON_EXEC]:
continue
- if match_and_exec(uzbl, bind, depth, keycmd):
+ if match_and_exec(uzbl, bind, depth, keylet):
return
def modcmd_exec(uzbl, keylet):
depth = get_stack_depth(uzbl)
- keycmd = keylet.get_modcmd()
for bind in get_filtered_binds(uzbl):
t = bind[depth]
if not t[MOD_CMD] or not t[ON_EXEC]:
continue
- if match_and_exec(uzbl, bind, depth, keycmd):
+ if match_and_exec(uzbl, bind, depth, keylet):
return uzbl.clear_modcmd()