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)
19 files changed:
AUTHORS
Makefile
README
docs/FAQ
docs/INSTALL
examples/configs/sampleconfig
examples/configs/sampleconfig-dev
examples/data/style.css [new file with mode: 0644]
examples/scripts/clipboard.sh
examples/scripts/cookies.sh
examples/scripts/formfiller.pl
examples/scripts/formfiller.sh
examples/scripts/linkfollow.js
examples/scripts/load_url_from_bookmarks.sh
examples/scripts/load_url_from_history.sh
examples/scripts/yank.sh
uzbl.c
uzbl.h
uzblctrl.c

diff --git a/AUTHORS b/AUTHORS
index 2212a87..24597f1 100644 (file)
--- a/AUTHORS
+++ b/AUTHORS
@@ -3,11 +3,11 @@ Developers:
     Dieter Plaetinck (Dieter@be) <email is dieter AT plaetinck.be>
     Dusan Popovic (dusanx)
     Michael Walker (Barrucadu) <email is mike AT barrucadu.co.uk>
-    Přemysl Hrubý, (anydot) <email is dfenze AT gmail.com>
+    Přemysl Hrubý (anydot) <email is dfenze AT gmail.com>
     Robert Manea (robm) <email is rob DOT manea AT gmail DOT com>
+    Henri Kemppainen (DuClare) <email is akarinotengoku AT THE DOMAIN OF gmail.com> 
 
 Contributors:
-    (DuClare) - Various improvements
     Zane Ashby (HashBox) - Rewrote FIFO interface. Fixed various bugs.
     (sentientswitch) - Cleaned up code. Added some commands.
     Jan Kolkmeier (jouz) - scrolling, link following
@@ -17,6 +17,7 @@ Contributors:
     (salinasv) - move some variables to heap
     Sylvester Johansson (scj) - form filler script & different take on link follower 
     (mxf) - uzblcat
+    Mark Nevill - misc patches
 
 Originaly based on http://trac.webkit.org/browser/trunk/WebKitTools/GtkLauncher/main.c
 Which is  copyrighted:
index f8277fb..40b395c 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -2,6 +2,8 @@ CPPFLAGS=$(shell pkg-config --cflags gtk+-2.0 webkit-1.0) -ggdb -Wall -pedantic
 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 @@ 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
diff --git a/README b/README
index 71cdcfa..4f394bd 100644 (file)
--- a/README
+++ b/README
@@ -83,62 +83,35 @@ When uzbl forks a new instance (eg "open in new window") it will use the same co
 If you made changes to the configuration at runtime, these are not pased on to the child.
 
 ### COMMAND SYNTAX
-Commands are used for:
-
-* creating keybindings
-* altering variables
-* getting the values of variables
-* running actions
-* setting the input buffer
-
 Uzbl will read commands via standard input, named fifo pipe (if `fifo_dir` is set) and IPC socket (when `socket_dir` is set).
 For convenience, uzbl can also be instructed to read commands from a file on startup by using the `-c` option.  Indeed, the config file is nothing more than a list of commands.
 
 Each command starts with the name of the command, which must be the first thing on a line; preceding whitespace is not allowed.
-A command is terminated by a newline.  Empty lines and lines that start with the hash sign are ignored by the parser.  Command names are not case sensitive.
+A command is terminated by a newline.  Empty lines and lines that start with the hash sign are ignored by the parser.  Command names are always written in lowercase.
 
 The following commands are recognized:
 
-    SET <key> = <value>
-Set is used for changing variables.  Every variable can be changed on the fly and for some variables, some additional logic is performed.
-For example, setting the variable `uri` will make uzbl start loading it, and changing the format of the statusbar/windowtitle/user agent/.. will be effective immediately.
-If you want to unset a string, use SET with one space after the equals sign.
-
-    GET <key>
-Use this to print the value of a key. (and TODO, get the value through the socket)
-
-    BIND <string> = <action>
-Makes the character sequence `<string>` invoke `<action>` when typed interactively in uzbl.
-There are a few tricks you can do:
-
-* `<string>` ends with an underscore: the action will only be invoked after pressing return/enter. If the user enters text where `<string>` has the underscore, `%s` in the `<action>` string will be replaced by this text. (optional)
-* `<string>` ends with an asterisk: similar behavior as with an underscore, but also makes the binding incremental (i.e. the action will be invoked on every keystroke).
-* `<string>` ends on a different character: you need to type the full string, which will trigger the action immediately, without pressing enter/return.
-
-Examples:
-
-    # uzbl will load the url when you type: 'o <url><enter>'
-    bind o _ = uri %s
-    # a search action which is called on every character typed after the slash, letting you see the search narrow down while typing.
-    #  Hitting return, enter or esc will terminate the search.
-    bind /*  = search %s
-    # when you type `ZZ` and nothing else, the exit action will be triggered immediately.
-    bind ZZ  = exit
-
-    ACT <action>
-This tells uzbl to execute an action immediately.  The simplest example of this would be `act exit`; you know what that'll do.
-
-    KEYCMD <string>
-This sets the interactive command buffer to `<string>`.  Keycmd is primarily useful for scripts that help you type a command while still letting you edit it before execution.
-For example, if you have a binding like "o _" that opens an URL, then you could create a binding `O` that spawns a script which will set the command buffer to "o current-uri-here", letting you enter relative URLs easily.
-
-    KEYCMDN <string>
-Like KEYCMD, but also emulates a press of return which causes binds with an asterisk or underscore to execute.
-(See sample config)
-
-### ACTIONS
-Actions are invoked via bindings and by the ACT command.  Most actions are self-explanatory, though a few need to be clarified.  A list of
-actions follows:
+* `set <key> = <value>`
+   - used for changing variables on the fly
+   - the changes are effective immediately; for example, setting the variable `uri` will make uzbl start loading, and changing `status_format` will make the status bar react immediately
+   - if you want to unset a string, use `set` with one space after the equals sign
+* `get <key>`
+   - use this to print the value of a variable. (and TODO, get the value through the socket)
+* `bind <string> = <command>`
+   - sets the character sequence `<string>` to invoke `<command>` when typed interactively in uzbl
+   - there are a few tricks you can do:
+       * `<string>` ends with an underscore: the command will only be invoked after pressing return/enter. If the user enters text where `<string>` has the underscore, `%s` in the `<command>` string will be replaced by this text. (optional)
+       * `<string>` ends with an asterisk: similar behavior as with an underscore, but also makes the binding incremental (i.e. the command will be invoked on every keystroke).
+       * `<string>` ends on a different character: you need to type the full string, which will trigger the command immediately, without pressing enter/return.
+   - examples:
+
+        # uzbl will load the url when you type: 'o <url><enter>'
+        bind o _ = uri %s
+        # a search command which is called on every character typed after the slash, letting you see the search narrow down while typing.
+        #  Hitting return, enter or esc will terminate the search.
+        bind /*  = search %s
+        # when you type `ZZ` and nothing else, the exit command will be triggered immediately.
+        bind ZZ  = exit
 
 * `back`
 * `forward`
@@ -156,7 +129,7 @@ actions follows:
 * `uri <address>`
 * `js <body>`
    - execute the javascript in `<body>`
-   - remember that the commands, and thus actions, must not contain line breaks
+   - remember that the commands must not contain line breaks
 * `script <file>`
    - execute the javascript in `<file>`
 * `toggle_status`
@@ -167,14 +140,25 @@ actions follows:
 * `sh <command>`
    - runs a shell command by expanding `%s` in the `shell_cmd` variable with the specified command; primarily useful as a shortcut for `spawn sh -c <body>`
    - note that the arguments as specified in "EXTERNAL SCRIPTS" are appended at the end, so the argument numbers will be higher.
+* `sync_spawn <executable> <additional args>`
+* `sync_sh <command>`
+   - these are synchronous variants of `spawn` and `sh`, which means uzbl will wait for them to return
+   - you should only need to use these manually if you want to use a chain command in a handler that wants output from the command it runs
 * `exit`
 * `search <string>`
 * `search_reverse <string>`
    - search with no string will search for the next/previous occurrence of the string previously searched for
 * `toggle_insert_mode <optional state>`
    - if the optional state is 0, disable insert mode. If 1, enable insert mode.
-* `runcmd`
-   - can be used for running a command such as SET or BIND
+* `keycmd <string>`
+* `keycmd_nl <string>`
+   - keycmd sets the interactive command buffer to `<string>`.  If the given string is a valid binding, it will execute.  `Keycmd_nl` is like `keycmd`, but it also emulates a press of return, causing bindings with a parameter to execute.  For example, `keycmd_nl o google.com` would load the said url if you have a binding like `bind o _ = uri %s`.
+* `keycmd_bs`
+   - erase (backspace) one character from the command buffer
+* `chain <command> <command> ..`
+   - use for chaining multiple commands
+   - remember to quote the commands; one command must come as one parameter
+   - if you use `chain` with a handler script which must return some output (such as a cookie handler -- uzbl will wait for and use its output), use sync_spawn or sync_sh instead of spawn or sh in the command that should give the output
 
 
 ### VARIABLE REPLACEMENT
index b5a6323..7286ec7 100644 (file)
--- a/docs/FAQ
+++ b/docs/FAQ
@@ -64,12 +64,19 @@ Note that we do *not* depend on any Gnome libraries such as gconf.  _That_ would
 ### Do you support flash? javascript? Ajax?  Recent html/css/.. standards?
 Yes, Webkit takes care of all of that.  Not that we like all of these, but you can use them if you want.
 
+### What's the difference between the socket file and the fifo?
+They both have advantages and disadvantages:
+
+ * fifo's are _very_ easy to work with. You can write just plaintext commands into them, but they are unidirectional (you can only communicate in one direction)
+ * Sockets are bidirectional but more complex.  You cannot just write a plaintext string into them.  In shellscripts you can use uzblctrl or netcat to work with sockets, when programming you need to use library functions.
+
+So, when writing scripts, using fifo's is usually the fastest method (because you do not need to fork another process), so fifo is preferred unless you need a response.
+
 ### Does the world really need another browser?
 We did try a lot of browsers, and we do not suffer [NIH](http://en.wikipedia.org/wiki/Not_Invented_Here).
 We believe that the approach taken by way too many browsers is wrong.  We do not want browsers that try to do everything,
 instead we prefer a system where different applications work together, which gives plenty of advantages.
 We also like open source.  We take a lot of things from other projects and we also try to contribute to other projects.
 
-
 ### What? You call all of this user-friendly?
 Yes.  If you don't agree, don't use it :)
index 3453e03..1c0d007 100644 (file)
@@ -1,11 +1,13 @@
-Arch Linux
-----------
+Packages
+--------
 [Arch Linux](http://www.archlinux.org) is our distro of choice, and the distro we use for testing.
 
 You can find a [PKGBUILD](http://aur.archlinux.org/packages.php?ID=25972) on the AUR, which installs the latest
 from the master branch. You can edit the PKGBUILD to change to any other
 branch you want.
 
+For other distros, see [uzbl.org/wiki/howtos](http://www.uzbl.org/wiki/howtos)
+
 From source
 -----------
 You can pull the code from git or get a tagged tarball.
index 603ee0f..ce36fa6 100644 (file)
@@ -2,13 +2,13 @@
 # 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
@@ -90,14 +90,14 @@ bind    B         = spawn /usr/share/uzbl/examples/scripts/insert_bookmark.sh
 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
@@ -105,7 +105,7 @@ bind    S         = js alert("hi");
 # 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)
index 3b1c069..939fa7e 100644 (file)
@@ -2,13 +2,13 @@
 # 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
@@ -60,7 +60,7 @@ set shell_cmd         = sh -c
 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 @@ set title_format_long = KEYCMD MODE TITLE - Uzbl browser <NAME> > SELECTED_URI
 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 @@ bind    B         = spawn ./examples/scripts/insert_bookmark.sh
 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
@@ -142,8 +143,7 @@ bind    S         = js alert("hi");
 # 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 --git a/examples/data/style.css b/examples/data/style.css
new file mode 100644 (file)
index 0000000..de0a38b
--- /dev/null
@@ -0,0 +1,26 @@
+.uzbl_highlight { background-color: yellow;}
+.uzbl_h_first   { background-color: lightgreen;}
+
+.uzbl_follow    { border-style:     dotted;
+                  border-width:     thin;
+}
+
+#uzbl_hint > div    { 
+       display:                        inline;
+       border:                         2px solid #4a6600;
+       background-color:               #b9ff00;
+       color:                          black;
+       font-size:                      9px;
+       font-weight:                    bold;
+       line-height:                    9px;
+       margin:                         0px;
+       padding:                        0px;
+       position:                       absolute;
+       z-index:                        1000;
+       -webkit-border-radius:          6px;
+       text-decoration:                none;
+       -wekit-transform:               scale(1) rotate(0deg) translate(-6px,-5px);
+}
+
+/* vim:set et ts=4: */
+
index e13f053..c64b65c 100755 (executable)
@@ -9,7 +9,7 @@ selection=$(xclip -o)
 
 case $action in
   "yank" ) echo -n "$url" | xclip;;
-  "goto" ) echo "act uri $selection" > "$fifo";;
+  "goto" ) echo "uri $selection" > "$fifo";;
   * ) echo "clipboard.sh: invalid action";;
 esac
 
index cd449dc..efac322 100755 (executable)
@@ -1,4 +1,7 @@
 #!/bin/bash
+
+# THIS IS EXPERIMENTAL AND COULD BE INSECURE !!!!!!
+
 # this is an example script of how you could manage your cookies..
 # we use the cookies.txt format (See http://kb.mozillazine.org/Cookies.txt)
 # This is one textfile with entries like this:
 # http://kb.mozillazine.org/Cookies.txt
 # don't always append cookies, sometimes we need to overwrite
 
-if [ -f /usr/share/uzbl/examples/configs/cookies ]
-then
-       file=/usr/share/uzbl/examples/configs/cookies
-else
-       file=./examples/configs/cookies #useful when developing
-fi
-
-#cookie_file=$XDG_DATA_HOME/uzbl/cookies.txt
-cookie_file=./examples/data/cookies.txt
-
+[ -f /usr/share/uzbl/examples/configs/cookies ] && file=/usr/share/uzbl/examples/configs/cookies
+[ -f $XDG_CONFIG_HOME/uzbl/cookies            ] && file=$XDG_CONFIG_HOME/uzbl/cookies
+[ -f ./examples/configs/cookies               ] && file=./examples/configs/cookies #useful when developing
+[ -z "$file" ] && exit 1
+
+[ -d /usr/share/uzbl/examples/data ] && cookie_file=/usr/share/uzbl/examples/data/cookies.txt
+[ -d $XDG_DATA_HOME/uzbl/          ] && cookie_file=$XDG_DATA_HOME/uzbl/cookies.txt
+[ -d ./examples/data/              ] && cookie_file=./examples/data/cookies.txt #useful when developing
+[ -z "$cookie_file" ] && exit 1
+
+# if this variable is set, we will use it to inform you when and which cookies we store, and when/which we send.
+#notifier=
+#notifier=notify-send
+notify_wrapper () {
+       echo "$@" >> $HOME/cookielog
+}
+notifier=notify_wrapper
 which zenity &>/dev/null || exit 2
 
 # Example cookie:
@@ -52,6 +62,10 @@ field_name=
 field_value=
 field_exp='end_session'
 
+function notify () {
+       [ -n "$notifier" ] && $notifier "$@"
+}
+
 
 # FOR NOW LETS KEEP IT SIMPLE AND JUST ALWAYS PUT AND ALWAYS GET
 function parse_cookie () {
@@ -79,19 +93,32 @@ function parse_cookie () {
 # match cookies in cookies.txt againsh hostname and path
 function get_cookie () {
        path_esc=${path//\//\\/}
-       cookie=`awk "/^[^\t]*$host\t[^\t]*\t$path_esc/" $cookie_file 2>/dev/null | tail -n 1`
+       search="^[^\t]*$host\t[^\t]*\t$path_esc"
+       cookie=`awk "/$search/" $cookie_file 2>/dev/null | tail -n 1`
        if [ -z "$cookie" ]
        then
+               notify "Get_cookie: search: $search in $cookie_file -> no result"
                false
        else
+               notify "Get_cookie: search: $search in $cookie_file -> result: $cookie"
                read domain alow_read_other_subdomains path http_required expiration name value <<< "$cookie"
                cookie="$name=$value" 
-               #echo "COOKIE $cookie" >> $HOME/cookielog
                true
        fi
 }
 
-[ $action == PUT ] && parse_cookie && echo -e "$field_domain\tFALSE\t$field_path\tFALSE\t$field_exp\t$field_name\t$field_value" >> $cookie_file
+function save_cookie () {
+       if parse_cookie
+       then
+               data="$field_domain\tFALSE\t$field_path\tFALSE\t$field_exp\t$field_name\t$field_value"
+               notify "save_cookie: adding $data to $cookie_file"
+               echo -e "$data" >> $cookie_file
+       else
+               notify "not saving a cookie. since we don't have policies yet, parse_cookie must have returned false. this is a bug"
+       fi
+}
+
+[ $action == PUT ] && save_cookie
 [ $action == GET ] && get_cookie && echo "$cookie"
 
 exit
index a6e07a0..c590836 100755 (executable)
 # bind LE = spawn /usr/share/uzbl/examples/scripts/formfiller.pl edit
 
 use strict;
-use Switch;
+use warnings;
 
 my $keydir = $ENV{XDG_CONFIG_HOME} . "/uzbl/forms";
-my ($config,$pid,$xid,$fifo,$socket,$url,$title,$cmd) = @ARGV;
-if($fifo eq "") { die "No fifo"; };
+my ($config,$pid,$xid,$fifoname,$socket,$url,$title,$cmd) = @ARGV;
+if (!defined $fifoname || $fifoname eq "") { die "No fifo"; }
 
 sub domain {
   my ($url) = @_;
@@ -41,29 +41,29 @@ my %command;
 
 $command{load} = sub {
   my ($domain) = @_;
-  my $file = "$keydir/$domain";
-  if( -e $file){
-    open(FH,$file);
-    my (@lines) = <FH>;
-    close(FH);
+  my $filename = "$keydir/$domain";
+  if (-e $filename){
+    open(my $file, $filename) or die "Failed to open $filename: $!";
+    my (@lines) = <$file>;
+    close($file);
     $|++;
-    open(FIFO,">>$fifo");
-    print "opened $fifo\n";
+    open(my $fifo, ">>", $fifoname) or die "Failed to open $fifoname: $!";
     foreach my $line (@lines) {
-        if($line !~ m/^#/){
-          my ($type,$name,$value) = ($line =~ /\s*(\w+)\s*\|\s*(.*?)\s*\|\s*(.*?)\s*$/);
-          switch ($type) {
-            case ""         {}
-            case "checkbox" { printf FIFO 'act js document.getElementsByName("%s")[0].checked = %s;',  $name, $value}
-            case "submit"   { printf FIFO 'act js function fs (n) {try{n.submit()} catch (e){fs(n.parentNode)}}; fs(document.getElementsByName("%s")[0]);', $name }
-            else            { printf FIFO 'act js document.getElementsByName("%s")[0].value = "%s";',  $name, $value}
-          }
-
-        print FIFO "\n";
+      next if ($line =~ m/^#/);
+      my ($type,$name,$value) = ($line =~ /^\s*(\w+)\s*\|\s*(.*?)\s*\|\s*(.*?)\s*$/);
+      if ($type eq "checkbox")
+      {
+        printf $fifo 'js document.getElementsByName("%s")[0].checked = %s;', $name, $value;
+      } elsif ($type eq "submit")
+      {
+        printf $fifo 'js function fs (n) {try{n.submit()} catch (e){fs(n.parentNode)}}; fs(document.getElementsByName("%s")[0]);', $name;
+      } elsif ($type ne "")
+      {
+        printf $fifo 'js document.getElementsByName("%s")[0].value = "%s";', $name, $value;
       }
+      print $fifo "\n";
     }
     $|--;
-    close(FIFO);
   } else {
     $command{new}->($domain);
     $command{edit}->($domain);
@@ -76,24 +76,24 @@ $command{edit} = sub {
     system ($editor, $file);
   } else {
     $command{new}->($domain);
-}
+  }
 };
 $command{new} = sub {
   my ($domain) = @_;
-  my $file = "$keydir/$domain";
-  open(FILE,">>$file");
+  my $filename = "$keydir/$domain";
+  open (my $file,">>", $filename) or die "Failed to open $filename: $!";
   $|++;
-  print FILE "#make sure that there are no extra submits, since it may trigger the wrong one\n";
-  printf FILE "#%-10s | %-10s | %s\n", @fields;
-  print FILE "#------------------------------\n";
+  print $file "# Make sure that there are no extra submits, since it may trigger the wrong one.\n";
+  printf $file "#%-10s | %-10s | %s\n", @fields;
+  print $file "#------------------------------\n";
   my @data = `$downloader $url`;
   foreach my $line (@data){
     if($line =~ m/<input ([^>].*?)>/i){
-      $line =~ s/.*(<input ([^>].*?)>).*/\1/;
-      printf FILE " %-10s | %-10s | %s\n", map { my ($r) = $line =~ /.*$_=["'](.*?)["']/;$r } @fields;
+      $line =~ s/.*(<input ([^>].*?)>).*/$1/;
+      printf $file " %-10s | %-10s | %s\n", map { my ($r) = $line =~ /.*$_=["'](.*?)["']/;$r } @fields;
     };
   };
-  close(FILE);
   $|--;
 };
+
 $command{$cmd}->(domain($url));
index 45cde69..5debcce 100755 (executable)
@@ -49,7 +49,7 @@ domain=$(echo $url | sed -re 's|(http\|https)+://([A-Za-z0-9\.]+)/.*|\2|')
 if [ "$action" = 'load' ]
 then
        [[ -e $keydir/$domain ]] || exit 2
-       gawk -F': ' '{ print "act js document.getElementsByName(\"" $1 "\")[0].value = \"" $2 "\";"}' $keydir/$domain >> $fifo
+       gawk -F': ' '{ print "js document.getElementsByName(\"" $1 "\")[0].value = \"" $2 "\";"}' $keydir/$domain >> $fifo
 else
        if [ "$action" == 'new' ]
        then
index 9b7d811..b90b82d 100644 (file)
 // requires http://github.com/DuClare/uzbl/commit/6c11777067bdb8aac09bba78d54caea04f85e059
 //
 // first, it needs to be loaded before every time it is used.
-// One way would be to use something like load_start_handler to send
-// "act script link_follower.js"
+// One way would be to use the load_commit_handler:
+// set load_commit_handler = sh 'echo "script /usr/share/uzbl/examples/scripts/linkfollow.js" > "$4"'
 //
 // when script is loaded, it can be invoked with
-// bind f* = js setHints("%s")
-// bind f_ = js followLink("%s")
+// bind f* = js hints.set("%s",   hints.open)
+// bind f_ = js hints.follow("%s",hints.open)
+//
+// At the moment, it may be useful to have way of forcing uzbl to load the script
+// bind :lf = script /usr/share/uzbl/examples/scripts/linkfollow.js
+//
+// The default style for the hints are pretty ugly, so it is recommended to add the following
+// to config file
+// set stylesheet_uri = /usr/share/uzbl/examples/data/style.css
 //
 // based on follow_Numbers.js
 //
-// TODO: add classes to hinted elements
+// TODO: fix styling for the first element
+// TODO: emulate mouseover events when visiting some elements
+// TODO: rewrite the element->action handling
+
+
+function Hints(){
+
+  // Settings
+  ////////////////////////////////////////////////////////////////////////////
 
+  // if set to true, you must explicitly call hints.follow(), otherwise it will
+  // follow the link if there is only one matching result
+  var requireReturn = true;
 
-var uzblid = 'uzbl_hint';
-var uzblclass = 'uzbl_hint_class'
+  // Case sensitivity flag
+  var matchCase = "i";
 
-var doc = document;
+  // For case sensitive matching, uncomment:
+  // var matchCase = "";
 
-function elementPosition(el) {
+
+  var uzblid = 'uzbl_hint';
+  var uzblclass = 'uzbl_highlight';
+  var uzblclassfirst = 'uzbl_h_first';
+  var doc = document;
+  var visible = [];
+  var hintdiv;
+
+  this.set = hint;
+  this.follow = follow;
+  this.keyPressHandler = keyPressHandler;
+
+  function elementPosition(el) {
     var up = el.offsetTop;
     var left = el.offsetLeft; var width = el.offsetWidth;
     var height = el.offsetHeight;
 
     while (el.offsetParent) {
-        el = el.offsetParent;
-        up += el.offsetTop;
-        left += el.offsetLeft;
+      el = el.offsetParent;
+      up += el.offsetTop;
+      left += el.offsetLeft;
     }
-    return [up, left, width, height];
-}
+    return {up: up, left: left, width: width, height: height};
+  }
 
-function generateHint(el, label) {
-    var hint = doc.createElement('div');
-    hint.setAttribute('class', uzblclass);
-    hint.innerText = label;
-    hint.style.display = 'inline';
-    hint.style.backgroundColor = '#B9FF00';
-    hint.style.border = '2px solid #4A6600';
-    hint.style.color = 'black';
-    hint.style.fontSize = '9px';
-    hint.style.fontWeight = 'bold';
-    hint.style.lineHeight = '9px';
-    hint.style.margin = '0px';
-    hint.style.padding = '1px';
-    hint.style.position = 'absolute';
-    hint.style.zIndex = '10000';
-    hint.style.textDecoration = 'none';
-    hint.style.webkitBorderRadius = '6px';
-    // Play around with this, pretty funny things to do :)
-    hint.style.webkitTransform = 'scale(1) rotate(0deg) translate(-6px,-5px)';
-    return hint;
-}
+  function elementInViewport(p) {
+    return  (p.up < window.pageYOffset + window.innerHeight && 
+            p.left < window.pageXOffset + window.innerWidth && 
+            (p.up + p.height) > window.pageYOffset && 
+            (p.left + p.width) > window.pageXOffset);
+  }
 
-function elementInViewport(el) {
-    offset = elementPosition(el);
-    var up = offset[0];
-    var left = offset[1];
-    var width = offset[2];
-    var height = offset[3];
-    return (up < window.pageYOffset + window.innerHeight && 
-                               left < window.pageXOffset + window.innerWidth 
-                               && (up + height) > window.pageYOffset 
-                               && (left + width) > window.pageXOffset);
-}
+  function isVisible(el) {
+    if (el == doc) { return true; }
+    if (!el) { return false; }
+    if (!el.parentNode) { return false; }
+    if (el.style) {
+      if (el.style.display == 'none') {
+          return false;
+      }
+      if (el.style.visibility == 'hidden') {
+          return false;
+      }
+    }
+    return isVisible(el.parentNode);
+  }
 
-function isVisible(el) {
-
-                       if (el == doc) { return true; }
-                       if (!el) { return false; }
-                       if (!el.parentNode) { return false; }
-                       if (el.style) {
-                                       if (el.style.display == 'none') {
-                                                       return false;
-                                       }
-                                       if (el.style.visibility == 'hidden') {
-                                                       return false;
-                                       }
-                       }
-                       return isVisible(el.parentNode);
-}
+  // the vimperator defaults minus the xhtml elements, since it gave DOM errors
+  var hintable = " //*[@onclick or @onmouseover or @onmousedown or @onmouseup or @oncommand or @class='lk' or @role='link' or @href] | //input[not(@type='hidden')] | //a | //area | //iframe | //textarea | //button | //select";
 
-var hintable = "//a[@href] | //img | //input";
-
-function Matcher(str){
-       var numbers = str.replace(/[^\d]/g,"");
-       var words = str.replace(/\d/g,"").split(/\s+/).map(function (n) { return new RegExp(n,"i")});
-       this.test = test;
-       this.toString = toString;
-       this.numbers = numbers;
-       function test(element) {
-               // test all the regexp
-               return words.every(function (regex) { return element.textContent.match(regex)});
-       }
-       function toString(){
-               return "{"+numbers+"},{"+words+"}";
-       }
-}
+  function Matcher(str){
+    var numbers = str.replace(/[^\d]/g,"");
+    var words = str.replace(/\d/g,"").split(/\s+/).map(function (n) { return new RegExp(n,matchCase)});
+    this.test = test;
+    this.toString = toString;
+    this.numbers = numbers;
+    function test(element) {
+      // test all the regexp
+      return words.every(function (regex) { return element.node.textContent.match(regex)});
+    }
+  }
 
+  function HintElement(node,pos){
 
-function setHints(r){
-       if(doc.body) doc.body.setAttribute("onkeyup","keyPressHandler(event)");
-       var re = new Matcher(r);
-       clearHints();
-       var c = 1;
-       var items = doc.evaluate(hintable,doc,null,XPathResult.ORDERED_NODE_SNAPSHOT_TYPE,null);
-       for (var i = 0; i < items.snapshotLength;i++){
-               var item = items.snapshotItem(i);
-               if(re.test(item) && isVisible(item) && elementInViewport(item)){
-                       var h = generateHint(item,c);
-                       item.appendChild(h);
-                       c++;
-               }
-       }
-}
+    this.node = node;
+    this.isHinted = false;
+    this.position = pos;
+    this.num = 0;
 
-function clearHints(){
-       var items = doc.evaluate("//div[@class='" + uzblclass + "']",doc,null,XPathResult.ORDERED_NODE_SNAPSHOT_TYPE,null);
-       for (var i = 0; i < items.snapshotLength;i++){
-               var item = items.snapshotItem(i);
-               item.parentNode.removeChild(item);
-       }
-}
+    this.addHint = function (labelNum) {
+      // TODO: fix uzblclassfirst
+      if(!this.isHinted){
+        this.node.className += " " + uzblclass;
+      }
+      this.isHinted = true;
+        
+      // create hint  
+      var hintNode = doc.createElement('div');
+      hintNode.name = uzblid;
+      hintNode.innerText = labelNum;
+      hintNode.style.left = this.position.left + 'px';
+      hintNode.style.top =  this.position.up + 'px';
+      hintNode.style.position = "absolute";
+      doc.body.firstChild.appendChild(hintNode);
+        
+    }
+    this.removeHint = function(){
+      if(this.isHinted){
+        var s = (this.num)?uzblclassfirst:uzblclass;
+        this.node.className = this.node.className.replace(new RegExp(" "+s,"g"),"");
+        this.isHinted = false;
+      }
+    }
+  }
+
+  function createHintDiv(){
+    var hintdiv = doc.getElementById(uzblid);
+    if(hintdiv){
+      hintdiv.parentNode.removeChild(hintdiv);
+    }
+    hintdiv = doc.createElement("div");
+    hintdiv.setAttribute('id',uzblid);
+    doc.body.insertBefore(hintdiv,doc.body.firstChild);
+    return hintdiv;
+  }
+
+  function init(){
+    // WHAT?
+    doc.body.setAttribute("onkeyup","hints.keyPressHandler(event)");
+    hintdiv = createHintDiv();
+    visible = [];
+
+    var items = doc.evaluate(hintable,doc,null,XPathResult.ORDERED_NODE_SNAPSHOT_TYPE,null);
+    for (var i = 0;i<items.snapshotLength;i++){
+      var item = items.snapshotItem(i);
+      var pos = elementPosition(item);
+      if(isVisible && elementInViewport(elementPosition(item))){
+        visible.push(new HintElement(item,pos));
+      }
+    }
+  }
+
+  function clear(){
+
+    visible.forEach(function (n) { n.removeHint(); } );
+    hintdiv = doc.getElementById(uzblid);
+    while(hintdiv){
+      hintdiv.parentNode.removeChild(hintdiv);
+      hintdiv = doc.getElementById(uzblid);
+    }
+  }
+
+  function update(str,openFun) {
+    var match = new Matcher(str);
+    hintdiv = createHintDiv();
+    var i = 1;
+    visible.forEach(function (n) {
+      if(match.test(n)) {
+        n.addHint(i);
+        i++;
+      } else {
+        n.removeHint();
+      }});
+    if(!requireReturn){
+      if(i==2){ //only been incremented once
+        follow(str,openFun);
+      }
+    }
+  }
+
+  function hint(str,openFun){
+    if(str.length == 0) init();
+    update(str,openFun);
+  }
 
-function keyPressHandler(e) {
+  function keyPressHandler(e) {
     var kC = window.event ? event.keyCode: e.keyCode;
     var Esc = window.event ? 27 : e.DOM_VK_ESCAPE;
     if (kC == Esc) {
-        clearHints();
-                               doc.body.removeAttribute("onkeyup");
+        clear();
+        doc.body.removeAttribute("onkeyup");
+    }
+  }
+
+  this.openNewWindow = function(item){
+    // TODO: this doesn't work yet
+    item.className += " uzbl_follow";
+    window.open(item.href,"uzblnew","");
+  }
+  this.open = function(item){
+    simulateMouseOver(item);
+    item.className += " uzbl_follow";
+    window.location = item.href;
+  }
+
+  function simulateMouseOver(item){
+    var evt = doc.createEvent("MouseEvents");
+    evt.initMouseEvent("MouseOver",true,true,
+        doc.defaultView,1,0,0,0,0,
+        false,false,false,false,0,null);
+    return item.dispatchEvent(evt);
+  }
+
+
+  function follow(str,openFunction){
+    var m = new Matcher(str);
+    var items = visible.filter(function (n) { return n.isHinted });
+    clear();
+    var num = parseInt(m.numbers,10);
+    if(num){
+      var item = items[num-1].node;
+    } else {
+      var item = items[0].node;
     }
-}
-function followLink(follow){
-       var m = new Matcher(follow);
-       var elements = doc.evaluate("//*/div[@class='"+uzblclass+"']",doc,null,XPathResult.ORDERED_NODE_SNAPSHOT_TYPE,null);
-       // filter
-       var matched = [];
-       for (var i = 0; i < elements.snapshotLength;i++){
-               var item = elements.snapshotItem(i);
-               if(m.test(item.parentNode)){
-                       matched.push(item.parentNode);
-               }
-       }
-       clearHints();
-       if(matched.length == 1) {
-               var item = matched[0];
-       } else {
-               var item = matched[parseInt(m.numbers,10)-1];
-       }
     if (item) {
-                       item.style.backgroundColor = "blue";
-
-        var name = item.tagName;
-        if (name == 'A') {
-            if(item.click) {item.click()};
-            window.location = item.href;
-        } else if (name == 'INPUT') {
-            var type = item.getAttribute('type').toUpperCase();
-            if (type == 'TEXT' || type == 'FILE' || type == 'PASSWORD') {
-                item.focus();
-                item.select();
-            } else {
-                item.click();
-            }
-        } else if (name == 'TEXTAREA' || name == 'SELECT') {
+      var name = item.tagName;
+      if (name == 'A') {
+        if(item.click) {item.click()};
+          openFunction(item);
+      } else if (name == 'INPUT') {
+        var type = item.getAttribute('type').toUpperCase();
+        if (type == 'TEXT' || type == 'FILE' || type == 'PASSWORD') {
             item.focus();
             item.select();
         } else {
             item.click();
-            window.location = item.href;
         }
+      } else if (name == 'TEXTAREA' || name == 'SELECT') {
+        item.focus();
+        item.select();
+      } else {
+        item.click();
+        openFunction(item);
+      }
     }
+  }
 }
+
+var hints = new Hints();
+
+// vim:set et sw=2:
+
+
index 21ea33d..1ae39ff 100755 (executable)
@@ -18,5 +18,5 @@ else
        goto=`awk '{print $1}' $file | $DMENU $COLORS`
 fi
 
-#[ -n "$goto" ] && echo "act uri $goto" > $4
-[ -n "$goto" ] && uzblctrl -s $5 -c "act uri $goto"
+#[ -n "$goto" ] && echo "uri $goto" > $4
+[ -n "$goto" ] && uzblctrl -s $5 -c "uri $goto"
index 649c6b7..37c2afc 100755 (executable)
@@ -17,5 +17,5 @@ else
        current=`tail -n 1 $history_file | awk '{print $3}'`; goto=`(echo $current; awk '{print $3}' $history_file | grep -v "^$current\$" | sort -u) | $DMENU $COLORS`
 fi 
 
-[ -n "$goto" ] && echo "act uri $goto" > $4
-#[ -n "$goto" ] && uzblctrl -s $5 -c "act uri $goto"
+[ -n "$goto" ] && echo "uri $goto" > $4
+#[ -n "$goto" ] && uzblctrl -s $5 -c "uri $goto"
index d4926be..ee140c7 100755 (executable)
@@ -2,10 +2,11 @@
 # in your uzbl config, make the first argument the number of the (later) argument you want to use (see README for list of args)
 # make the 2nd argument one of : primary, secondary, clipboard.
 # examples:
-# 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
 
 which xclip &>/dev/null || exit 1
-[ "$2" == primary -o "$2" == secondary -o "$2" == clipboard ] || exit 2
+[ "$9" == primary -o "$9" == secondary -o "$9" == clipboard ] || exit 2
 
-echo -n "${!1}" | xclip -selection $2
\ No newline at end of file
+echo echo -n "${!8}" '|' xclip -selection $9
+echo -n "${!8}" | xclip -selection $9
diff --git a/uzbl.c b/uzbl.c
index 084c354..94369b0 100644 (file)
--- a/uzbl.c
+++ b/uzbl.c
@@ -81,19 +81,20 @@ GOptionEntry entries[] =
 typedef const struct {
     void **ptr;
     int type;
+    int dump;
     void (*func)(void);
 } uzbl_cmdprop;
 
 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, cmd_load_uri)},
     { "mode",                PTR(uzbl.behave.mode,                INT, NULL)},
@@ -184,8 +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 +431,27 @@ scroll (GtkAdjustment* bar, GArray *argv) {
     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);
 }
@@ -558,8 +606,15 @@ static struct {char *name; Command command[2];} cmdlist[] =
     { "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 +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 +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 +1013,8 @@ expand_template(const char *template, gboolean escape_markup) {
                      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 +1133,9 @@ run_command (const gchar *command, const guint npre, const gchar **args,
         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 +1268,6 @@ parse_command(const char *cmd, const char *param) {
         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;
@@ -1265,7 +1361,7 @@ cmd_disable_plugins() {
 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 +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,10 +1519,12 @@ static gboolean
 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 = g_strdup(val);
         } else if (c->type == TYPE_INT) {
@@ -1443,12 +1542,6 @@ set_var_value(gchar *name, gchar *val) {
 }
 
 static void
-runcmd(WebKitWebView* page, GArray *argv) {
-    (void) page;
-    parse_cmd_line(argv_idx(argv, 0));
-}
-
-static void
 render_html() {
     Behaviour *b = &uzbl.behave;
 
@@ -1463,90 +1556,42 @@ render_html() {
 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 +1893,8 @@ key_press_cb (GtkWidget* window, GdkEventKey* event)
         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 +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 +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 ("");
@@ -2108,10 +2228,13 @@ static void handle_cookies (SoupSession *session, SoupMessage *msg, gpointer use
     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 +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 +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);
 
@@ -2269,7 +2423,10 @@ main (int argc, char* argv[]) {
     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();
@@ -2316,12 +2473,14 @@ main (int argc, char* argv[]) {
 
     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 --git a/uzbl.h b/uzbl.h
index 91421bd..1dbc552 100644 (file)
--- a/uzbl.h
+++ b/uzbl.h
@@ -93,12 +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;
 
@@ -172,6 +166,8 @@ typedef struct {
     guint    mode;  
     gchar*   base_url;
     gchar*   html_endmarker;
+    gchar*   insert_indicator;
+    gchar*   cmd_indicator;
     GString* html_buffer;
     guint    html_timeout;  
 
@@ -247,6 +243,9 @@ setup_signal(int signe, sigfunc *shandler);
 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 +304,18 @@ static void
 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 +338,6 @@ static void
 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 +426,26 @@ static void
 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
index 55a3aac..f0fe732 100644 (file)
@@ -23,7 +23,7 @@ static gchar* command;
 
 static GOptionEntry entries[] =
 {
-    { "socket",  's', 0, G_OPTION_ARG_STRING, &sockpath, "Socket path of the client uzbl", NULL },
+    { "socket",  's', 0, G_OPTION_ARG_STRING, &sockpath, "Path to the uzbl socket",        NULL },
     { "command", 'c', 0, G_OPTION_ARG_STRING, &command,  "The uzbl command to execute",    NULL },
     { NULL,       0,  0, 0,                    NULL,      NULL,                            NULL }
 };
@@ -31,7 +31,7 @@ static GOptionEntry entries[] =
 int
 main(int argc, char* argv[]) {
     GError *error = NULL;
-    GOptionContext* context = g_option_context_new ("- some stuff here maybe someday");
+    GOptionContext* context = g_option_context_new ("- utility for controlling and interacting with uzbl through its socket file"); //TODO: get stuff back from uzbl
     g_option_context_add_main_entries (context, entries, NULL);
     g_option_context_add_group        (context, gtk_get_option_group (TRUE));
     g_option_context_parse            (context, &argc, &argv, &error);
@@ -64,8 +64,7 @@ main(int argc, char* argv[]) {
         
         return 0;
     } else {
-        printf ("You need to specify the -s and -c parameters for uzblctrl to do anything of use.\n");
-        printf ("Usage: uzblctrl -s /path/to/socket -c \"command\"\n");
+        puts ("Usage: uzblctrl -s /path/to/socket -c \"command\"");
         return 1;
     }
 }