aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--README13
-rw-r--r--examples/config/config6
-rw-r--r--examples/data/scripts/formfiller.js9
-rwxr-xr-xexamples/data/scripts/formfiller.sh20
-rw-r--r--extras/vim/syntax/uzbl.vim4
-rw-r--r--src/commands.c121
-rw-r--r--src/commands.h3
-rw-r--r--src/uzbl-core.c4
-rw-r--r--src/variables.c100
-rw-r--r--src/variables.h8
-rw-r--r--tests/test-command.c49
11 files changed, 256 insertions, 81 deletions
diff --git a/README b/README
index 925392c..2ef6c8d 100644
--- a/README
+++ b/README
@@ -141,6 +141,7 @@ The following commands are recognized:
- argument can be `begin`, `end`, or an amount given in pixels(?) or as a
percentage of the size of the view
- set the amount to 100% to scroll a whole page
+ - argument can be appended with a `!` to scroll absolutely
* `reload`
- Reload the current page.
* `reload_ign_cache`
@@ -151,11 +152,6 @@ The following commands are recognized:
- Increase the zoom level.
* `zoom_out`
- Decrease the zoom level.
-* `toggle_zoom_type`
- - Toggles the variable `zoom_type` between "full-content" and "text-only"
- zoom. In "text-only" zoom, only the text of the page is zoomed, while in
- "full-content" zoom, images and other page elements are zoomed along with
- the text.
* `uri <address>`
- Attempt to load `<address>`. This is equivalent to `set uri = <address>`.
* `js <body>`
@@ -163,8 +159,6 @@ The following commands are recognized:
- Remember that the commands must not contain line breaks.
* `script <file>`
- Execute the JavaScript in `<file>`.
-* `toggle_status`
- - Toggle the display of the status bar.
* `spawn <executable> <additional args>` TODO explain path-alike expansion
- Runs a command; see EXTERNAL SCRIPTS for details.
- `$PATH` is searched, so giving the full path to commands is not necessary.
@@ -201,6 +195,11 @@ The following commands are recognized:
the status bar react immediately.
- If you want to unset a string, use `set` with one space after the equals
sign.
+* `toggle <var> [possibilities]`
+ - Cycles the variable `var` through the list of options given in
+ `possibilities`.
+ - If `possibilities` are not given and the variable is an int or a float,
+ toggles between 0 and 1.
* `dump_config`
- Dumps the current config (which may have been changed at runtime) to stdout.
- Uses a format which can be piped into `uzbl` again or saved as a config
diff --git a/examples/config/config b/examples/config/config
index e061e12..d295347 100644
--- a/examples/config/config
+++ b/examples/config/config
@@ -238,6 +238,8 @@ set ebind = @mode_bind global,-insert
@cbind ^ = scroll horizontal begin
@cbind $ = scroll horizontal end
@cbind <Space> = scroll vertical end
+@cbind G<Go To:>_ = scroll vertical %r!
+@cbind _G<Go To:>_ = scroll horizontal %r!
# Navigation binds
@cbind b = back
@@ -249,12 +251,12 @@ set ebind = @mode_bind global,-insert
# Zoom binds
@cbind + = zoom_in
@cbind - = zoom_out
-@cbind T = toggle_zoom_type
+@cbind T = toggle zoom_type
@cbind 1 = set zoom_level = 1.0
@cbind 2 = set zoom_level = 2.0
# Appearance binds
-@cbind t = toggle_status
+@cbind t = toggle show_status
# Page searching binds
@cbind /* = search %s
diff --git a/examples/data/scripts/formfiller.js b/examples/data/scripts/formfiller.js
index 1b10db4..06db648 100644
--- a/examples/data/scripts/formfiller.js
+++ b/examples/data/scripts/formfiller.js
@@ -29,6 +29,9 @@ uzbl.formfiller = {
for( var k = 0; k < inputs.length; ++k ) {
var input = inputs[k];
+ if ( ! input.name ) {
+ continue
+ }
if ( uzbl.formfiller.inputTypeIsText(input.type) ) {
rv += '%' + escape(input.name) + '(' + input.type + '):' + input.value + '\n';
} else if ( input.type == 'checkbox' || input.type == 'radio' ) {
@@ -39,8 +42,10 @@ uzbl.formfiller = {
var textareas = allFrames[j].document.getElementsByTagName("textarea");
for( var k = 0; k < textareas.length; ++k ) {
var textarea = textareas[k];
- rv += '%' + escape(textarea.name) + '(textarea):\n' + textarea.value.replace(/\n%/g,"\n\\%") + '\n%\n';
- rv += '%' + escape(textarea.name) + '(textarea):\n' + textarea.value.replace(/\n\\/g,"\n\\\\").replace(/\n%/g,"\n\\%") + '%\n';
+ if ( ! textarea.name ) {
+ continue
+ }
+ rv += '%' + escape(textarea.name) + '(textarea):\n' + textarea.value.replace(/(^|\n)\\/g,"$1\\\\").replace(/(^|\n)%/g,"$1\\%") + '\n%\n';
}
}
catch (err) { }
diff --git a/examples/data/scripts/formfiller.sh b/examples/data/scripts/formfiller.sh
index 394bfbd..52d6ec6 100755
--- a/examples/data/scripts/formfiller.sh
+++ b/examples/data/scripts/formfiller.sh
@@ -63,6 +63,9 @@ ParseFields ()
awk '/^%/ {
sub ( /%/, "" )
+ gsub ( /\\/, "\\\\\\\\" )
+ gsub ( /@/, "\\@" )
+ gsub ( /"/, "\\\"" )
split( $0, parts, /\(|\)|\{|\}/ )
@@ -73,15 +76,24 @@ ParseFields ()
printf( "js uzbl.formfiller.insert(\"%s\",\"%s\",\"%s\",%s);\n",
parts[1], parts[2], parts[3], field )
- else if ( parts[2] ~ /^textarea$/ ) {
+ else if ( parts[2] == "textarea" ) {
field = ""
while (getline) {
if ( /^%/ ) break
sub ( /^\\/, "" )
+ # JavaScript escape
+ gsub ( /\\/, "\\\\\\\\" )
gsub ( /"/, "\\\"" )
- gsub ( /\\/, "\\\\" )
- field = field $0 "\\\\n"
+ # To support the possibility of the last line of the textarea
+ # not being terminated by a newline, we add the newline here.
+ # The "if (field)" is so that this does not happen in the first
+ # iteration.
+ if (field) field = field "\\n"
+ field = field $0
}
+ # Uzbl escape
+ gsub ( /\\/, "\\\\\\\\", field )
+ gsub ( /@/, "\\@", field )
printf( "js uzbl.formfiller.insert(\"%s\",\"%s\",\"%s\",0);\n",
parts[1], parts[2], field )
}
@@ -120,7 +132,6 @@ Load ()
ParseProfile $option < "$file" \
| ParseFields \
- | sed 's/@/\\@/g' \
> "$UZBL_FIFO"
}
@@ -136,7 +147,6 @@ Once ()
test -e "$tmpfile" &&
ParseFields < "$tmpfile" \
- | sed 's/@/\\@/g' \
> "$UZBL_FIFO"
}
diff --git a/extras/vim/syntax/uzbl.vim b/extras/vim/syntax/uzbl.vim
index 1a4172b..2cb4006 100644
--- a/extras/vim/syntax/uzbl.vim
+++ b/extras/vim/syntax/uzbl.vim
@@ -26,8 +26,8 @@ elseif exists("b:current_syntax")
endif
syn keyword uzblKeyword back forward scroll reload reload_ign_cache stop
-syn keyword uzblKeyword zoom_in zoom_out toggle_zoom_type uri script
-syn keyword uzblKeyword toggle_status spawn sync_spawn sync_sh sync_spawn_exec
+syn keyword uzblKeyword zoom_in zoom_out toggle uri script
+syn keyword uzblKeyword spawn sync_spawn sync_sh sync_spawn_exec
syn keyword uzblKeyword exit search search_reverse search_clear dehilight set
syn keyword uzblKeyword dump_config dump_config_as_events chain print event
syn keyword uzblKeyword request menu_add menu_link_add menu_image_add
diff --git a/src/commands.c b/src/commands.c
index ff3b15f..032bb4a 100644
--- a/src/commands.c
+++ b/src/commands.c
@@ -18,11 +18,9 @@ CommandInfo cmdlist[] =
{ "stop", view_stop_loading, 0 },
{ "zoom_in", view_zoom_in, 0 }, //Can crash (when max zoom reached?).
{ "zoom_out", view_zoom_out, 0 },
- { "toggle_zoom_type", toggle_zoom_type, 0 },
{ "uri", load_uri, TRUE },
{ "js", run_js, TRUE },
{ "script", run_external_js, 0 },
- { "toggle_status", toggle_status, 0 },
{ "spawn", spawn_async, 0 },
{ "sync_spawn", spawn_sync, 0 },
{ "sync_spawn_exec", spawn_sync_exec, 0 }, // needed for load_cookies.sh :(
@@ -34,6 +32,7 @@ CommandInfo cmdlist[] =
{ "search_clear", search_clear, TRUE },
{ "dehilight", dehilight, 0 },
{ "set", set_var, TRUE },
+ { "toggle", toggle_var, 0 },
{ "dump_config", act_dump_config, 0 },
{ "dump_config_as_events", act_dump_config_as_events, 0 },
{ "chain", chain, 0 },
@@ -96,26 +95,11 @@ VIEWFUNC(go_back)
VIEWFUNC(go_forward)
#undef VIEWFUNC
-void
-toggle_zoom_type (WebKitWebView* page, GArray *argv, GString *result) {
- (void)page; (void)argv; (void)result;
-
- int current_type = get_zoom_type();
- set_zoom_type(!current_type);
-}
-
-void
-toggle_status (WebKitWebView* page, GArray *argv, GString *result) {
- (void)page; (void)argv; (void)result;
-
- int current_status = get_show_status();
- set_show_status(!current_status);
-}
-
/*
* scroll vertical 20
* scroll vertical 20%
* scroll vertical -40
+ * scroll vertical 20!
* scroll vertical begin
* scroll vertical end
* scroll horizontal 10
@@ -164,6 +148,107 @@ set_var(WebKitWebView *page, GArray *argv, GString *result) {
g_strfreev(split);
}
+void
+toggle_var(WebKitWebView *page, GArray *argv, GString *result) {
+ (void) page; (void) result;
+
+ if(!argv_idx(argv, 0))
+ return;
+
+ const gchar *var_name = argv_idx(argv, 0);
+
+ uzbl_cmdprop *c = get_var_c(var_name);
+
+ switch(c->type) {
+ case TYPE_STR:
+ {
+ const gchar *next;
+
+ if(argv->len >= 3) {
+ gchar *current = get_var_value_string_c(c);
+
+ guint i = 2;
+ const gchar *first = argv_idx(argv, 1);
+ const gchar *this = first;
+ next = argv_idx(argv, 2);
+
+ while(next && strcmp(current, this)) {
+ this = next;
+ next = argv_idx(argv, ++i);
+ }
+
+ if(!next)
+ next = first;
+
+ g_free(current);
+ } else
+ next = "";
+
+ set_var_value_string_c(c, next);
+ break;
+ }
+ case TYPE_INT:
+ {
+ int current = get_var_value_int_c(c);
+ int next;
+
+ if(argv->len >= 3) {
+ guint i = 2;
+
+ int first = strtoul(argv_idx(argv, 1), NULL, 10);
+ int this = first;
+
+ const gchar *next_s = argv_idx(argv, 2);
+
+ while(next_s && this != current) {
+ this = strtoul(next_s, NULL, 10);
+ next_s = argv_idx(argv, ++i);
+ }
+
+ if(next_s)
+ next = strtoul(next_s, NULL, 10);
+ else
+ next = first;
+ } else
+ next = !current;
+
+ set_var_value_int_c(c, next);
+ break;
+ }
+ case TYPE_FLOAT:
+ {
+ float current = get_var_value_float_c(c);
+ float next;
+
+ if(argv->len >= 3) {
+ guint i = 2;
+
+ float first = strtod(argv_idx(argv, 1), NULL);
+ float this = first;
+
+ const gchar *next_s = argv_idx(argv, 2);
+
+ while(next_s && this != current) {
+ this = strtod(next_s, NULL);
+ next_s = argv_idx(argv, ++i);
+ }
+
+ if(next_s)
+ next = strtod(next_s, NULL);
+ else
+ next = first;
+ } else
+ next = !current;
+
+ set_var_value_float_c(c, next);
+ break;
+ }
+ default:
+ g_assert_not_reached();
+ }
+
+ send_set_var_event(var_name, c);
+}
void
event(WebKitWebView *page, GArray *argv, GString *result) {
diff --git a/src/commands.h b/src/commands.h
index b8cf095..c39b541 100644
--- a/src/commands.h
+++ b/src/commands.h
@@ -58,10 +58,9 @@ void delete_cookie(WebKitWebView *page, GArray *argv, GString *result);
void clear_cookies(WebKitWebView *pag, GArray *argv, GString *result);
void download(WebKitWebView *pag, GArray *argv, GString *result);
void set_var(WebKitWebView *page, GArray *argv, GString *result);
+void toggle_var(WebKitWebView *page, GArray *argv, GString *result);
void run_js (WebKitWebView * web_view, GArray *argv, GString *result);
void run_external_js (WebKitWebView * web_view, GArray *argv, GString *result);
-void toggle_zoom_type (WebKitWebView* page, GArray *argv, GString *result);
-void toggle_status (WebKitWebView* page, GArray *argv, GString *result);
void act_dump_config(WebKitWebView* page, GArray *argv, GString *result);
void act_dump_config_as_events(WebKitWebView* page, GArray *argv, GString *result);
diff --git a/src/uzbl-core.c b/src/uzbl-core.c
index c3bc2dd..e70b5e7 100644
--- a/src/uzbl-core.c
+++ b/src/uzbl-core.c
@@ -331,11 +331,15 @@ scroll(GtkAdjustment* bar, gchar *amount_str) {
if (*end == '%')
value += page_size * amount * 0.01;
+ else if (*end == '!')
+ value = amount;
else
value += amount;
max_value = gtk_adjustment_get_upper(bar) - page_size;
+ if (value < 0)
+ value = 0; /* don't scroll past the beginning of the page */
if (value > max_value)
value = max_value; /* don't scroll past the end of the page */
diff --git a/src/variables.c b/src/variables.c
index 3bd941b..ed76f95 100644
--- a/src/variables.c
+++ b/src/variables.c
@@ -5,6 +5,11 @@
#include "io.h"
#include "util.h"
+uzbl_cmdprop *
+get_var_c(const gchar *name) {
+ return g_hash_table_lookup(uzbl.behave.proto_var, name);
+}
+
void
send_set_var_event(const char *name, const uzbl_cmdprop *c) {
/* check for the variable type */
@@ -41,8 +46,8 @@ send_set_var_event(const char *name, const uzbl_cmdprop *c) {
void
expand_variable(GString *buf, const gchar *name) {
- uzbl_cmdprop* c;
- if((c = g_hash_table_lookup(uzbl.behave.proto_var, name))) {
+ uzbl_cmdprop* c = get_var_c(name);
+ if(c) {
if(c->type == TYPE_STR) {
gchar *v = get_var_value_string_c(c);
g_string_append(buf, v);
@@ -54,50 +59,59 @@ expand_variable(GString *buf, const gchar *name) {
}
}
+void
+set_var_value_string_c(uzbl_cmdprop *c, const gchar *val) {
+ if(c->setter)
+ ((void (*)(const gchar *))c->setter)(val);
+ else {
+ g_free(*(c->ptr.s));
+ *(c->ptr.s) = g_strdup(val);
+ }
+}
+
+void
+set_var_value_int_c(uzbl_cmdprop *c, int i) {
+ if(c->setter)
+ ((void (*)(int))c->setter)(i);
+ else
+ *(c->ptr.i) = i;
+}
+
+void
+set_var_value_float_c(uzbl_cmdprop *c, float f) {
+ if(c->setter)
+ ((void (*)(float))c->setter)(f);
+ else
+ *(c->ptr.f) = f;
+}
+
gboolean
set_var_value(const gchar *name, gchar *val) {
- uzbl_cmdprop *c = NULL;
-
g_assert(val != NULL);
- if( (c = g_hash_table_lookup(uzbl.behave.proto_var, name)) ) {
+ uzbl_cmdprop *c = get_var_c(name);
+
+ if(c) {
if(!c->writeable) return FALSE;
- if(c->setter) {
- switch(c->type) {
- case TYPE_STR:
- ((void (*)(const gchar *))c->setter)(val);
- break;
- case TYPE_INT:
- {
- int i = (int)strtoul(val, NULL, 10);
- ((void (*)(int))c->setter)(i);
- break;
- }
- case TYPE_FLOAT:
- {
- float f = strtod(val, NULL);
- ((void (*)(float))c->setter)(f);
- break;
- }
- default:
- g_assert_not_reached();
- }
- } else {
- switch(c->type) {
- case TYPE_STR:
- g_free(*(c->ptr.s));
- *(c->ptr.s) = g_strdup(val);
- break;
- case TYPE_INT:
- *(c->ptr.i) = (int)strtoul(val, NULL, 10);
- break;
- case TYPE_FLOAT:
- *(c->ptr.f) = strtod(val, NULL);
- break;
- default:
- g_assert_not_reached();
- }
+ switch(c->type) {
+ case TYPE_STR:
+ set_var_value_string_c(c, val);
+ break;
+ case TYPE_INT:
+ {
+ int i = (int)strtoul(val, NULL, 10);
+ set_var_value_int_c(c, i);
+ break;
+ }
+ case TYPE_FLOAT:
+ {
+ float f = strtod(val, NULL);
+ set_var_value_float_c(c, f);
+ break;
+ }
+ default:
+ g_assert_not_reached();
}
send_set_var_event(name, c);
@@ -148,7 +162,7 @@ get_var_value_string_c(const uzbl_cmdprop *c) {
gchar*
get_var_value_string(const gchar *name) {
- uzbl_cmdprop *c = g_hash_table_lookup(uzbl.behave.proto_var, name);
+ uzbl_cmdprop *c = get_var_c(name);
return get_var_value_string_c(c);
}
@@ -166,7 +180,7 @@ get_var_value_int_c(const uzbl_cmdprop *c) {
int
get_var_value_int(const gchar *name) {
- uzbl_cmdprop *c = g_hash_table_lookup(uzbl.behave.proto_var, name);
+ uzbl_cmdprop *c = get_var_c(name);
return get_var_value_int_c(c);
}
@@ -184,7 +198,7 @@ get_var_value_float_c(const uzbl_cmdprop *c) {
float
get_var_value_float(const gchar *name) {
- uzbl_cmdprop *c = g_hash_table_lookup(uzbl.behave.proto_var, name);
+ uzbl_cmdprop *c = get_var_c(name);
return get_var_value_float_c(c);
}
diff --git a/src/variables.h b/src/variables.h
index 4f85474..dade652 100644
--- a/src/variables.h
+++ b/src/variables.h
@@ -10,6 +10,8 @@
#include "type.h"
+uzbl_cmdprop *get_var_c(const gchar *name);
+
gboolean set_var_value(const gchar *name, gchar *val);
void expand_variable(GString *buf, const gchar *name);
void variables_hash();
@@ -21,6 +23,12 @@ int get_var_value_int(const char *name);
float get_var_value_float_c(const uzbl_cmdprop *c);
float get_var_value_float(const char *name);
+void set_var_value_string_c(uzbl_cmdprop *c, const gchar *val);
+void set_var_value_int_c(uzbl_cmdprop *c, int f);
+void set_var_value_float_c(uzbl_cmdprop *c, float f);
+
+void send_set_var_event(const char *name, const uzbl_cmdprop *c);
+
void dump_config();
void dump_config_as_events();
diff --git a/tests/test-command.c b/tests/test-command.c
index b6a1063..b3c3d0c 100644
--- a/tests/test-command.c
+++ b/tests/test-command.c
@@ -308,6 +308,51 @@ test_no_such_command (void) {
/* if we didn't crash then we're ok! */
}
+// TODO: test toggling emits an event
+void
+test_toggle_int (void) {
+ g_assert_cmpint(0, ==, uzbl.behave.forward_keys);
+
+ parse_cmd_line("toggle forward_keys", NULL);
+ g_assert_cmpint(1, ==, uzbl.behave.forward_keys);
+
+ parse_cmd_line("toggle forward_keys", NULL);
+ g_assert_cmpint(0, ==, uzbl.behave.forward_keys);
+
+ // if cycle values are specified it should use those
+ parse_cmd_line("toggle forward_keys 1 2", NULL);
+ g_assert_cmpint(1, ==, uzbl.behave.forward_keys);
+
+ parse_cmd_line("toggle forward_keys 1 2", NULL);
+ g_assert_cmpint(2, ==, uzbl.behave.forward_keys);
+
+ // and wrap to the first value when it reaches the end.
+ parse_cmd_line("toggle forward_keys 1 2", NULL);
+ g_assert_cmpint(1, ==, uzbl.behave.forward_keys);
+}
+
+void
+test_toggle_string (void) {
+ parse_cmd_line("set useragent = something interesting", NULL);
+ g_assert_cmpstr("something interesting", ==, uzbl.net.useragent);
+
+ // when something was set, it gets reset
+ parse_cmd_line("toggle useragent", NULL);
+ g_assert_cmpstr("", ==, uzbl.net.useragent);
+
+ // if cycle values are specified it should use those
+ parse_cmd_line("set useragent = something interesting", NULL);
+ parse_cmd_line("toggle useragent 'x' 'y'", NULL);
+ g_assert_cmpstr("x", ==, uzbl.net.useragent);
+
+ parse_cmd_line("toggle useragent 'x' 'y'", NULL);
+ g_assert_cmpstr("y", ==, uzbl.net.useragent);
+
+ // and wrap to the first value when it reaches the end.
+ parse_cmd_line("toggle useragent 'x' 'y'", NULL);
+ g_assert_cmpstr("x", ==, uzbl.net.useragent);
+}
+
int
main (int argc, char *argv[]) {
/* set up tests */
@@ -329,6 +374,10 @@ main (int argc, char *argv[]) {
g_test_add_func("/test-command/no-such-command", test_no_such_command);
+ g_test_add_func("/test-command/toggle-int", test_toggle_int);
+ // we should probably test toggle float, but meh.
+ g_test_add_func("/test-command/toggle-string", test_toggle_string);
+
/* set up uzbl */
initialize(argc, argv);