From 4e9b6fad6b65f6ca107726e8819f0db73721aa3b Mon Sep 17 00:00:00 2001 From: Mason Larobina Date: Tue, 1 Dec 2009 15:24:06 +0800 Subject: Use builtin and default library functions over custom functions. --- examples/data/uzbl/scripts/uzbl-event-manager | 31 ++++----------------------- 1 file changed, 4 insertions(+), 27 deletions(-) diff --git a/examples/data/uzbl/scripts/uzbl-event-manager b/examples/data/uzbl/scripts/uzbl-event-manager index 0054ff6..e926643 100755 --- a/examples/data/uzbl/scripts/uzbl-event-manager +++ b/examples/data/uzbl/scripts/uzbl-event-manager @@ -39,6 +39,7 @@ from select import select from signal import signal, SIGTERM from optparse import OptionParser from traceback import print_exc +from functools import partial # ============================================================================ @@ -111,18 +112,6 @@ 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__") - - def find_plugins(plugin_dirs): '''Find all event manager plugins in the plugin dirs and return a dictionary of {'plugin-name.py': '/full/path/to/plugin-name.py', ...}''' @@ -289,24 +278,12 @@ def term_process(pid): time.sleep(0.25) -def prepender(function, *pre_args): - '''Creates a wrapper around a callable object injecting a list of - arguments before the called arguments.''' - - locals = (function, pre_args) - def _prepender(*args, **kargs): - (function, pre_args) = locals - return function(*(pre_args + args), **kargs) - - return _prepender - - class EventHandler(object): nexthid = counter().next def __init__(self, event, handler, *args, **kargs): - if not iscallable(handler): + if not callable(handler): raise ArgumentError("EventHandler object requires a callable " "object function for the handler argument not: %r" % handler) @@ -378,8 +355,8 @@ class UzblInstance(object): raise KeyError("conflicting export: %r" % export) obj = getattr(plugin, export) - if iscallable(obj): - obj = prepender(obj, self) + if callable(obj): + obj = partial(obj, self) self._exports[export] = obj -- cgit v1.2.3 From 253f986e4be9dcfd496774cb325a4b7251254fc4 Mon Sep 17 00:00:00 2001 From: Mason Larobina Date: Tue, 1 Dec 2009 17:27:18 +0800 Subject: Made force default to False and added config attribute. --- examples/data/uzbl/plugins/config.py | 41 ++++++++++++++++-------------------- 1 file changed, 18 insertions(+), 23 deletions(-) diff --git a/examples/data/uzbl/plugins/config.py b/examples/data/uzbl/plugins/config.py index 47b59f9..b43161b 100644 --- a/examples/data/uzbl/plugins/config.py +++ b/examples/data/uzbl/plugins/config.py @@ -3,8 +3,8 @@ import types __export__ = ['set', 'get_config'] -_VALIDSETKEY = re.compile("^[a-zA-Z][a-zA-Z0-9_]*$").match -_TYPECONVERT = {'int': int, 'float': float, 'str': unicode} +VALIDKEY = re.compile("^[a-zA-Z][a-zA-Z0-9_]*$").match +TYPECONVERT = {'int': int, 'float': float, 'str': unicode} UZBLS = {} @@ -15,14 +15,7 @@ def escape(value): return unicode(value) -def get_config(uzbl): - if uzbl not in UZBLS: - add_instance(uzbl) - - return UZBLS[uzbl] - - -def set(uzbl, key, value='', force=True): +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.''' @@ -32,7 +25,7 @@ def set(uzbl, key, value='', force=True): else: value = unicode(value) - if not _VALIDSETKEY(key): + if not VALIDKEY(key): raise KeyError("%r" % key) value = escape(value) @@ -40,13 +33,25 @@ def set(uzbl, key, value='', force=True): value = value.replace("\n", "\\n") if not force: - config = get_config(uzbl) + if config is None: + config = get_config(uzbl) + if key in config and config[key] == value: return uzbl.send('set %s = %s' % (key, value)) +class ConfigDict(dict): + def __init__(self, uzbl): + self._uzbl = uzbl + + def __setitem__(self, key, value): + '''Makes "config[key] = value" a wrapper for the set function.''' + + set(self._uzbl, key, value, config=self) + + def add_instance(uzbl, *args): UZBLS[uzbl] = ConfigDict(uzbl) @@ -63,22 +68,12 @@ def get_config(uzbl): return UZBLS[uzbl] -class ConfigDict(dict): - def __init__(self, uzbl): - self._uzbl = uzbl - - def __setitem__(self, key, value): - '''Makes "config[key] = value" a wrapper for the set function.''' - - set(self._uzbl, key, value, force=False) - - def variable_set(uzbl, args): config = get_config(uzbl) key, type, value = list(args.split(' ', 2) + ['',])[:3] old = config[key] if key in config else None - value = _TYPECONVERT[type](value) + value = TYPECONVERT[type](value) dict.__setitem__(config, key, value) -- cgit v1.2.3 From efa8ee4e63d8c07130c6b02d93ab3cc46209e948 Mon Sep 17 00:00:00 2001 From: Mason Larobina Date: Tue, 1 Dec 2009 17:43:26 +0800 Subject: Added example in the config to reset the keycmd on page navigation. --- examples/config/uzbl/config | 5 +++-- examples/data/uzbl/plugins/bind.py | 2 +- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/examples/config/uzbl/config b/examples/config/uzbl/config index 9fda268..fa82fda 100644 --- a/examples/config/uzbl/config +++ b/examples/config/uzbl/config @@ -43,9 +43,11 @@ set new_window = sh 'uzbl-browser -u $8' # equivalent to the default beh # Load start handlers @on_event LOAD_START @set_status wait -# Load commit handler +# Load commit handlers @on_event LOAD_COMMIT @set_status recv @on_event LOAD_COMMIT script @scripts_dir/scroll-percentage.js +# Reset the keycmd on navigation +@on_event LOAD_COMMIT @set_mode # Load finish handlers @on_event LOAD_FINISH @set_status done @@ -63,7 +65,6 @@ set new_window = sh 'uzbl-browser -u $8' # equivalent to the default beh # Misc on_event handlers #@on_event CONFIG_CHANGED print Config changed: %1 = %2 - # === Behaviour and appearance =============================================== set show_status = 1 diff --git a/examples/data/uzbl/plugins/bind.py b/examples/data/uzbl/plugins/bind.py index 3169b15..3e47e38 100644 --- a/examples/data/uzbl/plugins/bind.py +++ b/examples/data/uzbl/plugins/bind.py @@ -294,7 +294,7 @@ def clear_stack(uzbl): uzbl.set_mode(bind_dict['last_mode']) bind_dict['last_mode'] = '' - uzbl.set('keycmd_prompt', force=False) + uzbl.set('keycmd_prompt') def stack_bind(uzbl, bind, args, depth): -- cgit v1.2.3 From dbdd7053b19275fff29787f50855eca82921bccf Mon Sep 17 00:00:00 2001 From: Mason Larobina Date: Tue, 1 Dec 2009 17:46:14 +0800 Subject: TOGGLE_MODES is not a configuration event so use the event function. --- examples/config/uzbl/config | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/config/uzbl/config b/examples/config/uzbl/config index fa82fda..a9ae29a 100644 --- a/examples/config/uzbl/config +++ b/examples/config/uzbl/config @@ -10,7 +10,7 @@ set bind = request BIND # request MODE_CONFIG = ... -set toggle_modes = request TOGGLE_MODES +set toggle_modes = event TOGGLE_MODES # request ON_EVENT set on_event = request ON_EVENT # request PROGRESS_CONFIG = @@ -313,7 +313,7 @@ set default_mode = command # Changing mode method via set. @bind I = @set_mode insert -# Or toggle between modes by rasing request events. +# Or toggle between modes by rasing the toggle event. set toggle_cmd_ins = @toggle_modes command insert @bind i = @toggle_cmd_ins -- cgit v1.2.3 From 1a109cb03c761cbeaa3bd81cb9f5f45953c7148e Mon Sep 17 00:00:00 2001 From: Mason Larobina Date: Tue, 1 Dec 2009 17:52:27 +0800 Subject: Keycmd and mode plugin config setting optimisations. --- examples/data/uzbl/plugins/keycmd.py | 35 +++++++++++++++-------------------- examples/data/uzbl/plugins/mode.py | 6 +----- 2 files changed, 16 insertions(+), 25 deletions(-) diff --git a/examples/data/uzbl/plugins/keycmd.py b/examples/data/uzbl/plugins/keycmd.py index 4c88fd8..fd17363 100644 --- a/examples/data/uzbl/plugins/keycmd.py +++ b/examples/data/uzbl/plugins/keycmd.py @@ -256,10 +256,7 @@ def clear_keycmd(uzbl): k.keycmd = '' k.cursor = 0 k._repr_cache = False - config = uzbl.get_config() - if 'keycmd' not in config or config['keycmd']: - uzbl.set('keycmd') - + uzbl.set('keycmd') uzbl.event('KEYCMD_CLEAR') @@ -273,10 +270,7 @@ def clear_modcmd(uzbl, clear_held=False): if clear_held: k.held = set() - config = uzbl.get_config() - if 'modcmd' not in config or config['modcmd']: - uzbl.set('modcmd') - + uzbl.set('modcmd') uzbl.event('MODCMD_CLEAR') @@ -314,22 +308,25 @@ def update_event(uzbl, k, execute=True): if 'modcmd_updates' not in config or config['modcmd_updates'] == '1': new_modcmd = k.get_modcmd() if not new_modcmd: - uzbl.set('modcmd') + uzbl.set('modcmd', config=config) elif new_modcmd == modcmd: - uzbl.set('modcmd', " %s " % uzbl_escape(new_modcmd)) + uzbl.set('modcmd', ' %s ' % uzbl_escape(new_modcmd), + config=config) if 'keycmd_events' in config and config['keycmd_events'] != '1': return - keycmd = k.get_keycmd() - if not keycmd: - return uzbl.set('keycmd') + new_keycmd = k.get_keycmd() + if not new_keycmd: + uzbl.set('keycmd', config=config) - # 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:]] - uzbl.set('keycmd', KEYCMD_FORMAT % tuple(map(uzbl_escape, chunks))) + 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) def inject_str(str, index, inj): @@ -380,9 +377,7 @@ def key_press(uzbl, key): if 'keycmd_events' in config and config['keycmd_events'] != '1': k.keycmd = '' k.cursor = 0 - if config['keycmd']: - uzbl.set('keycmd') - + uzbl.set('keycmd', config=config) return k.keycmd = inject_str(k.keycmd, k.cursor, key) diff --git a/examples/data/uzbl/plugins/mode.py b/examples/data/uzbl/plugins/mode.py index 52b104a..2b2579a 100644 --- a/examples/data/uzbl/plugins/mode.py +++ b/examples/data/uzbl/plugins/mode.py @@ -63,11 +63,7 @@ def mode_changed(uzbl, mode): config = uzbl.get_config() mode_config = get_mode_config(uzbl, mode) for (key, value) in mode_config.items(): - if key not in config: - config[key] = value - - elif config[key] != value: - config[key] = value + uzbl.set(key, value, config=config) if 'mode_indicator' not in mode_config: config['mode_indicator'] = mode -- cgit v1.2.3 From 585b542bd332284525ad5f4ce4a69b2880974a3f Mon Sep 17 00:00:00 2001 From: Mason Larobina Date: Tue, 1 Dec 2009 18:10:33 +0800 Subject: Pylint rating of the EM raised to 9.38/10. --- examples/data/uzbl/scripts/uzbl-event-manager | 317 +++++++++++++------------- 1 file changed, 164 insertions(+), 153 deletions(-) diff --git a/examples/data/uzbl/scripts/uzbl-event-manager b/examples/data/uzbl/scripts/uzbl-event-manager index e926643..6669282 100755 --- a/examples/data/uzbl/scripts/uzbl-event-manager +++ b/examples/data/uzbl/scripts/uzbl-event-manager @@ -30,7 +30,6 @@ import imp import os import sys import re -import types import socket import pprint import time @@ -64,8 +63,9 @@ DATA_DIR = os.path.join(xdghome('DATA', '.local/share/'), 'uzbl/') CACHE_DIR = os.path.join(xdghome('CACHE', '.cache/'), 'uzbl/') -# Config dict (NOT the same as the uzbl.config). -config = { +# Event manager config dictionary. This is not to be confused with the config +# dict that tracks variables in the uzbl instance. +CONFIG = { 'verbose': False, 'daemon_mode': True, 'auto_close': False, @@ -87,20 +87,25 @@ config = { # Define some globals. -_SCRIPTNAME = os.path.basename(sys.argv[0]) -_RE_FINDSPACES = re.compile("\s+") +SCRIPTNAME = os.path.basename(sys.argv[0]) +FINDSPACES = re.compile("\s+") + + +class ArgumentError(Exception): + pass + def echo(msg): '''Prints only if the verbose flag has been set.''' - if config['verbose']: - sys.stdout.write("%s: %s\n" % (_SCRIPTNAME, msg)) + if CONFIG['verbose']: + sys.stdout.write("%s: %s\n" % (SCRIPTNAME, msg)) def error(msg): '''Prints error messages to stderr.''' - sys.stderr.write("%s: error: %s\n" % (_SCRIPTNAME, msg)) + sys.stderr.write("%s: error: %s\n" % (SCRIPTNAME, msg)) def counter(): @@ -123,23 +128,26 @@ def find_plugins(plugin_dirs): if not os.path.isdir(plugin_dir): continue - for file in os.listdir(plugin_dir): - if not file.lower().endswith('.py'): + for filename in os.listdir(plugin_dir): + if not filename.lower().endswith('.py'): continue - path = os.path.join(plugin_dir, file) + path = os.path.join(plugin_dir, filename) if not os.path.isfile(path): continue - if file not in plugins: - plugins[file] = plugin_dir + if filename not in plugins: + plugins[filename] = plugin_dir return plugins -def load_plugins(plugin_dirs, load=[], ignore=[]): +def load_plugins(plugin_dirs, load=None, ignore=None): '''Load event manager plugins found in the plugin_dirs.''' + load = [] if load is None else load + ignore = [] if ignore is None else ignore + # Find the plugins in the plugin_dirs. found = find_plugins(plugin_dirs) @@ -160,11 +168,11 @@ def load_plugins(plugin_dirs, load=[], ignore=[]): loaded = {} # Load all found plugins into the loaded dict. - for (filename, dir) in found.items(): + for (filename, plugin_dir) in found.items(): name = filename[:-3] - info = imp.find_module(name, [dir,]) + info = imp.find_module(name, [plugin_dir]) plugin = imp.load_module(name, *info) - loaded[(dir, filename)] = plugin + loaded[(plugin_dir, filename)] = plugin return loaded @@ -219,9 +227,9 @@ def make_pid_file(pid_file): '''Make pid file at given pid_file location.''' make_dirs(pid_file) - file = open(pid_file, 'w') - file.write('%d' % os.getpid()) - file.close() + fileobj = open(pid_file, 'w') + fileobj.write('%d' % os.getpid()) + fileobj.close() def del_pid_file(pid_file): @@ -235,13 +243,12 @@ def get_pid(pid_file): '''Read pid from pid_file.''' try: - file = open(pid_file, 'r') - strpid = file.read() - file.close() - pid = int(strpid.strip()) + fileobj = open(pid_file, 'r') + pid = int(fileobj.read()) + fileobj.close() return pid - except: + except IOError, ValueError: print_exc() return None @@ -278,6 +285,34 @@ def term_process(pid): time.sleep(0.25) +def parse_msg(uzbl, msg): + '''Parse an incoming msg from a uzbl instance. All non-event messages + will be printed here and not be passed to the uzbl instance event + handler function.''' + + if not msg: + return + + cmd = FINDSPACES.split(msg, 3) + if not cmd or cmd[0] != 'EVENT': + # Not an event message. + print '---', msg + return + + while len(cmd) < 4: + cmd.append('') + + event, args = cmd[2], cmd[3] + if not event: + return + + try: + uzbl.event(event, args) + + except: + print_exc() + + class EventHandler(object): nexthid = counter().next @@ -310,7 +345,7 @@ class EventHandler(object): class UzblInstance(object): # Give all plugins access to the main config dict. - config = config + config = CONFIG def __init__(self, parent, client_socket): @@ -419,7 +454,7 @@ class UzblInstance(object): handlers.remove(handler) return - echo('unable to find & remove handler with id: %d' % handler.hid) + echo('unable to find & remove handler with id: %d' % hid) def remove(self, handler): @@ -493,7 +528,7 @@ class UzblEventDaemon(dict): # Register that the event daemon server has started by creating the # pid file. - make_pid_file(config['pid_file']) + make_pid_file(CONFIG['pid_file']) # Register a function to clean up the socket and pid file on exit. atexit.register(self.quit) @@ -502,15 +537,15 @@ class UzblEventDaemon(dict): signal(SIGTERM, lambda signum, stack_frame: sys.exit(1)) # Load plugins, first-build of the plugins may be a costly operation. - self['plugins'] = load_plugins(config['plugin_dirs'], - config['plugins_load'], config['plugins_ignore']) + self['plugins'] = load_plugins(CONFIG['plugin_dirs'], + CONFIG['plugins_load'], CONFIG['plugins_ignore']) def _create_server_socket(self): '''Create the event manager daemon socket for uzbl instance duplex communication.''' - server_socket = config['server_socket'] + server_socket = CONFIG['server_socket'] server_socket = os.path.realpath(os.path.expandvars(server_socket)) self.socket_location = server_socket @@ -540,11 +575,11 @@ class UzblEventDaemon(dict): def run(self): '''Main event daemon loop.''' - if config['daemon_mode']: + if CONFIG['daemon_mode']: echo('entering daemon mode.') daemonize() # The pid has changed so update the pid file. - make_pid_file(config['pid_file']) + make_pid_file(CONFIG['pid_file']) # Create event daemon socket. self._create_server_socket() @@ -564,18 +599,18 @@ class UzblEventDaemon(dict): self.running = True while self.running: - sockets = [self.server_socket,] + self['uzbls'].keys() + sockets = [self.server_socket] + self['uzbls'].keys() - read, _, error = select(sockets, [], sockets, 1) + reads, _, errors = select(sockets, [], sockets, 1) - if self.server_socket in read: + if self.server_socket in reads: self.accept_connection() - read.remove(self.server_socket) + reads.remove(self.server_socket) - for client in read: + for client in reads: self.read_socket(client) - for client in error: + for client in errors: error('Unknown error on socket: %r' % client) self.close_connection(client) @@ -584,55 +619,28 @@ class UzblEventDaemon(dict): '''Read data from an instance socket and pass to the uzbl objects event handler function.''' + uzbl = self['uzbls'][client] try: - uzbl = self['uzbls'][client] - try: - raw = unicode(client.recv(8192), 'utf-8', 'ignore') - - except: - print_exc() - raw = None - - if not raw: - # Read null byte, close socket. - return self.close_connection(client) - - uzbl.buffer += raw - msgs = uzbl.buffer.split('\n') - uzbl.buffer = msgs.pop() - - for msg in msgs: - self.parse_msg(uzbl, msg) + raw = unicode(client.recv(8192), 'utf-8', 'ignore') except: - raise - - - def parse_msg(self, uzbl, msg): - '''Parse an incoming msg from a uzbl instance. All non-event messages - will be printed here and not be passed to the uzbl instance event - handler function.''' - - msg = msg.strip() - if not msg: - return - - cmd = _RE_FINDSPACES.split(msg, 3) - if not cmd or cmd[0] != 'EVENT': - # Not an event message. - print '---', msg - return + print_exc() + raw = None - if len(cmd) < 4: - cmd.append('') + if not raw: + # Read null byte, close socket. + return self.close_connection(client) - event, args = cmd[2], cmd[3] + uzbl.buffer += raw + msgs = uzbl.buffer.split('\n') + uzbl.buffer = msgs.pop() - try: - uzbl.event(event, args) + for msg in msgs: + try: + parse_msg(uzbl, msg.strip()) - except: - print_exc() + except: + print_exc() def accept_connection(self): @@ -656,7 +664,7 @@ class UzblEventDaemon(dict): except: print_exc() - if not len(self['uzbls']) and config['auto_close']: + if not len(self['uzbls']) and CONFIG['auto_close']: echo('auto closing event manager.') self.running = False @@ -673,14 +681,14 @@ class UzblEventDaemon(dict): echo('unlinking: %r' % self.socket_location) self._close_server_socket() - echo('deleting pid file: %r' % config['pid_file']) - del_pid_file(config['pid_file']) + echo('deleting pid file: %r' % CONFIG['pid_file']) + del_pid_file(CONFIG['pid_file']) -def stop(): +def stop_action(): '''Stop the event manager daemon.''' - pid_file = config['pid_file'] + pid_file = CONFIG['pid_file'] if not os.path.isfile(pid_file): return echo('no running daemon found.') @@ -698,10 +706,10 @@ def stop(): echo('stopped event daemon.') -def start(): +def start_action(): '''Start the event manager daemon.''' - pid_file = config['pid_file'] + pid_file = CONFIG['pid_file'] if os.path.isfile(pid_file): echo('found pid file: %r' % pid_file) pid = get_pid(pid_file) @@ -715,126 +723,129 @@ def start(): UzblEventDaemon().run() -def restart(): +def restart_action(): '''Restart the event manager daemon.''' echo('restarting event manager daemon.') - stop() - start() + stop_action() + start_action() -def list_plugins(): +def list_action(): '''List all the plugins being loaded by the event daemon.''' - plugins = find_plugins(config['plugin_dirs']) + plugins = find_plugins(CONFIG['plugin_dirs']) dirs = {} - for (plugin, dir) in plugins.items(): - if dir not in dirs: - dirs[dir] = [] + for (plugin, plugin_dir) in plugins.items(): + if plugin_dir not in dirs: + dirs[plugin_dir] = [] - dirs[dir].append(plugin) + dirs[plugin_dir].append(plugin) - for (index, (dir, plugin_list)) in enumerate(sorted(dirs.items())): + for (index, (plugin_dir, plugin_list)) in enumerate(sorted(dirs.items())): if index: print - print "%s:" % dir + print "%s:" % plugin_dir for plugin in sorted(plugin_list): print " %s" % plugin if __name__ == "__main__": - usage = "usage: %prog [options] {start|stop|restart|list}" - parser = OptionParser(usage=usage) - parser.add_option('-v', '--verbose', dest='verbose', action="store_true", + USAGE = "usage: %prog [options] {start|stop|restart|list}" + PARSER = OptionParser(usage=USAGE) + PARSER.add_option('-v', '--verbose', dest='verbose', action="store_true", help="print verbose output.") - parser.add_option('-d', '--plugin-dirs', dest='plugin_dirs', action="store", + PARSER.add_option('-d', '--plugin-dirs', dest='plugin_dirs', action="store", metavar="DIRS", help="Specify plugin directories in the form of "\ "'dir1:dir2:dir3'.") - parser.add_option('-l', '--load-plugins', dest="load", action="store", + PARSER.add_option('-l', '--load-plugins', dest="load", action="store", metavar="PLUGINS", help="comma separated list of plugins to load") - parser.add_option('-i', '--ignore-plugins', dest="ignore", action="store", + PARSER.add_option('-i', '--ignore-plugins', dest="ignore", action="store", metavar="PLUGINS", help="comma separated list of plugins to ignore") - parser.add_option('-p', '--pid-file', dest='pid', action='store', + PARSER.add_option('-p', '--pid-file', dest='pid', action='store', metavar='FILE', help="specify pid file location") - parser.add_option('-s', '--server-socket', dest='socket', action='store', + PARSER.add_option('-s', '--server-socket', dest='socket', action='store', metavar='SOCKET', help="specify the daemon socket location") - parser.add_option('-n', '--no-daemon', dest="daemon", + PARSER.add_option('-n', '--no-daemon', dest="daemon", action="store_true", help="don't enter daemon mode.") - parser.add_option('-a', '--auto-close', dest='autoclose', + PARSER.add_option('-a', '--auto-close', dest='autoclose', action='store_true', help='auto close after all instances disconnect.') - (options, args) = parser.parse_args() + (OPTIONS, ARGS) = PARSER.parse_args() - # init like {start|stop|..} daemon control section. - daemon_controls = {'start': start, 'stop': stop, 'restart': restart, - 'list': list_plugins} + # init like {start|stop|..} daemon actions dict. + DAEMON_ACTIONS = {'start': start_action, 'stop': stop_action, + 'restart': restart_action, 'list': list_action} - if len(args) == 1: - action = args[0] - if action not in daemon_controls: - error('unknown action: %r' % action) - sys.exit(1) + if not ARGS: + ACTION = 'start' - elif len(args) > 1: - error("too many arguments: %r" % args) - sys.exit(1) + elif len(ARGS) == 1: + ACTION = ARGS[0] + if ACTION not in DAEMON_ACTIONS: + raise ArgumentError("unknown argument: %r" % ACTION) else: - action = 'start' + raise ArgumentError("too many arguments: %r" % ARGS) # parse other flags & options. - if options.verbose: - config['verbose'] = True + if OPTIONS.verbose: + CONFIG['verbose'] = True + + if OPTIONS.plugin_dirs: + PLUGIN_DIRS = [] + for DIR in OPTIONS.plugin_dirs.split(':'): + if not DIR: + continue + + PLUGIN_DIRS.append(os.path.realpath(DIR)) - if options.plugin_dirs: - plugin_dirs = map(os.path.realpath, map(str.strip, - options.plugin_dirs.split(':'))) - config['plugin_dirs'] = plugin_dirs - echo("plugin search dirs: %r" % plugin_dirs) + CONFIG['plugin_dirs'] = PLUGIN_DIRS + echo("plugin search dirs: %r" % PLUGIN_DIRS) - if options.load and options.ignore: + if OPTIONS.load and OPTIONS.ignore: error("you can't load and ignore at the same time.") sys.exit(1) - elif options.load: - plugins_load = config['plugins_load'] - for plugin in options.load.split(','): - if plugin.strip(): - plugins_load.append(plugin.strip()) + elif OPTIONS.load: + LOAD = CONFIG['plugins_load'] + for PLUGIN in OPTIONS.load.split(','): + if PLUGIN.strip(): + LOAD.append(PLUGIN.strip()) - echo('only loading plugin(s): %s' % ', '.join(plugins_load)) + echo('only loading plugin(s): %s' % ', '.join(LOAD)) - elif options.ignore: - plugins_ignore = config['plugins_ignore'] - for plugin in options.ignore.split(','): - if plugin.strip(): - plugins_ignore.append(plugin.strip()) + elif OPTIONS.ignore: + IGNORE = CONFIG['plugins_ignore'] + for PLUGIN in OPTIONS.ignore.split(','): + if PLUGIN.strip(): + IGNORE.append(PLUGIN.strip()) - echo('ignoring plugin(s): %s' % ', '.join(plugins_ignore)) + echo('ignoring plugin(s): %s' % ', '.join(IGNORE)) - if options.autoclose: - config['auto_close'] = True + if OPTIONS.autoclose: + CONFIG['auto_close'] = True echo('will auto close.') - if options.pid: - config['pid_file'] = os.path.realpath(options.pid) - echo("pid file location: %r" % config['pid_file']) + if OPTIONS.pid: + CONFIG['pid_file'] = os.path.realpath(OPTIONS.pid) + echo("pid file location: %r" % CONFIG['pid_file']) - if options.socket: - config['server_socket'] = os.path.realpath(options.socket) - echo("daemon socket location: %s" % config['server_socket']) + if OPTIONS.socket: + CONFIG['server_socket'] = os.path.realpath(OPTIONS.socket) + echo("daemon socket location: %s" % CONFIG['server_socket']) - if options.daemon: - config['daemon_mode'] = False + if OPTIONS.daemon: + CONFIG['daemon_mode'] = False # Now {start|stop|...} - daemon_controls[action]() + DAEMON_ACTIONS[ACTION]() -- cgit v1.2.3 From e81b577aefac01eb2219ee048d84c1ee21106e15 Mon Sep 17 00:00:00 2001 From: Rob Date: Wed, 2 Dec 2009 22:24:29 +0100 Subject: always execute @(...)@ expansion in a shell --- uzbl-core.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/uzbl-core.c b/uzbl-core.c index f224c60..edb3e54 100644 --- a/uzbl-core.c +++ b/uzbl-core.c @@ -267,8 +267,14 @@ expand(const char *s, guint recurse) { else if(recurse != 1 && etype == EXP_EXPR) { mycmd = expand(ret, 1); - g_spawn_command_line_sync(mycmd, &cmd_stdout, NULL, NULL, &err); + gchar *quoted = g_shell_quote(mycmd); + gchar *tmp = g_strdup_printf("%s %s", + uzbl.behave.shell_cmd?uzbl.behave.shell_cmd:"/bin/sh -c", + quoted); + g_spawn_command_line_sync(tmp, &cmd_stdout, NULL, NULL, &err); g_free(mycmd); + g_free(quoted); + g_free(tmp); if (err) { g_printerr("error on running command: %s\n", err->message); -- cgit v1.2.3 From 2ca39207613d6cbb78991baf4d6102fecabeb50f Mon Sep 17 00:00:00 2001 From: Mason Larobina Date: Thu, 3 Dec 2009 14:56:10 +0800 Subject: Was raising an exception that didn't exist. --- examples/data/uzbl/plugins/bind.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/examples/data/uzbl/plugins/bind.py b/examples/data/uzbl/plugins/bind.py index 3e47e38..517bf98 100644 --- a/examples/data/uzbl/plugins/bind.py +++ b/examples/data/uzbl/plugins/bind.py @@ -27,6 +27,10 @@ find_prompts = re.compile('<([^:>]*):(\"[^\"]*\"|\'[^\']*\'|[^>]*)>').split ON_EXEC, HAS_ARGS, MOD_CMD, GLOB, MORE = range(5) +class ArgumentError(Exception): + pass + + def ismodbind(glob): '''Return True if the glob specifies a modbind.''' -- cgit v1.2.3 From 1cc25d8c1c98dd2c301984a2487b0d817dc96eba Mon Sep 17 00:00:00 2001 From: Mason Larobina Date: Thu, 3 Dec 2009 22:02:17 +0800 Subject: The MODE_CONFIG event was triggering itself in the bind plugin. --- examples/data/uzbl/plugins/bind.py | 3 ++- examples/data/uzbl/plugins/mode.py | 11 +++++------ 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/examples/data/uzbl/plugins/bind.py b/examples/data/uzbl/plugins/bind.py index 517bf98..10cce6a 100644 --- a/examples/data/uzbl/plugins/bind.py +++ b/examples/data/uzbl/plugins/bind.py @@ -295,8 +295,9 @@ def clear_stack(uzbl): bind_dict['depth'] = 0 bind_dict['args'] = [] if bind_dict['last_mode']: - uzbl.set_mode(bind_dict['last_mode']) + mode = bind_dict['last_mode'] bind_dict['last_mode'] = '' + uzbl.set_mode(mode) uzbl.set('keycmd_prompt') diff --git a/examples/data/uzbl/plugins/mode.py b/examples/data/uzbl/plugins/mode.py index 2b2579a..f85d999 100644 --- a/examples/data/uzbl/plugins/mode.py +++ b/examples/data/uzbl/plugins/mode.py @@ -58,7 +58,8 @@ def get_mode(uzbl): def mode_changed(uzbl, mode): '''The mode has just been changed, now set the per-mode config.''' - get_mode_dict(uzbl)['mode'] = mode + if get_mode(uzbl) != mode: + return config = uzbl.get_config() mode_config = get_mode_config(uzbl, mode) @@ -92,12 +93,10 @@ def set_mode(uzbl, mode=None): if 'mode' not in config or config['mode'] != mode: config['mode'] = mode - return - - elif get_mode(uzbl) == mode: - return - uzbl.event("MODE_CHANGED", mode) + elif mode_dict['mode'] != mode: + mode_dict['mode'] = mode + uzbl.event("MODE_CHANGED", mode) def config_changed(uzbl, key, value): -- cgit v1.2.3 From b61c04fd5af9747e2b868ed6d47d86a75e4baa2d Mon Sep 17 00:00:00 2001 From: Rob Date: Thu, 3 Dec 2009 17:11:21 +0100 Subject: added @<+file.js>@ capability and documentation --- README | 4 ++++ uzbl-core.c | 20 +++++++++++++++++--- 2 files changed, 21 insertions(+), 3 deletions(-) diff --git a/README b/README index 348ba5f..23b0f4e 100644 --- a/README +++ b/README @@ -306,6 +306,10 @@ the java script in @< >@. print The currently viewed document contains @@ links +The @<>@ substitution can also load JavaScript from a file, syntax: @<+filename>@ + + print JS return value from file: @<+/path/to/file.js>@ + Variable expansion also works within a java script substitution. diff --git a/uzbl-core.c b/uzbl-core.c index edb3e54..2e5e14e 100644 --- a/uzbl-core.c +++ b/uzbl-core.c @@ -266,6 +266,7 @@ expand(const char *s, guint recurse) { } else if(recurse != 1 && etype == EXP_EXPR) { + mycmd = expand(ret, 1); gchar *quoted = g_shell_quote(mycmd); gchar *tmp = g_strdup_printf("%s %s", @@ -293,9 +294,22 @@ expand(const char *s, guint recurse) { } else if(recurse != 2 && etype == EXP_JS) { - mycmd = expand(ret, 2); - eval_js(uzbl.gui.web_view, mycmd, js_ret); - g_free(mycmd); + + /* read JS from file */ + if(ret[0] == '+') { + GArray *tmp = g_array_new(TRUE, FALSE, sizeof(gchar *)); + mycmd = expand(ret+1, 2); + g_array_append_val(tmp, mycmd); + + run_external_js(uzbl.gui.web_view, tmp, js_ret); + g_array_free(tmp, TRUE); + } + /* JS from string */ + else { + mycmd = expand(ret, 2); + eval_js(uzbl.gui.web_view, mycmd, js_ret); + g_free(mycmd); + } if(js_ret->str) { g_string_append(buf, js_ret->str); -- cgit v1.2.3 From 5f5ffd41a76a9ef6bf09e5fd5737ea1e2b2cd471 Mon Sep 17 00:00:00 2001 From: Mason Larobina Date: Fri, 4 Dec 2009 01:20:06 +0800 Subject: Renamed {MOD,KEY}CMD_CLEAR to {MOD,KEY}CMD_CLEARED to reduce confusion. --- examples/data/uzbl/plugins/completion.py | 2 +- examples/data/uzbl/plugins/keycmd.py | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/examples/data/uzbl/plugins/completion.py b/examples/data/uzbl/plugins/completion.py index 42e7e17..770f310 100644 --- a/examples/data/uzbl/plugins/completion.py +++ b/examples/data/uzbl/plugins/completion.py @@ -194,5 +194,5 @@ def init(uzbl): # And connect the dicts event handlers to the handler stack. uzbl.connect_dict(connects) - for event in ['STOP_COMPLETION', 'KEYCMD_EXEC', 'KEYCMD_CLEAR']: + for event in ['STOP_COMPLETION', 'KEYCMD_EXEC', 'KEYCMD_CLEARED']: uzbl.connect(event, stop_completion) diff --git a/examples/data/uzbl/plugins/keycmd.py b/examples/data/uzbl/plugins/keycmd.py index fd17363..0f5bb9b 100644 --- a/examples/data/uzbl/plugins/keycmd.py +++ b/examples/data/uzbl/plugins/keycmd.py @@ -257,7 +257,7 @@ def clear_keycmd(uzbl): k.cursor = 0 k._repr_cache = False uzbl.set('keycmd') - uzbl.event('KEYCMD_CLEAR') + uzbl.event('KEYCMD_CLEARED') def clear_modcmd(uzbl, clear_held=False): @@ -271,7 +271,7 @@ def clear_modcmd(uzbl, clear_held=False): k.held = set() uzbl.set('modcmd') - uzbl.event('MODCMD_CLEAR') + uzbl.event('MODCMD_CLEARED') def clear_current(uzbl): -- cgit v1.2.3 From c0eac2a19e3b0cbcad45566e79795f89996b98aa Mon Sep 17 00:00:00 2001 From: Mason Larobina Date: Fri, 4 Dec 2009 01:23:09 +0800 Subject: Use restart instead of start to close any daemons before running. --- Makefile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Makefile b/Makefile index 9ae1055..50fe09b 100644 --- a/Makefile +++ b/Makefile @@ -63,8 +63,8 @@ test-dev: uzbl-core XDG_DATA_HOME=./examples/data XDG_CONFIG_HOME=./examples/config ./uzbl-core --uri http://www.uzbl.org --verbose test-dev-browser: uzbl-browser - XDG_DATA_HOME=./examples/data XDG_CACHE_HOME=./examples/cache XDG_CONFIG_HOME=./examples/config PATH="`pwd`:$$PATH" ./examples/data/uzbl/scripts/uzbl-cookie-daemon start -nv & - XDG_DATA_HOME=./examples/data XDG_CACHE_HOME=./examples/cache XDG_CONFIG_HOME=./examples/config PATH="`pwd`:$$PATH" ./examples/data/uzbl/scripts/uzbl-event-manager start -nv & + XDG_DATA_HOME=./examples/data XDG_CACHE_HOME=./examples/cache XDG_CONFIG_HOME=./examples/config PATH="`pwd`:$$PATH" ./examples/data/uzbl/scripts/uzbl-cookie-daemon restart -nv & + XDG_DATA_HOME=./examples/data XDG_CACHE_HOME=./examples/cache XDG_CONFIG_HOME=./examples/config PATH="`pwd`:$$PATH" ./examples/data/uzbl/scripts/uzbl-event-manager restart -nav & XDG_DATA_HOME=./examples/data XDG_CACHE_HOME=./examples/cache XDG_CONFIG_HOME=./examples/config PATH="`pwd`:`pwd`/examples/data/uzbl/scripts/:$$PATH" ./uzbl-browser --uri http://www.uzbl.org --verbose XDG_DATA_HOME=./examples/data XDG_CACHE_HOME=./examples/cache XDG_CONFIG_HOME=./examples/config PATH="`pwd`:$$PATH" ./examples/data/uzbl/scripts/uzbl-cookie-daemon stop -v XDG_DATA_HOME=./examples/data XDG_CACHE_HOME=./examples/cache XDG_CONFIG_HOME=./examples/config PATH="`pwd`:$$PATH" ./examples/data/uzbl/scripts/uzbl-event-manager stop -v -- cgit v1.2.3 From 24d8b632eaa7e9622603fbd58cd4bc360f965dd8 Mon Sep 17 00:00:00 2001 From: Rob Date: Thu, 3 Dec 2009 19:00:07 +0100 Subject: generate COMMAND_ERROR if script file cannot be read --- Makefile | 4 ++-- uzbl-core.c | 4 +++- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/Makefile b/Makefile index 9ae1055..44d21bd 100644 --- a/Makefile +++ b/Makefile @@ -1,7 +1,7 @@ # first entries are for gnu make, 2nd for BSD make. see http://lists.uzbl.org/pipermail/uzbl-dev-uzbl.org/2009-July/000177.html -CFLAGS:=-std=c99 $(shell pkg-config --cflags gtk+-2.0 webkit-1.0 libsoup-2.4 gthread-2.0) -ggdb -Wall -W -DARCH="\"$(shell uname -m)\"" -lgthread-2.0 -DCOMMIT="\"$(shell git log | head -n1 | sed "s/.* //")\"" $(CPPFLAGS) -fPIC -W -Wall -Wextra -pedantic -ggdb3 -CFLAGS!=echo -std=c99 `pkg-config --cflags gtk+-2.0 webkit-1.0 libsoup-2.4 gthread-2.0` -ggdb -Wall -W -DARCH='"\""'`uname -m`'"\""' -lgthread-2.0 -DCOMMIT='"\""'`git log | head -n1 | sed "s/.* //"`'"\""' $(CPPFLAGS) -fPIC -W -Wall -Wextra -pedantic -ggdb3 +CFLAGS:=-std=c99 $(shell pkg-config --cflags gtk+-2.0 webkit-1.0 libsoup-2.4 gthread-2.0) -ggdb -Wall -W -DARCH="\"$(shell uname -m)\"" -lgthread-2.0 -DCOMMIT="\"$(shell git log | head -n1 | sed "s/.* //")\"" $(CPPFLAGS) -fPIC -W -Wall -Wextra -pedantic +CFLAGS!=echo -std=c99 `pkg-config --cflags gtk+-2.0 webkit-1.0 libsoup-2.4 gthread-2.0` -ggdb -Wall -W -DARCH='"\""'`uname -m`'"\""' -lgthread-2.0 -DCOMMIT='"\""'`git log | head -n1 | sed "s/.* //"`'"\""' $(CPPFLAGS) -fPIC -W -Wall -Wextra -pedantic LDFLAGS:=$(shell pkg-config --libs gtk+-2.0 webkit-1.0 libsoup-2.4 gthread-2.0) -pthread $(LDFLAGS) LDFLAGS!=echo `pkg-config --libs gtk+-2.0 webkit-1.0 libsoup-2.4 gthread-2.0` -pthread $(LDFLAGS) diff --git a/uzbl-core.c b/uzbl-core.c index 2e5e14e..85330b9 100644 --- a/uzbl-core.c +++ b/uzbl-core.c @@ -394,7 +394,9 @@ read_file_by_line (const gchar *path) { g_io_channel_unref (chan); } else { - fprintf(stderr, "File '%s' not be read.\n", path); + gchar *tmp = g_strdup_printf("File %s can not be read.", path); + send_event(COMMAND_ERROR, tmp, NULL); + g_free(tmp); } return lines; -- cgit v1.2.3 From a9de45fd575cb47914b71ac23544a797b276cf3c Mon Sep 17 00:00:00 2001 From: Rob Date: Fri, 4 Dec 2009 09:25:03 +0100 Subject: generate a message on SIGSEGV --- uzbl-core.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/uzbl-core.c b/uzbl-core.c index 85330b9..42e274e 100644 --- a/uzbl-core.c +++ b/uzbl-core.c @@ -535,13 +535,17 @@ void catch_signal(int s) { if(s == SIGTERM || s == SIGINT || - s == SIGSEGV || s == SIGILL || s == SIGFPE || s == SIGQUIT) { clean_up(); exit(EXIT_SUCCESS); } + else if(s == SIGSEGV) { + clean_up(); + fprintf(stderr, "Program aborted, segmentation fault!\nAttempting to clean up...\n"); + exit(EXIT_FAILURE); + } else if(s == SIGALRM && uzbl.state.event_buffer) { g_ptr_array_free(uzbl.state.event_buffer, TRUE); uzbl.state.event_buffer = NULL; -- cgit v1.2.3 From 0061e5afefebcba68f5922e5d9d97ff6852788f3 Mon Sep 17 00:00:00 2001 From: Mason Larobina Date: Fri, 4 Dec 2009 21:36:51 +0800 Subject: Fixed problem with keys persisting after their release events. --- examples/data/uzbl/plugins/keycmd.py | 29 ++++++++++++++++++++--------- 1 file changed, 20 insertions(+), 9 deletions(-) diff --git a/examples/data/uzbl/plugins/keycmd.py b/examples/data/uzbl/plugins/keycmd.py index 0f5bb9b..af6beff 100644 --- a/examples/data/uzbl/plugins/keycmd.py +++ b/examples/data/uzbl/plugins/keycmd.py @@ -33,6 +33,7 @@ class Keylet(object): def __init__(self): # Modcmd tracking self.held = set() + self.ignored = set() self.modcmd = '' self.is_modcmd = False @@ -82,15 +83,18 @@ class Keylet(object): results in a modkey addition. Return that addition and remove all modkeys that created it.''' - already_added = self.held & set(self.additions.keys()) - for key in already_added: - if modkey in self.additions[key]: + # Intersection of (held list + modkey) and additions. + added = (self.held | set([modkey])) & set(self.additions.keys()) + for key in added: + if key == modkey or modkey in self.additions[key]: + self.held -= self.additions[key] return key - modkeys = set(list(self.held) + [modkey,]) + # Held list + ignored list + modkey. + modkeys = self.held | self.ignored | set([modkey]) for (key, value) in self.additions.items(): if modkeys.issuperset(value): - self.held = modkeys ^ value + self.held -= value return key return modkey @@ -268,6 +272,7 @@ def clear_modcmd(uzbl, clear_held=False): k.is_modcmd = False k._repr_cache = False if clear_held: + k.ignored = set() k.held = set() uzbl.set('modcmd') @@ -335,7 +340,7 @@ def inject_str(str, index, inj): return "%s%s%s" % (str[:index], inj, str[index:]) -def get_keylet_and_key(uzbl, key): +def get_keylet_and_key(uzbl, key, add=True): '''Return the keylet and apply any transformations to the key as defined by the modmapping or modkey addition rules. Return None if the key is ignored.''' @@ -346,6 +351,14 @@ def get_keylet_and_key(uzbl, key): return (keylet, key) modkey = "<%s>" % key.strip("<>") + + if keylet.key_ignored(modkey): + if add: + keylet.ignored.add(modkey) + + elif modkey in keylet.ignored: + keylet.ignored.remove(modkey) + modkey = keylet.find_addition(modkey) if keylet.key_ignored(modkey): @@ -403,9 +416,7 @@ def key_release(uzbl, key): 3. Check if any modkey is held, if so set modcmd mode. 4. Update the keycmd uzbl variable if anything changed.''' - (k, key) = get_keylet_and_key(uzbl, key.strip()) - if not key: - return + (k, key) = get_keylet_and_key(uzbl, key.strip(), add=False) if key in k.held: if k.is_modcmd: -- cgit v1.2.3 From 4ba53742159e166fd25cc5c83a953bc1e39c81d9 Mon Sep 17 00:00:00 2001 From: Mason Larobina Date: Sat, 5 Dec 2009 17:12:59 +0800 Subject: Added @jsh JavaScript helper variable. --- examples/config/uzbl/config | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/examples/config/uzbl/config b/examples/config/uzbl/config index a9ae29a..54de972 100644 --- a/examples/config/uzbl/config +++ b/examples/config/uzbl/config @@ -29,6 +29,8 @@ 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 +# Javascipt helpers. +set jsh = js var run=Uzbl.run; function get(k){return run("print \\\@"+k)}; function set(k, v) {run("set "+k+" = "+v)}; # === Handlers =============================================================== @@ -141,7 +143,6 @@ set open_new_window = sh 'uzbl-browser -u \@SELECTED_URI' @bind = js if("\@SELECTED_URI") { Uzbl.run("\@open_new_window"); } else { Uzbl.run("\\\@load_from_xclip"); } # Edit HTML forms in external editor -# set external_editor = gvim #set external_editor = xterm -e vim @bind E = script @scripts_dir/extedit.js -- cgit v1.2.3 From 5c514a0d42324efbb60c657d171e93720ba422b1 Mon Sep 17 00:00:00 2001 From: Mason Larobina Date: Sat, 5 Dec 2009 18:19:55 +0800 Subject: Updated binding to use the new @jsh helper. --- examples/config/uzbl/config | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/config/uzbl/config b/examples/config/uzbl/config index 54de972..69a211c 100644 --- a/examples/config/uzbl/config +++ b/examples/config/uzbl/config @@ -140,7 +140,7 @@ set socket_dir = /tmp # otherwise open the selection in the current window set load_from_xclip = sh 'echo "uri $(xclip -o)" > $4' set open_new_window = sh 'uzbl-browser -u \@SELECTED_URI' -@bind = js if("\@SELECTED_URI") { Uzbl.run("\@open_new_window"); } else { Uzbl.run("\\\@load_from_xclip"); } +@bind = @jsh if(get("SELECTED_URI")) { run("\@open_new_window"); } else { run("\\\@load_from_xclip"); } # Edit HTML forms in external editor set external_editor = gvim -- cgit v1.2.3 From ff64a2d37fa68015e70928a9dc7867c8d1c3815e Mon Sep 17 00:00:00 2001 From: Mason Larobina Date: Sun, 6 Dec 2009 16:21:12 +0800 Subject: Standardise expansion across plugins. --- examples/data/uzbl/plugins/bind.py | 23 +++++++++++++++-------- 1 file changed, 15 insertions(+), 8 deletions(-) diff --git a/examples/data/uzbl/plugins/bind.py b/examples/data/uzbl/plugins/bind.py index 10cce6a..076d712 100644 --- a/examples/data/uzbl/plugins/bind.py +++ b/examples/data/uzbl/plugins/bind.py @@ -224,6 +224,20 @@ class Bind(object): return self._repr_cache +def expand(cmd, args): + '''Replaces "%s %1 %2 %3..." with " ...".''' + + if '%s' in cmd: + cmd = cmd.replace('%s', ' '.join(map(unicode, args))) + + for (index, arg) in enumerate(args): + index += 1 + if '%%%d' % index in cmd: + cmd = cmd.replace('%%%d' % index, unicode(arg)) + + return cmd + + def exec_bind(uzbl, bind, *args, **kargs): '''Execute bind objects.''' @@ -240,14 +254,7 @@ def exec_bind(uzbl, bind, *args, **kargs): commands = [] for cmd in bind.commands: - if '%s' in cmd: - if len(args) > 1: - for arg in args: - cmd = cmd.replace('%s', arg, 1) - - elif len(args) == 1: - cmd = cmd.replace('%s', args[0]) - + cmd = expand(cmd, args) uzbl.send(cmd) -- cgit v1.2.3 From 3d2043d8f46855e8c3724e65bd5848c06ed27069 Mon Sep 17 00:00:00 2001 From: Mason Larobina Date: Sun, 6 Dec 2009 17:26:48 +0800 Subject: Multiple stack binds that have the same prefix now work. --- examples/data/uzbl/plugins/bind.py | 113 +++++++++++++++++++++---------------- 1 file changed, 63 insertions(+), 50 deletions(-) diff --git a/examples/data/uzbl/plugins/bind.py b/examples/data/uzbl/plugins/bind.py index 076d712..9702434 100644 --- a/examples/data/uzbl/plugins/bind.py +++ b/examples/data/uzbl/plugins/bind.py @@ -11,13 +11,15 @@ And it is also possible to execute a function on activation: import sys import re +import pprint # Export these functions to uzbl. __export__ = ['bind', 'del_bind', 'del_bind_by_glob', 'get_binds'] # Hold the bind dicts for each uzbl instance. UZBLS = {} -DEFAULTS = {'binds': [], 'depth': 0, 'stack': [], 'args': [], 'last_mode': ''} +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-_]*)>') @@ -78,21 +80,11 @@ def get_binds(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'] - - -def get_filtered_binds(uzbl): +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.''' - bind_dict = get_bind_dict(uzbl) - if bind_dict['depth']: - return list(bind_dict['stack']) - - return list(bind_dict['binds']) + return bd['stack'] if bd['depth'] else bd['binds'] def del_bind(uzbl, bind): @@ -294,44 +286,51 @@ def mode_changed(uzbl, mode): clear_stack(uzbl) -def clear_stack(uzbl): +def clear_stack(uzbl, bd=None): '''Clear everything related to stacked binds.''' - bind_dict = get_bind_dict(uzbl) - bind_dict['stack'] = [] - bind_dict['depth'] = 0 - bind_dict['args'] = [] - if bind_dict['last_mode']: - mode = bind_dict['last_mode'] - bind_dict['last_mode'] = '' + 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) uzbl.set('keycmd_prompt') -def stack_bind(uzbl, bind, args, depth): +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.''' - bind_dict = get_bind_dict(uzbl) - if bind_dict['depth'] != depth: - if bind not in bind_dict['stack']: - bind_dict['stack'].append(bind) + if bd['depth'] != depth: + if bind not in bd['stack']: + bd['stack'].append(bind) return if uzbl.get_mode() != 'stack': - bind_dict['last_mode'] = uzbl.get_mode() + bd['last_mode'] = uzbl.get_mode() uzbl.set_mode('stack') - globalcmds = [cmd for cmd in bind_dict['binds'] if cmd.is_global] - bind_dict['stack'] = [bind,] + globalcmds - bind_dict['args'] += args - bind_dict['depth'] = depth + 1 + 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] + - uzbl.send('event BIND_STACK_LEVEL %d' % bind_dict['depth']) +def after_bind(uzbl, bd): + '''Check if there are afte-actions to perform.''' + + if bd['after'] is None: + return - (prompt, set) = bind.prompts[depth] + (prompt, set), bd['after'] = bd['after'], None if prompt: uzbl.set('keycmd_prompt', '%s:' % prompt) @@ -344,9 +343,11 @@ def stack_bind(uzbl, bind, args, depth): else: uzbl.clear_keycmd() + uzbl.send('event BIND_STACK_LEVEL %d' % bd['depth']) + + +def match_and_exec(uzbl, bind, depth, keylet, bd): -def match_and_exec(uzbl, bind, depth, keylet): - bind_dict = get_bind_dict(uzbl) (on_exec, has_args, mod_cmd, glob, more) = bind[depth] held = keylet.held @@ -375,62 +376,74 @@ def match_and_exec(uzbl, bind, depth, keylet): return True elif more: - stack_bind(uzbl, bind, args, depth) + stack_bind(uzbl, bind, args, depth, bd) return False - args = bind_dict['args'] + args + args = bd['args'] + args exec_bind(uzbl, bind, *args) uzbl.set_mode() if not has_args: - clear_stack(uzbl) + clear_stack(uzbl, bd) uzbl.clear_current() return True def keycmd_update(uzbl, keylet): - depth = get_stack_depth(uzbl) - for bind in get_filtered_binds(uzbl): + bd = get_bind_dict(uzbl) + depth = bd['depth'] + for bind in get_filtered_binds(uzbl, bd): t = bind[depth] if t[MOD_CMD] or t[ON_EXEC]: continue - if match_and_exec(uzbl, bind, depth, keylet): + if match_and_exec(uzbl, bind, depth, keylet, bd): return + after_bind(uzbl, bd) + def keycmd_exec(uzbl, keylet): - depth = get_stack_depth(uzbl) - for bind in get_filtered_binds(uzbl): + bd = get_bind_dict(uzbl) + depth = bd['depth'] + for bind in get_filtered_binds(uzbl, bd): t = bind[depth] if t[MOD_CMD] or not t[ON_EXEC]: continue - if match_and_exec(uzbl, bind, depth, keylet): + if match_and_exec(uzbl, bind, depth, keylet, bd): return uzbl.clear_keycmd() + after_bind(uzbl, bd) + def modcmd_update(uzbl, keylet): - depth = get_stack_depth(uzbl) - for bind in get_filtered_binds(uzbl): + bd = get_bind_dict(uzbl) + depth = bd['depth'] + for bind in get_filtered_binds(uzbl, bd): t = bind[depth] if not t[MOD_CMD] or t[ON_EXEC]: continue - if match_and_exec(uzbl, bind, depth, keylet): + if match_and_exec(uzbl, bind, depth, keylet, bd): return + after_bind(uzbl, bd) + def modcmd_exec(uzbl, keylet): - depth = get_stack_depth(uzbl) - for bind in get_filtered_binds(uzbl): + bd = get_bind_dict(uzbl) + depth = bd['depth'] + for bind in get_filtered_binds(uzbl, bd): t = bind[depth] if not t[MOD_CMD] or not t[ON_EXEC]: continue - if match_and_exec(uzbl, bind, depth, keylet): + if match_and_exec(uzbl, bind, depth, keylet, bd): return uzbl.clear_modcmd() + after_bind(uzbl, bd) + def init(uzbl): connects = {'BIND': parse_bind_event, -- cgit v1.2.3