Damien Leon - misc
Peter Suschlik - backwards searching
(salinasv) - move some variables to heap
- Sylvester Johansson (scj) - original form filler script
+ Sylvester Johansson (scj) - form filler script & different take on link follower
+ (mxf) - uzblcat
Originaly based on http://trac.webkit.org/browser/trunk/WebKitTools/GtkLauncher/main.c
Which is copyrighted:
### CONFIGURATION / CONTROL:
The general idea is that uzbl by default is very bare bones. you can send it commands to update settings and perform actions, through various interfaces.
There is a limited default configuration. Please see config.h to see what it contains.
+By default, there are *no* keybinds defined at all. (Default keybinds would work counterproductive when you try to customize)
For examples of the possibilities what you can do, please see the sample config(s).
There are several interfaces to interact with uzbl:
const struct {
char *command;
} default_config[] = {
-{ "bind j = scroll_vert 20"},
-{ "bind k = scroll_vert -20"},
-{ "bind h = scroll_horz -20"},
-{ "bind l = scroll_horz 20"},
-{ "bind << = scroll_begin"},
-{ "bind >> = scroll_end"},
-{ "bind b = back"},
-{ "bind m = forward"},
-{ "bind s = stop "},
-{ "bind r = reload"},
-{ "bind R = reload_ign_cache"},
-{ "bind + = zoom_in"},
-{ "bind - = zoom_out"},
-{ "bind t = toggle_status"},
-{ "bind /* = search %s"},
-{ "bind ?* = search_reverse %s"},
-{ "bind n = search"},
-{ "bind N = search_reverse"},
-{ "bind o _ = uri %s"},
-{ "bind i = toggle_insert_mode"},
-{ "bind ZZ = exit"},
{ "set reset_command_mode = 1"},
{ "set status_format = <span background=\"darkblue\" foreground=\"white\"> MODE </span> <span background=\"red\" foreground=\"white\">KEYCMD</span> (LOAD_PROGRESS%) <b>TITLE</b> - Uzbl browser"},
{ "set title_format_long = KEYCMD MODE TITLE - Uzbl browser <NAME> > SELECTED_URI"},
---
### I just installed uzbl but it doesn't do much. What now?
-Uzbl does not create a default config file on startup like some other programs do.
+Uzbl includes very limited default settings (statusbar settings, but no keybinds, history/download handlers etc.)
+Look at /usr/share/uzbl/docs/config.h to see the default settings.
+Neither does uzbl create a default config file on startup like some other programs do.
Because we want to give you the freedom to place your config where you want, and to use a config or not.
-Uzbl includes *some* default settings hardcoded, but these are rather limited (some navigation keybinds, statusbar settings, but no history/download handlers etc.)
-Look at config.h to see the default settings.
-Have a look in /usr/share/uzbl/examples/configs to see what you can do. You will probably want to create your own config based on an example config.
+Have a look in /usr/share/uzbl/examples/configs to see what you can do. You will probably want to create your own config based on an example config
+so you can add keybinds and to use scripts.
Use the --config parameter or save your config as $XDG\_CONFIG\_HOME/uzbl/config to have it auto-loaded.
### Where is the location bar? How do I change the URL ?
bind zn = spawn ./examples/scripts/formfiller.sh new
bind zl = spawn ./examples/scripts/formfiller.sh load
+# other - more advanced - implementation using perl: (could not get this to run - Dieter )
+bind LL = spawn ./examples/scripts/formfiller.pl load
+bind LN = spawn ./examples/scripts/formfiller.pl new
+bind LE = spawn ./examples/scripts/formfiller.pl edit
+
# we ship some javascripts to do keyboard based link hinting/following. (webkit does not have C DOM bindings yet)
# this is similar to how it works in vimperator (and konqueror)
# TODO: did we resolve: "no click() event for hyperlinks so no referrer set" ?
--- /dev/null
+#!/usr/bin/perl
+
+# a slightly more advanced form filler
+#
+# uses settings file like: $keydir/<domain>
+
+# user arg 1:
+# edit: force editing of the file (fetches if file is missing)
+# load: fill forms from file (fetches if file is missing)
+# new: fetch new file
+
+# usage example:
+# bind LL = spawn /usr/share/uzbl/examples/scripts/formfiller.pl load
+# bind LN = spawn /usr/share/uzbl/examples/scripts/formfiller.pl new
+# bind LE = spawn /usr/share/uzbl/examples/scripts/formfiller.pl edit
+
+use strict;
+use Switch;
+
+my $keydir = $ENV{XDG_CONFIG_HOME} . "/uzbl/forms";
+my ($config,$pid,$xid,$fifo,$socket,$url,$title,$cmd) = @ARGV;
+if($fifo eq "") { die "No fifo"; };
+
+sub domain {
+ my ($url) = @_;
+ $url =~ s#http(s)?://([A-Za-z0-9\.-]+)(/.*)?#$2#;
+ return $url;
+};
+
+my $editor = "xterm -e vim";
+#my $editor = "gvim";
+
+# ideally, there would be some way to ask uzbl for the html content instead of having to redownload it with
+# Also, you may need to fake the user-agent on some sites (like facebook)
+ my $downloader = "curl -A 'Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.0.10) Gecko/2009042810 GranParadiso/3.0.10' ";
+#my $downloader = "curl -s";
+
+my @fields = ("type","name","value");
+
+my %command;
+
+$command{load} = sub {
+ my ($domain) = @_;
+ my $file = "$keydir/$domain";
+ if( -e $file){
+ open(FH,$file);
+ my (@lines) = <FH>;
+ close(FH);
+ $|++;
+ open(FIFO,">>$fifo");
+ print "opened $fifo\n";
+ 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";
+ }
+ }
+ $|--;
+ close(FIFO);
+ } else {
+ $command{new}->($domain);
+ $command{edit}->($domain);
+ }
+};
+$command{edit} = sub {
+ my ($domain) = @_;
+ my $file = "$keydir/$domain";
+ if(-e $file){
+ system ($editor, $file);
+ } else {
+ $command{new}->($domain);
+}
+};
+$command{new} = sub {
+ my ($domain) = @_;
+ my $file = "$keydir/$domain";
+ open(FILE,">>$file");
+ $|++;
+ 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;
+ };
+ };
+ close(FILE);
+ $|--;
+};
+$command{$cmd}->(domain($url));
--- /dev/null
+// link follower for uzbl
+// 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"
+//
+// when script is loaded, it can be invoked with
+// bind f* = js setHints("%s")
+// bind f_ = js followLink("%s")
+//
+// based on follow_Numbers.js
+//
+// TODO: add classes to hinted elements
+
+
+var uzblid = 'uzbl_hint';
+var uzblclass = 'uzbl_hint_class'
+
+var doc = document;
+
+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;
+ }
+ return [up, left, width, 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(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);
+}
+
+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 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++;
+ }
+ }
+}
+
+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);
+ }
+}
+
+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");
+ }
+}
+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') {
+ item.focus();
+ item.select();
+ } else {
+ item.click();
+ window.location = item.href;
+ }
+ }
+}
--- /dev/null
+#!/usr/bin/env perl
+# uzblcat - safely push html to uzbl
+# See http://www.uzbl.org/wiki/html-mode
+use strict; use warnings;
+
+my $html;
+local $/; # slurp files
+# automagically choose to read from stdin/files/...
+$html .= $_ for <>;
+
+my $endmarker = rand;
+$endmarker .= rand() while $html =~ /^\Q$endmarker\E$/m;
+
+print "set base_url = $ENV{BASE_URL}\n" if $ENV{BASE_URL};
+print << "EOS";
+set html_endmarker = $endmarker
+set mode = 1
+$html
+$endmarker
+EOS
{ "exit", {close_uzbl, 0} },
{ "search", {search_forward_text, NOSPLIT} },
{ "search_reverse", {search_reverse_text, NOSPLIT} },
+ { "dehilight", {dehilight, 0} },
{ "toggle_insert_mode", {toggle_insert_mode, 0} },
{ "runcmd", {runcmd, NOSPLIT} },
{ "set", {set_var, NOSPLIT} }
}
static void
+dehilight (WebKitWebView *page, GArray *argv) {
+ (void) argv;
+ webkit_web_view_set_highlight_text_matches (page, FALSE);
+}
+
+
+static void
new_window_load_uri (const gchar * uri) {
GString* to_execute = g_string_new ("");
g_string_append_printf (to_execute, "%s --uri '%s'", uzbl.state.executable_path, uri);
if (event->keyval == GDK_Escape) {
g_string_truncate(uzbl.state.keycmd, 0);
update_title();
+ dehilight(uzbl.gui.web_view, NULL);
return TRUE;
}
static void
set_up_inspector() {
GUI *g = &uzbl.gui;
- WebKitWebSettings *settings = webkit_web_settings_new();
+ WebKitWebSettings *settings = view_settings();
g_object_set(G_OBJECT(settings), "enable-developer-extras", TRUE, NULL);
- webkit_web_view_set_settings(WEBKIT_WEB_VIEW(uzbl.gui.web_view), settings);
-
uzbl.gui.inspector = webkit_web_view_get_inspector(uzbl.gui.web_view);
g_signal_connect (G_OBJECT (g->inspector), "inspect-web-view", G_CALLBACK (create_inspector_cb), NULL);
search_reverse_text (WebKitWebView *page, GArray *argv);
static void
+dehilight (WebKitWebView *page, GArray *argv);
+
+static void
run_js (WebKitWebView * web_view, GArray *argv);
static void