aboutsummaryrefslogtreecommitdiffhomepage
path: root/examples/data/plugins
diff options
context:
space:
mode:
authorGravatar Mason Larobina <mason.larobina@gmail.com>2010-04-04 04:44:03 +0800
committerGravatar Mason Larobina <mason.larobina@gmail.com>2010-04-04 04:44:03 +0800
commitd3cbe16bf16ff63c0e3db15d645e958712bd02d8 (patch)
tree6bea7bda62f07b73329fdb136a0b907661ca356c /examples/data/plugins
parentae15d257a858fe27090f3e5798357aea2f5a76da (diff)
Huge plugin & event manager upgrades.
1. Removed unused modules 2. Re-use event handlers with identical callbacks and args. 3. Removed plugin exceptions in favour of assertions. 4. Remove useless raw_keycmd and raw_bind config vars. 5. Implemented and use `after` and `cleanup` plugin hooks (correctly) 6. EM & plugins now use the python logging module to output messages 7. Null config items are removed automatically 8. Simpler mode plugin 9. The init plugins function is called after the INSTANCE_START event 10. New optparse option to silence event echoing to stdout 11. Close instance socket on INSTANCE_EXIT before event handling 12. Caught signals are logged 13. Show times on the messages in the log file 14. Refactor bind pluin to use uzbl.bindlet directly. 15. Refactor keycmd plugin to use uzbl.keycmd directly. 16. Refactored on_event plugin to use uzbl.on_events dict over UZBLS dict 17. Refactor completion plugin to use uzbl.completion set object. 18. Modified progress plugin to use config vars instead of `@progress k = v` 19. mode_config now a defaultdict(dict) (I.e. this allows you to `uzbl.mode_config[mode][var] = value` without needing to check `mode` is in the `uzbl.mode_config` dict). 20. Removed all default mode config values. 21. Removed all `get_mode()` and `set_mode(..)` functions (and the like). 22. Setting the mode is now done via the config object directly (I.e. `uzbl.config['mode'] = 'insert'`). 23. Uses the on_set plugin to watch for 'mode' and 'default_mode' config changes. 24. Don't raise the useless NEW_ON_SET event, missing ON_SET connect. 25. Plugin and EventHandler aren't suited as dict objects. 26. Also using collections.defaultdict(list) for uzbl.handlers dict. 27. Plugin `on_set.py` allows you to attach handlers to config var changes 28. Config plugin reduced to one `uzbl.config` dict-like object. 29. Update export and connect calls in plugins. 30. The functions connect, connect_dict, export, export_dict, require, logging are exported directly to the plugin namespace. 31. Moved parse_msg into Uzbl class. 32. Generally improved comments. 33. UzblEventDaemon now an object. 34. Various variable, function & class renames.
Diffstat (limited to 'examples/data/plugins')
-rw-r--r--examples/data/plugins/bind.py63
-rw-r--r--examples/data/plugins/cmd_expand.py6
-rw-r--r--examples/data/plugins/completion.py129
-rw-r--r--examples/data/plugins/config.py129
-rw-r--r--examples/data/plugins/keycmd.py121
-rw-r--r--examples/data/plugins/mode.py204
-rw-r--r--examples/data/plugins/on_event.py69
-rw-r--r--examples/data/plugins/on_set.py92
-rw-r--r--examples/data/plugins/plugin_template.py76
-rw-r--r--examples/data/plugins/progress_bar.py152
10 files changed, 373 insertions, 668 deletions
diff --git a/examples/data/plugins/bind.py b/examples/data/plugins/bind.py
index a1a5d89..5b13476 100644
--- a/examples/data/plugins/bind.py
+++ b/examples/data/plugins/bind.py
@@ -11,10 +11,6 @@ And it is also possible to execute a function on activation:
import sys
import re
-import pprint
-
-# Hold the bind dicts for each uzbl instance.
-UZBLS = {}
# Commonly used regular expressions.
MOD_START = re.compile('^<([A-Z][A-Za-z0-9-_]*)>').match
@@ -62,9 +58,9 @@ class Bindlet(object):
if self.last_mode:
mode, self.last_mode = self.last_mode, None
- self.uzbl.set_mode(mode)
+ self.uzbl.config['mode'] = mode
- self.uzbl.set('keycmd_prompt')
+ del self.uzbl.config['keycmd_prompt']
def stack(self, bind, args, depth):
@@ -76,10 +72,10 @@ class Bindlet(object):
return
- current_mode = self.uzbl.get_mode()
- if current_mode != 'stack':
- self.last_mode = current_mode
- self.uzbl.set_mode('stack')
+ mode = self.uzbl.config.get('mode', None)
+ if mode != 'stack':
+ self.last_mode = mode
+ self.uzbl.config['mode'] = 'stack'
self.stack_binds = [bind,]
self.args += args
@@ -97,7 +93,7 @@ class Bindlet(object):
self.uzbl.clear_keycmd()
if prompt:
- self.uzbl.set('keycmd_prompt', prompt)
+ self.uzbl.config['keycmd_prompt'] = prompt
if set and is_cmd:
self.uzbl.send(set)
@@ -111,7 +107,7 @@ class Bindlet(object):
the filtered stack list and modkey & non-stack globals.'''
if mode is None:
- mode = self.uzbl.get_mode()
+ mode = self.uzbl.config.get('mode', None)
if not mode:
mode = 'global'
@@ -145,24 +141,6 @@ class Bindlet(object):
self.globals.append(bind)
-def add_instance(uzbl, *args):
- UZBLS[uzbl] = Bindlet(uzbl)
-
-
-def del_instance(uzbl, *args):
- if uzbl in UZBLS:
- del UZBLS[uzbl]
-
-
-def get_bindlet(uzbl):
- '''Return the bind tracklet for the given uzbl instance.'''
-
- if uzbl not in UZBLS:
- add_instance(uzbl)
-
- return UZBLS[uzbl]
-
-
def ismodbind(glob):
'''Return True if the glob specifies a modbind.'''
@@ -324,7 +302,7 @@ def exec_bind(uzbl, bind, *args, **kargs):
def mode_bind(uzbl, modes, glob, handler=None, *args, **kargs):
'''Add a mode bind.'''
- bindlet = get_bindlet(uzbl)
+ bindlet = uzbl.bindlet
if not hasattr(modes, '__iter__'):
modes = unicode(modes).split(',')
@@ -400,7 +378,8 @@ def mode_changed(uzbl, mode):
'''Clear the stack on all non-stack mode changes.'''
if mode != 'stack':
- get_bindlet(uzbl).reset()
+ uzbl.bindlet.reset()
+ uzbl.clear_keycmd()
def match_and_exec(uzbl, bind, depth, keylet, bindlet):
@@ -440,7 +419,7 @@ def match_and_exec(uzbl, bind, depth, keylet, bindlet):
args = bindlet.args + args
exec_bind(uzbl, bind, *args)
if not has_args or on_exec:
- uzbl.set_mode()
+ del uzbl.config['mode']
bindlet.reset()
uzbl.clear_current()
@@ -448,7 +427,7 @@ def match_and_exec(uzbl, bind, depth, keylet, bindlet):
def key_event(uzbl, keylet, mod_cmd=False, on_exec=False):
- bindlet = get_bindlet(uzbl)
+ bindlet = uzbl.bindlet
depth = bindlet.depth
for bind in bindlet.get_binds():
t = bind[depth]
@@ -463,12 +442,14 @@ def key_event(uzbl, keylet, mod_cmd=False, on_exec=False):
# Return to the previous mode if the KEYCMD_EXEC keycmd doesn't match any
# binds in the stack mode.
if on_exec and not mod_cmd and depth and depth == bindlet.depth:
- uzbl.set_mode()
+ del uzbl.config['mode']
+# plugin init hook
def init(uzbl):
- # Event handling hooks.
- uzbl.connect_dict({
+ '''Export functions and connect handlers to events.'''
+
+ connect_dict(uzbl, {
'BIND': parse_bind,
'MODE_BIND': parse_mode_bind,
'MODE_CHANGED': mode_changed,
@@ -481,12 +462,10 @@ def init(uzbl):
for mod_cmd in range(2):
for on_exec in range(2):
event = events[mod_cmd][on_exec]
- uzbl.connect(event, key_event, bool(mod_cmd), bool(on_exec))
+ connect(uzbl, event, key_event, bool(mod_cmd), bool(on_exec))
- # Function exports to the uzbl object, `function(uzbl, *args, ..)`
- # becomes `uzbl.function(*args, ..)`.
- uzbl.export_dict({
+ export_dict(uzbl, {
'bind': bind,
'mode_bind': mode_bind,
- 'get_bindlet': get_bindlet,
+ 'bindlet': Bindlet(uzbl),
})
diff --git a/examples/data/plugins/cmd_expand.py b/examples/data/plugins/cmd_expand.py
index 3f6ae2b..b007975 100644
--- a/examples/data/plugins/cmd_expand.py
+++ b/examples/data/plugins/cmd_expand.py
@@ -35,8 +35,6 @@ def cmd_expand(uzbl, cmd, args):
return cmd
-
+# plugin init hook
def init(uzbl):
- # Function exports to the uzbl object, `function(uzbl, *args, ..)`
- # becomes `uzbl.function(*args, ..)`.
- uzbl.export('cmd_expand', cmd_expand)
+ export(uzbl, 'cmd_expand', cmd_expand)
diff --git a/examples/data/plugins/completion.py b/examples/data/plugins/completion.py
index 8cea203..e8c7f34 100644
--- a/examples/data/plugins/completion.py
+++ b/examples/data/plugins/completion.py
@@ -1,19 +1,10 @@
'''Keycmd completion.'''
-# A list of functions this plugin exports to be used via uzbl object.
-__export__ = ['start_completion', 'get_completion_dict']
-
import re
-# Holds the per-instance completion dicts.
-UZBLS = {}
-
# Completion level
NONE, ONCE, LIST, COMPLETE = range(4)
-# Default instance dict.
-DEFAULTS = {'completions': [], 'level': NONE, 'lock': False}
-
# The reverse keyword finding re.
FIND_SEGMENT = re.compile("(\@[\w_]+|set[\s]+[\w_]+|[\w_]+)$").findall
@@ -21,39 +12,17 @@ FIND_SEGMENT = re.compile("(\@[\w_]+|set[\s]+[\w_]+|[\w_]+)$").findall
LIST_FORMAT = "<span> %s </span>"
ITEM_FORMAT = "<span @hint_style>%s</span>%s"
-
def escape(str):
return str.replace("@", "\@")
-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:
- del UZBLS[uzbl]
-
-
-def get_completion_dict(uzbl):
- '''Get data stored for an instance.'''
-
- if uzbl not in UZBLS:
- add_instance(uzbl)
-
- return UZBLS[uzbl]
-
-
def get_incomplete_keyword(uzbl):
'''Gets the segment of the keycmd leading up to the cursor position and
uses a regular expression to search backwards finding parially completed
keywords or @variables. Returns a null string if the correct completion
conditions aren't met.'''
- keylet = uzbl.get_keylet()
+ keylet = uzbl.keylet
left_segment = keylet.keycmd[:keylet.cursor]
partial = (FIND_SEGMENT(left_segment) + ['',])[0].lstrip()
if partial.startswith('set '):
@@ -65,9 +34,8 @@ def get_incomplete_keyword(uzbl):
def stop_completion(uzbl, *args):
'''Stop command completion and return the level to NONE.'''
- d = get_completion_dict(uzbl)
- d['level'] = NONE
- uzbl.set('completion_list')
+ uzbl.completion.level = NONE
+ del uzbl.config['completion_list']
def complete_completion(uzbl, partial, hint, set_completion=False):
@@ -99,46 +67,46 @@ def update_completion_list(uzbl, *args):
if not partial:
return stop_completion(uzbl)
- d = get_completion_dict(uzbl)
- if d['level'] < LIST:
+ if uzbl.completion.level < LIST:
return
- hints = [h for h in d['completions'] if h.startswith(partial)]
+ hints = filter(lambda h: h.startswith(partial), uzbl.completion)
if not hints:
- return uzbl.set('completion_list')
+ del uzbl.config['completion_list']
+ return
j = len(partial)
l = [ITEM_FORMAT % (escape(h[:j]), h[j:]) for h in sorted(hints)]
- uzbl.set('completion_list', LIST_FORMAT % ' '.join(l))
+ uzbl.config['completion_list'] = LIST_FORMAT % ' '.join(l)
def start_completion(uzbl, *args):
- d = get_completion_dict(uzbl)
- if d['lock']:
+ comp = uzbl.completion
+ if comp.locked:
return
(partial, set_completion) = get_incomplete_keyword(uzbl)
if not partial:
return stop_completion(uzbl)
- if d['level'] < COMPLETE:
- d['level'] += 1
+ if comp.level < COMPLETE:
+ comp.level += 1
- hints = [h for h in d['completions'] if h.startswith(partial)]
+ hints = filter(lambda h: h.startswith(partial), comp)
if not hints:
return
elif len(hints) == 1:
- d['lock'] = True
+ comp.lock()
complete_completion(uzbl, partial, hints[0], set_completion)
- d['lock'] = False
+ comp.unlock()
return
- elif partial in hints and d['level'] == COMPLETE:
- d['lock'] = True
+ elif partial in hints and comp.level == COMPLETE:
+ comp.lock()
complete_completion(uzbl, partial, partial, set_completion)
- d['lock'] = False
+ comp.unlock()
return
smalllen, smallest = sorted([(len(h), h) for h in hints])[0]
@@ -156,51 +124,56 @@ def start_completion(uzbl, *args):
common += char
if common:
- d['lock'] = True
+ comp.lock()
partial_completion(uzbl, partial, partial+common)
- d['lock'] = False
+ comp.unlock()
update_completion_list(uzbl)
-def add_builtins(uzbl, args):
+def add_builtins(uzbl, builtins):
'''Pump the space delimited list of builtin commands into the
builtin list.'''
- completions = get_completion_dict(uzbl)['completions']
- builtins = filter(None, map(unicode.strip, args.split(" ")))
- for builtin in builtins:
- if builtin not in completions:
- completions.append(builtin)
+ uzbl.completion.update(builtins.split())
def add_config_key(uzbl, key, value):
'''Listen on the CONFIG_CHANGED event and add config keys to the variable
list for @var<Tab> like expansion support.'''
- completions = get_completion_dict(uzbl)['completions']
- key = "@%s" % key
- if key not in completions:
- completions.append(key)
+ uzbl.completion.add("@%s" % key)
+
+
+class Completions(set):
+ def __init__(self):
+ set.__init__(self)
+ self.locked = False
+ self.level = NONE
+
+ def lock(self):
+ self.locked = True
+
+ def unlock(self):
+ self.locked = False
def init(uzbl):
- # Event handling hooks.
- uzbl.connect_dict({
- 'BUILTINS': add_builtins,
- 'CONFIG_CHANGED': add_config_key,
- 'INSTANCE_EXIT': del_instance,
- 'INSTANCE_START': add_instance,
- 'KEYCMD_CLEARED': stop_completion,
- 'KEYCMD_EXEC': stop_completion,
- 'KEYCMD_UPDATE': update_completion_list,
- 'START_COMPLETION': start_completion,
- 'STOP_COMPLETION': stop_completion,
+ '''Export functions and connect handlers to events.'''
+
+ export_dict(uzbl, {
+ 'completion': Completions(),
+ 'start_completion': start_completion,
})
- # Function exports to the uzbl object, `function(uzbl, *args, ..)`
- # becomes `uzbl.function(*args, ..)`.
- uzbl.export_dict({
- 'get_completion_dict': get_completion_dict,
- 'start_completion': start_completion,
+ connect_dict(uzbl, {
+ 'BUILTINS': add_builtins,
+ 'CONFIG_CHANGED': add_config_key,
+ 'KEYCMD_CLEARED': stop_completion,
+ 'KEYCMD_EXEC': stop_completion,
+ 'KEYCMD_UPDATE': update_completion_list,
+ 'START_COMPLETION': start_completion,
+ 'STOP_COMPLETION': stop_completion,
})
+
+ uzbl.send('dump_config_as_events')
diff --git a/examples/data/plugins/config.py b/examples/data/plugins/config.py
index 4a848a3..ed2d761 100644
--- a/examples/data/plugins/config.py
+++ b/examples/data/plugins/config.py
@@ -1,97 +1,90 @@
-import re
-import types
+from re import compile
+from types import BooleanType
+from UserDict import DictMixin
-__export__ = ['set', 'get_config']
-
-VALIDKEY = re.compile("^[a-zA-Z][a-zA-Z0-9_]*$").match
-TYPECONVERT = {'int': int, 'float': float, 'str': unicode}
-
-UZBLS = {}
-
-
-def escape(value):
- '''A real escaping function may be required.'''
-
- return unicode(value)
+valid_key = compile('^[A-Za-z0-9_\.]+$').match
+types = {'int': int, 'float': float, 'str': unicode}
+escape = lambda s: unicode(s).replace('\n', '\\n')
+class Config(DictMixin):
+ def __init__(self, uzbl):
+ self.uzbl = uzbl
-def set(uzbl, key, value='', config=None, force=False):
- '''Sends a: "set key = value" command to the uzbl instance. If force is
- False then only send a set command if the values aren't equal.'''
+ # Create the base dict and map allowed methods to `self`.
+ self.data = data = {}
- if type(value) == types.BooleanType:
- value = int(value)
+ methods = ['__contains__', '__getitem__', '__iter__',
+ '__len__', 'get', 'has_key', 'items', 'iteritems',
+ 'iterkeys', 'itervalues', 'values']
- else:
- value = unicode(value)
+ for method in methods:
+ setattr(self, method, getattr(data, method))
- if not VALIDKEY(key):
- raise KeyError("%r" % key)
- value = escape(value)
- if '\n' in value:
- value = value.replace("\n", "\\n")
+ def __setitem__(self, key, value):
+ self.set(key, value)
- if not force:
- if config is None:
- config = get_config(uzbl)
+ def __delitem__(self, key):
+ self.set(key)
- if key in config and config[key] == value:
- return
+ def update(self, other=None, **kwargs):
+ if other is None:
+ other = {}
- uzbl.send('set %s = %s' % (key, value))
+ for (key, value) in dict(other).items() + kwargs.items():
+ self[key] = value
-class ConfigDict(dict):
- def __init__(self, uzbl):
- self._uzbl = uzbl
+ def set(self, key, value='', force=False):
+ '''Generates a `set <key> = <value>` command string to send to the
+ current uzbl instance.
- def __setitem__(self, key, value):
- '''Makes "config[key] = value" a wrapper for the set function.'''
+ Note that the config dict isn't updated by this function. The config
+ dict is only updated after a successful `VARIABLE_SET ..` event
+ returns from the uzbl instance.'''
- set(self._uzbl, key, value, config=self)
+ assert valid_key(key)
+ if type(value) == BooleanType:
+ value = int(value)
-def add_instance(uzbl, *args):
- UZBLS[uzbl] = ConfigDict(uzbl)
+ else:
+ value = escape(value)
+ if not force and key in self and self[key] == value:
+ return
-def del_instance(uzbl, *args):
- if uzbl in UZBLS:
- del uzbl
+ self.uzbl.send(u'set %s = %s' % (key, value))
-def get_config(uzbl):
- if uzbl not in UZBLS:
- add_instance(uzbl)
+def parse_set_event(uzbl, args):
+ '''Parse `VARIABLE_SET <var> <type> <value>` event and load the
+ (key, value) pair into the `uzbl.config` dict.'''
- return UZBLS[uzbl]
+ (key, type, raw_value) = (args.split(' ', 2) + ['',])[:3]
+ assert valid_key(key)
+ assert type in types
-def variable_set(uzbl, args):
- config = get_config(uzbl)
+ new_value = types[type](raw_value)
+ old_value = uzbl.config.get(key, None)
- key, type, value = list(args.split(' ', 2) + ['',])[:3]
- old = config[key] if key in config else None
- value = TYPECONVERT[type](value)
+ # Update new value.
+ uzbl.config.data[key] = new_value
- dict.__setitem__(config, key, value)
+ if old_value != new_value:
+ uzbl.event('CONFIG_CHANGED', key, new_value)
- if old != value:
- uzbl.event("CONFIG_CHANGED", key, value)
+ # Cleanup null config values.
+ if type == 'str' and not new_value:
+ del uzbl.config.data[key]
+# plugin init hook
def init(uzbl):
- # Event handling hooks.
- uzbl.connect_dict({
- 'INSTANCE_EXIT': del_instance,
- 'INSTANCE_START': add_instance,
- 'VARIABLE_SET': variable_set,
- })
-
- # Function exports to the uzbl object, `function(uzbl, *args, ..)`
- # becomes `uzbl.function(*args, ..)`.
- uzbl.export_dict({
- 'get_config': get_config,
- 'set': set,
- })
+ export(uzbl, 'config', Config(uzbl))
+ connect(uzbl, 'VARIABLE_SET', parse_set_event)
+
+# plugin cleanup hook
+def cleanup(uzbl):
+ uzbl.config.data.clear()
diff --git a/examples/data/plugins/keycmd.py b/examples/data/plugins/keycmd.py
index c119077..b600afe 100644
--- a/examples/data/plugins/keycmd.py
+++ b/examples/data/plugins/keycmd.py
@@ -1,8 +1,5 @@
import re
-# Hold the keylets.
-UZBLS = {}
-
# Keycmd format which includes the markup for the cursor.
KEYCMD_FORMAT = "%s<span @cursor_style>%s</span>%s"
MODCMD_FORMAT = "<span> %s </span>"
@@ -38,9 +35,6 @@ class Keylet(object):
self.ignores = {}
self.additions = {}
- # Keylet string repr cache.
- self._repr_cache = None
-
def get_keycmd(self):
'''Get the keycmd-part of the keylet.'''
@@ -106,9 +100,6 @@ class Keylet(object):
def __repr__(self):
'''Return a string representation of the keylet.'''
- if self._repr_cache:
- return self._repr_cache
-
l = []
if self.is_modcmd:
l.append('modcmd=%r' % self.get_modcmd())
@@ -119,8 +110,7 @@ class Keylet(object):
if self.keycmd:
l.append('keycmd=%r' % self.get_keycmd())
- self._repr_cache = '<Keylet(%s)>' % ', '.join(l)
- return self._repr_cache
+ return '<keylet(%s)>' % ', '.join(l)
def add_modmap(uzbl, key, map):
@@ -140,7 +130,7 @@ def add_modmap(uzbl, key, map):
'''
assert len(key)
- modmaps = get_keylet(uzbl).modmaps
+ modmaps = uzbl.keylet.modmaps
if key[0] == "<" and key[-1] == ">":
key = key[1:-1]
@@ -171,7 +161,7 @@ def add_key_ignore(uzbl, glob):
'''
assert len(glob) > 1
- ignores = get_keylet(uzbl).ignores
+ ignores = uzbl.keylet.ignores
glob = "<%s>" % glob.strip("<> ")
restr = glob.replace('*', '[^\s]*')
@@ -197,7 +187,7 @@ def add_modkey_addition(uzbl, modkeys, result):
...
'''
- additions = get_keylet(uzbl).additions
+ additions = uzbl.keylet.additions
modkeys = set(modkeys)
assert len(modkeys) and result and result not in modkeys
@@ -220,65 +210,34 @@ def modkey_addition_parse(uzbl, modkeys):
add_modkey_addition(uzbl, keys[:-1], keys[-1])
-def add_instance(uzbl, *args):
- '''Create the Keylet object for this uzbl instance.'''
-
- UZBLS[uzbl] = Keylet()
-
-
-def del_instance(uzbl, *args):
- '''Delete the Keylet object for this uzbl instance.'''
-
- if uzbl in UZBLS:
- del UZBLS[uzbl]
-
-
-def get_keylet(uzbl):
- '''Return the corresponding keylet for this uzbl instance.'''
-
- # Startup events are not correctly captured and sent over the uzbl socket
- # yet so this line is needed because the INSTANCE_START event is lost.
- if uzbl not in UZBLS:
- add_instance(uzbl)
-
- keylet = UZBLS[uzbl]
- keylet._repr_cache = False
- return keylet
-
-
def clear_keycmd(uzbl):
'''Clear the keycmd for this uzbl instance.'''
- k = get_keylet(uzbl)
+ k = uzbl.keylet
k.keycmd = ''
k.cursor = 0
- k._repr_cache = False
- uzbl.set('keycmd')
- uzbl.set('raw_keycmd')
+ del uzbl.config['keycmd']
uzbl.event('KEYCMD_CLEARED')
def clear_modcmd(uzbl, clear_held=False):
'''Clear the modcmd for this uzbl instance.'''
- k = get_keylet(uzbl)
+ k = uzbl.keylet
k.modcmd = ''
k.is_modcmd = False
- k._repr_cache = False
if clear_held:
k.ignored = set()
k.held = set()
- uzbl.set('modcmd')
- uzbl.set('raw_modcmd')
+ del uzbl.config['modcmd']
uzbl.event('MODCMD_CLEARED')
def clear_current(uzbl):
'''Clear the modcmd if is_modcmd else clear keycmd.'''
- k = get_keylet(uzbl)
- if k.is_modcmd:
+ if uzbl.keylet.is_modcmd:
clear_modcmd(uzbl)
else:
@@ -296,7 +255,6 @@ def focus_changed(uzbl, *args):
def update_event(uzbl, k, execute=True):
'''Raise keycmd & modcmd update events.'''
- config = uzbl.get_config()
keycmd, modcmd = k.get_keycmd(), k.get_modcmd()
if k.is_modcmd:
@@ -305,32 +263,28 @@ def update_event(uzbl, k, execute=True):
else:
uzbl.event('KEYCMD_UPDATE', k)
- if 'modcmd_updates' not in config or config['modcmd_updates'] == '1':
+ if uzbl.config.get('modcmd_updates', '1') == '1':
new_modcmd = k.get_modcmd()
if not new_modcmd:
- uzbl.set('modcmd', config=config)
- uzbl.set('raw_modcmd', config=config)
+ del uzbl.config['modcmd']
elif new_modcmd == modcmd:
- uzbl.set('raw_modcmd', escape(modcmd), config=config)
- uzbl.set('modcmd', MODCMD_FORMAT % uzbl_escape(modcmd),
- config=config)
+ uzbl.config['modcmd'] = MODCMD_FORMAT % uzbl_escape(modcmd)
- if 'keycmd_events' in config and config['keycmd_events'] != '1':
+ if uzbl.config.get('keycmd_events', '1') != '1':
return
new_keycmd = k.get_keycmd()
if not new_keycmd:
- uzbl.set('keycmd', config=config)
- uzbl.set('raw_keycmd', config=config)
+ del uzbl.config['keycmd']
elif new_keycmd == keycmd:
# Generate the pango markup for the cursor in the keycmd.
curchar = keycmd[k.cursor] if k.cursor < len(keycmd) else ' '
chunks = [keycmd[:k.cursor], curchar, keycmd[k.cursor+1:]]
value = KEYCMD_FORMAT % tuple(map(uzbl_escape, chunks))
- uzbl.set('keycmd', value, config=config)
- uzbl.set('raw_keycmd', escape(keycmd), config=config)
+
+ uzbl.config['keycmd'] = value
def inject_str(str, index, inj):
@@ -344,7 +298,7 @@ def get_keylet_and_key(uzbl, key, add=True):
by the modmapping or modkey addition rules. Return None if the key is
ignored.'''
- keylet = get_keylet(uzbl)
+ keylet = uzbl.keylet
key = keylet.modmap_key(key)
if len(key) == 1:
return (keylet, key)
@@ -385,12 +339,11 @@ def key_press(uzbl, key):
k.cursor += 1
elif not k.held and len(key) == 1:
- config = uzbl.get_config()
- if 'keycmd_events' in config and config['keycmd_events'] != '1':
+
+ if uzbl.config.get('keycmd_events', '1') != '1':
k.keycmd = ''
k.cursor = 0
- uzbl.set('keycmd', config=config)
- uzbl.set('raw_keycmd', config=config)
+ del uzbl.config['keycmd']
return
k.keycmd = inject_str(k.keycmd, k.cursor, key)
@@ -429,9 +382,8 @@ def key_release(uzbl, key):
def set_keycmd(uzbl, keycmd):
'''Allow setting of the keycmd externally.'''
- k = get_keylet(uzbl)
+ k = uzbl.keylet
k.keycmd = keycmd
- k._repr_cache = None
k.cursor = len(keycmd)
update_event(uzbl, k, False)
@@ -439,9 +391,8 @@ def set_keycmd(uzbl, keycmd):
def inject_keycmd(uzbl, keycmd):
'''Allow injecting of a string into the keycmd at the cursor position.'''
- k = get_keylet(uzbl)
+ k = uzbl.keylet
k.keycmd = inject_str(k.keycmd, k.cursor, keycmd)
- k._repr_cache = None
k.cursor += len(keycmd)
update_event(uzbl, k, False)
@@ -449,9 +400,8 @@ def inject_keycmd(uzbl, keycmd):
def append_keycmd(uzbl, keycmd):
'''Allow appening of a string to the keycmd.'''
- k = get_keylet(uzbl)
+ k = uzbl.keylet
k.keycmd += keycmd
- k._repr_cache = None
k.cursor = len(k.keycmd)
update_event(uzbl, k, False)
@@ -460,7 +410,7 @@ def keycmd_strip_word(uzbl, sep):
''' Removes the last word from the keycmd, similar to readline ^W '''
sep = sep or ' '
- k = get_keylet(uzbl)
+ k = uzbl.keylet
if not k.keycmd:
return
@@ -475,7 +425,7 @@ def keycmd_strip_word(uzbl, sep):
def keycmd_backspace(uzbl, *args):
'''Removes the character at the cursor position in the keycmd.'''
- k = get_keylet(uzbl)
+ k = uzbl.keylet
if not k.keycmd:
return
@@ -487,7 +437,7 @@ def keycmd_backspace(uzbl, *args):
def keycmd_delete(uzbl, *args):
'''Removes the character after the cursor position in the keycmd.'''
- k = get_keylet(uzbl)
+ k = uzbl.keylet
if not k.keycmd:
return
@@ -499,8 +449,7 @@ def keycmd_exec_current(uzbl, *args):
'''Raise a KEYCMD_EXEC with the current keylet and then clear the
keycmd.'''
- k = get_keylet(uzbl)
- uzbl.event('KEYCMD_EXEC', k)
+ uzbl.event('KEYCMD_EXEC', uzbl.keylet)
clear_keycmd(uzbl)
@@ -508,7 +457,7 @@ def set_cursor_pos(uzbl, index):
'''Allow setting of the cursor position externally. Supports negative
indexing and relative stepping with '+' and '-'.'''
- k = get_keylet(uzbl)
+ k = uzbl.keylet
if index == '-':
cursor = k.cursor - 1
@@ -530,18 +479,16 @@ def set_cursor_pos(uzbl, index):
update_event(uzbl, k, False)
+# plugin init hook
def init(uzbl):
- '''Connect handlers to uzbl events.'''
+ '''Export functions and connect handlers to events.'''
- # Event handling hooks.
- uzbl.connect_dict({
+ connect_dict(uzbl, {
'APPEND_KEYCMD': append_keycmd,
'FOCUS_GAINED': focus_changed,
'FOCUS_LOST': focus_changed,
'IGNORE_KEY': add_key_ignore,
'INJECT_KEYCMD': inject_keycmd,
- 'INSTANCE_EXIT': del_instance,
- 'INSTANCE_START': add_instance,
'KEYCMD_BACKSPACE': keycmd_backspace,
'KEYCMD_DELETE': keycmd_delete,
'KEYCMD_EXEC_CURRENT': keycmd_exec_current,
@@ -554,9 +501,7 @@ def init(uzbl):
'SET_KEYCMD': set_keycmd,
})
- # Function exports to the uzbl object, `function(uzbl, *args, ..)`
- # becomes `uzbl.function(*args, ..)`.
- uzbl.export_dict({
+ export_dict(uzbl, {
'add_key_ignore': add_key_ignore,
'add_modkey_addition': add_modkey_addition,
'add_modmap': add_modmap,
@@ -564,8 +509,8 @@ def init(uzbl):
'clear_current': clear_current,
'clear_keycmd': clear_keycmd,
'clear_modcmd': clear_modcmd,
- 'get_keylet': get_keylet,
'inject_keycmd': inject_keycmd,
+ 'keylet': Keylet(),
'set_cursor_pos': set_cursor_pos,
'set_keycmd': set_keycmd,
})
diff --git a/examples/data/plugins/mode.py b/examples/data/plugins/mode.py
index 54d865a..e0de706 100644
--- a/examples/data/plugins/mode.py
+++ b/examples/data/plugins/mode.py
@@ -1,176 +1,68 @@
-import sys
-import re
+from collections import defaultdict
-__export__ = ['set_mode', 'get_mode', 'set_mode_config', 'get_mode_config']
+def parse_mode_config(uzbl, args):
+ '''Parse `MODE_CONFIG <mode> <var> = <value>` event and update config if
+ the `<mode>` is the current mode.'''
-UZBLS = {}
+ ustrip = unicode.strip
+ args = unicode(args)
-DEFAULTS = {
- 'mode': '',
- 'modes': {
- 'insert': {
- 'forward_keys': True,
- 'keycmd_events': False,
- 'modcmd_updates': False,
- 'mode_indicator': 'I'},
- 'command': {
- 'forward_keys': False,
- 'keycmd_events': True,
- 'modcmd_updates': True,
- 'mode_indicator': 'C'}}}
+ assert args.strip(), "missing mode config args"
+ (mode, args) = map(ustrip, (args.strip().split(' ', 1) + ['',])[:2])
-FINDSPACES = re.compile("\s+")
-VALID_KEY = re.compile("^[\w_]+$").match
+ assert args.strip(), "missing mode config set arg"
+ (key, value) = map(ustrip, (args.strip().split('=', 1) + [None,])[:2])
+ assert key and value is not None, "invalid mode config set syntax"
+ uzbl.mode_config[mode][key] = value
+ if uzbl.config.get('mode', None) == mode:
+ uzbl.config[key] = value
-def add_instance(uzbl, *args):
- UZBLS[uzbl] = dict(DEFAULTS)
+def default_mode_updated(uzbl, var, mode):
+ if mode and not uzbl.config.get('mode', None):
+ logger.debug('setting mode to default %r' % mode)
+ uzbl.config['mode'] = mode
-def del_instance(uzbl, *args):
- if uzbl in UZBLS:
- del UZBLS[uzbl]
-
-def get_mode_dict(uzbl):
- '''Return the mode dict for an instance.'''
-
- if uzbl not in UZBLS:
- add_instance(uzbl)
-
- return UZBLS[uzbl]
-
-
-def get_mode_config(uzbl, mode):
- '''Return the mode config for a given mode.'''
-
- modes = get_mode_dict(uzbl)['modes']
- if mode not in modes:
- modes[mode] = {}
-
- return modes[mode]
-
-
-def get_mode(uzbl):
- return get_mode_dict(uzbl)['mode']
-
-
-def mode_changed(uzbl, mode):
- '''The mode has just been changed, now set the per-mode config.'''
-
- if get_mode(uzbl) != mode:
+def mode_updated(uzbl, var, mode):
+ if not mode:
+ mode = uzbl.config.get('default_mode', 'command')
+ logger.debug('setting mode to default %r' % mode)
+ uzbl.config['mode'] = mode
return
- config = uzbl.get_config()
- mode_config = get_mode_config(uzbl, mode)
- for (key, value) in mode_config.items():
- uzbl.set(key, value, config=config)
-
- if 'mode_indicator' not in mode_config:
- config['mode_indicator'] = mode
-
- uzbl.clear_keycmd()
- uzbl.clear_modcmd()
-
-
-def set_mode(uzbl, mode=None):
- '''Set the mode and raise the MODE_CHANGED event if the mode has changed.
- Fallback on the default mode if no mode argument was given and the default
- mode is not null.'''
-
- config = uzbl.get_config()
- mode_dict = get_mode_dict(uzbl)
- if mode is None:
- mode_dict['mode'] = ''
- if 'default_mode' in config:
- mode = config['default_mode']
-
- else:
- mode = 'command'
-
- if not VALID_KEY(mode):
- raise KeyError("invalid mode name: %r" % mode)
-
- if 'mode' not in config or config['mode'] != mode:
- config['mode'] = mode
+ # Load mode config
+ mode_config = uzbl.mode_config.get(mode, None)
+ if mode_config:
+ uzbl.config.update(mode_config)
- elif mode_dict['mode'] != mode:
- mode_dict['mode'] = mode
- uzbl.event("MODE_CHANGED", mode)
+ uzbl.send('event MODE_CONFIRM %s' % mode)
-def config_changed(uzbl, key, value):
- '''Check for mode related config changes.'''
+def confirm_change(uzbl, mode):
+ if mode and uzbl.config.get('mode', None) == mode:
+ uzbl.event('MODE_CHANGED', mode)
- value = None if not value else value
- if key == 'default_mode':
- if not get_mode(uzbl):
- set_mode(uzbl, value)
- elif key == 'mode':
- set_mode(uzbl, value)
-
-
-def set_mode_config(uzbl, mode, key, value):
- '''Set mode specific configs. If the mode being modified is the current
- mode then apply the changes on the go.'''
-
- assert VALID_KEY(mode) and VALID_KEY(key)
-
- mode_config = get_mode_config(uzbl, mode)
- mode_config[key] = value
-
- if get_mode(uzbl) == mode:
- uzbl.set(key, value)
-
-
-def mode_config(uzbl, args):
- '''Parse mode config events.'''
-
- split = map(unicode.strip, FINDSPACES.split(args.lstrip(), 1))
- if len(split) != 2:
- raise SyntaxError('invalid mode config syntax: %r' % args)
-
- mode, set = split
- split = map(unicode.strip, set.split('=', 1))
- if len(split) != 2:
- raise SyntaxError('invalid set syntax: %r' % args)
-
- key, value = split
- set_mode_config(uzbl, mode, key, value)
-
-
-def toggle_modes(uzbl, modes):
- '''Toggle or cycle between or through a list of modes.'''
-
- assert len(modes.strip())
-
- modelist = filter(None, map(unicode.strip, modes.split(' ')))
- mode = get_mode(uzbl)
-
- index = 0
- if mode in modelist:
- index = (modelist.index(mode)+1) % len(modelist)
-
- set_mode(uzbl, modelist[index])
+# plugin init hook
+def init(uzbl):
+ require('config')
+ require('on_set')
+ # Usage `uzbl.mode_config[mode][key] = value`
+ export(uzbl, 'mode_config', defaultdict(dict))
-def init(uzbl):
- # Event handling hooks.
- uzbl.connect_dict({
- 'CONFIG_CHANGED': config_changed,
- 'INSTANCE_EXIT': del_instance,
- 'INSTANCE_START': add_instance,
- 'MODE_CHANGED': mode_changed,
- 'MODE_CONFIG': mode_config,
- 'TOGGLE_MODES': toggle_modes,
+ connect_dict(uzbl, {
+ 'MODE_CONFIG': parse_mode_config,
+ 'MODE_CONFIRM': confirm_change,
})
- # Function exports to the uzbl object, `function(uzbl, *args, ..)`
- # becomes `uzbl.function(*args, ..)`.
- uzbl.export_dict({
- 'get_mode': get_mode,
- 'get_mode_config': get_mode_config,
- 'set_mode': set_mode,
- 'set_mode_config': set_mode_config,
- })
+# plugin after hook
+def after(uzbl):
+ uzbl.on_set('mode', mode_updated)
+ uzbl.on_set('default_mode', default_mode_updated)
+
+# plugin cleanup hook
+def cleanup(uzbl):
+ uzbl.mode_config.clear()
diff --git a/examples/data/plugins/on_event.py b/examples/data/plugins/on_event.py
index b9c504a..5142275 100644
--- a/examples/data/plugins/on_event.py
+++ b/examples/data/plugins/on_event.py
@@ -20,36 +20,11 @@ Usage:
import sys
import re
-__export__ = ['get_on_events', 'on_event']
-
-UZBLS = {}
-
-
-def error(msg):
- sys.stderr.write('on_event plugin: error: %s\n' % msg)
-
-
-def add_instance(uzbl, *args):
- UZBLS[uzbl] = {}
-
-
-def del_instance(uzbl, *args):
- if uzbl in UZBLS:
- del UZBLS[uzbl]
-
-
-def get_on_events(uzbl):
- if uzbl not in UZBLS:
- add_instance(uzbl)
-
- return UZBLS[uzbl]
-
-
def event_handler(uzbl, *args, **kargs):
'''This function handles all the events being watched by various
on_event definitions and responds accordingly.'''
- events = get_on_events(uzbl)
+ events = uzbl.on_events
event = kargs['on_event']
if event not in events:
return
@@ -65,9 +40,9 @@ def on_event(uzbl, event, cmd):
'''Add a new event to watch and respond to.'''
event = event.upper()
- events = get_on_events(uzbl)
+ events = uzbl.on_events
if event not in events:
- uzbl.connect(event, event_handler, on_event=event)
+ connect(uzbl, event, event_handler, on_event=event)
events[event] = []
cmds = events[event]
@@ -80,28 +55,28 @@ def parse_on_event(uzbl, args):
Syntax: "event ON_EVENT <EVENT_NAME> commands".'''
- if not args:
- return error("missing on_event arguments")
-
- split = args.split(' ', 1)
- if len(split) != 2:
- return error("invalid ON_EVENT syntax: %r" % args)
+ args = args.strip()
+ assert args, 'missing on event arguments'
- event, cmd = split
- on_event(uzbl, event, cmd)
+ (event, command) = (args.split(' ', 1) + ['',])[:2]
+ assert event and command, 'missing on event command'
+ on_event(uzbl, event, command)
+# plugin init hook
def init(uzbl):
- # Event handling hooks.
- uzbl.connect_dict({
- 'INSTANCE_EXIT': del_instance,
- 'INSTANCE_START': add_instance,
- 'ON_EVENT': parse_on_event,
- })
+ '''Export functions and connect handlers to events.'''
+
+ connect(uzbl, 'ON_EVENT', parse_on_event)
- # Function exports to the uzbl object, `function(uzbl, *args, ..)`
- # becomes `uzbl.function(*args, ..)`.
- uzbl.export_dict({
- 'get_on_events': get_on_events,
- 'on_event': on_event,
+ export_dict(uzbl, {
+ 'on_event': on_event,
+ 'on_events': {},
})
+
+# plugin cleanup hook
+def cleanup(uzbl):
+ for handlers in uzbl.on_events.values():
+ del handlers[:]
+
+ uzbl.on_events.clear()
diff --git a/examples/data/plugins/on_set.py b/examples/data/plugins/on_set.py
new file mode 100644
index 0000000..130b816
--- /dev/null
+++ b/examples/data/plugins/on_set.py
@@ -0,0 +1,92 @@
+from re import compile
+from functools import partial
+
+valid_glob = compile('^[A-Za-z0-9_\*\.]+$').match
+
+def make_matcher(glob):
+ '''Make matcher function from simple glob.'''
+
+ pattern = "^%s$" % glob.replace('*', '[^\s]*')
+ return compile(pattern).match
+
+
+def exec_handlers(uzbl, handlers, key, arg):
+ '''Execute the on_set handlers that matched the key.'''
+
+ for handler in handlers:
+ if callable(handler):
+ handler(key, arg)
+
+ else:
+ uzbl.send(uzbl.cmd_expand(handler, [key, arg]))
+
+
+def check_for_handlers(uzbl, key, arg):
+ '''Check for handlers for the current key.'''
+
+ for (matcher, handlers) in uzbl.on_sets.values():
+ if matcher(key):
+ exec_handlers(uzbl, handlers, key, arg)
+
+
+def on_set(uzbl, glob, handler, prepend=True):
+ '''Add a new handler for a config key change.
+
+ Structure of the `uzbl.on_sets` dict:
+ { glob : ( glob matcher function, handlers list ), .. }
+ '''
+
+ assert valid_glob(glob)
+
+ while '**' in glob:
+ glob = glob.replace('**', '*')
+
+ if callable(handler):
+ orig_handler = handler
+ if prepend:
+ handler = partial(handler, uzbl)
+
+ else:
+ orig_handler = handler = unicode(handler)
+
+ if glob in uzbl.on_sets:
+ (matcher, handlers) = uzbl.on_sets[glob]
+ handlers.append(handler)
+
+ else:
+ matcher = make_matcher(glob)
+ uzbl.on_sets[glob] = (matcher, [handler,])
+
+ uzbl.logger.info('on set %r call %r' % (glob, orig_handler))
+
+
+def parse_on_set(uzbl, args):
+ '''Parse `ON_SET <glob> <command>` event then pass arguments to the
+ `on_set(..)` function.'''
+
+ (glob, command) = (args.split(' ', 1) + [None,])[:2]
+ assert glob and command and valid_glob(glob)
+ on_set(uzbl, glob, command)
+
+
+# plugins init hook
+def init(uzbl):
+ require('config')
+ require('cmd_expand')
+
+ export_dict(uzbl, {
+ 'on_sets': {},
+ 'on_set': on_set,
+ })
+
+ connect_dict(uzbl, {
+ 'ON_SET': parse_on_set,
+ 'CONFIG_CHANGED': check_for_handlers,
+ })
+
+# plugins cleanup hook
+def cleanup(uzbl):
+ for (matcher, handlers) in uzbl.on_sets.values():
+ del handlers[:]
+
+ uzbl.on_sets.clear()
diff --git a/examples/data/plugins/plugin_template.py b/examples/data/plugins/plugin_template.py
deleted file mode 100644
index 565a999..0000000
--- a/examples/data/plugins/plugin_template.py
+++ /dev/null
@@ -1,76 +0,0 @@
-'''Plugin template.'''
-
-# Holds the per-instance data dict.
-UZBLS = {}
-
-# The default instance dict.
-DEFAULTS = {}
-
-
-def add_instance(uzbl, *args):
- '''Add a new instance with default config options.'''
-
- UZBLS[uzbl] = dict(DEFAULTS)
-
-
-def del_instance(uzbl, *args):
- '''Delete data stored for an instance.'''
-
- if uzbl in UZBLS:
- del UZBLS[uzbl]
-
-
-def get_myplugin_dict(uzbl):
- '''Get data stored for an instance.'''
-
- if uzbl not in UZBLS:
- add_instance(uzbl)
-
- return UZBLS[uzbl]
-
-
-def myplugin_function(uzbl, *args, **kargs):
- '''Custom plugin function which is exported by the __export__ list at the
- top of the file for use by other functions/callbacks.'''
-
- print "My plugin function arguments:", args, kargs
-
- # Get the per-instance data object.
- data = get_myplugin_dict(uzbl)
-
- # Function logic goes here.
-
-
-def myplugin_event_parser(uzbl, args):
- '''Parses MYPLUGIN_EVENT raised by uzbl or another plugin.'''
-
- print "Got MYPLUGIN_EVENT with arguments: %r" % args
-
- # Parsing logic goes here.
-
-
-def init(uzbl):
- '''The main function of the plugin which is used to attach all the event
- hooks that are going to be used throughout the plugins life. This function
- is called each time a UzblInstance() object is created in the event
- manager.'''
-
- # Make a dictionary comprising of {"EVENT_NAME": handler, ..} to the event
- # handler stack:
- uzbl.connect_dict({
- # event name function
- 'INSTANCE_START': add_instance,
- 'INSTANCE_EXIT': del_instance,
- 'MYPLUGIN_EVENT': myplugin_event_parser,
- })
-
- # Or connect a handler to an event manually and supply additional optional
- # arguments:
- #uzbl.connect("MYOTHER_EVENT", myother_event_parser, True, limit=20)
-
- # Function exports to the uzbl object, `function(uzbl, *args, ..)`
- # becomes `uzbl.function(*args, ..)`.
- uzbl.connect_dict({
- # external name function
- 'myplugin_function': myplugin_function,
- })
diff --git a/examples/data/plugins/progress_bar.py b/examples/data/plugins/progress_bar.py
index 89ba175..b2edffc 100644
--- a/examples/data/plugins/progress_bar.py
+++ b/examples/data/plugins/progress_bar.py
@@ -1,39 +1,7 @@
-import sys
+UPDATES = 0
-UZBLS = {}
-
-DEFAULTS = {'width': 8,
- 'done': '=',
- 'pending': '.',
- 'format': '[%d%a%p]%c',
- 'spinner': '-\\|/',
- 'sprites': 'loading',
- 'updates': 0,
- 'progress': 100}
-
-
-def error(msg):
- sys.stderr.write("progress_bar plugin: error: %s\n" % msg)
-
-
-def add_instance(uzbl, *args):
- UZBLS[uzbl] = dict(DEFAULTS)
-
-
-def del_instance(uzbl, *args):
- if uzbl in UZBLS:
- del UZBLS[uzbl]
-
-
-def get_progress_config(uzbl):
- if uzbl not in UZBLS:
- add_instance(uzbl)
-
- return UZBLS[uzbl]
-
-
-def update_progress(uzbl, prog=None):
- '''Updates the progress_format variable on LOAD_PROGRESS update.
+def update_progress(uzbl, progress=None):
+ '''Updates the progress.output variable on LOAD_PROGRESS update.
The current substitution options are:
%d = done char * done
@@ -44,116 +12,82 @@ def update_progress(uzbl, prog=None):
%t = percent pending
%o = int pending
%r = sprites
+
+ Default configuration options:
+ progress.format = [%d>%p]%c
+ progress.width = 8
+ progress.done = =
+ progress.pending =
+ progress.spinner = -\|/
+ progress.sprites = loading
'''
- prog_config = get_progress_config(uzbl)
- config = uzbl.get_config()
+ global UPDATES
- if prog is None:
- prog = prog_config['progress']
+ if progress is None:
+ UPDATES = 0
+ progress = 100
else:
- prog = int(prog)
- prog_config['progress'] = prog
+ UPDATES += 1
+ progress = int(progress)
- prog_config['updates'] += 1
- format = prog_config['format']
- width = prog_config['width']
+ # Get progress config vars.
+ format = uzbl.config.get('progress.format', '[%d>%p]%c')
+ width = int(uzbl.config.get('progress.width', 8))
+ done_symbol = uzbl.config.get('progress.done', '=')
+ pend = uzbl.config.get('progress.pending', None)
+ pending_symbol = pend if pend else ' '
# Inflate the done and pending bars to stop the progress bar
# jumping around.
if '%c' in format or '%i' in format:
count = format.count('%c') + format.count('%i')
- width += (3-len(str(prog))) * count
+ width += (3-len(str(progress))) * count
if '%t' in format or '%o' in format:
count = format.count('%t') + format.count('%o')
- width += (3-len(str(100-prog))) * count
+ width += (3-len(str(100-progress))) * count
- done = int(((prog/100.0)*width)+0.5)
+ done = int(((progress/100.0)*width)+0.5)
pending = width - done
if '%d' in format:
- format = format.replace('%d', prog_config['done']*done)
+ format = format.replace('%d', done_symbol * done)
if '%p' in format:
- format = format.replace('%p', prog_config['pending']*pending)
+ format = format.replace('%p', pending_symbol * pending)
if '%c' in format:
- format = format.replace('%c', '%d%%' % prog)
+ format = format.replace('%c', '%d%%' % progress)
if '%i' in format:
- format = format.replace('%i', '%d' % prog)
+ format = format.replace('%i', '%d' % progress)
if '%t' in format:
- format = format.replace('%t', '%d%%' % (100-prog))
+ format = format.replace('%t', '%d%%' % (100-progress))
if '%o' in format:
- format = format.replace('%o', '%d' % (100-prog))
+ format = format.replace('%o', '%d' % (100-progress))
if '%s' in format:
- spinner = prog_config['spinner']
- spin = '-' if not spinner else spinner
- index = 0 if prog == 100 else prog_config['updates'] % len(spin)
- char = '\\\\' if spin[index] == '\\' else spin[index]
- format = format.replace('%s', char)
+ spinner = uzbl.config.get('progress.spinner', '-\\|/')
+ index = 0 if progress == 100 else UPDATES % len(spinner)
+ spin = '\\\\' if spinner[index] == '\\' else spinner[index]
+ format = format.replace('%s', spin)
if '%r' in format:
- sprites = prog_config['sprites']
- sprites = '-' if not sprites else sprites
- index = int(((prog/100.0)*len(sprites))+0.5)-1
+ sprites = uzbl.config.get('progress.sprites', 'loading')
+ index = int(((progress/100.0)*len(sprites))+0.5)-1
sprite = '\\\\' if sprites[index] == '\\' else sprites[index]
format = format.replace('%r', sprite)
- if 'progress_format' not in config or config['progress_format'] != format:
- config['progress_format'] = format
-
-
-def progress_config(uzbl, args):
- '''Parse PROGRESS_CONFIG events from the uzbl instance.
-
- Syntax: event PROGRESS_CONFIG <key> = <value>
- '''
-
- split = args.split('=', 1)
- if len(split) != 2:
- return error("invalid syntax: %r" % args)
-
- key, value = map(unicode.strip, split)
- prog_config = get_progress_config(uzbl)
-
- if key not in prog_config:
- return error("key error: %r" % args)
-
- if type(prog_config[key]) == type(1):
- try:
- value = int(value)
-
- except:
- return error("invalid type: %r" % args)
-
- elif not value:
- value = ' '
-
- prog_config[key] = value
- update_progress(uzbl)
-
-
-def reset_progress(uzbl, args):
- '''Reset the spinner counter, reset the progress int and re-draw the
- progress bar on LOAD_COMMIT.'''
-
- prog_dict = get_progress_config(uzbl)
- prog_dict['updates'] = prog_dict['progress'] = 0
- update_progress(uzbl)
-
+ if uzbl.config.get('progress.output', None) != format:
+ uzbl.config['progress.output'] = format
+# plugin init hook
def init(uzbl):
- # Event handling hooks.
- uzbl.connect_dict({
- 'INSTANCE_EXIT': del_instance,
- 'INSTANCE_START': add_instance,
- 'LOAD_COMMIT': reset_progress,
+ connect_dict(uzbl, {
+ 'LOAD_COMMIT': lambda uzbl, uri: update_progress(uzbl),
'LOAD_PROGRESS': update_progress,
- 'PROGRESS_CONFIG': progress_config,
})