diff options
author | Dieter Plaetinck <dieter@plaetinck.be> | 2009-12-20 18:21:53 +0100 |
---|---|---|
committer | Dieter Plaetinck <dieter@plaetinck.be> | 2009-12-20 18:21:53 +0100 |
commit | 31f9b4165c2723192a8e53af3456733f0d3f5503 (patch) | |
tree | 98f3614c9954370deaf1d63a551a94582bb45186 /examples | |
parent | 276e7fc2f9d6423a0771aae7b918731d30e96b7d (diff) | |
parent | 69bbac176fd112fdfa785bdf72ab0918ad1d13af (diff) |
Merge remote branch 'mason/master'
Diffstat (limited to 'examples')
-rw-r--r-- | examples/config/uzbl/config | 39 | ||||
-rw-r--r-- | examples/data/uzbl/plugins/bind.py | 395 | ||||
-rw-r--r-- | examples/data/uzbl/plugins/completion.py | 3 | ||||
-rwxr-xr-x | examples/data/uzbl/scripts/uzbl-cookie-daemon | 8 | ||||
-rwxr-xr-x | examples/data/uzbl/scripts/uzbl-event-manager | 8 |
5 files changed, 267 insertions, 186 deletions
diff --git a/examples/config/uzbl/config b/examples/config/uzbl/config index 092a369..33e074f 100644 --- a/examples/config/uzbl/config +++ b/examples/config/uzbl/config @@ -1,33 +1,36 @@ # example uzbl config. # all settings are optional. you can use uzbl without any config at all (but it won't do much) -set prefix = /usr/local +set prefix = /usr/local # === Shortcuts / Aliases =================================================== +# Config related events (use the request function): # request BIND <keycmd> = <command> -set bind = request BIND +set bind = request BIND # request MODE_CONFIG <mode> <key> = <value -set mode_config = request MODE_CONFIG -# request TOGGLE_MODES <mode1> <mode2> ... <moden> -set toggle_modes = event TOGGLE_MODES +set mode_config = request MODE_CONFIG # request ON_EVENT <EVENT_NAME> <command> -set on_event = request ON_EVENT +set on_event = request ON_EVENT # request PROGRESS_CONFIG <key> = <value> -set progress = request PROGRESS_CONFIG +set progress = request PROGRESS_CONFIG # request MODMAP From To -set modmap = request MODMAP +set modmap = request MODMAP # request IGNORE_KEY <glob> -set ignore_key = request IGNORE_KEY +set ignore_key = request IGNORE_KEY # request MODKEY_ADDITION <key1> <key2> <keyn> <result> set modkey_addition = request MODKEY_ADDITION -set set_mode = set mode = -set set_status = set status_message = -set shell_cmd = sh -c +# Action related events (use the event function): +# event TOGGLE_MODES <mode1> <mode2> ... <moden> +set toggle_modes = event TOGGLE_MODES + +set set_mode = set mode = +set set_status = set status_message = +set shell_cmd = sh -c # Spawn path shortcuts. In spawn the first dir+path match is used in "dir1:dir2:dir3:executable" -set scripts_dir = $XDG_DATA_HOME/uzbl:@prefix/share/uzbl/examples/data/uzbl:scripts +set scripts_dir = $XDG_DATA_HOME/uzbl:@prefix/share/uzbl/examples/data/uzbl:scripts # Javascipt helpers. set jsh = js var run=Uzbl.run; function get(k){return run("print \\\@"+k)}; function set(k, v) {run("set "+k+" = "+v)}; @@ -231,15 +234,15 @@ set formfiller = spawn @scripts_dir/formfiller # Examples using multi-stage-bindings with text prompts. -@bind o<uri:>_ = uri %s -@bind O<uri:\@uri>_ = uri %s +@bind o<uri:>_ = uri %s +@bind O<uri:\@uri>_ = uri %s # multi-stage binding way to write bookmarks to file from inside uzbl. -@bind <Ctrl>b<tags:>_ = sh 'echo -e "$6 %s" >> $XDG_DATA_HOME/uzbl/bookmarks' +@bind <Ctrl>b<tags:>_ = sh 'echo -e "$6 %s" >> $XDG_DATA_HOME/uzbl/bookmarks' # Multi-stage bindings with blank prompts (similar behaviour to emacs M-c M-s bindings?) -@bind <Ctrl>a<:><Ctrl>q = exit -@bind <Ctrl>a<:><Ctrl>h = uri http://uzbl.org/ +@bind <Ctrl>a<:><Ctrl>q = exit +@bind <Ctrl>a<:><Ctrl>h = uri http://uzbl.org/ # Inject handy values into the keycmd. @bind <Ctrl>su = event INJECT_KEYCMD \@uri diff --git a/examples/data/uzbl/plugins/bind.py b/examples/data/uzbl/plugins/bind.py index 3dedf16..1cba7b2 100644 --- a/examples/data/uzbl/plugins/bind.py +++ b/examples/data/uzbl/plugins/bind.py @@ -11,52 +11,145 @@ 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'] +__export__ = ['bind', 'mode_bind', 'get_bindlet'] # Hold the bind dicts for each uzbl instance. UZBLS = {} -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-_]*)>') -find_prompts = re.compile('<([^:>]*):(\"[^\"]*\"|\'[^\']*\'|[^>]*)>').split +MOD_START = re.compile('^<([A-Z][A-Za-z0-9-_]*)>').match +# Matches <x:y>, <'x':y>, <:'y'>, <x!y>, <'x'!y>, ... +PROMPTS = '<(\"[^\"]*\"|\'[^\']*\'|[^:!>]*)(:|!)(\"[^\"]*\"|\'[^\']*\'|[^>]*)>' +FIND_PROMPTS = re.compile(PROMPTS).split +VALID_MODE = re.compile('^(-|)[A-Za-z0-9][A-Za-z0-9_]*$').match # For accessing a bind glob stack. ON_EXEC, HAS_ARGS, MOD_CMD, GLOB, MORE = range(5) -class ArgumentError(Exception): - pass +# Custom errors. +class ArgumentError(Exception): pass -def ismodbind(glob): - '''Return True if the glob specifies a modbind.''' +class Bindlet(object): + '''Per-instance bind status/state tracker.''' - return bool(starts_with_mod.match(glob)) + def __init__(self, uzbl): + self.binds = {'global': {}} + self.uzbl = uzbl + self.depth = 0 + self.args = [] + self.last_mode = None + self.after_cmds = None + self.stack_binds = [] + # A subset of the global mode binds containing non-stack and modkey + # activiated binds for use in the stack mode. + self.globals = [] -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 = set() - while True: - match = starts_with_mod.match(glob) - if not match: - break + def __getitem__(self, key): + return self.get_binds(key) - end = match.span()[1] - mods.add(glob[:end]) - glob = glob[end:] - return (mods, glob) + def reset(self): + '''Reset the tracker state and return to last mode.''' + + self.depth = 0 + self.args = [] + self.after_cmds = None + self.stack_binds = [] + + if self.last_mode: + mode, self.last_mode = self.last_mode, None + self.uzbl.set_mode(mode) + + self.uzbl.set('keycmd_prompt') + + + def stack(self, bind, args, depth): + '''Enter or add new bind in the next stack level.''' + + if self.depth != depth: + if bind not in self.stack_binds: + self.stack_binds.append(bind) + + return + + current_mode = self.uzbl.get_mode() + if current_mode != 'stack': + self.last_mode = current_mode + self.uzbl.set_mode('stack') + + self.stack_binds = [bind,] + self.args += args + self.depth += 1 + self.after_cmds = bind.prompts[depth] + + + def after(self): + '''If a stack was triggered then set the prompt and default value.''' + + if self.after_cmds is None: + return + + (prompt, is_cmd, set), self.after_cmds = self.after_cmds, None + + self.uzbl.clear_keycmd() + if prompt: + self.uzbl.set('keycmd_prompt', prompt) + + if set and is_cmd: + self.uzbl.send(set) + + elif set and not is_cmd: + self.uzbl.send('event SET_KEYCMD %s' % set) + + + def get_binds(self, mode=None): + '''Return the mode binds + globals. If we are stacked then return + the filtered stack list and modkey & non-stack globals.''' + + if mode is None: + mode = self.uzbl.get_mode() + + if not mode: + mode = 'global' + + if self.depth: + return self.stack_binds + self.globals + + globals = self.binds['global'] + if mode not in self.binds or mode == 'global': + return filter(None, globals.values()) + + binds = dict(globals.items() + self.binds[mode].items()) + return filter(None, binds.values()) + + + def add_bind(self, mode, glob, bind=None): + '''Insert (or override) a bind into the mode bind dict.''' + + if mode not in self.binds: + self.binds[mode] = {glob: bind} + return + + binds = self.binds[mode] + binds[glob] = bind + + if mode == 'global': + # Regen the global-globals list. + self.globals = [] + for bind in binds.values(): + if bind is not None and bind.is_global: + self.globals.append(bind) def add_instance(uzbl, *args): - UZBLS[uzbl] = dict(DEFAULTS) + UZBLS[uzbl] = Bindlet(uzbl) def del_instance(uzbl, *args): @@ -64,8 +157,8 @@ def del_instance(uzbl, *args): del UZBLS[uzbl] -def get_bind_dict(uzbl): - '''Return the bind dict for the uzbl instance.''' +def get_bindlet(uzbl): + '''Return the bind tracklet for the given uzbl instance.''' if uzbl not in UZBLS: add_instance(uzbl) @@ -73,42 +166,36 @@ def get_bind_dict(uzbl): return UZBLS[uzbl] -def get_binds(uzbl): - '''Return the bind list for the uzbl instance.''' - - return get_bind_dict(uzbl)['binds'] - +def ismodbind(glob): + '''Return True if the glob specifies a modbind.''' -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.''' + return bool(MOD_START(glob)) - return bd['stack'] if bd['depth'] else bd['binds'] +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.''' -def del_bind(uzbl, bind): - '''Delete bind object if bind in the uzbl binds.''' + mods = set() + while True: + match = MOD_START(glob) + if not match: + break - binds = get_binds(uzbl) - if bind in binds: - binds.remove(bind) - uzbl.event('DELETED_BIND', bind) - return True + end = match.span()[1] + mods.add(glob[:end]) + glob = glob[end:] - return False + return (mods, glob) -def del_bind_by_glob(uzbl, glob): - '''Delete bind by glob if bind in the uzbl binds.''' +def unquote(str): + '''Remove quotation marks around string.''' - binds = get_binds(uzbl) - for bind in list(binds): - if bind.glob == glob: - binds.remove(bind) - uzbl.event('DELETED_BIND', bind) - return True + if str and str[0] == str[-1] and str[0] in ['"', "'"]: + str = str[1:-1] - return False + return str class Bind(object): @@ -143,39 +230,40 @@ class Bind(object): self.counter[0] += 1 self.bid = self.counter[0] - self.split = split = find_prompts(glob) + self.split = split = FIND_PROMPTS(glob) self.prompts = [] - for (prompt, set) in zip(split[1::3], split[2::3]): - if set and set[0] == set[-1] and set[0] in ['"', "'"]: - # Remove quotes around set. - set = set[1:-1] + for (prompt, cmd, set) in zip(split[1::4], split[2::4], split[3::4]): + prompt, set = map(unquote, [prompt, set]) + cmd = True if cmd == '!' else False + if prompt and prompt[-1] != ":": + prompt = "%s:" % prompt - self.prompts.append((prompt, set)) + self.prompts.append((prompt, cmd, set)) # Check that there is nothing like: fl*<int:>* - for glob in split[:-1:3]: + for glob in split[:-1:4]: if glob.endswith('*'): msg = "token '*' not at the end of a prompt bind: %r" % split raise SyntaxError(msg) # Check that there is nothing like: fl<prompt1:><prompt2:>_ - for glob in split[3::3]: + for glob in split[4::4]: if not glob: msg = 'found null segment after first prompt: %r' % split raise SyntaxError(msg) stack = [] - for (index, glob) in enumerate(reversed(split[::3])): + for (index, glob) in enumerate(reversed(split[::4])): # 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 + # Do we execute on UPDATES or EXEC events? + on_exec = True if glob[-1] in ['!', '_'] else False - # Does the command store arguments: + # Does the command take arguments? has_args = True if glob[-1] in ['*', '_'] else False - glob = glob[:-1] if has_args else glob + glob = glob[:-1] if has_args or on_exec else glob mods, glob = split_glob(glob) stack.append((on_exec, has_args, mods, glob, index)) @@ -249,110 +337,94 @@ def exec_bind(uzbl, bind, *args, **kargs): uzbl.send(cmd) -def bind(uzbl, glob, handler, *args, **kargs): - '''Add a bind handler object.''' - - # Mods come from the keycmd sorted so make sure the modkeys in the bind - # command are sorted too. - - del_bind_by_glob(uzbl, glob) - binds = get_binds(uzbl) - - bind = Bind(glob, handler, *args, **kargs) - binds.append(bind) +def mode_bind(uzbl, modes, glob, handler=None, *args, **kargs): + '''Add a mode bind.''' - uzbl.event('ADDED_BIND', bind) + bindlet = get_bindlet(uzbl) + if not hasattr(modes, '__iter__'): + modes = unicode(modes).split(',') -def parse_bind_event(uzbl, args): - '''Break "event BIND fl* = js follownums.js" into (glob, command).''' + # Sort and filter binds. + modes = filter(None, map(unicode.strip, modes)) - if not args: - raise ArgumentError('missing bind arguments') - - split = map(unicode.strip, args.split('=', 1)) - if len(split) != 2: - raise ArgumentError('missing delimiter in bind: %r' % args) - - glob, command = split - bind(uzbl, glob, command) + if callable(handler) or (handler is not None and handler.strip()): + bind = Bind(glob, handler, *args, **kargs) + else: + bind = None -def mode_changed(uzbl, mode): - '''Clear the stack on all non-stack mode changes.''' + for mode in modes: + if not VALID_MODE(mode): + raise NameError('invalid mode name: %r' % mode) - if mode != 'stack': - clear_stack(uzbl) + for mode in modes: + if mode[0] == '-': + mode, bind = mode[1:], None + bindlet.add_bind(mode, glob, bind) + uzbl.event('ADDED_MODE_BIND', mode, glob, bind) -def clear_stack(uzbl, bd=None): - '''Clear everything related to stacked binds.''' - 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) +def bind(uzbl, glob, handler, *args, **kargs): + '''Legacy bind function.''' - uzbl.set('keycmd_prompt') + mode_bind(uzbl, 'global', glob, handler, *args, **kargs) -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.''' +def parse_mode_bind(uzbl, args): + '''Parser for the MODE_BIND event. - if bd['depth'] != depth: - if bind not in bd['stack']: - bd['stack'].append(bind) + Example events: + MODE_BIND <mode> <bind> = <command> + MODE_BIND command o<location:>_ = uri %s + MODE_BIND insert,command <BackSpace> = ... + MODE_BIND global ... = ... + MODE_BIND global,-insert ... = ... + ''' - return + if not args: + raise ArgumentError('missing bind arguments') - if uzbl.get_mode() != 'stack': - bd['last_mode'] = uzbl.get_mode() - uzbl.set_mode('stack') + split = map(unicode.strip, args.split(' ', 1)) + if len(split) != 2: + raise ArgumentError('missing mode or bind section: %r' % args) - 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] + modes, args = split[0].split(','), split[1] + split = map(unicode.strip, args.split('=', 1)) + if len(split) != 2: + raise ArgumentError('missing delimiter in bind section: %r' % args) + glob, command = split + mode_bind(uzbl, modes, glob, command) -def after_bind(uzbl, bd): - '''Check if there are afte-actions to perform.''' - if bd['after'] is None: - return +def parse_bind(uzbl, args): + '''Legacy parsing of the BIND event and conversion to the new format. - (prompt, set), bd['after'] = bd['after'], None - if prompt: - uzbl.set('keycmd_prompt', '%s:' % prompt) + Example events: + request BIND <bind> = <command> + request BIND o<location:>_ = uri %s + request BIND <BackSpace> = ... + request BIND ... = ... + ''' - else: - uzbl.set('keycmd_prompt') + parse_mode_bind(uzbl, "global %s" % args) - if set: - uzbl.send('event SET_KEYCMD %s' % set) - else: - uzbl.clear_keycmd() +def mode_changed(uzbl, mode): + '''Clear the stack on all non-stack mode changes.''' - uzbl.send('event BIND_STACK_LEVEL %d' % bd['depth']) + if mode != 'stack': + get_bindlet(uzbl).reset() -def match_and_exec(uzbl, bind, depth, keylet, bd): +def match_and_exec(uzbl, bind, depth, keylet, bindlet): (on_exec, has_args, mod_cmd, glob, more) = bind[depth] - - held = keylet.held cmd = keylet.modcmd if mod_cmd else keylet.keycmd - if mod_cmd and held != mod_cmd: + if mod_cmd and keylet.held != mod_cmd: return False if has_args: @@ -375,77 +447,78 @@ def match_and_exec(uzbl, bind, depth, keylet, bd): return True elif more: - stack_bind(uzbl, bind, args, depth, bd) + bindlet.stack(bind, args, depth) return False - args = bd['args'] + args + args = bindlet.args + args exec_bind(uzbl, bind, *args) uzbl.set_mode() if not has_args: - clear_stack(uzbl, bd) + bindlet.reset() uzbl.clear_current() return True def keycmd_update(uzbl, keylet): - bd = get_bind_dict(uzbl) - depth = bd['depth'] - for bind in get_filtered_binds(uzbl, bd): + bindlet = get_bindlet(uzbl) + depth = bindlet.depth + for bind in bindlet.get_binds(): t = bind[depth] if t[MOD_CMD] or t[ON_EXEC]: continue - if match_and_exec(uzbl, bind, depth, keylet, bd): + if match_and_exec(uzbl, bind, depth, keylet, bindlet): return - after_bind(uzbl, bd) + bindlet.after() def keycmd_exec(uzbl, keylet): - bd = get_bind_dict(uzbl) - depth = bd['depth'] - for bind in get_filtered_binds(uzbl, bd): + bindlet = get_bindlet(uzbl) + depth = bindlet.depth + for bind in bindlet.get_binds(): t = bind[depth] if t[MOD_CMD] or not t[ON_EXEC]: continue - if match_and_exec(uzbl, bind, depth, keylet, bd): + if match_and_exec(uzbl, bind, depth, keylet, bindlet): return uzbl.clear_keycmd() - after_bind(uzbl, bd) + bindlet.after() def modcmd_update(uzbl, keylet): - bd = get_bind_dict(uzbl) - depth = bd['depth'] - for bind in get_filtered_binds(uzbl, bd): + bindlet = get_bindlet(uzbl) + depth = bindlet.depth + for bind in bindlet.get_binds(): t = bind[depth] if not t[MOD_CMD] or t[ON_EXEC]: continue - if match_and_exec(uzbl, bind, depth, keylet, bd): + if match_and_exec(uzbl, bind, depth, keylet, bindlet): return - after_bind(uzbl, bd) + bindlet.after() def modcmd_exec(uzbl, keylet): - bd = get_bind_dict(uzbl) - depth = bd['depth'] - for bind in get_filtered_binds(uzbl, bd): + bindlet = get_bindlet(uzbl) + depth = bindlet.depth + for bind in bindlet.get_binds(): t = bind[depth] if not t[MOD_CMD] or not t[ON_EXEC]: continue - if match_and_exec(uzbl, bind, depth, keylet, bd): + if match_and_exec(uzbl, bind, depth, keylet, bindlet): return uzbl.clear_modcmd() - after_bind(uzbl, bd) + bindlet.after() def init(uzbl): - connects = {'BIND': parse_bind_event, + connects = {'BIND': parse_bind, + 'MODE_BIND': parse_mode_bind, 'KEYCMD_UPDATE': keycmd_update, 'MODCMD_UPDATE': modcmd_update, 'KEYCMD_EXEC': keycmd_exec, diff --git a/examples/data/uzbl/plugins/completion.py b/examples/data/uzbl/plugins/completion.py index 770f310..8e055e1 100644 --- a/examples/data/uzbl/plugins/completion.py +++ b/examples/data/uzbl/plugins/completion.py @@ -29,6 +29,9 @@ def escape(str): def add_instance(uzbl, *args): UZBLS[uzbl] = dict(DEFAULTS) + # Make sure the config keys for all possible completions are known. + uzbl.send('dump_config_as_events') + def del_instance(uzbl, *args): if uzbl in UZBLS: diff --git a/examples/data/uzbl/scripts/uzbl-cookie-daemon b/examples/data/uzbl/scripts/uzbl-cookie-daemon index 87a2e87..fde8b8e 100755 --- a/examples/data/uzbl/scripts/uzbl-cookie-daemon +++ b/examples/data/uzbl/scripts/uzbl-cookie-daemon @@ -304,6 +304,9 @@ class CookieMonster: if daemon_running(config['cookie_socket']): sys.exit(1) + # Create cookie daemon socket. + self.create_socket() + # Daemonize process. if config['daemon_mode']: echo("entering daemon mode") @@ -322,9 +325,6 @@ class CookieMonster: self._running = True while self._running: - # Create cookie daemon socket. - self.create_socket() - try: # Enter main listen loop. self.listen() @@ -345,6 +345,8 @@ class CookieMonster: # Always delete the socket before calling create again. self.del_socket() + # Create cookie daemon socket. + self.create_socket() def load_whitelist(self): diff --git a/examples/data/uzbl/scripts/uzbl-event-manager b/examples/data/uzbl/scripts/uzbl-event-manager index 7a02da9..916259a 100755 --- a/examples/data/uzbl/scripts/uzbl-event-manager +++ b/examples/data/uzbl/scripts/uzbl-event-manager @@ -583,16 +583,16 @@ class UzblEventDaemon(dict): def run(self): '''Main event daemon loop.''' + # Create event daemon socket. + self._create_server_socket() + echo('listening on: %s' % self.socket_location) + if CONFIG['daemon_mode']: echo('entering daemon mode.') daemonize() # The pid has changed so update the pid file. make_pid_file(CONFIG['pid_file']) - # Create event daemon socket. - self._create_server_socket() - echo('listening on: %s' % self.socket_location) - # Now listen for incoming connections and or data. self.listen() |