aboutsummaryrefslogtreecommitdiffhomepage
path: root/examples/data/uzbl/scripts
diff options
context:
space:
mode:
authorGravatar Mason Larobina <mason.larobina@gmail.com>2009-09-20 18:51:44 +0800
committerGravatar Mason Larobina <mason.larobina@gmail.com>2009-09-20 18:51:44 +0800
commit5de17212ff77e1021e2a87b528b51bab173efd8d (patch)
tree100d9ab957843c96ac8f4ec7d983aa57d2d2c756 /examples/data/uzbl/scripts
parent41540a5e1085c50fc3c6b5a7fab51ce4d1234926 (diff)
Added new binding syntax which allows setting a customisable prompt mid-bind.
Diffstat (limited to 'examples/data/uzbl/scripts')
-rwxr-xr-xexamples/data/uzbl/scripts/event_manager.py33
-rw-r--r--examples/data/uzbl/scripts/plugins/bind.py200
-rw-r--r--examples/data/uzbl/scripts/plugins/keycmd.py10
3 files changed, 190 insertions, 53 deletions
diff --git a/examples/data/uzbl/scripts/event_manager.py b/examples/data/uzbl/scripts/event_manager.py
index c9be9bb..c5f2eda 100755
--- a/examples/data/uzbl/scripts/event_manager.py
+++ b/examples/data/uzbl/scripts/event_manager.py
@@ -376,6 +376,17 @@ class UzblInstance(object):
self._socket = sock
+ def _close_socket(self):
+ '''Close the socket used for communication with the uzbl instance.
+ This function is normally called upon receiving the INSTANCE_EXIT
+ event.'''
+
+ if self._socket:
+ self._socket.close()
+
+ self.uzbl_socket = self._socket = None
+
+
def _flush(self):
'''Flush messages from the outgoing queue to the uzbl instance.'''
@@ -384,7 +395,7 @@ class UzblInstance(object):
h = open(self.uzbl_fifo, 'w')
while len(self._fifo_cmd_queue):
msg = self._fifo_cmd_queue.pop(0)
- print "Sending via fifo: %r" % msg
+ print '<-- %s' % msg
h.write("%s\n" % msg)
h.close()
@@ -396,7 +407,7 @@ class UzblInstance(object):
if self._socket:
while len(self._socket_cmd_queue):
msg = self._socket_cmd_queue.pop(0)
- print "Sending via socket: %r" % msg
+ print '<-- %s' % msg
self._socket.send("%s\n" % msg)
@@ -424,7 +435,7 @@ class UzblInstance(object):
handler = Handler(event, handler, *args, **kargs)
self._handlers[event].append(handler)
- print "New event handler:", handler
+ print handler
return handler
@@ -488,7 +499,7 @@ class UzblInstance(object):
if not msg or msg[0] != "EVENT":
# Not an event message
- print raw.rstrip()
+ print "---", raw.rstrip()
return
event, args = msg[1], msg[3]
@@ -558,10 +569,6 @@ class UzblInstance(object):
def handle_event(self, event, args):
'''Handle uzbl events internally before dispatch.'''
- # Silence _printing_ of geo events while still debugging.
- if event != "GEOMETRY_CHANGED":
- print event, args
-
if event == 'FIFO_SET':
self.uzbl_fifo = args
self._flush()
@@ -571,7 +578,9 @@ class UzblInstance(object):
self._init_uzbl_socket(args)
self._flush()
- elif event == 'SHUTDOWN':
+ elif event == 'INSTANCE_EXIT':
+ self._close_socket()
+ self._running = False
for (name, plugin) in self.plugins.items():
if hasattr(plugin, "cleanup"):
plugin.cleanup(uzbl)
@@ -608,6 +617,10 @@ class UzblInstance(object):
def event(self, event, *args, **kargs):
'''Raise a custom event.'''
+ # Silence _printing_ of geo events while still debugging.
+ if event != "GEOMETRY_CHANGED":
+ print "--> %s %s %s" % (event, args, '' if not kargs else kargs)
+
if event in self._handlers:
for handler in self._handlers[event]:
try:
@@ -630,7 +643,7 @@ if __name__ == "__main__":
help="print verbose output.")
parser.add_option('-d', '--plugin-dir', dest='plugin_dir', action="store",
- metavar="FILE", help="change plugin directory.")
+ metavar="DIR", help="change plugin directory.")
parser.add_option('-p', '--load-plugins', dest="load", action="store",
metavar="PLUGINS", help="comma separated list of plugins to load")
diff --git a/examples/data/uzbl/scripts/plugins/bind.py b/examples/data/uzbl/scripts/plugins/bind.py
index 2321679..eaa1d40 100644
--- a/examples/data/uzbl/scripts/plugins/bind.py
+++ b/examples/data/uzbl/scripts/plugins/bind.py
@@ -17,10 +17,18 @@ from event_manager import config, counter, iscallable, isiterable
__export__ = ['bind', 'del_bind', 'del_bind_by_glob', 'get_binds']
# Hold the bind lists per uzbl instance.
-_UZBLS = {}
+UZBLS = {}
# Commonly used regular expressions.
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 = range(4)
+
+
+class BindParseError(Exception):
+ pass
def echo(msg):
@@ -56,21 +64,45 @@ def sort_mods(glob):
def add_instance(uzbl, *args):
- _UZBLS[uzbl] = []
+ UZBLS[uzbl] = {'binds': [], 'depth': 0, 'filter': [],
+ 'args': [], 'last_mode': ''}
def del_instance(uzbl, *args):
- if uzbl in _UZBLS:
- del _UZBLS[uzbl]
+ if uzbl in UZBLS:
+ del UZBLS[uzbl]
+
+
+def get_bind_dict(uzbl):
+ '''Return the bind dict for the uzbl instance.'''
+
+ if uzbl not in UZBLS:
+ add_instance(uzbl)
+
+ return UZBLS[uzbl]
def get_binds(uzbl):
'''Return the bind list for the uzbl instance.'''
- if uzbl not in _UZBLS:
- add_instance(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']
- return _UZBLS[uzbl]
+
+def get_filtered_binds(uzbl):
+ '''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['filter'])
+
+ return list(bind_dict['binds'])
def del_bind(uzbl, bind):
@@ -125,20 +157,35 @@ class Bind(object):
self.glob = glob
self.bid = self.nextbid()
- # Is the binding a MODCMD or KEYCMD.
- self.mod_bind = ismodbind(glob)
+ self.split = split = find_prompts(glob)
+ self.prompts = split[1::2]
- # Execute the command on UPDATES or EXEC's.
- self.on_exec = True if glob.endswith('_') else False
+ # Check that there is nothing like: fl*<int:>*
+ for glob in split[:-1:2]:
+ if glob.endswith('*'):
+ msg = "token '*' not at the end of a prompt bind: %r" % split
+ raise BindParseError(msg)
- if glob[-1] in ['*', '_']:
- self.has_args = True
- glob = glob[:-1]
+ # Check that there is nothing like: fl<prompt1:><prompt2:>_
+ for glob in split[2::2]:
+ if not glob:
+ msg = 'found null segment after first prompt: %r' % split
+ raise BindParseError(msg)
- else:
- self.has_args = False
+ self.stack = []
+
+ for glob in split[::2]:
+ # Is the binding a MODCMD or KEYCMD:
+ mod_cmd = ismodbind(glob)
+
+ # Execute the command on UPDATES or EXEC's:
+ on_exec = True if glob.endswith('_') else False
- self.match = glob
+ # Does the command store arguments:
+ has_args = True if glob[-1] in ['*', '_'] else False
+ glob = glob[:-1] if has_args else glob
+
+ self.stack.append((mod_cmd, on_exec, has_args, glob))
def __repr__(self):
@@ -173,11 +220,12 @@ def bind(uzbl, glob, handler, *args, **kargs):
bind = Bind(glob, handler, *args, **kargs)
binds.append(bind)
+ print bind
uzbl.event('ADDED_BIND', bind)
def parse_bind_event(uzbl, args):
- '''Parse "event BIND fl* = js follownums.js" commands.'''
+ '''Break "event BIND fl* = js follownums.js" into (glob, command).'''
split = map(str.strip, args.split('=', 1))
if len(split) != 2:
@@ -187,68 +235,138 @@ def parse_bind_event(uzbl, args):
bind(uzbl, glob, command)
-def match_and_exec(uzbl, bind, keylet):
+def set_stack_mode(uzbl, prompt):
+ if uzbl.get_mode() != 'stack':
+ uzbl.set_mode('stack')
- keycmd = keylet.to_string()
- if bind.has_args:
- if not keycmd.startswith(bind.match):
+ if prompt:
+ prompt = "%s: " % prompt
+
+ uzbl.set('keycmd_prompt', prompt)
+
+
+def clear_stack(uzbl, mode):
+ bind_dict = get_bind_dict(uzbl)
+ if mode != "stack" and bind_dict['last_mode'] == "stack":
+ uzbl.set('keycmd_prompt', '')
+
+ if mode != "stack":
+ bind_dict = get_bind_dict(uzbl)
+ bind_dict['filter'] = []
+ 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, keycmd):
+ bind_dict = get_bind_dict(uzbl)
+ mode_cmd, on_exec, has_args, glob = bind.stack[depth]
+
+ if has_args:
+ if not keycmd.startswith(glob):
+ filter_bind(uzbl, bind_dict, bind)
return False
- args = [keycmd[len(bind.match):],]
+ args = [keycmd[len(glob):],]
- elif keycmd != bind.match:
+ elif keycmd != glob:
+ filter_bind(uzbl, bind_dict, bind)
return False
else:
args = []
- uzbl.exec_handler(bind, *args)
+ execindex = len(bind.stack)-1
+ if execindex == depth == 0:
+ uzbl.exec_handler(bind, *args)
+ if not has_args:
+ uzbl.clear_keycmd()
+
+ return True
- if not bind.has_args:
- uzbl.clear_keycmd()
+ elif depth != execindex:
+ if bind_dict['depth'] == depth:
+ bind_dict['filter'] = [bind,]
+ bind_dict['args'] += args
+ bind_dict['depth'] = depth + 1
+
+ else:
+ if bind not in bind_dict['filter']:
+ bind_dict['filter'].append(bind)
+
+ set_stack_mode(uzbl, bind.prompts[depth])
+ return False
+
+ args = bind_dict['args'] + args
+ uzbl.exec_handler(bind, *args)
+ if on_exec:
+ uzbl.set_mode()
return True
def keycmd_update(uzbl, keylet):
- for bind in get_binds(uzbl):
- if bind.mod_bind or bind.on_exec:
+ depth = get_stack_depth(uzbl)
+ keycmd = keylet.to_string()
+ for bind in get_filtered_binds(uzbl):
+ t = bind.stack[depth]
+ if t[MOD_CMD] or t[ON_EXEC]:
continue
- match_and_exec(uzbl, bind, keylet)
+ match_and_exec(uzbl, bind, depth, keycmd)
def keycmd_exec(uzbl, keylet):
- for bind in get_binds(uzbl):
- if bind.mod_bind or not bind.on_exec:
+ depth = get_stack_depth(uzbl)
+ keycmd = keylet.to_string()
+ for bind in get_filtered_binds(uzbl):
+ t = bind.stack[depth]
+ if t[MOD_CMD] or not t[ON_EXEC]:
continue
- match_and_exec(uzbl, bind, keylet)
+ match_and_exec(uzbl, bind, depth, keycmd)
def modcmd_update(uzbl, keylet):
- for bind in get_binds(uzbl):
- if not bind.mod_bind or bind.on_exec:
+ depth = get_stack_depth(uzbl)
+ keycmd = keylet.to_string()
+ for bind in get_filtered_binds(uzbl):
+ t = bind.stack[depth]
+ if not t[MOD_CMD] or t[ON_EXEC]:
continue
- match_and_exec(uzbl, bind, keylet)
+ match_and_exec(uzbl, bind, depth, keycmd)
def modcmd_exec(uzbl, keylet):
- for bind in get_binds(uzbl):
- if not bind.mod_bind or not bind.on_exec:
+ depth = get_stack_depth(uzbl)
+ keycmd = keylet.to_string()
+ for bind in get_filtered_binds(uzbl):
+ t = bind.stack[depth]
+ if not t[MOD_CMD] or not t[ON_EXEC]:
continue
- match_and_exec(uzbl, bind, keylet)
+ match_and_exec(uzbl, bind, depth, keycmd)
def init(uzbl):
-
connects = {'BIND': parse_bind_event,
'KEYCMD_UPDATE': keycmd_update,
'MODCMD_UPDATE': modcmd_update,
'KEYCMD_EXEC': keycmd_exec,
- 'MODCMD_EXEC': modcmd_exec}
+ 'MODCMD_EXEC': modcmd_exec,
+ 'MODE_CHANGED': clear_stack}
for (event, handler) in connects.items():
uzbl.connect(event, handler)
diff --git a/examples/data/uzbl/scripts/plugins/keycmd.py b/examples/data/uzbl/scripts/plugins/keycmd.py
index 6377905..886f38f 100644
--- a/examples/data/uzbl/scripts/plugins/keycmd.py
+++ b/examples/data/uzbl/scripts/plugins/keycmd.py
@@ -220,9 +220,15 @@ def key_press(uzbl, key):
k.cmd += key
else:
- if len(key) == 1:
+ config = uzbl.get_config()
+ if 'keycmd_events' not in config or config['keycmd_events'] == '1':
+ if len(key) == 1:
+ cmdmod = True
+ k.cmd += key
+
+ elif k.cmd:
cmdmod = True
- k.cmd += key
+ k.cmd = ''
if cmdmod:
update_event(uzbl, k)