diff options
-rw-r--r-- | examples/config/uzbl/config | 26 | ||||
-rwxr-xr-x | examples/data/uzbl/scripts/event_manager.py | 33 | ||||
-rw-r--r-- | examples/data/uzbl/scripts/plugins/bind.py | 200 | ||||
-rw-r--r-- | examples/data/uzbl/scripts/plugins/keycmd.py | 10 |
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) |