merge with Dieterbe/experimental
authoruranther <jwheaton@purdue.edu>
Mon, 1 Jun 2009 17:44:45 +0000 (13:44 -0400)
committeruranther <jwheaton@purdue.edu>
Mon, 1 Jun 2009 17:44:45 +0000 (13:44 -0400)
1  2 
Makefile
examples/configs/sampleconfig
examples/configs/sampleconfig-dev
uzbl.c
uzbl.h

diff --combined Makefile
+++ b/Makefile
@@@ -1,7 -1,9 +1,9 @@@
 -CPPFLAGS:=$(shell pkg-config --cflags gtk+-2.0 webkit-1.0) -ggdb -Wall -W -DARCH="\"$(shell uname -m)\"" -DG_ERRORCHECK_MUTEXES -DCOMMIT="\"$(shell git log | head -n1 | sed "s/.* //")\"" $(CPPFLAGS)
 -LDFLAGS:=$(shell pkg-config --libs gtk+-2.0 webkit-1.0) $(LDFLAGS)
 +CPPFLAGS=$(shell pkg-config --cflags gtk+-2.0 webkit-1.0) -ggdb -Wall -pedantic -std=gnu99 -W -DARCH="\"$(shell uname -m)\"" -DG_ERRORCHECK_MUTEXES -DCOMMIT="\"$(shell git log | head -n1 | sed "s/.* //")\""
 +LDFLAGS=$(shell pkg-config --libs gtk+-2.0 webkit-1.0)
  all: uzbl uzblctrl
  
+ PREFIX?=$(DESTDIR)/usr
  test: uzbl
        ./uzbl --uri http://www.uzbl.org
  
@@@ -16,18 -18,19 +18,19 @@@ clean
        rm -f uzblctrl
  
  install:
-       install -d $(DESTDIR)/usr/bin
-       install -d $(DESTDIR)/usr/share/uzbl/docs
-       install -d $(DESTDIR)/usr/share/uzbl/examples
-       install -D -m755 uzbl $(DESTDIR)/usr/bin/uzbl
-       install -D -m755 uzblctrl $(DESTDIR)/usr/bin/uzblctrl
-       cp -ax docs     $(DESTDIR)/usr/share/uzbl/
-       cp -ax config.h $(DESTDIR)/usr/share/uzbl/docs/
-       cp -ax examples $(DESTDIR)/usr/share/uzbl/
-       install -D -m644 AUTHORS $(DESTDIR)/usr/share/uzbl/docs
-       install -D -m644 README  $(DESTDIR)/usr/share/uzbl/docs
+       install -d $(PREFIX)/bin
+       install -d $(PREFIX)/share/uzbl/docs
+       install -d $(PREFIX)/share/uzbl/examples
+       install -D -m755 uzbl $(PREFIX)/bin/uzbl
+       install -D -m755 uzblctrl $(PREFIX)/bin/uzblctrl
+       cp -ax docs     $(PREFIX)/share/uzbl/
+       cp -ax config.h $(PREFIX)/share/uzbl/docs/
+       cp -ax examples $(PREFIX)/share/uzbl/
+       install -D -m644 AUTHORS $(PREFIX)/share/uzbl/docs
+       install -D -m644 README  $(PREFIX)/share/uzbl/docs
  
  uninstall:
-       rm -rf $(DESTDIR)/usr/bin/uzbl
-       rm -rf $(DESTDIR)/usr/bin/uzblctrl
-       rm -rf $(DESTDIR)/usr/share/uzbl
+       rm -rf $(PREFIX)/bin/uzbl
+       rm -rf $(PREFIX)/bin/uzblctrl
+       rm -rf $(PREFIX)/share/uzbl
@@@ -2,16 -2,16 +2,16 @@@
  # example uzbl config. in a real config, we should obey the xdg spec
  # all settings are optional.  you can use uzbl without any config at all (but it won't do much)
  
- # keyboard behavior is vimstyle by default (all actions -> 1 key). set
+ # keyboard behavior is vimstyle by default (all commands -> 1 key). set
  # always_insert_mode to always be in insert mode and disable going out of it.
- # if you do this, make sure you've set a modkey so you can reach the actions
+ # if you do this, make sure you've set a modkey so you can reach the commands
  # from insert mode by combining them with the modkey
  
  # TODO: ability to attach misc things (spawn <foo>, script <bar>,.. to internal events)
- # You can use any action in place of spawn
+ # You can use any command in place of spawn
  set history_handler  = spawn /usr/share/uzbl/examples/scripts/history.sh
  set download_handler = spawn /usr/share/uzbl/examples/scripts/download.sh
 -set cookie_handler   = spawn /usr/share/uzbl/examples/scripts/cookies.sh
 +#set cookie_handler   = spawn /usr/share/uzbl/examples/scripts/cookies.sh
  
  set minimum_font_size = 6
  set font_size = 11
@@@ -69,7 -69,6 +69,7 @@@ bind    r         = reloa
  bind    R         = reload_ign_cache
  bind    +         = zoom_in
  bind    -         = zoom_out
 +bind    =         = sh "echo set zoom_level = 1.0 > $4"
  bind    t         = toggle_status
  # Hilight matches. Notice the * after the slash - it makes the command incremental, i.e. gets called
  # on every character you type.  You can do `bind /_ = search %s' if you want it less interactive.
@@@ -90,14 -89,14 +90,14 @@@ bind    B         = spawn /usr/share/uz
  bind    U         = spawn /usr/share/uzbl/examples/scripts/load_url_from_history.sh
  bind    u         = spawn /usr/share/uzbl/examples/scripts/load_url_from_bookmarks.sh
  # with the sample yank script, you can yank one of the arguments into clipboard/selection
- bind    yurl      = spawn /usr/share/uzbl/examples/scripts/yank.sh 8 primary
- bind    ytitle    = spawn /usr/share/uzbl/examples/scripts/yank.sh 9 clipboard
+ bind    yurl      = spawn /usr/share/uzbl/examples/scripts/yank.sh 6 primary
+ bind    ytitle    = spawn /usr/share/uzbl/examples/scripts/yank.sh 7 clipboard
  # does the same as yurl but without needing a script
  bind    y2url     = sh "echo -n $6 | xclip"
  # go the page from primary selection
- bind    p         = sh "echo act uri `xclip -selection primary -o` > $4"
+ bind    p         = sh "echo uri `xclip -selection primary -o` > $4"
  # go to the page in clipboard
- bind    P         = sh "echo act uri `xclip -selection clipboard -o` > $4"
+ bind    P         = sh "echo uri `xclip -selection clipboard -o` > $4"
  bind    ZZ        = exit
  bind    S         = js alert("hi");
  # example showing how to use sh
  # if fifo_dir is not set, it'll echo to a file named (null) somewhere >:) remember to delete it
  # Parameters are separated by spaces and the script body must be one parameter, so enclose it in
  # quotes and escape any inner quotes using backslashes
- bind    XS        = sh 'echo "act script alert (\'This is sent by the shell via a fifo\')" > "$4"'
+ bind    XS        = sh 'echo "js alert (\'This is sent by the shell via a fifo\')" > "$4"'
  
  
  # we ship some javascripts to do keyboard based link hinting/following.  (webkit does not have C DOM bindings yet)
@@@ -2,16 -2,16 +2,16 @@@
  # example uzbl config. in a real config, we should obey the xdg spec
  # all settings are optional.  you can use uzbl without any config at all (but it won't do much)
  
- # keyboard behavior is vimstyle by default (all actions -> 1 key). set
+ # keyboard behavior is vimstyle by default (all commands -> 1 key). set
  # always_insert_mode to always be in insert mode and disable going out of it.
- # if you do this, make sure you've set a modkey so you can reach the actions
+ # if you do this, make sure you've set a modkey so you can reach the commands
  # from insert mode by combining them with the modkey
  
  # TODO: ability to attach misc things (spawn <foo>, script <bar>,.. to internal events)
- # Usually you want to spawn a script to handle things, but any action (such as sh) can be used
+ # Usually you want to spawn a script to handle things, but any command (such as sh) can be used
  set history_handler  = spawn ./examples/scripts/history.sh
  set download_handler = spawn ./examples/scripts/download.sh
 -set cookie_handler   = spawn ./examples/scripts/cookies.sh
 +#set cookie_handler   = spawn ./examples/scripts/cookies.sh
  
  set minimum_font_size = 6
  set font_size = 11
@@@ -60,7 -60,7 +60,7 @@@ set shell_cmd         = sh -
  set show_status       = 1
  # you can optionally use this setting to override the background color of the statusbar from your GTK theme.
  set status_background = #303030
- set status_format     = <span font_family="monospace"><span background="khaki" foreground="black">MODE</span> [<span weight="bold" foreground="red">KEYCMD</span>] <span foreground="#606060"> LOAD_PROGRESSBAR </span><span foreground="#99FF66">URI</span> <span foreground="khaki">NAME</span> <span foreground="orange">MSG</span><span foreground="#606060">SELECTED_URI</span></span>
+ set status_format     = <span font_family="monospace"><span background="khaki" foreground="black">[MODE]</span> [<span weight="bold" foreground="red">KEYCMD</span>] <span foreground="#606060"> LOAD_PROGRESSBAR </span><span foreground="#99FF66">URI</span> <span foreground="khaki">NAME</span> <span foreground="orange">MSG</span><span foreground="#606060">SELECTED_URI</span></span>
  set status_top = 0
  # define how your titlebar should look like. (short = statusbar is also shown, long = show everything you must see if statusbar is off)
  set title_format_short = TITLE - Uzbl browser <NAME>
@@@ -69,7 -69,8 +69,8 @@@ set title_format_long = KEYCMD MODE TIT
  set status_pbar_done  = *
  set status_pbar_pending = -
  set status_pbar_width = 12
+ set insert_indicator = I
+ set command_indicator = C
  set modkey = Mod1
  # reset to command mode when new page is loaded
  set reset_command_mode = 1
@@@ -125,14 -126,14 +126,14 @@@ bind    B         = spawn ./examples/sc
  bind    U         = spawn ./examples/scripts/load_url_from_history.sh
  bind    u         = spawn ./examples/scripts/load_url_from_bookmarks.sh
  # with the sample yank script, you can yank one of the arguments into clipboard/selection
- bind    yurl      = spawn ./examples/scripts/yank.sh 8 primary
- bind    ytitle    = spawn ./examples/scripts/yank.sh 9 clipboard
+ bind    yurl      = spawn ./examples/scripts/yank.sh 6 primary
+ bind    ytitle    = spawn ./examples/scripts/yank.sh 7 clipboard
  # does the same as yurl but without needing a script
  bind    y2url     = sh 'echo -n $6 | xclip'
  # go the page from primary selection
- bind    p         = sh "echo act uri `xclip -selection primary -o` > $4"
+ bind    p         = sh "echo uri `xclip -selection primary -o` > $4"
  # go to the page in clipboard
- bind    P         = sh "echo act uri `xclip -selection clipboard -o` > $4"
+ bind    P         = sh "echo uri `xclip -selection clipboard -o` > $4"
  bind    ZZ        = exit
  bind    S         = js alert("hi");
  # example showing how to use sh
  # 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.)
- bind    XS        = sh 'echo "act script alert (\\"This is sent by the shell via a fifo\\")" > "$4"'
+ bind    XS        = sh 'echo "js alert (\\"This is sent by the shell via a fifo\\")" > "$4"'
  
  # this script allows you to configure (per domain) values to fill in form fields (eg login information) and to fill in these values automatically
  bind za = spawn ./examples/scripts/formfiller.sh
diff --combined uzbl.c
--- 1/uzbl.c
--- 2/uzbl.c
+++ b/uzbl.c
@@@ -1,6 -1,6 +1,6 @@@
  /* -*- c-basic-offset: 4; -*- */
 -// Original code taken from the example webkit-gtk+ application. see notice below.
 -// Modified code is licensed under the GPL 3.  See LICENSE file.
 +/* Original code taken from the example webkit-gtk+ application. see notice below. */
 +/* Modified code is licensed under the GPL 3.  See LICENSE file. */
  
  
  /*
  #include <gtk/gtk.h>
  #include <gdk/gdkx.h>
  #include <gdk/gdkkeysyms.h>
 +
 +#include <sys/types.h>
  #include <sys/socket.h>
  #include <sys/stat.h>
 -#include <sys/types.h>
 -#include <sys/un.h>
  #include <sys/utsname.h>
  #include <sys/time.h>
 +#include <sys/un.h>
 +
  #include <webkit/webkit.h>
 +#include <libsoup/soup.h>
 +
  #include <stdio.h>
  #include <string.h>
  #include <unistd.h>
  #include <stdlib.h>
  #include <errno.h>
 -#include <string.h>
  #include <fcntl.h>
 -#include <sys/socket.h>
 -#include <sys/un.h>
 -#include <libsoup/soup.h>
  #include <signal.h>
  #include "uzbl.h"
  #include "config.h"
@@@ -81,73 -81,76 +81,74 @@@ GOptionEntry entries[] 
  typedef const struct {
      void **ptr;
      int type;
+     int dump;
      void (*func)(void);
  } uzbl_cmdprop;
  
 -enum {TYPE_INT, TYPE_STR};
 +enum {TYPE_INT, TYPE_STR, TYPE_FLOAT};
  
  /* an abbreviation to help keep the table's width humane */
- #define PTR(var, t, fun) { .ptr = (void*)&(var), .type = TYPE_##t, .func = fun }
+ #define PTR(var, t, d, fun) { .ptr = (void*)&(var), .type = TYPE_##t, .dump = d, .func = fun }
  
  const struct {
      char *name;
      uzbl_cmdprop cp;
  } var_name_to_ptr[] = {
- /*    variable name         pointer to variable in code          type  callback function    */
+ /*    variable name         pointer to variable in code          type  dump callback function    */
  /*  --------------------------------------------------------------------------------------- */
 -    { "uri",                 PTR(uzbl.state.uri,                  STR,  1,   cmd_load_uri)},
 -    { "verbose",             PTR(uzbl.state.verbose,              INT,  1,   NULL)},
 -    { "mode",                PTR(uzbl.behave.mode,                INT,  0,   NULL)},
 -    { "inject_html",         PTR(uzbl.behave.inject_html,         STR,  0,   cmd_inject_html)},
 -    { "base_url",            PTR(uzbl.behave.base_url,            STR,  1,   NULL)},
 -    { "html_endmarker",      PTR(uzbl.behave.html_endmarker,      STR,  1,   NULL)},
 -    { "html_mode_timeout",   PTR(uzbl.behave.html_timeout,        INT,  1,   NULL)},
 -    { "status_message",      PTR(uzbl.gui.sbar.msg,               STR,  1,   update_title)},
 -    { "show_status",         PTR(uzbl.behave.show_status,         INT,  1,   cmd_set_status)},
 -    { "status_top",          PTR(uzbl.behave.status_top,          INT,  1,   move_statusbar)},
 -    { "status_format",       PTR(uzbl.behave.status_format,       STR,  1,   update_title)},
 -    { "status_pbar_done",    PTR(uzbl.gui.sbar.progress_s,        STR,  1,   update_title)},
 -    { "status_pbar_pending", PTR(uzbl.gui.sbar.progress_u,        STR,  1,   update_title)},
 -    { "status_pbar_width",   PTR(uzbl.gui.sbar.progress_w,        INT,  1,   update_title)},
 -    { "status_background",   PTR(uzbl.behave.status_background,   STR,  1,   update_title)},
 -    { "insert_indicator",    PTR(uzbl.behave.insert_indicator,    STR,  1,   update_title)},
 -    { "command_indicator",   PTR(uzbl.behave.cmd_indicator,       STR,  1,   update_title)},
 -    { "title_format_long",   PTR(uzbl.behave.title_format_long,   STR,  1,   update_title)},
 -    { "title_format_short",  PTR(uzbl.behave.title_format_short,  STR,  1,   update_title)},
 -    { "insert_mode",         PTR(uzbl.behave.insert_mode,         INT,  1,   NULL)},
 -    { "always_insert_mode",  PTR(uzbl.behave.always_insert_mode,  INT,  1,   cmd_always_insert_mode)},
 -    { "reset_command_mode",  PTR(uzbl.behave.reset_command_mode,  INT,  1,   NULL)},
 -    { "modkey",              PTR(uzbl.behave.modkey,              STR,  1,   cmd_modkey)},
 -    { "load_finish_handler", PTR(uzbl.behave.load_finish_handler, STR,  1,   NULL)},
 -    { "load_start_handler",  PTR(uzbl.behave.load_start_handler,  STR,  1,   NULL)},
 -    { "load_commit_handler", PTR(uzbl.behave.load_commit_handler, STR,  1,   NULL)},
 -    { "history_handler",     PTR(uzbl.behave.history_handler,     STR,  1,   NULL)},
 -    { "download_handler",    PTR(uzbl.behave.download_handler,    STR,  1,   NULL)},
 -    { "cookie_handler",      PTR(uzbl.behave.cookie_handler,      STR,  1,   cmd_cookie_handler)},
 -    { "fifo_dir",            PTR(uzbl.behave.fifo_dir,            STR,  1,   cmd_fifo_dir)},
 -    { "socket_dir",          PTR(uzbl.behave.socket_dir,          STR,  1,   cmd_socket_dir)},
 -    { "http_debug",          PTR(uzbl.behave.http_debug,          INT,  1,   cmd_http_debug)},
 -    { "shell_cmd",           PTR(uzbl.behave.shell_cmd,           STR,  1,   NULL)},
 -    { "proxy_url",           PTR(uzbl.net.proxy_url,              STR,  1,   set_proxy_url)},
 -    { "max_conns",           PTR(uzbl.net.max_conns,              INT,  1,   cmd_max_conns)},
 -    { "max_conns_host",      PTR(uzbl.net.max_conns_host,         INT,  1,   cmd_max_conns_host)},
 -    { "useragent",           PTR(uzbl.net.useragent,              STR,  1,   cmd_useragent)},
 -    /* exported WebKitWebSettings properties*/
 -    { "font_size",           PTR(uzbl.behave.font_size,           INT,  1,   cmd_font_size)},
 -    { "monospace_size",      PTR(uzbl.behave.monospace_size,      INT,  1,   cmd_font_size)},
 -    { "minimum_font_size",   PTR(uzbl.behave.minimum_font_size,   INT,  1,   cmd_minimum_font_size)},
 -    { "disable_plugins",     PTR(uzbl.behave.disable_plugins,     INT,  1,   cmd_disable_plugins)},
 -    { "disable_scripts",     PTR(uzbl.behave.disable_scripts,     INT,  1,   cmd_disable_scripts)},
 -    { "autoload_images",     PTR(uzbl.behave.autoload_img,        INT,  1,   cmd_autoload_img)},
 -    { "autoshrink_images",   PTR(uzbl.behave.autoshrink_img,      INT,  1,   cmd_autoshrink_img)},
 -    { "enable_spellcheck",   PTR(uzbl.behave.enable_spellcheck,   INT,  1,   cmd_enable_spellcheck)},
 -    { "enable_private",      PTR(uzbl.behave.enable_private,      INT,  1,   cmd_enable_private)},
 -    { "print_backgrounds",   PTR(uzbl.behave.print_bg,            INT,  1,   cmd_print_bg)},
 -    { "stylesheet_uri",      PTR(uzbl.behave.style_uri,           STR,  1,   cmd_style_uri)},
 -    { "resizable_text_areas",PTR(uzbl.behave.resizable_txt,       INT,  1,   cmd_resizable_txt)},
 -    { "default_encoding",    PTR(uzbl.behave.default_encoding,    STR,  1,   cmd_default_encoding)},
 -    { "enforce_96_dpi",      PTR(uzbl.behave.enforce_96dpi,       INT,  1,   cmd_enforce_96dpi)},
 -    { "caret_browsing",      PTR(uzbl.behave.caret_browsing,      INT,  1,   cmd_caret_browsing)},
 -
 -    { NULL,                  {.ptr = NULL, .type = TYPE_INT, .dump = 0, .func = NULL}}
 +    { "uri",                 PTR(uzbl.state.uri,                  STR, cmd_load_uri)},
 +    { "mode",                PTR(uzbl.behave.mode,                INT, NULL)},
 +    { "inject_html",         PTR(uzbl.behave.inject_html,         STR, cmd_inject_html)},
 +    { "base_url",            PTR(uzbl.behave.base_url,            STR, NULL)},
 +    { "html_endmarker",      PTR(uzbl.behave.html_endmarker,      STR, NULL)},
 +    { "html_mode_timeout",   PTR(uzbl.behave.html_timeout,        INT, NULL)},
 +    { "status_message",      PTR(uzbl.gui.sbar.msg,               STR, update_title)},
 +    { "show_status",         PTR(uzbl.behave.show_status,         INT, cmd_set_status)},
 +    { "status_top",          PTR(uzbl.behave.status_top,          INT, move_statusbar)},
 +    { "status_format",       PTR(uzbl.behave.status_format,       STR, update_title)},
 +    { "status_pbar_done",    PTR(uzbl.gui.sbar.progress_s,        STR, update_title)},
 +    { "status_pbar_pending", PTR(uzbl.gui.sbar.progress_u,        STR, update_title)},
 +    { "status_pbar_width",   PTR(uzbl.gui.sbar.progress_w,        INT, update_title)},
 +    { "status_background",   PTR(uzbl.behave.status_background,   STR, update_title)},
 +    { "title_format_long",   PTR(uzbl.behave.title_format_long,   STR, update_title)},
 +    { "title_format_short",  PTR(uzbl.behave.title_format_short,  STR, update_title)},
 +    { "insert_mode",         PTR(uzbl.behave.insert_mode,         INT, NULL)},
 +    { "always_insert_mode",  PTR(uzbl.behave.always_insert_mode,  INT, cmd_always_insert_mode)},
 +    { "reset_command_mode",  PTR(uzbl.behave.reset_command_mode,  INT, NULL)},
 +    { "modkey",              PTR(uzbl.behave.modkey,              STR, cmd_modkey)},
 +    { "load_finish_handler", PTR(uzbl.behave.load_finish_handler, STR, NULL)},
 +    { "load_start_handler",  PTR(uzbl.behave.load_start_handler,  STR, NULL)},
 +    { "load_commit_handler", PTR(uzbl.behave.load_commit_handler, STR, NULL)},
 +    { "history_handler",     PTR(uzbl.behave.history_handler,     STR, NULL)},
 +    { "download_handler",    PTR(uzbl.behave.download_handler,    STR, NULL)},
 +    { "cookie_handler",      PTR(uzbl.behave.cookie_handler,      STR, cmd_cookie_handler)},
 +    { "fifo_dir",            PTR(uzbl.behave.fifo_dir,            STR, cmd_fifo_dir)},
 +    { "socket_dir",          PTR(uzbl.behave.socket_dir,          STR, cmd_socket_dir)},
 +    { "http_debug",          PTR(uzbl.behave.http_debug,          INT, cmd_http_debug)},
 +    { "shell_cmd",           PTR(uzbl.behave.shell_cmd,           STR, NULL)},
 +    { "proxy_url",           PTR(uzbl.net.proxy_url,              STR, set_proxy_url)},
 +    { "max_conns",           PTR(uzbl.net.max_conns,              INT, cmd_max_conns)},
 +    { "max_conns_host",      PTR(uzbl.net.max_conns_host,         INT, cmd_max_conns_host)},
 +    { "useragent",           PTR(uzbl.net.useragent,              STR, cmd_useragent)},
 +    /* exported WebKitWebSettings properties */
 +    { "font_size",           PTR(uzbl.behave.font_size,           INT, cmd_font_size)},
 +    { "monospace_size",      PTR(uzbl.behave.monospace_size,      INT, cmd_font_size)},
 +    { "minimum_font_size",   PTR(uzbl.behave.minimum_font_size,   INT, cmd_minimum_font_size)},
 +    { "zoom_level",          PTR(uzbl.behave.zoom_level,          FLOAT, cmd_zoom_level)},
 +    { "disable_plugins",     PTR(uzbl.behave.disable_plugins,     INT, cmd_disable_plugins)},
 +    { "disable_scripts",     PTR(uzbl.behave.disable_scripts,     INT, cmd_disable_scripts)},
 +    { "autoload_images",     PTR(uzbl.behave.autoload_img,        INT, cmd_autoload_img)},
 +    { "autoshrink_images",   PTR(uzbl.behave.autoshrink_img,      INT, cmd_autoshrink_img)},
 +    { "enable_spellcheck",   PTR(uzbl.behave.enable_spellcheck,   INT, cmd_enable_spellcheck)},
 +    { "enable_private",      PTR(uzbl.behave.enable_private,      INT, cmd_enable_private)},
 +    { "print_backgrounds",   PTR(uzbl.behave.print_bg,            INT, cmd_print_bg)},
 +    { "stylesheet_uri",      PTR(uzbl.behave.style_uri,           STR, cmd_style_uri)},
 +    { "resizable_text_areas",PTR(uzbl.behave.resizable_txt,       INT, cmd_resizable_txt)},
 +    { "default_encoding",    PTR(uzbl.behave.default_encoding,    STR, cmd_default_encoding)},
 +    { "enforce_96_dpi",      PTR(uzbl.behave.enforce_96dpi,       INT, cmd_enforce_96dpi)},
 +    { "caret_browsing",      PTR(uzbl.behave.caret_browsing,      INT, cmd_caret_browsing)},
 +
 +    { NULL,                  {.ptr = NULL, .type = TYPE_INT, .func = NULL}}
  }, *n2v_p = var_name_to_ptr;
  
  const struct {
@@@ -184,8 -187,51 +185,51 @@@ make_var_to_name_hash() 
      }
  }
  
  /* --- UTILITY FUNCTIONS --- */
+ static gchar *
+ expand_vars(char *s) {
+     uzbl_cmdprop *c;
+     char upto = ' ';
+     char ret[256],  *vend;
+     GString *buf = g_string_new("");
+     while(*s) {
+         switch(*s) {
+             case '\\':
+                 g_string_append_c(buf, *++s);
+                 s++;
+                 break;
+             case '@':
+                 if(*(s+1) == '{') {
+                     upto = '}'; s++;
+                 }
+                 s++;
+                 if( (vend = strchr(s, upto)) ||
+                         (vend = strchr(s, '\0')) ) {
+                     strncpy(ret, s, vend-s);
+                     ret[vend-s] = '\0';
+                     if( (c = g_hash_table_lookup(uzbl.comm.proto_var, ret)) ) {
+                         if(c->type == TYPE_STR)
+                             g_string_append(buf, (gchar *)*c->ptr);
+                         else if(c->type == TYPE_INT) {
+                             char *b = itos((int)*c->ptr);
+                             g_string_append(buf, b);
+                             g_free(b);
+                         }
+                     }
+                     if(upto == ' ') s = vend;
+                     else s = vend+1;
+                     upto = ' ';
+                 }
+                 break;
+             default:
+                 g_string_append_c(buf, *s);
+                 s++;
+                 break;
+         }
+     }
+     return g_string_free(buf, FALSE);
+ }
  
  char *
  itos(int val) {
@@@ -387,23 -433,27 +431,27 @@@ scroll (GtkAdjustment* bar, GArray *arg
      gtk_adjustment_set_value (bar, gtk_adjustment_get_value(bar)+amount);
  }
  
- static void scroll_begin(WebKitWebView* page, GArray *argv) {
+ static void
+ scroll_begin(WebKitWebView* page, GArray *argv) {
      (void) page; (void) argv;
      gtk_adjustment_set_value (uzbl.gui.bar_v, gtk_adjustment_get_lower(uzbl.gui.bar_v));
  }
  
- static void scroll_end(WebKitWebView* page, GArray *argv) {
+ static void
+ scroll_end(WebKitWebView* page, GArray *argv) {
      (void) page; (void) argv;
      gtk_adjustment_set_value (uzbl.gui.bar_v, gtk_adjustment_get_upper(uzbl.gui.bar_v) -
                                gtk_adjustment_get_page_size(uzbl.gui.bar_v));
  }
  
- static void scroll_vert(WebKitWebView* page, GArray *argv) {
+ static void
+ scroll_vert(WebKitWebView* page, GArray *argv) {
      (void) page;
      scroll(uzbl.gui.bar_v, argv);
  }
  
- static void scroll_horz(WebKitWebView* page, GArray *argv) {
+ static void
+ scroll_horz(WebKitWebView* page, GArray *argv) {
      (void) page;
      scroll(uzbl.gui.bar_h, argv);
  }
@@@ -532,6 -582,7 +580,6 @@@ VIEWFUNC(go_forward
  #undef VIEWFUNC
  
  /* -- command to callback/function map for things we cannot attach to any signals */
 -// TODO: reload
  static struct {char *name; Command command[2];} cmdlist[] =
  {   /* key                   function      no_split      */
      { "back",               {view_go_back, 0}              },
      { "search_reverse",     {search_reverse_text, NOSPLIT} },
      { "dehilight",          {dehilight, 0}                 },
      { "toggle_insert_mode", {toggle_insert_mode, 0}        },
-     { "runcmd",             {runcmd, NOSPLIT}              },
-     { "set",                {set_var, NOSPLIT}          }
+     { "set",                {set_var, NOSPLIT}             },
+     //{ "get",                {get_var, NOSPLIT}             },
+     { "bind",               {act_bind, NOSPLIT}            },
+     { "dump_config",        {act_dump_config, 0}           },
+     { "keycmd",             {keycmd, NOSPLIT}              },
+     { "keycmd_nl",          {keycmd_nl, NOSPLIT}           },
+     { "keycmd_bs",          {keycmd_bs, 0}                 },
+     { "chain",              {chain, 0}                     },
+     { "print",              {print, NOSPLIT}               }
  };
  
  static void
@@@ -604,11 -662,37 +659,37 @@@ file_exists (const char * filename) 
  static void
  set_var(WebKitWebView *page, GArray *argv) {
      (void) page;
-     gchar *ctl_line;
+     gchar **split = g_strsplit(argv_idx(argv, 0), "=", 2);
+     gchar *value = parseenv(g_strdup(split[1] ? g_strchug(split[1]) : " "));
+     set_var_value(g_strstrip(split[0]), value);
+     g_free(value);
+     g_strfreev(split);
+ }
  
-     ctl_line = g_strdup_printf("%s %s", "set", argv_idx(argv, 0));
-     parse_cmd_line(ctl_line);
-     g_free(ctl_line);
+ static void
+ print(WebKitWebView *page, GArray *argv) {
+     (void) page;
+     gchar* buf;
+     buf = expand_vars(argv_idx(argv, 0));
+     puts(buf);
+     g_free(buf);
+ }
+ static void
+ act_bind(WebKitWebView *page, GArray *argv) {
+     (void) page;
+     gchar **split = g_strsplit(argv_idx(argv, 0), " = ", 2);
+     gchar *value = parseenv(g_strdup(split[1] ? g_strchug(split[1]) : " "));
+     add_binding(g_strstrip(split[0]), value);
+     g_free(value);
+     g_strfreev(split);
+ }
+ static void
+ act_dump_config() {
+     dump_config();
  }
  
  static void
@@@ -734,6 -818,45 +815,45 @@@ new_window_load_uri (const gchar * uri
  }
  
  static void
+ chain (WebKitWebView *page, GArray *argv) {
+     (void)page;
+     gchar *a = NULL;
+     gchar **parts = NULL;
+     guint i = 0;    
+     while ((a = argv_idx(argv, i++))) {
+         parts = g_strsplit (a, " ", 2);
+         parse_command(parts[0], parts[1]);
+         g_strfreev (parts);
+     }
+ }
+ static void
+ keycmd (WebKitWebView *page, GArray *argv) {
+     (void)page;
+     (void)argv;
+     g_string_assign(uzbl.state.keycmd, argv_idx(argv, 0));
+     run_keycmd(FALSE);
+     update_title();
+ }
+ static void
+ keycmd_nl (WebKitWebView *page, GArray *argv) {
+     (void)page;
+     (void)argv;
+     g_string_assign(uzbl.state.keycmd, argv_idx(argv, 0));
+     run_keycmd(TRUE);
+     update_title();
+ }
+ static void
+ keycmd_bs (WebKitWebView *page, GArray *argv) {
+     (void)page;
+     (void)argv;
+     g_string_truncate(uzbl.state.keycmd, uzbl.state.keycmd->len - 1);
+     update_title();
+ }
+ static void
  close_uzbl (WebKitWebView *page, GArray *argv) {
      (void)page;
      (void)argv;
@@@ -893,7 -1016,8 +1013,8 @@@ expand_template(const char *template, g
                       break;
                   case SYM_MODE:
                       g_string_append(ret,
-                              uzbl.behave.insert_mode?"[I]":"[C]");
+                              uzbl.behave.insert_mode?
+                              uzbl.behave.insert_indicator:uzbl.behave.cmd_indicator);
                       break;
                   case SYM_MSG:
                       g_string_append(ret,
@@@ -1012,6 -1136,9 +1133,9 @@@ run_command (const gchar *command, cons
          g_string_append_printf(s, " -- result: %s", (result ? "true" : "false"));
          printf("%s\n", s->str);
          g_string_free(s, TRUE);
+         if(stdout) {
+             printf("Stdout: %s\n", *stdout);
+         }
      }
      if (err) {
          g_printerr("error on run_command: %s\n", err->message);
@@@ -1144,34 -1271,6 +1268,6 @@@ parse_command(const char *cmd, const ch
          g_printerr ("command \"%s\" not understood. ignoring.\n", cmd);
  }
  
- /* command parser */
- static void
- setup_regex() {
-     uzbl.comm.get_regex  = g_regex_new("^[Gg][a-zA-Z]*\\s+([^ \\n]+)$",
-             G_REGEX_OPTIMIZE, 0, NULL);
-     uzbl.comm.set_regex  = g_regex_new("^[Ss][a-zA-Z]*\\s+([^ ]+)\\s*=\\s*([^\\n].*)$",
-             G_REGEX_OPTIMIZE, 0, NULL);
-     uzbl.comm.bind_regex = g_regex_new("^[Bb][a-zA-Z]*\\s+?(.*[^ ])\\s*?=\\s*([a-z][^\\n].+)$",
-             G_REGEX_UNGREEDY|G_REGEX_OPTIMIZE, 0, NULL);
-     uzbl.comm.act_regex = g_regex_new("^[Aa][a-zA-Z]*\\s+([^ \\n]+)\\s*([^\\n]*)?$",
-             G_REGEX_OPTIMIZE, 0, NULL);
-     uzbl.comm.keycmd_regex = g_regex_new("^[Kk][a-zA-Z]*\\s+([^\\n]+)$",
-             G_REGEX_OPTIMIZE, 0, NULL);
- }
- static gboolean
- get_var_value(gchar *name) {
-     uzbl_cmdprop *c;
-     if( (c = g_hash_table_lookup(uzbl.comm.proto_var, name)) ) {
-         if(c->type == TYPE_STR)
-             printf("VAR: %s VALUE: %s\n", name, (char *)*c->ptr);
-         else if(c->type == TYPE_INT)
-             printf("VAR: %s VALUE: %d\n", name, (int)*c->ptr);
-     }
-     return TRUE;
- }
  static void
  set_proxy_url() {
      SoupURI *suri;
@@@ -1252,11 -1351,6 +1348,11 @@@ cmd_font_size() 
  }
  
  static void
 +cmd_zoom_level() {
 +    webkit_web_view_set_zoom_level (uzbl.gui.web_view, uzbl.behave.zoom_level);
 +}
 +
 +static void
  cmd_disable_plugins() {
      g_object_set (G_OBJECT(view_settings()), "enable-plugins", 
              !uzbl.behave.disable_plugins, NULL);
  static void
  cmd_disable_scripts() {
      g_object_set (G_OBJECT(view_settings()), "enable-scripts",
-             !uzbl.behave.disable_plugins, NULL);
+             !uzbl.behave.disable_scripts, NULL);
  }
  
  static void
@@@ -1338,6 -1432,7 +1434,7 @@@ cmd_caret_browsing() 
  static void
  cmd_cookie_handler() {
      gchar **split = g_strsplit(uzbl.behave.cookie_handler, " ", 2);
+     /* pitfall: doesn't handle chain actions; must the sync_ action manually */
      if ((g_strcmp0(split[0], "sh") == 0) ||
          (g_strcmp0(split[0], "spawn") == 0)) {
          g_free (uzbl.behave.cookie_handler);
@@@ -1422,18 -1517,19 +1519,20 @@@ static gboolea
  set_var_value(gchar *name, gchar *val) {
      uzbl_cmdprop *c = NULL;
      char *endp = NULL;
+     char *buf = NULL;
  
      if( (c = g_hash_table_lookup(uzbl.comm.proto_var, name)) ) {
          /* check for the variable type */
          if (c->type == TYPE_STR) {
+             buf = expand_vars(val);
              g_free(*c->ptr);
 -            *c->ptr = buf;
 -        } else if(c->type == TYPE_INT) {
 +            *c->ptr = g_strdup(val);
 +        } else if (c->type == TYPE_INT) {
              int *ip = (int *)c->ptr;
 -            buf = expand_vars(val);
 -            *ip = (int)strtoul(buf, &endp, 10);
 -            g_free(buf);
 +            *ip = (int)strtoul(val, &endp, 10);
 +        } else if (c->type == TYPE_FLOAT) {
 +            float *fp = (float *)c->ptr;
 +            *fp = strtof(val, &endp);
          }
  
          /* invoke a command specific function */
  }
  
  static void
- runcmd(WebKitWebView* page, GArray *argv) {
-     (void) page;
-     parse_cmd_line(argv_idx(argv, 0));
- }
- static void
  render_html() {
      Behaviour *b = &uzbl.behave;
  
  enum {M_CMD, M_HTML};
  static void
  parse_cmd_line(const char *ctl_line) {
-     gchar **tokens = NULL;
      Behaviour *b = &uzbl.behave;
+     size_t len=0;
  
      if(b->mode == M_HTML) {
-         if(!strncmp(b->html_endmarker, ctl_line, strlen(b->html_endmarker))) {
+         len = strlen(b->html_endmarker);
+         /* ctl_line has trailing '\n' so we check for strlen(ctl_line)-1 */
+         if(len == strlen(ctl_line)-1 &&
+            !strncmp(b->html_endmarker, ctl_line, len)) {
              set_timeout(0);
              set_var_value("mode", "0");
              render_html();
              return;
          }
          else {
-             /* set an alarm to kill us after the timeout */
              set_timeout(b->html_timeout);
              g_string_append(b->html_buffer, ctl_line);
          }
      }
-     else {
-         /* SET command */
-         if(ctl_line[0] == 's' || ctl_line[0] == 'S') {
-             tokens = g_regex_split(uzbl.comm.set_regex, ctl_line, 0);
-             if(tokens[0][0] == 0) {
-                 gchar* value = parseenv(g_strdup(tokens[2]));
-                 set_var_value(tokens[1], value);
-                 g_free(value);
-             }
-             else
-                 printf("Error in command: %s\n", tokens[0]);
-         }
-         /* GET command */
-         else if(ctl_line[0] == 'g' || ctl_line[0] == 'G') {
-             tokens = g_regex_split(uzbl.comm.get_regex, ctl_line, 0);
-             if(tokens[0][0] == 0) {
-                 get_var_value(tokens[1]);
-             }
-             else
-                 printf("Error in command: %s\n", tokens[0]);
-         }
-         /* BIND command */
-         else if(ctl_line[0] == 'b' || ctl_line[0] == 'B') {
-             tokens = g_regex_split(uzbl.comm.bind_regex, ctl_line, 0);
-             if(tokens[0][0] == 0) {
-                 gchar* value = parseenv(g_strdup(tokens[2]));
-                 add_binding(tokens[1], value);
-                 g_free(value);
-             }
-             else
-                 printf("Error in command: %s\n", tokens[0]);
-         }
-         /* ACT command */
-         else if(ctl_line[0] == 'A' || ctl_line[0] == 'a') {
-             tokens = g_regex_split(uzbl.comm.act_regex, ctl_line, 0);
-             if(tokens[0][0] == 0) {
-                 parse_command(tokens[1], tokens[2]);
-             }
-             else
-                 printf("Error in command: %s\n", tokens[0]);
-         }
-         /* KEYCMD command */
-         else if(ctl_line[0] == 'K' || ctl_line[0] == 'k') {
-             tokens = g_regex_split(uzbl.comm.keycmd_regex, ctl_line, 0);
-             if(tokens[0][0] == 0) {
-                 /* should incremental commands want each individual "keystroke"
-                    sent in a loop or the whole string in one go like now? */
-                 g_string_assign(uzbl.state.keycmd, tokens[1]);
-                 run_keycmd(FALSE);
-                 if (g_strstr_len(ctl_line, 7, "n") || g_strstr_len(ctl_line, 7, "N"))
-                     run_keycmd(TRUE);
-                 update_title();
-             }
-         }
-         /* Comments */
-         else if(   (ctl_line[0] == '#')
-                 || (ctl_line[0] == ' ')
-                 || (ctl_line[0] == '\n'))
-             ; /* ignore these lines */
-         else
-             printf("Command not understood (%s)\n", ctl_line);
-         if(tokens)
-             g_strfreev(tokens);
+     else if((ctl_line[0] == '#') /* Comments */
+             || (ctl_line[0] == ' ')
+             || (ctl_line[0] == '\n'))
+         ; /* ignore these lines */
+     else { /* parse a command */
+         gchar *ctlstrip;
+         gchar **tokens = NULL;
+         len = strlen(ctl_line);
+         if (ctl_line[len - 1] == '\n') /* strip trailing newline */
+             ctlstrip = g_strndup(ctl_line, len - 1);
+         else ctlstrip = g_strdup(ctl_line);
+         tokens = g_strsplit(ctlstrip, " ", 2);
+         parse_command(tokens[0], tokens[1]);
+         g_free(ctlstrip);
+         g_strfreev(tokens);
      }
-     return;
  }
  
  static gchar*
@@@ -1848,10 -1890,8 +1893,8 @@@ key_press_cb (GtkWidget* window, GdkEve
          return TRUE;
      }
  
-     if ((event->keyval == GDK_BackSpace) && (uzbl.state.keycmd->len > 0)) {
-         g_string_truncate(uzbl.state.keycmd, uzbl.state.keycmd->len - 1);
-         update_title();
-     }
+     if (event->keyval == GDK_BackSpace)
+         keycmd_bs(NULL, NULL);
  
      gboolean key_ret = FALSE;
      if ((event->keyval == GDK_Return) || (event->keyval == GDK_KP_Enter))
@@@ -1973,29 -2013,105 +2016,105 @@@ GtkWidget* create_window () 
      return window;
  }
  
+ static gchar**
+ inject_handler_args(const gchar *actname, const gchar *origargs, const gchar *newargs) {
+     /*
+       If actname is one that calls an external command, this function will inject
+       newargs in front of the user-provided args in that command line.  They will
+       come become after the body of the script (in sh) or after the name of
+       the command to execute (in spawn).
+       i.e. sh <body> <userargs> becomes sh <body> <ARGS> <userargs> and
+       span <command> <userargs> becomes spawn <command> <ARGS> <userargs>.
+       The return value consist of two strings: the action (sh, ...) and its args.
+       If act is not one that calls an external command, then the given action merely
+       gets duplicated.
+     */
+     GArray *rets = g_array_new(TRUE, FALSE, sizeof(gchar*));
+     gchar *actdup = g_strdup(actname);
+     g_array_append_val(rets, actdup);
+     if ((g_strcmp0(actname, "spawn") == 0) ||
+         (g_strcmp0(actname, "sh") == 0) ||
+         (g_strcmp0(actname, "sync_spawn") == 0) ||
+         (g_strcmp0(actname, "sync_sh") == 0)) {
+         guint i;
+         GString *a = g_string_new("");
+         gchar **spawnparts = split_quoted(origargs, FALSE);
+         g_string_append_printf(a, "%s", spawnparts[0]); /* sh body or script name */
+         if (newargs) g_string_append_printf(a, " %s", newargs); /* handler args */
+         for (i = 1; i < g_strv_length(spawnparts); i++) /* user args */
+             if (spawnparts[i]) g_string_append_printf(a, " %s", spawnparts[i]);
+         g_array_append_val(rets, a->str);
+         g_string_free(a, FALSE);
+         g_strfreev(spawnparts);
+     } else {
+         gchar *origdup = g_strdup(origargs);
+         g_array_append_val(rets, origdup);
+     }
+     return (gchar**)g_array_free(rets, FALSE);
+ }
  static void
  run_handler (const gchar *act, const gchar *args) {
+     /* Consider this code a temporary hack to make the handlers usable.
+        In practice, all this splicing, injection, and reconstruction is
+        inefficient, annoying and hard to manage.  Potential pitfalls arise
+        when the handler specific args 1) are not quoted  (the handler
+        callbacks should take care of this)  2) are quoted but interfere
+        with the users' own quotation.  A more ideal solution is
+        to refactor parse_command so that it doesn't just take a string
+        and execute it; rather than that, we should have a function which
+        returns the argument vector parsed from the string.  This vector
+        could be modified (e.g. insert additional args into it) before
+        passing it to the next function that actually executes it.  Though
+        it still isn't perfect for chain actions..  will reconsider & re-
+        factor when I have the time. -duc */
      char **parts = g_strsplit(act, " ", 2);
      if (!parts) return;
-     else if ((g_strcmp0(parts[0], "spawn") == 0)
-              || (g_strcmp0(parts[0], "sh") == 0)
-              || (g_strcmp0(parts[0], "sync_spawn") == 0)
-              || (g_strcmp0(parts[0], "sync_sh") == 0)) {
-         guint i;
-         GString *a = g_string_new ("");
-         char **spawnparts;
-         spawnparts = split_quoted(parts[1], FALSE);
-         g_string_append_printf(a, "%s", spawnparts[0]);
-         if (args) g_string_append_printf(a, " %s", args); /* append handler args before user args */
+     if (g_strcmp0(parts[0], "chain") == 0) {
+         GString *newargs = g_string_new("");
+         gchar **chainparts = split_quoted(parts[1], FALSE);
          
-         for (i = 1; i < g_strv_length(spawnparts); i++) /* user args */
-             g_string_append_printf(a, " %s", spawnparts[i]);
-         parse_command(parts[0], a->str);
-         g_string_free (a, TRUE);
-         g_strfreev (spawnparts);
-     } else
-         parse_command(parts[0], parts[1]);
-     g_strfreev (parts);
+         /* for every argument in the chain, inject the handler args
+            and make sure the new parts are wrapped in quotes */
+         gchar **cp = chainparts;
+         gchar quot = '\'';
+         gchar *quotless = NULL;
+         gchar **spliced_quotless = NULL; // sigh -_-;
+         gchar **inpart = NULL;
+         
+         while (*cp) {
+             if ((**cp == '\'') || (**cp == '\"')) { /* strip old quotes */
+                 quot = **cp;
+                 quotless = g_strndup(&(*cp)[1], strlen(*cp) - 2);
+             } else quotless = g_strdup(*cp);
+             spliced_quotless = g_strsplit(quotless, " ", 2);
+             inpart = inject_handler_args(spliced_quotless[0], spliced_quotless[1], args);
+             g_strfreev(spliced_quotless);
+             
+             g_string_append_printf(newargs, " %c%s %s%c", quot, inpart[0], inpart[1], quot);
+             g_free(quotless);
+             g_strfreev(inpart);
+             cp++;
+         }
+         parse_command(parts[0], &(newargs->str[1]));
+         g_string_free(newargs, TRUE);
+         g_strfreev(chainparts);
+         
+     } else {
+         gchar **inparts = inject_handler_args(parts[0], parts[1], args);
+         parse_command(inparts[0], inparts[1]);
+         g_free(inparts[0]);
+         g_free(inparts[1]);
+     }
+     g_strfreev(parts);
  }
  
  static void
@@@ -2100,7 -2216,8 +2219,8 @@@ settings_init () 
  static void handle_cookies (SoupSession *session, SoupMessage *msg, gpointer user_data){
      (void) session;
      (void) user_data;
-     if (!uzbl.behave.cookie_handler) return;
+     if (!uzbl.behave.cookie_handler)
+          return;
  
      soup_message_add_header_handler(msg, "got-headers", "Set-Cookie", G_CALLBACK(save_cookies), NULL);
      GString *s = g_string_new ("");
      g_string_printf(s, "GET '%s' '%s'", soup_uri->host, soup_uri->path);
      run_handler(uzbl.behave.cookie_handler, s->str);
  
-     if(uzbl.comm.sync_stdout)
-         soup_message_headers_replace (msg->request_headers, "Cookie", uzbl.comm.sync_stdout);
-     //printf("stdout: %s\n", uzbl.comm.sync_stdout);   // debugging
-     if (uzbl.comm.sync_stdout) uzbl.comm.sync_stdout = strfree(uzbl.comm.sync_stdout);
+     if(uzbl.comm.sync_stdout && strcmp (uzbl.comm.sync_stdout, "") != 0) {
+         char *p = strchr(uzbl.comm.sync_stdout, '\n' );
+         if ( p != NULL ) *p = '\0';
+         soup_message_headers_replace (msg->request_headers, "Cookie", (const char *) uzbl.comm.sync_stdout);
+     }
+     if (uzbl.comm.sync_stdout)
+         uzbl.comm.sync_stdout = strfree(uzbl.comm.sync_stdout);
          
      g_string_free(s, TRUE);
  }
@@@ -2225,7 -2345,34 +2348,34 @@@ set_up_inspector() 
      g_signal_connect (G_OBJECT (g->inspector), "notify::inspected-uri", G_CALLBACK (inspector_uri_changed_cb), NULL);
  }
  
+ static void
+ dump_var_hash(gpointer k, gpointer v, gpointer ud) {
+     (void) ud;
+     uzbl_cmdprop *c = v;
+     if(!c->dump)
+         return;
+     if(c->type == TYPE_STR)
+         printf("set %s = %s\n", (char *)k, *c->ptr?(char *)*c->ptr:" ");
+     else if(c->type == TYPE_INT)
+         printf("set %s = %d\n", (char *)k, (int)*c->ptr);
+ }
+ static void
+ dump_key_hash(gpointer k, gpointer v, gpointer ud) {
+     (void) ud;
+     Action *a = v;
  
+     printf("bind %s = %s %s\n", (char *)k ,
+             (char *)a->name, a->param?(char *)a->param:"");
+ }
+ static void
+ dump_config() {
+     g_hash_table_foreach(uzbl.comm.proto_var, dump_var_hash, NULL);
+     g_hash_table_foreach(uzbl.bindings, dump_key_hash, NULL);
+ }
  
  /** -- MAIN -- **/
  int
@@@ -2242,6 -2389,10 +2392,10 @@@ main (int argc, char* argv[]) 
      g_option_context_add_group (context, gtk_get_option_group (TRUE));
      g_option_context_parse (context, &argc, &argv, NULL);
      g_option_context_free(context);
+     
+     gchar *uri_override = (uzbl.state.uri ? g_strdup(uzbl.state.uri) : NULL);
+     gboolean verbose_override = uzbl.state.verbose;
      /* initialize hash table */
      uzbl.bindings = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, free_action);
  
      uzbl.behave.html_timeout = 60;
      uzbl.behave.base_url = g_strdup("http://invalid");
  
-     setup_regex();
+     /* default mode indicators */
+     uzbl.behave.insert_indicator = g_strdup("I");
+     uzbl.behave.cmd_indicator    = g_strdup("C");
      setup_scanner();
      commands_hash ();
      make_var_to_name_hash();
  
      create_stdin();
  
-     if(uzbl.state.uri) {
-         GArray *a = g_array_new (TRUE, FALSE, sizeof(gchar*));
-         g_array_append_val(a, uzbl.state.uri);
-         load_uri (uzbl.gui.web_view, a);
-         g_array_free (a, TRUE);
-     }
+     if (verbose_override > uzbl.state.verbose)
+         uzbl.state.verbose = verbose_override;
+     
+     if (uri_override) {
+         set_var_value("uri", uri_override);
+         g_free(uri_override);
+     } else if (uzbl.state.uri)
+         cmd_load_uri(uzbl.gui.web_view, NULL);
  
      gtk_main ();
      clean_up();
diff --combined uzbl.h
--- 1/uzbl.h
--- 2/uzbl.h
+++ b/uzbl.h
@@@ -71,10 -71,10 +71,10 @@@ typedef struct 
      GtkWidget*     vbox;
      GtkWidget*     mainbar;
      GtkWidget*     mainbar_label;
 -    GtkScrollbar*  scbar_v;   // Horizontal and Vertical Scrollbar
 -    GtkScrollbar*  scbar_h;   // (These are still hidden)
 -    GtkAdjustment* bar_v; // Information about document length
 -    GtkAdjustment* bar_h; // and scrolling position
 +    GtkScrollbar*  scbar_v;   /* Horizontal and Vertical Scrollbar */
 +    GtkScrollbar*  scbar_h;   /* (These are still hidden) */
 +    GtkAdjustment* bar_v; /* Information about document length */
 +    GtkAdjustment* bar_h; /* and scrolling position */
      WebKitWebView* web_view;
      gchar*         main_title;
  
@@@ -93,12 -93,6 +93,6 @@@ typedef struct 
      gchar          *socket_path;
      /* stores (key)"variable name" -> (value)"pointer to this var*/
      GHashTable     *proto_var;
-     /* command parsing regexes */
-     GRegex         *set_regex;
-     GRegex         *act_regex;
-     GRegex         *keycmd_regex;
-     GRegex         *get_regex;
-     GRegex         *bind_regex;
      gchar          *sync_stdout;
  } Communication;
  
@@@ -155,7 -149,6 +149,7 @@@ typedef struct 
      guint    font_size;
      guint    monospace_size;
      guint    minimum_font_size;
 +    gfloat   zoom_level;
      guint    disable_plugins;
      guint    disable_scripts;
      guint    autoload_img;    
      guint    mode;  
      gchar*   base_url;
      gchar*   html_endmarker;
+     gchar*   insert_indicator;
+     gchar*   cmd_indicator;
      GString* html_buffer;
      guint    html_timeout;  
  
@@@ -247,6 -242,9 +243,9 @@@ setup_signal(int signe, sigfunc *shandl
  static gboolean
  set_var_value(gchar *name, gchar *val);
  
+ static void
+ print(WebKitWebView *page, GArray *argv);
  static gboolean
  new_window_cb (WebKitWebView *web_view, WebKitWebFrame *frame, WebKitNetworkRequest *request, WebKitWebNavigationAction *navigation_action, WebKitWebPolicyDecision *policy_decision, gpointer user_data);
  
@@@ -305,6 -303,18 +304,18 @@@ static voi
  new_window_load_uri (const gchar * uri);
  
  static void
+ chain (WebKitWebView *page, GArray *argv);
+ static void
+ keycmd (WebKitWebView *page, GArray *argv);
+ static void
+ keycmd_nl (WebKitWebView *page, GArray *argv);
+ static void
+ keycmd_bs (WebKitWebView *page, GArray *argv);
+ static void
  close_uzbl (WebKitWebView *page, GArray *argv);
  
  static gboolean
@@@ -327,9 -337,6 +338,6 @@@ static voi
  parse_command(const char *cmd, const char *param);
  
  static void
- runcmd(WebKitWebView *page, GArray *argv);
- static void
  parse_cmd_line(const char *ctl_line);
  
  static gchar*
@@@ -418,11 -425,26 +426,26 @@@ static voi
  set_var(WebKitWebView *page, GArray *argv);
  
  static void
+ act_bind(WebKitWebView *page, GArray *argv);
+ static void
+ act_dump_config();
+ static void
  render_html();
  
  static void
  set_timeout(int seconds);
  
+ static void
+ dump_var_hash(gpointer k, gpointer v, gpointer ud);
+ static void
+ dump_key_hash(gpointer k, gpointer v, gpointer ud);
+ static void
+ dump_config();
  
  /* Command callbacks */
  static void
@@@ -452,15 -474,10 +475,15 @@@ cmd_max_conns()
  static void
  cmd_max_conns_host();
  
 +/* exported WebKitWebSettings properties */
 +
  static void
  cmd_font_size();
  
  static void
 +cmd_zoom_level();
 +
 +static void
  cmd_disable_plugins();
  
  static void