(sentientswitch) - Cleaned up code. Added some commands.
Jan Kolkmeier (jouz) - scrolling, link following
Evgeny Grablyk - libsoup settings
+ Damien Leon - misc
+ Peter Suschlik - backwards searching
Originaly based on http://trac.webkit.org/browser/trunk/WebKitTools/GtkLauncher/main.c
Which is copyrighted:
an utitly we include with uzbl made especially for writing commnands to the socket (and at some point, it will be able to tell you the response
too): `uzblctrl -s <socketfile> -c <command>`
+When uzbl forks a new instance (eg "open in new window") it will use the same commandline arguments (eg the same --config <file>), except --uri and--name.
+If you made changes to the configuration at runtime, these are not pased on to the child.
+
### COMMAND SYNTAX
Commands are used for creating binds, altering variables and running actions. 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.
Have a look at the sample configs and scripts!
-Scripts that are called by uzbl are passed the following arguments:
+Handler scripts that are called by uzbl are passed the following arguments:
$1 uzbl-config-file
$2 uzbl-pid
$11 cookie (only with PUT requests)
+Custom, userdefined scripts (`spawn foo bar`) get first the arguments as specified in the config and then the above 7 are added at the end.
+
### COMMAND LINE ARGUMENTS
-u, --uri=URI Uri to load (equivalent to 'set uri = URI')
- -v, --verbose=VERBOSE Whether to print all messages or just errors.
+ -v, --verbose Whether to print all messages or just errors.
-n, --name=NAME Name of the current instance (defaults to Xorg window id)
-c, --config=FILE Config file (this is pretty much equivalent to uzbl < FILE )
--display=DISPLAY X display to use
* check that in new version pageup etc works also in command
* tab key to jump between input fields should probably work in both insert and command mode
* do not delete fifo/socket if they exist already. rather give error and don't create one.
-* backspace key to pop characters from (multichar) command
* optional logging of http requests&responses with ip/hostname and port. -> how to implement? handler? stdout? (through a socket so you know what corresponds to what?)
* bench/optimize fifo vs socket performance. measure delays. minimize forks. does glib use a shell? how does it detect the shebang line?
* "remember account settings" support. but how? configure post data per site? regex match eg '^bbs.archlinux.org' ?
* check for real command name, not just the first letter.
* let users attach handlers to the most common events/signals in uzbl.
* write little script to open new urls with the urxvt url thing +document.
-* add Rob/anydots trees on website
SOMEDAY:
figure out caching with webkit and in general how we can speed up everything
figure out how webkit intercepts key input
make "disable insert mode" (esc key) configurable
keywords don't work for external commands. is this a problem?
+* pass a bit less arguments by default, use the socket to query for them instead, or export the stuff through environment variables, or export them as xorg window properties
+* write a config "generator" that iterates over the Uzbl uzbl and generates the commands needed to become in that state.
\ No newline at end of file
--- /dev/null
+
+# 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
+# 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
+# from insert mode by combining them with the modkey
+
+# TODO: ability to attach misc things (spawn <foo>, script <bar>,.. to internal events)
+set history_handler = /usr/share/uzbl/examples/scripts/history.sh
+set download_handler = /usr/share/uzbl/examples/scripts/download.sh
+set cookie_handler = /usr/share/uzbl/examples/scripts/cookies.sh
+set minimum_font_size = 6
+set default_font_size = 11
+
+# use with bind ... = sh <shell-oneliner>
+# notice the '' - it's a spacer to keep bash and sh from shifting the positional parameters
+# by one, so they will appear in the same position as with scripts invoked via spawn
+set shell_cmd = sh -c %s ''
+
+
+
+# Behaviour and appearance
+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_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>
+set title_format_long = KEYCMD MODE TITLE - Uzbl browser <NAME> > SELECTED_URI
+
+set modkey = Mod1
+# reset to command mode when new page is loaded
+set reset_command_mode = 1
+# this var has precedence over reset_command_mode
+set always_insert_mode = 0
+# to start a local socks server, do : ssh -fND localhost:8118 localhost
+#set proxy_url = http://127.0.0.1:8118
+#values 0-3
+#set http_debug = 0
+#set useragent = uzbl (Webkit %webkit-major%.%webkit-minor%.%webkit-micro%)
+# Example user agent containing everything:
+#set useragent = Uzbl (Webkit %webkit-major%.%webkit-minor%.%webkit-micro%) (%sysname% %nodename% %kernrel% %kernver% %arch-system% [%arch-uzbl%]) (Commit %commit%)
+#set max_conns = 0
+#set max_conns_host = 0
+
+set fifo_dir = /tmp
+set socket_dir = /tmp
+
+# Key bindings
+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
+# 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.
+bind /* = search %s
+bind ?* = search_reverse %s
+#jump to next
+bind n = search
+bind N = search_reverse
+bind gh = uri http://www.uzbl.org
+#TODO: set uri?
+bind o _ = uri %s
+bind :wiki _ = uri http://wiki.archlinux.org/index.php/Special:Search?search=%s&go=Go
+bind gg _ = uri http://www.google.com/search?q=%s
+bind i = insert_mode
+#TODO: no 'toggle' command?
+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 ZZ = exit
+bind S = script alert("hi");
+# example showing how to use sh
+# it sends a command to the fifo, whose path is told via a positional param
+# if fifo_dir is not set, it'll echo to a file named (null) somewhere >:) remember to delete it
+bind XS = sh 'echo "act script alert (\"This is sent by the shell via a fifo\")" > "$4"'
+# Keyboard based link following: work in progress! No C DOM bindings yet, no click() event for hyperlinks so no referrer set..Quite basic but does the job for now...
+#hit F to toggle the Hints (now in form of link numbering)
+bind F= script for (var i=0; i < document.links.length; i++) {var uzblid = 'uzbl_link_hint_';var li = document.links[i];var pre = document.getElementById(uzblid+i);if (pre) {li.removeChild(pre);} else {var hint = document.createElement('div');hint.setAttribute('id',uzblid+i);hint.innerHTML = i;hint.style.display='inline';hint.style.lineHeight='90%';hint.style.backgroundColor='red';hint.style.color='white';hint.style.fontSize='small-xx';hint.style.fontWeight='light';hint.style.margin='0px';hint.style.padding='2px';hint.style.position='absolute';hint.style.textDecoration='none';hint.style.left=li.style.left;hint.style.top=li.style.top;li.insertAdjacentElement('afterBegin',hint);}}
+#hit f followed by linknumber and ENTER to follow that link
+bind f_ = script window.location = document.links[%s].href;
+
+# "home" page if you will
+set uri = uzbl.org
set reset_command_mode = 1
# this var has precedence over reset_command_mode
set always_insert_mode = 0
+
# to start a local socks server, do : ssh -fND localhost:8118 localhost
-#set proxy_url = http://127.0.0.1:8118
+#set proxy_url = http://127.0.0.1:8118
#values 0-3
-#set http_debug = 0
-#set useragent uzbl (Webkit %webkit-major%.%webkit-minor%.%webkit-micro%)
+#set http_debug = 0
+#set useragent = uzbl (Webkit %webkit-major%.%webkit-minor%.%webkit-micro%)
# Example user agent containing everything:
-#set useragent Uzbl (Webkit %webkit-major%.%webkit-minor%.%webkit-micro%) (%sysname% %nodename% %kernrel% %kernver% %arch-system% [%arch-uzbl%]) (Commit %commit%)
-#set max_conns 0
-#set max_conns_host 0
+#set useragent = Uzbl (Webkit %webkit-major%.%webkit-minor%.%webkit-micro%) (%sysname% %nodename% %kernrel% %kernver% %arch-system% [%arch-uzbl%]) (Commit %commit%)
+#set max_conns = 0
+#set max_conns_host = 0
set fifo_dir = /tmp
set socket_dir = /tmp
# 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.
bind /* = search %s
+bind ?* = search_reverse %s
#jump to next
-bind ; = search
+bind n = search
+bind N = search_reverse
bind gh = uri http://www.uzbl.org
#TODO: set uri?
bind o _ = uri %s
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 ZZ = exit
bind S = script alert("hi");
# example showing how to use sh
# use this script to pipe any variable to xclip, so you have it in your clipboard
-exit
-# this script is not done yet
-
-# can we make this universal?
-# add xclip to optdeps
+# 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
which xclip &>/dev/null || exit 1
+[ "$2" == primary -o "$2" == secondary -o "$2" == clipboard ] || exit 2
-echo -n `eval "$3"` #| xclip
\ No newline at end of file
+echo -n "${!1}" | xclip -selection $2
\ No newline at end of file
static GOptionEntry entries[] =
{
{ "uri", 'u', 0, G_OPTION_ARG_STRING, &uzbl.state.uri, "Uri to load at startup (equivalent to 'set uri = URI')", "URI" },
- { "verbose", 'v', 0, G_OPTION_ARG_NONE, &uzbl.state.verbose, "Whether to print all messages or just errors.", "VERBOSE" },
+ { "verbose", 'v', 0, G_OPTION_ARG_NONE, &uzbl.state.verbose, "Whether to print all messages or just errors.", NULL },
{ "name", 'n', 0, G_OPTION_ARG_STRING, &uzbl.state.instance_name, "Name of the current instance (defaults to Xorg window id)", "NAME" },
{ "config", 'c', 0, G_OPTION_ARG_STRING, &uzbl.state.config_file, "Config file (this is pretty much equivalent to uzbl < FILE )", "FILE" },
{ NULL, 0, 0, 0, NULL, NULL, NULL }
{ "spawn", spawn },
{ "sh", spawn_sh },
{ "exit", close_uzbl },
- { "search", search_text },
+ { "search", search_forward_text },
+ { "search_reverse", search_reverse_text },
{ "insert_mode", set_insert_mode },
{ "runcmd", runcmd }
};
}
static void
-search_text (WebKitWebView *page, const char *param) {
+search_text (WebKitWebView *page, const char *param, const gboolean forward) {
if ((param) && (param[0] != '\0')) {
strcpy(uzbl.state.searchtx, param);
}
webkit_web_view_unmark_text_matches (page);
webkit_web_view_mark_text_matches (page, uzbl.state.searchtx, FALSE, 0);
webkit_web_view_set_highlight_text_matches (page, TRUE);
- webkit_web_view_search_text (page, uzbl.state.searchtx, FALSE, TRUE, TRUE);
+ webkit_web_view_search_text (page, uzbl.state.searchtx, FALSE, forward, TRUE);
}
}
static void
+search_forward_text (WebKitWebView *page, const char *param) {
+ search_text(page, param, TRUE);
+}
+
+static void
+search_reverse_text (WebKitWebView *page, const char *param) {
+ search_text(page, param, 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);
int i;
for (i = 0; entries[i].long_name != NULL; i++) {
- if ((entries[i].arg == G_OPTION_ARG_STRING) && (strcmp(entries[i].long_name,"uri")!=0)) {
+ if ((entries[i].arg == G_OPTION_ARG_STRING) && (strcmp(entries[i].long_name,"uri")!=0) && (strcmp(entries[i].long_name,"name")!=0)) {
gchar** str = (gchar**)entries[i].arg_data;
if (*str!=NULL) {
g_string_append_printf (to_execute, " --%s '%s'", entries[i].long_name, *str);
static void
spawn(WebKitWebView *web_view, const char *param) {
(void)web_view;
+/*
+ TODO: allow more control over argument order so that users can have some arguments before the default ones from run_command, and some after
+ gchar** cmd = g_strsplit(param, " ", 2);
+ gchar * args = NULL;
+ if (cmd[1]) {
+ args = g_shell_quote(cmd[1]);
+ }
+ if (cmd) {
+ run_command(cmd[0], args, FALSE, NULL);
+ }
+ if (args) {
+ g_free(args);
+ }
+*/
run_command(param, NULL, FALSE, NULL);
}
return NULL;
}
+/*
+ NOTE: we want to keep variables like b->title_format_long in their "unprocessed" state
+ it will probably improve performance if we would "cache" the processed variant, but for now it works well enough...
+*/
+// this function may be called very early when the templates are not set (yet), hence the checks
static void
update_title (void) {
Behaviour *b = &uzbl.behave;
+ gchar *parsed;
if (b->show_status) {
- gchar *statln;
- gtk_window_set_title (GTK_WINDOW(uzbl.gui.main_window), expand_template(b->title_format_short));
- // TODO: we should probably not do this every time we want to update the title..?
- statln = expand_template(uzbl.behave.status_format);
- gtk_label_set_markup(GTK_LABEL(uzbl.gui.mainbar_label), statln);
+ if (b->title_format_short) {
+ parsed = expand_template(b->title_format_short);
+ gtk_window_set_title (GTK_WINDOW(uzbl.gui.main_window), parsed);
+ g_free(parsed);
+ }
+ if (b->status_format) {
+ parsed = expand_template(b->status_format);
+ gtk_label_set_markup(GTK_LABEL(uzbl.gui.mainbar_label), parsed);
+ g_free(parsed);
+ }
if (b->status_background) {
GdkColor color;
gdk_color_parse (b->status_background, &color);
//labels and hboxes do not draw their own background. applying this on the window is ok as we the statusbar is the only affected widget. (if not, we could also use GtkEventBox)
gtk_widget_modify_bg (uzbl.gui.main_window, GTK_STATE_NORMAL, &color);
}
- g_free(statln);
} else {
- gtk_window_set_title (GTK_WINDOW(uzbl.gui.main_window), expand_template(b->title_format_long));
+ if (b->title_format_long) {
+ parsed = expand_template(b->title_format_long);
+ gtk_window_set_title (GTK_WINDOW(uzbl.gui.main_window), parsed);
+ g_free(parsed);
+ }
}
}
xdg_type = 1 => data
xdg_type = 2 => cache*/
- gchar* xdg_config_home = get_xdg_var (XDG[0]);
- gchar* xdg_data_home = get_xdg_var (XDG[1]);
- gchar* xdg_cache_home = get_xdg_var (XDG[2]);
- gchar* xdg_config_dirs = get_xdg_var (XDG[3]);
- gchar* xdg_data_dirs = get_xdg_var (XDG[4]);
gchar* temporary_file = (char *)malloc (1024);
gchar* temporary_string = NULL;
char* saveptr;
- if (xdg_type == 0)
- strcpy (temporary_file, xdg_config_home);
-
- if (xdg_type == 1)
- strcpy (temporary_file, xdg_data_home);
-
- if (xdg_type == 2)
- strcpy (temporary_file, xdg_cache_home);
+ strcpy (temporary_file, get_xdg_var (XDG[xdg_type]));
strcat (temporary_file, filename);
if (! file_exists (temporary_file) && xdg_type != 2) {
- if (xdg_type == 0)
- temporary_string = (char *) strtok_r (xdg_config_dirs, ":", &saveptr);
-
- if (xdg_type == 1)
- temporary_string = (char *) strtok_r (xdg_data_dirs, ":", &saveptr);
+ temporary_string = (char *) strtok_r (get_xdg_var (XDG[3 + xdg_type]), ":", &saveptr);
while (temporary_string && ! file_exists (temporary_file)) {
strcpy (temporary_file, temporary_string);
printf ("No configuration file loaded.\n");
}
if (!uzbl.behave.status_format)
- uzbl.behave.status_format = g_strdup(STATUS_DEFAULT);
+ set_var_value("status_format", STATUS_DEFAULT);
if (!uzbl.behave.title_format_long)
- uzbl.behave.title_format_long = g_strdup(TITLE_LONG_DEFAULT);
+ set_var_value("title_format_long", TITLE_LONG_DEFAULT);
if (!uzbl.behave.title_format_short)
- uzbl.behave.title_format_short = g_strdup(TITLE_SHORT_DEFAULT);
+ set_var_value("title_format_short", TITLE_SHORT_DEFAULT);
g_signal_connect(n->soup_session, "request-queued", G_CALLBACK(handle_cookies), NULL);
settings_init ();
static void
-search_text (WebKitWebView *page, const char *param);
+search_text (WebKitWebView *page, const char *param, const gboolean forward);
+
+static void
+search_forward_text (WebKitWebView *page, const char *param);
+
+static void
+search_reverse_text (WebKitWebView *page, const char *param);
static void
run_js (WebKitWebView * web_view, const gchar *param);