aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorGravatar tczy <cy@wre.ath.cx>2010-01-06 06:44:34 +0200
committerGravatar tczy <cy@wre.ath.cx>2010-01-06 06:44:34 +0200
commite302b74a1bf6ff2edd2730bf32e1db28d7caff0a (patch)
tree1de88f97e6b3234004867dabc68d941841eae1bf
parentb073f78bbcb1bbf7699707aa1381df78737b06fc (diff)
parentf7608a8fc48ad98e6d7227c10cf3786e37c4a2ab (diff)
Merge branch 'master' of git://github.com/Dieterbe/uzbl into follow
-rw-r--r--README21
-rw-r--r--examples/config/uzbl/config47
-rw-r--r--examples/data/uzbl/plugins/bind.py47
-rw-r--r--examples/data/uzbl/plugins/cmd_expand.py42
-rw-r--r--examples/data/uzbl/plugins/completion.py25
-rw-r--r--examples/data/uzbl/plugins/config.py19
-rw-r--r--examples/data/uzbl/plugins/keycmd.py85
-rw-r--r--examples/data/uzbl/plugins/mode.py27
-rw-r--r--examples/data/uzbl/plugins/on_event.py37
-rw-r--r--examples/data/uzbl/plugins/plugin_template.py25
-rw-r--r--examples/data/uzbl/plugins/progress_bar.py15
-rwxr-xr-xexamples/data/uzbl/scripts/uzbl-event-manager101
-rw-r--r--tests/test-command.c5
-rw-r--r--uzbl-core.c10
14 files changed, 260 insertions, 246 deletions
diff --git a/README b/README
index ac044e4..3486a8f 100644
--- a/README
+++ b/README
@@ -398,7 +398,7 @@ The script specific arguments are this:
Custom, userdefined scripts (`spawn foo bar`) get first the arguments as specified in the config and then the above 7 are added at the end.
-### JAVASCRIPT HELPER OBJECT
+### JAVASCRIPT HELPER OBJECT DISABLED BECAUSE OF SECURITY LEAK
Javascript code run from uzbl is given a special object in the global namespace which gives special privileges to these scripts. This object is called `Uzbl`, and it is added and removed before and after the script execution so that it is hidden to web javascripts (There is no race condition, since all the javascript code runs in a single thread)
@@ -411,25 +411,6 @@ Currently, the `Uzbl` object provides only one function:
* `Uzbl.run("spawn insert_bookmark.sh")`
* `uri = Uzbl.run("print @uri")` (see variable expansion below)
-### JAVASCRIPT SECURITY
-
-Since defined variables and functions are set in the global namespace (`window` object) as default, it is recommended to wrap your scripts like this:
-
- (function(Uzbl) {
- ...
- })(Uzbl);
-
-This way, everything is kept private. It also turns Uzbl into a local variable, which can be accessed from callback functions defined inside. However for some situations, isolating everything isn't an option, for example, with binds. You can define them directly in the script body, and use `var Uzbl = window.Uzbl;` to make the Uzbl variable local, as in the following example:
-
- function f() {
- var Uzbl = window.Uzbl;
- Uzbl.run(...);
- setTimeout(function() {
- Uzbl.run(...);
- }, 500);
- }
-
-Copying the Uzbl object and creating public functions should be taken with care to avoid creating security holes. Keep in mind that the "f" function above would be defined in the `window` object, and as such any javascript in the current page can call it.
### EVENTS ###
diff --git a/examples/config/uzbl/config b/examples/config/uzbl/config
index d696c19..f8a2058 100644
--- a/examples/config/uzbl/config
+++ b/examples/config/uzbl/config
@@ -39,15 +39,24 @@ set jsh = js var run=Uzbl.run; function get(k){return run("print \\\@"+k)}; func
# === Handlers ===============================================================
-set download_handler = spawn @scripts_dir/download.sh
-set cookie_handler = talk_to_socket $XDG_CACHE_HOME/uzbl/cookie_daemon_socket
-set scheme_handler = sync_spawn @scripts_dir/scheme.py
+# --- Hardcoded event handlers -----------------------------------------------
-# New window handler options
-#set new_window = sh 'echo uri "$8" > $4' # open in same window
-set new_window = sh 'uzbl-browser -u $8' # equivalent to the default behaviour
+# These handlers can't be moved to the new event system yet as we don't
+# support events that can wait for a response from a script.
+set cookie_handler = talk_to_socket $XDG_CACHE_HOME/uzbl/cookie_daemon_socket
+set scheme_handler = sync_spawn @scripts_dir/scheme.py
-# Load start handlers
+# Open in the same window.
+#set new_window = sh 'echo uri "$8" > $4'
+# Open a link in a new window. equivalent to default behavior
+set new_window = sh 'uzbl-browser -u $8'
+
+# --- Optional dynamic event handlers ----------------------------------------
+
+# Download handler
+@on_event DOWNLOAD_REQUEST spawn @scripts_dir/download.sh %s \@proxy_url
+
+# Load start handler
@on_event LOAD_START @set_status <span foreground="khaki">wait</span>
# Load commit handlers
@@ -69,7 +78,7 @@ set new_window = sh 'uzbl-browser -u $8' # equivalent to the default beh
# Switch to command mode if anything else is clicked
@on_event ROOT_ACTIVE @set_mode command
-# Misc on_event handlers
+# Example CONFIG_CHANGED event handler
#@on_event CONFIG_CHANGED print Config changed: %1 = %2
# === Behaviour and appearance ===============================================
@@ -96,6 +105,8 @@ set selected_section = <span foreground="#606060">\@[\@SELECTED_URI]\@</span>
set status_format = <span font_family="monospace">@mode_section @keycmd_section @progress_section @uri_section @name_section @status_section @scroll_section @selected_section</span>
+set title_format_long = \@keycmd_prompt \@raw_modcmd \@raw_keycmd \@TITLE - Uzbl browser <\@NAME> \@SELECTED_URI
+
# Progress bar config
@progress width = 8
# %d = done, %p = pending %c = percent done, %i = int done, %s = spinner,
@@ -230,9 +241,9 @@ set open_new_window = sh 'uzbl-browser -u \@SELECTED_URI'
@cbind N = search_reverse
# --- Web searching binds ---
-@cbind gg<Google:>_ = uri http://www.google.com/search?q=%s
-@cbind \\awiki<Archwiki:>_ = uri http://wiki.archlinux.org/index.php/Special:Search?search=%s&go=Go
-@cbind \\wiki<Wikipedia:>_ = uri http://en.wikipedia.org/w/index.php?title=Special:Search&search=%s&go=Go
+@cbind gg<Google:>_ = uri http://www.google.com/search?q=\@<encodeURIComponent(%r)>\@
+@cbind \\awiki<Archwiki:>_ = uri http://wiki.archlinux.org/index.php/Special:Search?search=\@<encodeURIComponent(%r)>\@&go=Go
+@cbind \\wiki<Wikipedia:>_ = uri http://en.wikipedia.org/w/index.php?title=Special:Search&search=\@<encodeURIComponent(%r)>\@&go=Go
# --- Handy binds ---
# Set function shortcut
@@ -243,6 +254,9 @@ set open_new_window = sh 'uzbl-browser -u \@SELECTED_URI'
@cbind !dump = sh "echo dump_config > $4"
# Reload config
@cbind !reload = sh "sed '/^# === Post-load misc commands/,$d' $1 > $4"
+# Uzbl Terminal. TODO explain why this is useful
+@cbind <Ctrl><Alt>t = sh 'xterm -e "socat unix-connect:$5 -"'
+#@cbind <Ctrl><Alt>t = sh 'urxvt -e socat unix-connect:$5 -'
# --- Uri opening prompts ---
@cbind o<uri:>_ = uri %s
@@ -287,17 +301,6 @@ set toggle_cmd_ins = @toggle_modes command insert
#set follow_hint_keys = thsnd-rcgmvwb/;789aefijkopquxyz234
@cbind f* = script @scripts_dir/follow.js '%s @{follow_hint_keys}'
-
-@cbind Xs = js alert("hi");
-# example showing how to use sh
-# it sends a command to the fifo, whose path is told via a positional param
-# if fifo_dir is not set, it'll echo to a file named (null) somewhere >:) remember to delete it
-# The body of the shell command should be one parameter, so if it has spaces like here,
-# you must enclose it in quotes. Remember to escape (and double-escape) quotes and backslashes
-# in the body. Any additional parameters you use will appear AFTER the default parameters (cfg file
-# path, fifo & socket dirs, etc.)
-@cbind XS = sh 'echo "js alert (\\"This is sent by the shell via a fifo\\")" > "$4"'
-
# --- Form filler binds ---
# this script allows you to configure (per domain) values to fill in form
# fields (eg login information) and to fill in these values automatically
diff --git a/examples/data/uzbl/plugins/bind.py b/examples/data/uzbl/plugins/bind.py
index 1cba7b2..9e09337 100644
--- a/examples/data/uzbl/plugins/bind.py
+++ b/examples/data/uzbl/plugins/bind.py
@@ -13,9 +13,6 @@ import sys
import re
import pprint
-# Export these functions to uzbl.<name>
-__export__ = ['bind', 'mode_bind', 'get_bindlet']
-
# Hold the bind dicts for each uzbl instance.
UZBLS = {}
@@ -303,20 +300,6 @@ class Bind(object):
return self._repr_cache
-def expand(cmd, args):
- '''Replaces "%s %1 %2 %3..." with "<all args> <arg 0> <arg 1>...".'''
-
- 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.'''
@@ -332,8 +315,9 @@ def exec_bind(uzbl, bind, *args, **kargs):
raise ArgumentError('cannot supply kargs for uzbl commands')
commands = []
+ cmd_expand = uzbl.cmd_expand
for cmd in bind.commands:
- cmd = expand(cmd, args)
+ cmd = cmd_expand(cmd, args)
uzbl.send(cmd)
@@ -517,12 +501,21 @@ def modcmd_exec(uzbl, keylet):
def init(uzbl):
- connects = {'BIND': parse_bind,
- 'MODE_BIND': parse_mode_bind,
- 'KEYCMD_UPDATE': keycmd_update,
- 'MODCMD_UPDATE': modcmd_update,
- 'KEYCMD_EXEC': keycmd_exec,
- 'MODCMD_EXEC': modcmd_exec,
- 'MODE_CHANGED': mode_changed}
-
- uzbl.connect_dict(connects)
+ # Event handling hooks.
+ uzbl.connect_dict({
+ 'BIND': parse_bind,
+ 'KEYCMD_EXEC': keycmd_exec,
+ 'KEYCMD_UPDATE': keycmd_update,
+ 'MODCMD_EXEC': modcmd_exec,
+ 'MODCMD_UPDATE': modcmd_update,
+ 'MODE_BIND': parse_mode_bind,
+ 'MODE_CHANGED': mode_changed,
+ })
+
+ # Function exports to the uzbl object, `function(uzbl, *args, ..)`
+ # becomes `uzbl.function(*args, ..)`.
+ uzbl.export_dict({
+ 'bind': bind,
+ 'mode_bind': mode_bind,
+ 'get_bindlet': get_bindlet,
+ })
diff --git a/examples/data/uzbl/plugins/cmd_expand.py b/examples/data/uzbl/plugins/cmd_expand.py
new file mode 100644
index 0000000..3f6ae2b
--- /dev/null
+++ b/examples/data/uzbl/plugins/cmd_expand.py
@@ -0,0 +1,42 @@
+def escape(str):
+ for (level, char) in [(3, '\\'), (2, "'"), (2, '"'), (1, '@')]:
+ str = str.replace(char, (level * '\\') + char)
+
+ return str
+
+
+def cmd_expand(uzbl, cmd, args):
+ '''Exports a function that provides the following
+ expansions in any uzbl command string:
+
+ %s = replace('%s', ' '.join(args))
+ %r = replace('%r', "'%s'" % escaped(' '.join(args)))
+ %1 = replace('%1', arg[0])
+ %2 = replace('%2', arg[1])
+ %n = replace('%n', arg[n-1])
+ '''
+
+ # Ensure (1) all string representable and (2) correct string encoding.
+ args = map(unicode, args)
+
+ # Direct string replace.
+ if '%s' in cmd:
+ cmd = cmd.replace('%s', ' '.join(args))
+
+ # Escaped and quoted string replace.
+ if '%r' in cmd:
+ cmd = cmd.replace('%r', "'%s'" % escape(' '.join(args)))
+
+ # Arg index string replace.
+ for (index, arg) in enumerate(args):
+ index += 1
+ if '%%%d' % index in cmd:
+ cmd = cmd.replace('%%%d' % index, unicode(arg))
+
+ return cmd
+
+
+def init(uzbl):
+ # Function exports to the uzbl object, `function(uzbl, *args, ..)`
+ # becomes `uzbl.function(*args, ..)`.
+ uzbl.export('cmd_expand', cmd_expand)
diff --git a/examples/data/uzbl/plugins/completion.py b/examples/data/uzbl/plugins/completion.py
index 8e055e1..8cea203 100644
--- a/examples/data/uzbl/plugins/completion.py
+++ b/examples/data/uzbl/plugins/completion.py
@@ -185,17 +185,22 @@ def add_config_key(uzbl, key, value):
def init(uzbl):
- connects = {
- 'INSTANCE_START': add_instance,
- 'INSTANCE_EXIT': del_instance,
+ # 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,
- }
-
- # And connect the dicts event handlers to the handler stack.
- uzbl.connect_dict(connects)
-
- for event in ['STOP_COMPLETION', 'KEYCMD_EXEC', 'KEYCMD_CLEARED']:
- uzbl.connect(event, stop_completion)
+ 'STOP_COMPLETION': stop_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,
+ })
diff --git a/examples/data/uzbl/plugins/config.py b/examples/data/uzbl/plugins/config.py
index b43161b..4a848a3 100644
--- a/examples/data/uzbl/plugins/config.py
+++ b/examples/data/uzbl/plugins/config.py
@@ -82,9 +82,16 @@ def variable_set(uzbl, args):
def init(uzbl):
-
- connects = {'VARIABLE_SET': variable_set,
- 'INSTANCE_START': add_instance,
- 'INSTANCE_EXIT': del_instance}
-
- uzbl.connect_dict(connects)
+ # 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,
+ })
diff --git a/examples/data/uzbl/plugins/keycmd.py b/examples/data/uzbl/plugins/keycmd.py
index af6beff..c119077 100644
--- a/examples/data/uzbl/plugins/keycmd.py
+++ b/examples/data/uzbl/plugins/keycmd.py
@@ -1,29 +1,22 @@
import re
-# Map these functions/variables in the plugins namespace to the uzbl object.
-__export__ = ['clear_keycmd', 'set_keycmd', 'set_cursor_pos', 'get_keylet',
- 'clear_current', 'clear_modcmd', 'add_modmap', 'add_key_ignore',
- 'append_keycmd', 'inject_keycmd', 'add_modkey_addition']
-
# 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>"
-def uzbl_escape(str):
- '''Prevent outgoing keycmd values from expanding inside the
- status_format.'''
+def escape(str):
+ for char in ['\\', '@']:
+ str = str.replace(char, '\\'+char)
- if not str:
- return ''
+ return str
- for char in ['\\', '@']:
- if char in str:
- str = str.replace(char, '\\'+char)
- return "@[%s]@" % str
+def uzbl_escape(str):
+ return "@[%s]@" % escape(str) if str else ''
class Keylet(object):
@@ -261,6 +254,7 @@ def clear_keycmd(uzbl):
k.cursor = 0
k._repr_cache = False
uzbl.set('keycmd')
+ uzbl.set('raw_keycmd')
uzbl.event('KEYCMD_CLEARED')
@@ -276,6 +270,7 @@ def clear_modcmd(uzbl, clear_held=False):
k.held = set()
uzbl.set('modcmd')
+ uzbl.set('raw_modcmd')
uzbl.event('MODCMD_CLEARED')
@@ -314,9 +309,11 @@ def update_event(uzbl, k, execute=True):
new_modcmd = k.get_modcmd()
if not new_modcmd:
uzbl.set('modcmd', config=config)
+ uzbl.set('raw_modcmd', config=config)
elif new_modcmd == modcmd:
- uzbl.set('modcmd', '<span> %s </span>' % uzbl_escape(new_modcmd),
+ uzbl.set('raw_modcmd', escape(modcmd), config=config)
+ uzbl.set('modcmd', MODCMD_FORMAT % uzbl_escape(modcmd),
config=config)
if 'keycmd_events' in config and config['keycmd_events'] != '1':
@@ -325,6 +322,7 @@ def update_event(uzbl, k, execute=True):
new_keycmd = k.get_keycmd()
if not new_keycmd:
uzbl.set('keycmd', config=config)
+ uzbl.set('raw_keycmd', config=config)
elif new_keycmd == keycmd:
# Generate the pango markup for the cursor in the keycmd.
@@ -332,6 +330,7 @@ def update_event(uzbl, k, execute=True):
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)
def inject_str(str, index, inj):
@@ -391,6 +390,7 @@ def key_press(uzbl, key):
k.keycmd = ''
k.cursor = 0
uzbl.set('keycmd', config=config)
+ uzbl.set('raw_keycmd', config=config)
return
k.keycmd = inject_str(k.keycmd, k.cursor, key)
@@ -533,22 +533,39 @@ def set_cursor_pos(uzbl, index):
def init(uzbl):
'''Connect handlers to uzbl events.'''
- connects = {'INSTANCE_START': add_instance,
- 'INSTANCE_EXIT': del_instance,
- 'KEY_PRESS': key_press,
- 'KEY_RELEASE': key_release,
- 'SET_KEYCMD': set_keycmd,
- 'KEYCMD_STRIP_WORD': keycmd_strip_word,
- 'KEYCMD_BACKSPACE': keycmd_backspace,
- 'KEYCMD_DELETE': keycmd_delete,
- 'KEYCMD_EXEC_CURRENT': keycmd_exec_current,
- 'SET_CURSOR_POS': set_cursor_pos,
- 'FOCUS_LOST': focus_changed,
- 'FOCUS_GAINED': focus_changed,
- 'MODMAP': modmap_parse,
- 'APPEND_KEYCMD': append_keycmd,
- 'INJECT_KEYCMD': inject_keycmd,
- 'IGNORE_KEY': add_key_ignore,
- 'MODKEY_ADDITION': modkey_addition_parse}
-
- uzbl.connect_dict(connects)
+ # Event handling hooks.
+ uzbl.connect_dict({
+ '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,
+ 'KEYCMD_STRIP_WORD': keycmd_strip_word,
+ 'KEY_PRESS': key_press,
+ 'KEY_RELEASE': key_release,
+ 'MODKEY_ADDITION': modkey_addition_parse,
+ 'MODMAP': modmap_parse,
+ 'SET_CURSOR_POS': set_cursor_pos,
+ 'SET_KEYCMD': set_keycmd,
+ })
+
+ # Function exports to the uzbl object, `function(uzbl, *args, ..)`
+ # becomes `uzbl.function(*args, ..)`.
+ uzbl.export_dict({
+ 'add_key_ignore': add_key_ignore,
+ 'add_modkey_addition': add_modkey_addition,
+ 'add_modmap': add_modmap,
+ 'append_keycmd': append_keycmd,
+ 'clear_current': clear_current,
+ 'clear_keycmd': clear_keycmd,
+ 'clear_modcmd': clear_modcmd,
+ 'get_keylet': get_keylet,
+ 'inject_keycmd': inject_keycmd,
+ 'set_cursor_pos': set_cursor_pos,
+ 'set_keycmd': set_keycmd,
+ })
diff --git a/examples/data/uzbl/plugins/mode.py b/examples/data/uzbl/plugins/mode.py
index f85d999..54d865a 100644
--- a/examples/data/uzbl/plugins/mode.py
+++ b/examples/data/uzbl/plugins/mode.py
@@ -156,12 +156,21 @@ def toggle_modes(uzbl, modes):
def init(uzbl):
-
- connects = {'CONFIG_CHANGED': config_changed,
- 'INSTANCE_EXIT': del_instance,
- 'INSTANCE_START': add_instance,
- 'MODE_CONFIG': mode_config,
- 'TOGGLE_MODES': toggle_modes,
- 'MODE_CHANGED': mode_changed}
-
- uzbl.connect_dict(connects)
+ # 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,
+ })
+
+ # 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,
+ })
diff --git a/examples/data/uzbl/plugins/on_event.py b/examples/data/uzbl/plugins/on_event.py
index afee4e6..b9c504a 100644
--- a/examples/data/uzbl/plugins/on_event.py
+++ b/examples/data/uzbl/plugins/on_event.py
@@ -2,6 +2,7 @@
Formatting options:
%s = space separated string of the arguments
+ %r = escaped and quoted version of %s
%1 = argument 1
%2 = argument 2
%n = argument n
@@ -44,20 +45,6 @@ def get_on_events(uzbl):
return UZBLS[uzbl]
-def expand(cmd, args):
- '''Replaces "%s %1 %2 %3..." with "<all args> <arg 0> <arg 1>...".'''
-
- 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 event_handler(uzbl, *args, **kargs):
'''This function handles all the events being watched by various
on_event definitions and responds accordingly.'''
@@ -68,8 +55,9 @@ def event_handler(uzbl, *args, **kargs):
return
commands = events[event]
+ cmd_expand = uzbl.cmd_expand
for cmd in commands:
- cmd = expand(cmd, args)
+ cmd = cmd_expand(cmd, args)
uzbl.send(cmd)
@@ -104,9 +92,16 @@ def parse_on_event(uzbl, args):
def init(uzbl):
-
- connects = {'ON_EVENT': parse_on_event,
- 'INSTANCE_START': add_instance,
- 'INSTANCE_EXIT': del_instance}
-
- uzbl.connect_dict(connects)
+ # Event handling hooks.
+ uzbl.connect_dict({
+ 'INSTANCE_EXIT': del_instance,
+ 'INSTANCE_START': add_instance,
+ '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,
+ })
diff --git a/examples/data/uzbl/plugins/plugin_template.py b/examples/data/uzbl/plugins/plugin_template.py
index 03cb748..565a999 100644
--- a/examples/data/uzbl/plugins/plugin_template.py
+++ b/examples/data/uzbl/plugins/plugin_template.py
@@ -1,8 +1,5 @@
'''Plugin template.'''
-# A list of functions this plugin exports to be used via uzbl object.
-__export__ = ['myplugin_function',]
-
# Holds the per-instance data dict.
UZBLS = {}
@@ -60,16 +57,20 @@ def init(uzbl):
# Make a dictionary comprising of {"EVENT_NAME": handler, ..} to the event
# handler stack:
- connects = {
- 'INSTANCE_START': add_instance,
- 'INSTANCE_EXIT': del_instance,
- 'MYPLUGIN_EVENT': myplugin_event_parser,
- }
-
- # And connect the dicts event handlers to the handler stack.
- uzbl.connect_dict(connects)
+ 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/uzbl/plugins/progress_bar.py b/examples/data/uzbl/plugins/progress_bar.py
index b6fcb1b..89ba175 100644
--- a/examples/data/uzbl/plugins/progress_bar.py
+++ b/examples/data/uzbl/plugins/progress_bar.py
@@ -149,10 +149,11 @@ def reset_progress(uzbl, args):
def init(uzbl):
- connects = {'LOAD_PROGRESS': update_progress,
- 'INSTANCE_START': add_instance,
- 'INSTANCE_EXIT': del_instance,
- 'PROGRESS_CONFIG': progress_config,
- 'LOAD_COMMIT': reset_progress}
-
- uzbl.connect_dict(connects)
+ # Event handling hooks.
+ uzbl.connect_dict({
+ 'INSTANCE_EXIT': del_instance,
+ 'INSTANCE_START': add_instance,
+ 'LOAD_COMMIT': reset_progress,
+ 'LOAD_PROGRESS': update_progress,
+ 'PROGRESS_CONFIG': progress_config,
+ })
diff --git a/examples/data/uzbl/scripts/uzbl-event-manager b/examples/data/uzbl/scripts/uzbl-event-manager
index 916259a..afef6fd 100755
--- a/examples/data/uzbl/scripts/uzbl-event-manager
+++ b/examples/data/uzbl/scripts/uzbl-event-manager
@@ -350,61 +350,23 @@ class UzblInstance(object):
def __init__(self, parent, client_socket):
# Internal variables.
- self._exports = {}
- self._handlers = {}
- self._parent = parent
- self._client_socket = client_socket
+ self.exports = {}
+ self.handlers = {}
+ self.parent = parent
+ self.client_socket = client_socket
self.depth = 0
self.buffer = ''
self.pid = None
- # Call the init() function in every plugin. Inside the init function
- # is where the plugins insert the hooks into the event system.
- self._init_plugins()
-
-
- def __getattribute__(self, attr):
- '''Expose any exported functions before class functions.'''
-
- if not attr.startswith('_'):
- exports = object.__getattribute__(self, '_exports')
- if attr in exports:
- return exports[attr]
-
- return object.__getattribute__(self, attr)
-
-
- def _init_plugins(self):
- '''Call the init() function in every plugin and expose all exposable
- functions in the plugins root namespace.'''
-
- plugins = self._parent['plugins']
-
- # Map all plugin exports
- for (name, plugin) in plugins.items():
- if not hasattr(plugin, '__export__'):
- continue
-
- for export in plugin.__export__:
- if export in self._exports:
- raise KeyError("conflicting export: %r" % export)
-
- obj = getattr(plugin, export)
- if callable(obj):
- obj = partial(obj, self)
-
- self._exports[export] = obj
-
- echo("exposed attribute(s): %s" % ', '.join(self._exports.keys()))
-
- # Now call the init function in all plugins.
- for (name, plugin) in plugins.items():
+ # Call the init function in every plugin. The init function in each
+ # plugin is where that plugin connects functions to events and exports
+ # functions to the uzbl object.
+ for plugin in self.parent['plugins'].values():
try:
plugin.init(self)
except:
- #print_exc()
raise
@@ -412,26 +374,43 @@ class UzblInstance(object):
'''Send a command to the uzbl instance via the socket file.'''
msg = msg.strip()
- if self._client_socket:
+ if self.client_socket:
print '%s<-- %s' % (' ' * self.depth, msg)
- self._client_socket.send(("%s\n" % msg).encode('utf-8'))
+ self.client_socket.send(("%s\n" % msg).encode('utf-8'))
else:
print '%s!-- %s' % (' ' * self.depth, msg)
+ def export(self, name, function):
+ '''Export `function(uzbl, *args, ..)` inside a plugin to the uzbl
+ object like so `uzbl.function(*args, ..)`. This will allow other
+ plugins to call functions inside the current plugin (which is currently
+ calling this function) via the uzbl object.'''
+
+ self.__dict__.__setitem__(name, partial(function, self))
+
+
+ def export_dict(self, export_dict):
+ '''Export multiple (name, function)'s at once inside a dict of the
+ form `{name1: function1, name2: function2, ...}`.'''
+
+ for (name, function) in export_dict.items():
+ self.export(name, function)
+
+
def connect(self, event, handler, *args, **kargs):
- '''Connect event with handler and return the newly created handler.
- Handlers can either be a function or a uzbl command string.'''
+ '''Connect a uzbl event with a handler. Handlers can either be a
+ function or a uzbl command string.'''
event = event.upper().strip()
assert event and ' ' not in event
- if event not in self._handlers.keys():
- self._handlers[event] = []
+ if event not in self.handlers.keys():
+ self.handlers[event] = []
handlerobj = EventHandler(event, handler, *args, **kargs)
- self._handlers[event].append(handlerobj)
+ self.handlers[event].append(handlerobj)
print handlerobj
@@ -449,7 +428,7 @@ class UzblInstance(object):
def remove_by_id(self, hid):
'''Remove connected event handler by unique handler id.'''
- for (event, handlers) in self._handlers.items():
+ for (event, handlers) in self.handlers.items():
for handler in list(handlers):
if hid != handler.hid:
continue
@@ -464,7 +443,7 @@ class UzblInstance(object):
def remove(self, handler):
'''Remove connected event handler.'''
- for (event, handlers) in self._handlers.items():
+ for (event, handlers) in self.handlers.items():
if handler in handlers:
echo("removed %r" % handler)
handlers.remove(handler)
@@ -493,10 +472,10 @@ class UzblInstance(object):
if event == "INSTANCE_START" and args:
self.pid = int(args[0])
- if event not in self._handlers:
+ if event not in self.handlers:
return
- for handler in self._handlers[event]:
+ for handler in self.handlers[event]:
self.depth += 1
try:
self.exec_handler(handler, *args, **kargs)
@@ -511,19 +490,15 @@ class UzblInstance(object):
'''Close the client socket and clean up.'''
try:
- self._client_socket.close()
+ self.client_socket.close()
except:
pass
- for (name, plugin) in self._parent['plugins'].items():
+ for (name, plugin) in self.parent['plugins'].items():
if hasattr(plugin, 'cleanup'):
plugin.cleanup(self)
- del self._exports
- del self._handlers
- del self._client_socket
-
class UzblEventDaemon(dict):
def __init__(self):
diff --git a/tests/test-command.c b/tests/test-command.c
index 49f3bb8..fc3b092 100644
--- a/tests/test-command.c
+++ b/tests/test-command.c
@@ -305,11 +305,6 @@ test_js (void) {
parse_cmd_line("js ('x' + 345).toUpperCase()", result);
g_assert_cmpstr("X345", ==, result->str);
- /* uzbl commands can be run from javascript */
- uzbl.net.useragent = "Test useragent";
- parse_cmd_line("js Uzbl.run('print @useragent').toUpperCase();", result);
- g_assert_cmpstr("TEST USERAGENT", ==, result->str);
-
g_string_free(result, TRUE);
}
diff --git a/uzbl-core.c b/uzbl-core.c
index fd8ee41..fca293c 100644
--- a/uzbl-core.c
+++ b/uzbl-core.c
@@ -1046,7 +1046,6 @@ eval_js(WebKitWebView * web_view, gchar *script, GString *result) {
WebKitWebFrame *frame;
JSGlobalContextRef context;
JSObjectRef globalobject;
- JSStringRef var_name;
JSStringRef js_script;
JSValueRef js_result;
@@ -1059,12 +1058,6 @@ eval_js(WebKitWebView * web_view, gchar *script, GString *result) {
context = webkit_web_frame_get_global_context(frame);
globalobject = JSContextGetGlobalObject(context);
- /* uzbl javascript namespace */
- var_name = JSStringCreateWithUTF8CString("Uzbl");
- JSObjectSetProperty(context, globalobject, var_name,
- JSObjectMake(context, uzbl.js.classref, NULL),
- kJSClassAttributeNone, NULL);
-
/* evaluate the script and get return value*/
js_script = JSStringCreateWithUTF8CString(script);
js_result = JSEvaluateScript(context, js_script, globalobject, NULL, 0, NULL);
@@ -1082,9 +1075,6 @@ eval_js(WebKitWebView * web_view, gchar *script, GString *result) {
}
/* cleanup */
- JSObjectDeleteProperty(context, globalobject, var_name, NULL);
-
- JSStringRelease(var_name);
JSStringRelease(js_script);
}