aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--examples/config/uzbl/config26
-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
4 files changed, 212 insertions, 57 deletions
diff --git a/examples/config/uzbl/config b/examples/config/uzbl/config
index 363e163..c6b9a6e 100644
--- a/examples/config/uzbl/config
+++ b/examples/config/uzbl/config
@@ -23,7 +23,8 @@ set load_finish_handler = chain 'set status_message = <span foreground="gold">do
set show_status = 1
set status_background = #303030
set keycmd_style = weight="bold" foreground="red"
-set status_format = <span font_family="monospace"><span background="khaki" foreground="black">[\@[\@mode_indicator]\@]</span> [<span \@keycmd_style>\@[\@keycmd]\@</span>] <span foreground="#606060"> \@[\@LOAD_PROGRESSBAR]\@ </span><span foreground="#99FF66">\@[\@uri]\@</span> <span foreground="khaki">\@[\@NAME]\@</span> <span foreground="orange">\@status_message</span><span foreground="#606060"> \@[\@SELECTED_URI]\@</span></span>
+set prompt_style = foreground="grey"
+set status_format = <span font_family="monospace"><span background="khaki" foreground="black">[\@[\@mode_indicator]\@]</span> [<span \@prompt_style>\@[\@keycmd_prompt]\@</span><span \@keycmd_style>\@[\@keycmd]\@</span>] <span foreground="#606060"> \@[\@LOAD_PROGRESSBAR]\@ </span><span foreground="#99FF66">\@[\@uri]\@</span> <span foreground="khaki">\@[\@NAME]\@</span> <span foreground="orange">\@status_message</span><span foreground="#606060"> \@[\@SELECTED_URI]\@</span></span>
set status_top = 0
set useragent = Uzbl (Webkit @WEBKIT_MAJOR.@WEBKIT_MINOR.@WEBKIT_MICRO) (@(uname -o)@ @(uname -m)@ [@ARCH_UZBL]) (Commit @COMMIT)
@@ -57,7 +58,7 @@ set socket_dir = /tmp
@bind N = search_reverse
@bind gh = uri http://www.uzbl.org
# shortcut to set the uri. TODO: i think we can abandon the uri command in favor of 'set uri = ..'
-@bind o _ = uri %s
+#@bind o _ = uri %s
# shortcut to set variables
@bind s _ = set %s
@bind \wiki _ = uri http://wiki.archlinux.org/index.php/Special:Search?search=%s&go=Go
@@ -67,7 +68,7 @@ set socket_dir = /tmp
@bind I = toggle_insert_mode 0
# Enclose the executable in quotes if it has spaces. Any additional parameters you use will
# appear AFTER the default parameters
-@bind B = spawn $XDG_DATA_HOME/uzbl/scripts/insert_bookmark.sh
+#@bind B = spawn $XDG_DATA_HOME/uzbl/scripts/insert_bookmark.sh
@bind U = spawn $XDG_DATA_HOME/uzbl/scripts/load_url_from_history.sh
@bind u = spawn $XDG_DATA_HOME/uzbl/scripts/load_url_from_bookmarks.sh
# with the sample yank script, you can yank one of the arguments into clipboard/selection
@@ -117,6 +118,16 @@ set socket_dir = /tmp
@bind fL* = script $XDG_DATA_HOME/uzbl/scripts/follow_Numbers_Strings.js %s
+# Examples using multi-stage-bindings with text prompts
+@bind o<uri:>_ = uri %s
+
+# Prints tab separated "uri title keyword tags" to the bookmarks file.
+@bind <Ctrl>b<bookmark keyword:>_<bookmark tags:>_ = sh 'echo -e "$6 $7 %s %s" >> $XDG_DATA_HOME/uzbl/bookmarks'
+
+@bind <Ctrl>a<:>q = exit
+@bind <Ctrl>a<:>h = uri http://uzbl.org/
+
+
### Mode config
set default_mode = command
@@ -134,6 +145,14 @@ set insert = @mode_config insert
@insert status_background = #303030
@insert mode_indicator = Ins
+# Multi-stage-binding mode config.
+set stack = @mode_config stack
+@stack keycmd_events = 1
+@stack prompt_style = foreground="#888" weight="light"
+@stack status_background = #202020
+@stack mode_indicator = Bnd
+
+
# Changing mode method via set.
set set_mode = set mode =
@bind I = @set_mode insert
@@ -145,6 +164,5 @@ set toggle_cmd_ins = @toggle_modes command insert
@bind i = @toggle_cmd_ins
@bind <Ctrl>i = @toggle_cmd_ins
-
# "home" page if you will
set uri = uzbl.org
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)