aboutsummaryrefslogtreecommitdiffhomepage
path: root/examples/data/uzbl/scripts
diff options
context:
space:
mode:
authorGravatar Mason Larobina <mason.larobina@gmail.com>2009-09-08 00:41:56 +0800
committerGravatar Mason Larobina <mason.larobina@gmail.com>2009-09-08 00:41:56 +0800
commitbb6d7ea31a56ebd43eb5e820877edad56f91b9b2 (patch)
tree5123153121c61730297ba8910edeb204b5996e27 /examples/data/uzbl/scripts
parentde8504736fd87147dcc588fe27165a5bf7c01507 (diff)
Custom event raising, added keycmd plugin & made handler class.
Diffstat (limited to 'examples/data/uzbl/scripts')
-rwxr-xr-xexamples/data/uzbl/scripts/event_manager.py228
-rw-r--r--examples/data/uzbl/scripts/plugins/dump_config.py13
-rw-r--r--examples/data/uzbl/scripts/plugins/echo_keys.py7
-rw-r--r--examples/data/uzbl/scripts/plugins/keycmd.py97
4 files changed, 261 insertions, 84 deletions
diff --git a/examples/data/uzbl/scripts/event_manager.py b/examples/data/uzbl/scripts/event_manager.py
index 5145653..967fe39 100755
--- a/examples/data/uzbl/scripts/event_manager.py
+++ b/examples/data/uzbl/scripts/event_manager.py
@@ -101,6 +101,18 @@ def counter():
yield i
+def iscallable(obj):
+ '''Return true if the object is callable.'''
+
+ return hasattr(obj, "__call__")
+
+
+def isiterable(obj):
+ '''Return true if you can iterate over the item.'''
+
+ return hasattr(obj, "__iter__")
+
+
class PluginManager(dict):
def __init__(self):
@@ -194,19 +206,83 @@ class PluginManager(dict):
self.load_plugins()
-def export_wrapper(uzbl, function):
- '''Return an object that appends the uzbl meta-instance to the front of
- the argument queue. I.e. (*args, **kargs) -> (uzbl, *args, **kargs)'''
+class CallPrepender(object):
+ '''Execution argument modifier. Takes (arg, function) then modifies the
+ function call:
+
+ -> function(*args, **kargs) -> function(arg, *args, **kargs) ->'''
+
+ def __init__(self, uzbl, function):
+ self.function = function
+ self.uzbl = uzbl
+
+ def call(self, *args, **kargs):
+ return self.function(self.uzbl, *args, **kargs)
+
+
+class Handler(object):
+
+ nexthid = counter().next
+
+ def __init__(self, uzbl, event, handler, *args, **kargs):
+ self._callable = iscallable(handler)
+ if self._callable:
+ self._function = handler
+ self._args = args
+ self._kargs = kargs
+
+ elif kargs:
+ raise ArgumentError("cannot supply kargs with a uzbl command")
+
+ elif isiterable(handler):
+ self._commands = handler
+
+ else:
+ self._commands = [handler,] + list(args)
+
+ self._uzbl = uzbl
+ self.event = event
+ self.hid = self.nexthid()
+
+
+ def exec_handler(self, *args, **kargs):
+ '''Execute either the handler function or send the uzbl commands to
+ the socket.'''
+
+ if self._callable:
+ args = args + self._args
+ kargs = dict(self._kargs.items()+kargs.items())
+ self._function(self._uzbl, *args, **kargs)
+
+ else:
+ for command in self._commands:
+ if '%s' in command and len(args) == 1:
+ command.replace('%s', args[0])
+
+ elif '%s' in command:
+ for arg in args:
+ command.replace('%s', arg, 1)
+
+ self._uzbl.send(command)
- class Export(object):
- def __init__(self, uzbl, function):
- self.function = function
- self.uzbl = uzbl
- def call(self, *args, **kargs):
- return self.function(self.uzbl, *args, **kargs)
+ def __repr__(self):
+ args = ["event=%s" % self.event, "hid=%d" % self.hid]
- return Export(uzbl, function).call
+ if self._callable:
+ args.append("function=%r" % self._function)
+ if self._args:
+ args.append("args=%r" % self.args)
+
+ if self._kargs:
+ args.append("kargs=%r" % self.kargs)
+
+ else:
+ cmdlen = len(self._commands)
+ cmds = self._commands[0] if cmdlen == 1 else self._commands
+ args.append("command%s=%r" % ("s" if cmdlen-1 else "", cmds))
+
+ return "<EventHandler(%s)>" % ', '.join(args)
class UzblInstance(object):
@@ -215,44 +291,38 @@ class UzblInstance(object):
# Singleton plugin manager.
plugins = None
- def __init__(self):
- '''Initialise event manager.'''
+ # Internal uzbl config dict.
+ class ConfigDict(dict):
+ def __init__(self, setcmd):
+ self._setcmd = setcmd
- # Hold functions exported by plugins.
- self._exports = {}
+ def __setitem__(self, key, value):
+ '''Updates the config dict and relays any changes back to the
+ uzbl instance via the set function.'''
- class ConfigDict(dict):
- def __init__(self, setcmd):
- self._setcmd = setcmd
+ if type(value) == types.BooleanType:
+ value = int(value)
- def __setitem__(self, key, value):
- '''Updates the config dict and relays any changes back to the
- uzbl instance via the set function.'''
+ if key in self.keys() and type(value) != type(self[key]):
+ raise TypeError("%r for %r" % (type(value), key))
- if type(value) == types.BooleanType:
- value = int(value)
+ else:
+ # All custom variables are strings.
+ value = "" if value is None else str(value)
- if key in self.keys() and type(value) != type(self[key]):
- raise TypeError("%r for %r" % (type(value), key))
+ self._setcmd(key, value)
+ dict.__setitem__(self, key, value)
- else:
- # All custom variables are strings.
- value = "" if value is None else str(value)
- self._setcmd(key, value)
- dict.__setitem__(self, key, value)
+ def __init__(self):
+ '''Initialise event manager.'''
- self._config = ConfigDict(self.set)
+ # Hold functions exported by plugins.
+ self._exports = {}
+ self._config = self.ConfigDict(self.set)
self._running = None
- self._cmdbuffer = []
- self.keysheld = []
- self.metaheld = []
- self.mode = "command"
-
- self.binds = {}
- self.handlers = {}
- self.nexthid = counter().next
+ self._handlers = {}
# Variables needed for fifo & socket communication with uzbl.
self.uzbl_fifo = None
@@ -300,8 +370,10 @@ class UzblInstance(object):
continue
obj = getattr(plugin, attr)
- if type(obj) in [types.LambdaType, types.FunctionType]:
- obj = export_wrapper(self, obj)
+ if iscallable(obj):
+ # Wrap the function in the CallPrepender object to make
+ # the exposed functions act like instance methods.
+ obj = CallPrepender(self, obj).call
self._exports[attr[7:]] = obj
@@ -356,32 +428,44 @@ class UzblInstance(object):
def connect(self, event, handler, *args, **kargs):
- '''Connect event with handler and return unique handler id. It goes
- without saying that if you connect handlers with non-existent events
- nothing will happen so be careful.
+ '''Connect event with handler and return the newly created handler.
+ Handlers can either be a function or a uzbl command string.'''
+
+ if event not in self._handlers.keys():
+ self._handlers[event] = []
+
+ handler = Handler(self, event, handler, *args, **kargs)
+ self._handlers[event].append(handler)
- If you choose the handler may be a uzbl command and upon receiving the
- event the chosen command will be executed by the uzbl instance.'''
+ print "New event handler:", handler
+ return handler
- if event not in self.handlers.keys():
- self.handlers[event] = {}
- id = self.nexthid()
- d = {'handler': handler, 'args': args, 'kargs': kargs}
+ def remove_by_id(self, hid):
+ '''Remove connected event handler by unique handler id.'''
- self.handlers[event][id] = d
- echo("added handler for %s: %r" % (event, d))
+ for (event, handlers) in self._handlers.items():
+ for handler in list(handlers):
+ if hid != handler.hid:
+ continue
- return id
+ echo("removed %r" % handler)
+ handlers.remove(handler)
+ return
+ echo('unable to find & remove handler with id: %d' % handler.hid)
- def remove(self, id):
- '''Remove connected event handler by unique handler id.'''
- for event in self.handlers.keys():
- if id in self.handlers[event].keys():
- echo("removed handler %d" % id)
- del self.handlers[event][id]
+ def remove(self, handler):
+ '''Remove connected event handler.'''
+
+ for (event, handlers) in self._handlers.items():
+ if handler in handlers:
+ echo("removed %r" % handler)
+ handlers.remove(handler)
+ return
+
+ echo('unable to find & remove handler: %r' % handler)
def set(self, key, value):
@@ -432,6 +516,7 @@ class UzblInstance(object):
if not msg or msg[0] != "EVENT":
# Not an event message
+ print raw.rstrip()
return
event, args = msg[1], msg[3]
@@ -464,6 +549,7 @@ class UzblInstance(object):
if hasattr(plugin, "cleanup"):
plugin.cleanup(uzbl)
+ # Now handle the event "publically".
self.dispatch_event(event, args)
@@ -471,27 +557,27 @@ class UzblInstance(object):
'''Now send the event to any event handlers added with the connect
function. In other words: handle plugin's event hooks.'''
- if event in self.handlers.keys():
- for hid in self.handlers[event]:
+ if event in self._handlers:
+ for handler in self._handlers[event]:
try:
- handler = self.handlers[event][hid]
- print "Executing handler:", event, handler
- self.exc_handler(handler, args)
+ handler.exec_handler(args)
except:
print_exc()
- def exc_handler(self, d, args):
- '''Handle handler.'''
+ def event(self, event, *args, **kargs):
+ '''Raise a custom event.'''
- if type(d['handler']) == types.FunctionType:
- handler = d['handler']
- handler(self, args, *d['args'], **d['kargs'])
+ print "Got custom event:", event, args, kargs
- else:
- cmd = d['handler']
- self.send(cmd)
+ if event in self._handlers:
+ for handler in self._handlers[event]:
+ try:
+ handler.exec_handler(*args, **kargs)
+
+ except:
+ print_ext()
if __name__ == "__main__":
diff --git a/examples/data/uzbl/scripts/plugins/dump_config.py b/examples/data/uzbl/scripts/plugins/dump_config.py
index 381dbf2..ba6543a 100644
--- a/examples/data/uzbl/scripts/plugins/dump_config.py
+++ b/examples/data/uzbl/scripts/plugins/dump_config.py
@@ -1,11 +1,4 @@
-import pprint
-
-def dump_config(uzbl, args):
- '''Dump the config every time the page finishes loading.'''
-
- print "%s\n" % pprint.pformat(uzbl.config)
-
-
def init(uzbl):
- id = uzbl.connect('LOAD_FINISH', dump_config)
- print "Dump config id:", id
+ commands = ['dump_config', 'dump_config_as_events']
+ handler = uzbl.connect('LOAD_FINISH', commands)
+ print "Added handler with id", handler.hid
diff --git a/examples/data/uzbl/scripts/plugins/echo_keys.py b/examples/data/uzbl/scripts/plugins/echo_keys.py
index e1a1850..b76a80f 100644
--- a/examples/data/uzbl/scripts/plugins/echo_keys.py
+++ b/examples/data/uzbl/scripts/plugins/echo_keys.py
@@ -2,7 +2,7 @@ def echo_keys(uzbl, key, print_meta=True):
'''Prints key-presses to the terminal.'''
keys_pressed = int(uzbl.config['keys_pressed']) + 1
- print "You pressed:", key, "Total keys pressed:", keys_pressed
+ print "Total keys pressed:", keys_pressed
uzbl.config['keys_pressed'] = str(keys_pressed)
@@ -10,7 +10,8 @@ def init(uzbl):
'''In this function attach all your event hooks using uzbl.connect and
uzbl.bind functions.'''
- id = uzbl.connect('KEY_PRESS', echo_keys)
- print "echo_keys hook id:", id
+ uzbl.connect('KEY_PRESS', echo_keys)
+ uzbl.connect('KEY_PRESS', "sh %r" % ("echo %r" % "You just pressed %s"))
+ # Start a running counter of all keys pressed.
uzbl.config['keys_pressed'] = str(0)
diff --git a/examples/data/uzbl/scripts/plugins/keycmd.py b/examples/data/uzbl/scripts/plugins/keycmd.py
new file mode 100644
index 0000000..d634f32
--- /dev/null
+++ b/examples/data/uzbl/scripts/plugins/keycmd.py
@@ -0,0 +1,97 @@
+class Keylet(object):
+ def __init__(self):
+ self.cmd = ""
+ self.held = []
+ self.modfirst = False
+
+ def __repr__(self):
+ fmt = "<Keycmd(%r)>"
+ if not self.cmd and not self.held:
+ return fmt % ""
+
+ elif not len(self.held):
+ return fmt % self.cmd
+
+ helds = '+'.join(["<%s>" % key for key in self.held])
+ if not self.cmd:
+ return fmt % helds
+
+ else:
+ return fmt % ("%s+%s" % (helds, self.cmd))
+
+
+class KeycmdTracker(dict):
+ def get_cmd(self, uzbl):
+ '''Returns a tuple of the form (keys held, cmdstr)'''
+
+ if uzbl not in self:
+ return ([], [])
+
+ return self[uzbl]
+
+
+ def key_press(self, uzbl, key):
+
+ if key.startswith('Shift_'):
+ return
+
+ t = self.get_keylet(uzbl)
+ if key not in t.held:
+ if not t.held and not t.cmd and len(key) != 1:
+ t.modfirst = True
+
+ t.held.append(key)
+
+ self.raise_event(uzbl)
+
+
+ def key_release(self, uzbl, key):
+
+ t = self.get_keylet(uzbl)
+ if key in t.held:
+ t.held.remove(key)
+ if len(key) == 1:
+ t.cmd += key
+
+ elif t.modfirst and not len(t.held):
+ self.clear(uzbl)
+
+ self.raise_event(uzbl)
+
+
+ def get_keylet(self, uzbl):
+ if uzbl not in self:
+ self.add_instance(uzbl)
+
+ return self[uzbl]
+
+
+ def clear(self, uzbl):
+ t = self.get_keylet(uzbl)
+ t.cmd = ""
+ t.modfirst = False
+
+
+ def add_instance(self, uzbl):
+ self[uzbl] = Keylet()
+
+
+ def del_instance(self, uzbl):
+ if uzbl in self:
+ del uzbl
+
+
+ def raise_event(self, uzbl):
+ '''Raise a custom event.'''
+
+ uzbl.event('KEYCMD_UPDATE', self.get_keylet(uzbl))
+
+
+keycmd = KeycmdTracker()
+
+def init(uzbl):
+
+ uzbl.connect('INSTANCE_START', keycmd.add_instance)
+ uzbl.connect('INSTANCE_STOP', keycmd.del_instance)
+ uzbl.connect('KEY_PRESS', keycmd.key_press)
+ uzbl.connect('KEY_RELEASE', keycmd.key_release)