From e44414affde4e5497386ce398cc2c40356c4e466 Mon Sep 17 00:00:00 2001 From: keis Date: Mon, 28 Feb 2011 22:03:26 +0100 Subject: add clear_cookies command --- README | 2 ++ src/uzbl-core.c | 15 ++++++++++++++- src/uzbl-core.h | 4 +--- 3 files changed, 17 insertions(+), 4 deletions(-) diff --git a/README b/README index 3ac9a28..6709bf5 100644 --- a/README +++ b/README @@ -260,6 +260,8 @@ The following commands are recognized: * 'delete_cookie [ ]` - Deletes a matching cookie from the cookie jar. scheme and expire time is currently not considered when matching. +* 'clear_cookies` + - Clears all cookies from the cookie jar ### VARIABLES AND CONSTANTS diff --git a/src/uzbl-core.c b/src/uzbl-core.c index bc75d87..3303797 100644 --- a/src/uzbl-core.c +++ b/src/uzbl-core.c @@ -551,7 +551,8 @@ CommandInfo cmdlist[] = { "include", include, TRUE }, { "show_inspector", show_inspector, 0 }, { "add_cookie", add_cookie, 0 }, - { "delete_cookie", delete_cookie, 0 } + { "delete_cookie", delete_cookie, 0 }, + { "clear_cookies", clear_cookies, 0 } }; void @@ -725,6 +726,18 @@ delete_cookie(WebKitWebView *page, GArray *argv, GString *result) { uzbl.net.soup_cookie_jar->in_manual_add = 0; } + +void +clear_cookies(WebKitWebView *page, GArray *argv, GString *result) { + (void) page; (void) argv; (void) result; + + // Replace the current cookie jar with a new empty jar + soup_session_remove_feature (uzbl.net.soup_session, uzbl.net.soup_cookie_jar); + g_object_unref (G_OBJECT (uzbl.net.soup_cookie_jar)); + uzbl.net.soup_cookie_jar = uzbl_cookie_jar_new (); + soup_session_add_feature(uzbl.net.soup_session, uzbl.net.soup_cookie_jar); +} + void act_dump_config() { dump_config(); diff --git a/src/uzbl-core.h b/src/uzbl-core.h index a4e055f..56f4fac 100644 --- a/src/uzbl-core.h +++ b/src/uzbl-core.h @@ -315,9 +315,6 @@ void handle_authentication (SoupSession *session, SoupAuth *auth, gboolean retrying, gpointer user_data); -void handle_cookies (SoupSession *session, - SoupMessage *msg, - gpointer user_data); gboolean valid_name(const gchar* name); void set_var(WebKitWebView *page, GArray *argv, GString *result); void act_dump_config(); @@ -339,6 +336,7 @@ void include(WebKitWebView *page, GArray *argv, GString *result); void show_inspector(WebKitWebView *page, GArray *argv, GString *result); void add_cookie(WebKitWebView *page, GArray *argv, GString *result); void delete_cookie(WebKitWebView *page, GArray *argv, GString *result); +void clear_cookies(WebKitWebView *pag, GArray *argv, GString *result); void builtins(); typedef void (*Command)(WebKitWebView*, GArray *argv, GString *result); -- cgit v1.2.3 From 1c7090b125ddf75c2646976f74ec3fdee8c34161 Mon Sep 17 00:00:00 2001 From: Ben Boeckel Date: Thu, 10 Mar 2011 19:41:56 -0500 Subject: Wrap util scripts in quotes --- examples/data/scripts/download.sh | 2 +- examples/data/scripts/formfiller.sh | 6 +++--- examples/data/scripts/history.sh | 2 +- examples/data/scripts/insert_bookmark.sh | 2 +- examples/data/scripts/instance-select-wmii.sh | 3 +-- examples/data/scripts/load_url_from_bookmarks.sh | 4 ++-- examples/data/scripts/load_url_from_history.sh | 4 ++-- examples/data/scripts/session.sh | 2 +- 8 files changed, 12 insertions(+), 13 deletions(-) diff --git a/examples/data/scripts/download.sh b/examples/data/scripts/download.sh index c410ad2..db0d8ac 100755 --- a/examples/data/scripts/download.sh +++ b/examples/data/scripts/download.sh @@ -6,7 +6,7 @@ # that path. # if nothing is printed to stdout, the download will be cancelled. -. $UZBL_UTIL_DIR/uzbl-dir.sh +. "$UZBL_UTIL_DIR/uzbl-dir.sh" # the URL that is being downloaded uri=$1 diff --git a/examples/data/scripts/formfiller.sh b/examples/data/scripts/formfiller.sh index c6822e6..1206464 100755 --- a/examples/data/scripts/formfiller.sh +++ b/examples/data/scripts/formfiller.sh @@ -43,9 +43,9 @@ DMENU_LINES="3" DMENU_PROMPT="Choose profile" DMENU_OPTIONS="vertical resize" -. $UZBL_UTIL_DIR/dmenu.sh -. $UZBL_UTIL_DIR/editor.sh -. $UZBL_UTIL_DIR/uzbl-dir.sh +. "$UZBL_UTIL_DIR/dmenu.sh" +. "$UZBL_UTIL_DIR/editor.sh" +. "$UZBL_UTIL_DIR/uzbl-dir.sh" RAND=$(dd if=/dev/urandom count=1 2> /dev/null | cksum | cut -c 1-5) MODELINE="> vim:ft=formfiller" diff --git a/examples/data/scripts/history.sh b/examples/data/scripts/history.sh index 266d65d..3972e3a 100755 --- a/examples/data/scripts/history.sh +++ b/examples/data/scripts/history.sh @@ -1,6 +1,6 @@ #!/bin/sh -. $UZBL_UTIL_DIR/uzbl-dir.sh +. "$UZBL_UTIL_DIR/uzbl-dir.sh" [ -w "$UZBL_HISTORY_FILE" ] || [ ! -a "$UZBL_HISTORY_FILE" ] || exit 1 diff --git a/examples/data/scripts/insert_bookmark.sh b/examples/data/scripts/insert_bookmark.sh index f67e67a..a42948c 100755 --- a/examples/data/scripts/insert_bookmark.sh +++ b/examples/data/scripts/insert_bookmark.sh @@ -1,6 +1,6 @@ #!/bin/sh -. "$UZBL_UTIL_DIR"/uzbl-dir.sh +. "$UZBL_UTIL_DIR/uzbl-dir.sh" [ -d "$UZBL_DATA_DIR" ] || exit 1 [ -w "$UZBL_BOOKMARKS_FILE" ] || [ ! -a "$UZBL_BOOKMARKS_FILE" ] || exit 1 diff --git a/examples/data/scripts/instance-select-wmii.sh b/examples/data/scripts/instance-select-wmii.sh index 19d04e8..b3a5a87 100755 --- a/examples/data/scripts/instance-select-wmii.sh +++ b/examples/data/scripts/instance-select-wmii.sh @@ -1,6 +1,5 @@ #!/bin/sh - # This script allows you to focus another uzbl window # It considers all uzbl windows in the current tag # you can select one from a list, or go to the next/previous one @@ -13,7 +12,7 @@ DMENU_SCHEME="wmii" -. $UZBL_UTIL_DIR/dmenu.sh +. "$UZBL_UTIL_DIR/dmenu.sh" case "$1" in "list" ) diff --git a/examples/data/scripts/load_url_from_bookmarks.sh b/examples/data/scripts/load_url_from_bookmarks.sh index a5d9586..704e106 100755 --- a/examples/data/scripts/load_url_from_bookmarks.sh +++ b/examples/data/scripts/load_url_from_bookmarks.sh @@ -5,8 +5,8 @@ DMENU_SCHEME="bookmarks" DMENU_OPTIONS="xmms vertical resize" -. "$UZBL_UTIL_DIR"/dmenu.sh -. "$UZBL_UTIL_DIR"/uzbl-dir.sh +. "$UZBL_UTIL_DIR/dmenu.sh" +. "$UZBL_UTIL_DIR/uzbl-dir.sh" [ -r "$UZBL_BOOKMARKS_FILE" ] || exit 1 diff --git a/examples/data/scripts/load_url_from_history.sh b/examples/data/scripts/load_url_from_history.sh index 59ad492..256a342 100755 --- a/examples/data/scripts/load_url_from_history.sh +++ b/examples/data/scripts/load_url_from_history.sh @@ -3,8 +3,8 @@ DMENU_SCHEME="history" DMENU_OPTIONS="xmms vertical resize" -. "$UZBL_UTIL_DIR"/dmenu.sh -. "$UZBL_UTIL_DIR"/uzbl-dir.sh +. "$UZBL_UTIL_DIR/dmenu.sh" +. "$UZBL_UTIL_DIR/uzbl-dir.sh" [ -r "$UZBL_HISTORY_FILE" ] || exit 1 diff --git a/examples/data/scripts/session.sh b/examples/data/scripts/session.sh index ee09cf2..185d722 100755 --- a/examples/data/scripts/session.sh +++ b/examples/data/scripts/session.sh @@ -25,7 +25,7 @@ if [ -z "$UZBL_UTIL_DIR" ]; then fi fi -. "$UZBL_UTIL_DIR"/uzbl-dir.sh +. "$UZBL_UTIL_DIR/uzbl-dir.sh" [ -d "$UZBL_DATA_DIR" ] || exit 1 UZBL="uzbl-browser -c $UZBL_CONFIG_FILE" # add custom flags and whatever here. -- cgit v1.2.3 From bfbd8eaf428b8cf04c88cc7acdcf9230c82120b4 Mon Sep 17 00:00:00 2001 From: Ben Boeckel Date: Thu, 10 Mar 2011 19:46:42 -0500 Subject: Use the -e flag on sed calls --- examples/data/scripts/download.sh | 2 +- examples/data/scripts/formfiller.sh | 32 ++++++++++++++++---------------- examples/data/scripts/session.sh | 2 +- 3 files changed, 18 insertions(+), 18 deletions(-) diff --git a/examples/data/scripts/download.sh b/examples/data/scripts/download.sh index db0d8ac..a382d9f 100755 --- a/examples/data/scripts/download.sh +++ b/examples/data/scripts/download.sh @@ -12,7 +12,7 @@ uri=$1 # a filename suggested by the server or based on the URL -suggested_filename=${2:-$(echo "$uri" | sed 's/\W/-/g')} +suggested_filename=${2:-$(echo "$uri" | sed -e 's/\W/-/g')} # the mimetype of the file being downloaded content_type=$3 diff --git a/examples/data/scripts/formfiller.sh b/examples/data/scripts/formfiller.sh index 1206464..408666f 100755 --- a/examples/data/scripts/formfiller.sh +++ b/examples/data/scripts/formfiller.sh @@ -55,7 +55,7 @@ MODELINE="> vim:ft=formfiller" action=$1 -domain=$(echo $UZBL_URI | sed 's/\(http\|https\):\/\/\([^\/]\+\)\/.*/\2/') +domain=$(echo $UZBL_URI | sed -e 's/\(http\|https\):\/\/\([^\/]\+\)\/.*/\2/') if [ "$action" != 'edit' -a "$action" != 'new' -a "$action" != 'load' -a "$action" != 'add' -a "$action" != 'once' ]; then action="new" @@ -124,21 +124,21 @@ if [ "$action" = 'load' ]; then [ -e $UZBL_FORMS_DIR/$domain ] || exit 2 if [ $(cat $UZBL_FORMS_DIR/$domain | grep "!profile" | wc -l) -gt 1 ]; then menu=$(cat $UZBL_FORMS_DIR/$domain | \ - sed -n 's/^!profile=\([^[:blank:]]\+\)/\1/p') + sed -n -e 's/^!profile=\([^[:blank:]]\+\)/\1/p') option=$(printf "$menu" | $DMENU) fi # Remove comments - sed '/^>/d' -i $tmpfile + sed -i -e '/^>/d' $tmpfile - sed 's/^\([^{]\+\){\([^}]*\)}(\(radio\|checkbox\)):\(off\|no\|false\|unchecked\|0\|$\)/\1{\2}(\3):0/I;s/^\([^{]\+\){\([^}]*\)}(\(radio\|checkbox\)):[^0]\+/\1{\2}(\3):1/I' -i $UZBL_FORMS_DIR/$domain + sed -i -e 's/^\([^{]\+\){\([^}]*\)}(\(radio\|checkbox\)):\(off\|no\|false\|unchecked\|0\|$\)/\1{\2}(\3):0/I;s/^\([^{]\+\){\([^}]*\)}(\(radio\|checkbox\)):[^0]\+/\1{\2}(\3):1/I' $UZBL_FORMS_DIR/$domain fields=$(cat $UZBL_FORMS_DIR/$domain | \ - sed -n "/^!profile=${option}/,/^!profile=/p" | \ - sed '/^!profile=/d' | \ - sed 's/^\([^(]\+(\)\(radio\|checkbox\|text\|search\|textarea\|password\)):/%{>\1\2):<}%/' | \ - sed 's/^\(.\+\)$/<{br}>\1/' | \ + sed -n -e "/^!profile=${option}/,/^!profile=/p" | \ + sed -e '/^!profile=/d' | \ + sed -e 's/^\([^(]\+(\)\(radio\|checkbox\|text\|search\|textarea\|password\)):/%{>\1\2):<}%/' | \ + sed -e 's/^\(.\+\)$/<{br}>\1/' | \ tr -d '\n' | \ - sed 's/<{br}>%{>\([^(]\+(\)\(radio\|checkbox\|text\|search\|textarea\|password\)):<}%/\\n\1\2):/g') + sed -e 's/<{br}>%{>\([^(]\+(\)\(radio\|checkbox\|text\|search\|textarea\|password\)):<}%/\\n\1\2):/g') printf '%s\n' "${fields}" | \ sed -n -e "s/\([^(]\+\)(\(password\|text\|search\|textarea\)\+):[ ]*\(.\+\)/js $insertFunction; insert('\1', '\2', '\3', 0);/p" | \ sed -e 's/@/\\@/g;s/<{br}>/\\\\n/g' | socat - unix-connect:$UZBL_SOCKET @@ -149,21 +149,21 @@ elif [ "$action" = "once" ]; then tmpfile=$(mktemp) printf 'js %s dump(); \n' "$dumpFunction" | \ socat - unix-connect:$UZBL_SOCKET | \ - sed -n '/^[^(]\+([^)]\+):/p' > $tmpfile + sed -n -e '/^[^(]\+([^)]\+):/p' > $tmpfile echo "$MODELINE" >> $tmpfile $UZBL_EDITOR $tmpfile [ -e $tmpfile ] || exit 2 # Remove comments - sed '/^>/d' -i $tmpfile + sed -i -e '/^>/d' $tmpfile - sed 's/^\([^{]\+\){\([^}]*\)}(\(radio\|checkbox\)):\(off\|no\|false\|unchecked\|0\|$\)/\1{\2}(\3):0/I;s/^\([^{]\+\){\([^}]*\)}(\(radio\|checkbox\)):[^0]\+/\1{\2}(\3):1/I' -i $tmpfile + sed -i -e 's/^\([^{]\+\){\([^}]*\)}(\(radio\|checkbox\)):\(off\|no\|false\|unchecked\|0\|$\)/\1{\2}(\3):0/I;s/^\([^{]\+\){\([^}]*\)}(\(radio\|checkbox\)):[^0]\+/\1{\2}(\3):1/I' $tmpfile fields=$(cat $tmpfile | \ - sed 's/^\([^(]\+(\)\(radio\|checkbox\|text\|search\|textarea\|password\)):/%{>\1\2):<}%/' | \ - sed 's/^\(.\+\)$/<{br}>\1/' | \ + sed -e 's/^\([^(]\+(\)\(radio\|checkbox\|text\|search\|textarea\|password\)):/%{>\1\2):<}%/' | \ + sed -e 's/^\(.\+\)$/<{br}>\1/' | \ tr -d '\n' | \ - sed 's/<{br}>%{>\([^(]\+(\)\(radio\|checkbox\|text\|search\|textarea\|password\)):<}%/\\n\1\2):/g') + sed -e 's/<{br}>%{>\([^(]\+(\)\(radio\|checkbox\|text\|search\|textarea\|password\)):<}%/\\n\1\2):/g') printf '%s\n' "${fields}" | \ sed -n -e "s/\([^(]\+\)(\(password\|text\|search\|textarea\)\+):[ ]*\(.\+\)/js $insertFunction; insert('\1', '\2', '\3', 0);/p" | \ sed -e 's/@/\\@/g;s/<{br}>/\\\\n/g' | socat - unix-connect:$UZBL_SOCKET @@ -193,7 +193,7 @@ else # printf 'js %s dump(); \n' "$dumpFunction" | \ socat - unix-connect:$UZBL_SOCKET | \ - sed -n '/^[^(]\+([^)]\+):/p' >> $UZBL_FORMS_DIR/$domain + sed -n -e '/^[^(]\+([^)]\+):/p' >> $UZBL_FORMS_DIR/$domain fi [ -e "$UZBL_FORMS_DIR/$domain" ] || exit 3 #this should never happen, but you never know. $UZBL_EDITOR "$UZBL_FORMS_DIR/$domain" #TODO: if user aborts save in editor, the file is already overwritten diff --git a/examples/data/scripts/session.sh b/examples/data/scripts/session.sh index 185d722..4466ef7 100755 --- a/examples/data/scripts/session.sh +++ b/examples/data/scripts/session.sh @@ -20,7 +20,7 @@ if [ -z "$UZBL_UTIL_DIR" ]; then # using the same logic as uzbl-browser does. UZBL_UTIL_DIR=${XDG_DATA_HOME:-$HOME/.local/share}/uzbl/scripts/util if ! [ -d "$UZBL_UTIL_DIR" ]; then - PREFIX=$(grep '^PREFIX' "$(which uzbl-browser)" | sed 's/.*=//') + PREFIX=$(grep '^PREFIX' "$(which uzbl-browser)" | sed -e 's/.*=//') UZBL_UTIL_DIR=$PREFIX/share/uzbl/examples/data/scripts/util fi fi -- cgit v1.2.3 From 06c29bbd5d1ad0542d8de4a6661bd8366d9c56d5 Mon Sep 17 00:00:00 2001 From: Ben Boeckel Date: Thu, 10 Mar 2011 19:54:44 -0500 Subject: Quote variables which may contain spaces --- examples/data/scripts/download.sh | 10 ++-- examples/data/scripts/follow.sh | 4 +- examples/data/scripts/formfiller.sh | 70 ++++++++++++------------ examples/data/scripts/go_input.sh | 2 +- examples/data/scripts/history.sh | 2 +- examples/data/scripts/insert_bookmark.sh | 6 +- examples/data/scripts/instance-select-wmii.sh | 14 ++--- examples/data/scripts/load_cookies.sh | 8 +-- examples/data/scripts/load_url_from_bookmarks.sh | 6 +- examples/data/scripts/load_url_from_history.sh | 8 +-- examples/data/scripts/session.sh | 14 ++--- examples/data/scripts/util/uzbl-dir.sh | 18 +++--- examples/data/scripts/util/uzbl-window.sh | 16 +++--- 13 files changed, 89 insertions(+), 89 deletions(-) diff --git a/examples/data/scripts/download.sh b/examples/data/scripts/download.sh index a382d9f..561ac31 100755 --- a/examples/data/scripts/download.sh +++ b/examples/data/scripts/download.sh @@ -9,17 +9,17 @@ . "$UZBL_UTIL_DIR/uzbl-dir.sh" # the URL that is being downloaded -uri=$1 +uri="$1" # a filename suggested by the server or based on the URL -suggested_filename=${2:-$(echo "$uri" | sed -e 's/\W/-/g')} +suggested_filename="${2:-$(echo "$uri" | sed -e 's/\W/-/g')}" # the mimetype of the file being downloaded -content_type=$3 +content_type="$3" # the size of the downloaded file in bytes. this is not always accurate, since # the server might not have sent a size with its response headers. -total_size=$4 +total_size="$4" # just save the file to the default directory with the suggested name -echo $UZBL_DOWNLOAD_DIR/$suggested_filename +echo "$UZBL_DOWNLOAD_DIR/$suggested_filename" diff --git a/examples/data/scripts/follow.sh b/examples/data/scripts/follow.sh index d1560bf..3d0e992 100755 --- a/examples/data/scripts/follow.sh +++ b/examples/data/scripts/follow.sh @@ -6,11 +6,11 @@ # if socat is installed then we can change Uzbl's input mode once a link is # selected; otherwise we just select a link. if ! which socat >/dev/null 2>&1; then - echo 'script @scripts_dir/follow.js "@{follow_hint_keys} '$1'"' > "$UZBL_FIFO" + echo "script @scripts_dir/follow.js \"@{follow_hint_keys} $1\"" > "$UZBL_FIFO" exit fi -result=$(echo 'script @scripts_dir/follow.js "@{follow_hint_keys} '$1'"' | socat - unix-connect:"$UZBL_SOCKET") +result="$(echo "script @scripts_dir/follow.js \"@{follow_hint_keys} $1\"" | socat - "unix-connect:$UZBL_SOCKET")" case $result in *XXXEMIT_FORM_ACTIVEXXX*) # a form element was selected diff --git a/examples/data/scripts/formfiller.sh b/examples/data/scripts/formfiller.sh index 408666f..9ce36b4 100755 --- a/examples/data/scripts/formfiller.sh +++ b/examples/data/scripts/formfiller.sh @@ -47,15 +47,15 @@ DMENU_OPTIONS="vertical resize" . "$UZBL_UTIL_DIR/editor.sh" . "$UZBL_UTIL_DIR/uzbl-dir.sh" -RAND=$(dd if=/dev/urandom count=1 2> /dev/null | cksum | cut -c 1-5) +RAND="$(dd if=/dev/urandom count=1 2> /dev/null | cksum | cut -c 1-5)" MODELINE="> vim:ft=formfiller" -[ -d "$(dirname $UZBL_FORMS_DIR)" ] || exit 1 -[ -d $UZBL_FORMS_DIR ] || mkdir $UZBL_FORMS_DIR || exit 1 +[ -d "$(dirname "$UZBL_FORMS_DIR")" ] || exit 1 +[ -d "$UZBL_FORMS_DIR" ] || mkdir "$UZBL_FORMS_DIR" || exit 1 -action=$1 +action="$1" -domain=$(echo $UZBL_URI | sed -e 's/\(http\|https\):\/\/\([^\/]\+\)\/.*/\2/') +domain="$(echo "$UZBL_URI" | sed -e 's/\(http\|https\):\/\/\([^\/]\+\)\/.*/\2/')" if [ "$action" != 'edit' -a "$action" != 'new' -a "$action" != 'load' -a "$action" != 'add' -a "$action" != 'once' ]; then action="new" @@ -92,7 +92,7 @@ dumpFunction="function dump() { \ catch(err) { } \ } \ return rv; \ -}; " +};" insertFunction="function insert(fname, ftype, fvalue, fchecked) { \ var allFrames = new Array(window); \ @@ -118,63 +118,63 @@ insertFunction="function insert(fname, ftype, fvalue, fchecked) { \ } \ catch(err) { } \ } \ -}; " +};" if [ "$action" = 'load' ]; then - [ -e $UZBL_FORMS_DIR/$domain ] || exit 2 - if [ $(cat $UZBL_FORMS_DIR/$domain | grep "!profile" | wc -l) -gt 1 ]; then - menu=$(cat $UZBL_FORMS_DIR/$domain | \ - sed -n -e 's/^!profile=\([^[:blank:]]\+\)/\1/p') - option=$(printf "$menu" | $DMENU) + [ -e "$UZBL_FORMS_DIR/$domain" ] || exit 2 + if [ "$(cat "$UZBL_FORMS_DIR/$domain" | grep "!profile" | wc -l)" -gt 1 ]; then + menu="$(cat "$UZBL_FORMS_DIR/$domain" | \ + sed -n -e 's/^!profile=\([^[:blank:]]\+\)/\1/p')" + option="$(printf "$menu" | $DMENU)" fi # Remove comments - sed -i -e '/^>/d' $tmpfile + sed -i -e '/^>/d' "$tmpfile" - sed -i -e 's/^\([^{]\+\){\([^}]*\)}(\(radio\|checkbox\)):\(off\|no\|false\|unchecked\|0\|$\)/\1{\2}(\3):0/I;s/^\([^{]\+\){\([^}]*\)}(\(radio\|checkbox\)):[^0]\+/\1{\2}(\3):1/I' $UZBL_FORMS_DIR/$domain - fields=$(cat $UZBL_FORMS_DIR/$domain | \ + sed -i -e 's/^\([^{]\+\){\([^}]*\)}(\(radio\|checkbox\)):\(off\|no\|false\|unchecked\|0\|$\)/\1{\2}(\3):0/I;s/^\([^{]\+\){\([^}]*\)}(\(radio\|checkbox\)):[^0]\+/\1{\2}(\3):1/I' "$UZBL_FORMS_DIR/$domain" + fields="$(cat "$UZBL_FORMS_DIR/$domain" | \ sed -n -e "/^!profile=${option}/,/^!profile=/p" | \ sed -e '/^!profile=/d' | \ sed -e 's/^\([^(]\+(\)\(radio\|checkbox\|text\|search\|textarea\|password\)):/%{>\1\2):<}%/' | \ sed -e 's/^\(.\+\)$/<{br}>\1/' | \ tr -d '\n' | \ - sed -e 's/<{br}>%{>\([^(]\+(\)\(radio\|checkbox\|text\|search\|textarea\|password\)):<}%/\\n\1\2):/g') + sed -e 's/<{br}>%{>\([^(]\+(\)\(radio\|checkbox\|text\|search\|textarea\|password\)):<}%/\\n\1\2):/g')" printf '%s\n' "${fields}" | \ sed -n -e "s/\([^(]\+\)(\(password\|text\|search\|textarea\)\+):[ ]*\(.\+\)/js $insertFunction; insert('\1', '\2', '\3', 0);/p" | \ - sed -e 's/@/\\@/g;s/<{br}>/\\\\n/g' | socat - unix-connect:$UZBL_SOCKET + sed -e 's/@/\\@/g;s/<{br}>/\\\\n/g' | socat - "unix-connect:$UZBL_SOCKET" printf '%s\n' "${fields}" | \ sed -n -e "s/\([^{]\+\){\([^}]*\)}(\(radio\|checkbox\)):[ ]*\(.\+\)/js $insertFunction; insert('\1', '\3', '\2', \4);/p" | \ - sed -e 's/@/\\@/g' | socat - unix-connect:$UZBL_SOCKET + sed -e 's/@/\\@/g' | socat - "unix-connect:$UZBL_SOCKET" elif [ "$action" = "once" ]; then - tmpfile=$(mktemp) + tmpfile="$(mktemp)" printf 'js %s dump(); \n' "$dumpFunction" | \ - socat - unix-connect:$UZBL_SOCKET | \ - sed -n -e '/^[^(]\+([^)]\+):/p' > $tmpfile - echo "$MODELINE" >> $tmpfile - $UZBL_EDITOR $tmpfile + socat - "unix-connect:$UZBL_SOCKET" | \ + sed -n -e '/^[^(]\+([^)]\+):/p' > "$tmpfile" + echo "$MODELINE" >> "$tmpfile" + $UZBL_EDITOR "$tmpfile" - [ -e $tmpfile ] || exit 2 + [ -e "$tmpfile" ] || exit 2 # Remove comments - sed -i -e '/^>/d' $tmpfile + sed -i -e '/^>/d' "$tmpfile" - sed -i -e 's/^\([^{]\+\){\([^}]*\)}(\(radio\|checkbox\)):\(off\|no\|false\|unchecked\|0\|$\)/\1{\2}(\3):0/I;s/^\([^{]\+\){\([^}]*\)}(\(radio\|checkbox\)):[^0]\+/\1{\2}(\3):1/I' $tmpfile - fields=$(cat $tmpfile | \ + sed -i -e 's/^\([^{]\+\){\([^}]*\)}(\(radio\|checkbox\)):\(off\|no\|false\|unchecked\|0\|$\)/\1{\2}(\3):0/I;s/^\([^{]\+\){\([^}]*\)}(\(radio\|checkbox\)):[^0]\+/\1{\2}(\3):1/I' "$tmpfile" + fields="$(cat "$tmpfile" | \ sed -e 's/^\([^(]\+(\)\(radio\|checkbox\|text\|search\|textarea\|password\)):/%{>\1\2):<}%/' | \ sed -e 's/^\(.\+\)$/<{br}>\1/' | \ tr -d '\n' | \ - sed -e 's/<{br}>%{>\([^(]\+(\)\(radio\|checkbox\|text\|search\|textarea\|password\)):<}%/\\n\1\2):/g') + sed -e 's/<{br}>%{>\([^(]\+(\)\(radio\|checkbox\|text\|search\|textarea\|password\)):<}%/\\n\1\2):/g')" printf '%s\n' "${fields}" | \ sed -n -e "s/\([^(]\+\)(\(password\|text\|search\|textarea\)\+):[ ]*\(.\+\)/js $insertFunction; insert('\1', '\2', '\3', 0);/p" | \ - sed -e 's/@/\\@/g;s/<{br}>/\\\\n/g' | socat - unix-connect:$UZBL_SOCKET + sed -e 's/@/\\@/g;s/<{br}>/\\\\n/g' | socat - "unix-connect:$UZBL_SOCKET" printf '%s\n' "${fields}" | \ sed -n -e "s/\([^{]\+\){\([^}]*\)}(\(radio\|checkbox\)):[ ]*\(.\+\)/js $insertFunction; insert('\1', '\3', '\2', \4);/p" | \ - sed -e 's/@/\\@/g' | socat - unix-connect:$UZBL_SOCKET - rm -f $tmpfile + sed -e 's/@/\\@/g' | socat - "unix-connect:$UZBL_SOCKET" + rm -f "$tmpfile" else if [ "$action" = 'new' -o "$action" = 'add' ]; then - [ "$action" = 'new' ] && echo "$MODELINE" > $UZBL_FORMS_DIR/$domain - echo "!profile=NAME_THIS_PROFILE$RAND" >> $UZBL_FORMS_DIR/$domain + [ "$action" = 'new' ] && echo "$MODELINE" > "$UZBL_FORMS_DIR/$domain" + echo "!profile=NAME_THIS_PROFILE$RAND" >> "$UZBL_FORMS_DIR/$domain" # # 2. and 3. line (tr -d and sed) are because, on gmail login for example, # tag is splited into lines @@ -192,8 +192,8 @@ else # passwd(password): # printf 'js %s dump(); \n' "$dumpFunction" | \ - socat - unix-connect:$UZBL_SOCKET | \ - sed -n -e '/^[^(]\+([^)]\+):/p' >> $UZBL_FORMS_DIR/$domain + socat - "unix-connect:$UZBL_SOCKET" | \ + sed -n -e '/^[^(]\+([^)]\+):/p' >> "$UZBL_FORMS_DIR/$domain" fi [ -e "$UZBL_FORMS_DIR/$domain" ] || exit 3 #this should never happen, but you never know. $UZBL_EDITOR "$UZBL_FORMS_DIR/$domain" #TODO: if user aborts save in editor, the file is already overwritten diff --git a/examples/data/scripts/go_input.sh b/examples/data/scripts/go_input.sh index ace0e79..a09c604 100755 --- a/examples/data/scripts/go_input.sh +++ b/examples/data/scripts/go_input.sh @@ -1,5 +1,5 @@ #!/bin/sh -case $(echo 'script @scripts_dir/go_input.js' | socat - unix-connect:"$UZBL_SOCKET") in +case "$(echo 'script @scripts_dir/go_input.js' | socat - "unix-connect:$UZBL_SOCKET")" in *XXXEMIT_FORM_ACTIVEXXX*) echo 'event FORM_ACTIVE' > "$UZBL_FIFO" ;; esac diff --git a/examples/data/scripts/history.sh b/examples/data/scripts/history.sh index 3972e3a..bbef20a 100755 --- a/examples/data/scripts/history.sh +++ b/examples/data/scripts/history.sh @@ -4,4 +4,4 @@ [ -w "$UZBL_HISTORY_FILE" ] || [ ! -a "$UZBL_HISTORY_FILE" ] || exit 1 -echo $(date +'%Y-%m-%d %H:%M:%S')" $UZBL_URI $UZBL_TITLE" >> $UZBL_HISTORY_FILE +echo "$( date +'%Y-%m-%d %H:%M:%S' ) $UZBL_URI $UZBL_TITLE" >> "$UZBL_HISTORY_FILE" diff --git a/examples/data/scripts/insert_bookmark.sh b/examples/data/scripts/insert_bookmark.sh index a42948c..374bea0 100755 --- a/examples/data/scripts/insert_bookmark.sh +++ b/examples/data/scripts/insert_bookmark.sh @@ -7,9 +7,9 @@ which zenity >/dev/null 2>&1 || exit 2 -tags=$(zenity --entry --text="Enter space-separated tags for bookmark $UZBL_URI:") -exitstatus=$? -[ $exitstatus -eq 0 ] || exit $exitstatus +tags="$(zenity --entry --text="Enter space-separated tags for bookmark $UZBL_URI:")" +exitstatus="$?" +[ "$exitstatus" -eq 0 ] || exit "$exitstatus" # TODO: check if already exists, if so, and tags are different: ask if you want to replace tags echo "$UZBL_URI $tags" >> "$UZBL_BOOKMARKS_FILE" diff --git a/examples/data/scripts/instance-select-wmii.sh b/examples/data/scripts/instance-select-wmii.sh index b3a5a87..57ef0cb 100755 --- a/examples/data/scripts/instance-select-wmii.sh +++ b/examples/data/scripts/instance-select-wmii.sh @@ -16,26 +16,26 @@ DMENU_SCHEME="wmii" case "$1" in "list" ) - list= + list="" # get window id's of uzbl clients. we could also get the label in one shot but it's pretty tricky for i in $(wmiir read /tag/sel/index | grep uzbl |cut -d ' ' -f2); do - label=$(wmiir read /client/$i/label) + label="$(wmiir read /client/$i/label)" list="$list$i : $label\n" done - window=$(printf "$list\n" | $DMENU | cut -d ' ' -f1) + window="$(printf "$list\n" | $DMENU | cut -d ' ' -f1)" wmiir xwrite /tag/sel/ctl "select client $window" ;; "next" ) - current=$(wmiir read /client/sel/ctl | head -n 1) + current="$(wmiir read /client/sel/ctl | head -n 1)" # find the next uzbl window and focus it - next=$(wmiir read /tag/sel/index | grep -A 10000 " $current " | grep -m 1 uzbl | cut -d ' ' -f2) + next="$(wmiir read /tag/sel/index | grep -A 10000 " $current " | grep -m 1 uzbl | cut -d ' ' -f2)" if [ -n "$next" ]; then wmiir xwrite /tag/sel/ctl "select client $next" fi ;; "prev" ) - current=$(wmiir read /client/sel/ctl | head -n 1) - prev=$(wmiir read /tag/sel/index | grep -B 10000 " $current " | tac | grep -m 1 uzbl | cut -d ' ' -f2) + current="$(wmiir read /client/sel/ctl | head -n 1)" + prev="$(wmiir read /tag/sel/index | grep -B 10000 " $current " | tac | grep -m 1 uzbl | cut -d ' ' -f2)" if [ -n "$prev" ]; then wmiir xwrite /tag/sel/ctl "select client $prev" fi diff --git a/examples/data/scripts/load_cookies.sh b/examples/data/scripts/load_cookies.sh index 17ec2ad..65541b4 100755 --- a/examples/data/scripts/load_cookies.sh +++ b/examples/data/scripts/load_cookies.sh @@ -1,9 +1,9 @@ #!/bin/sh -if [ "$1" != "" ]; then - cookie_file=$1 +if [ -n "$1" ]; then + cookie_file="$1" else - cookie_file=${XDG_DATA_HOME:-$HOME/.local/share}/uzbl/cookies.txt + cookie_file="${XDG_DATA_HOME:-$HOME/.local/share}/uzbl/cookies.txt" fi awk -F \\t ' @@ -17,4 +17,4 @@ printf("add_cookie \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\"\n", substr($1,lengt $0 !~ /^#/ { printf("add_cookie \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\"\n", $1, $3, $6, $7, scheme[$4], $5) } -' $cookie_file +' "$cookie_file" diff --git a/examples/data/scripts/load_url_from_bookmarks.sh b/examples/data/scripts/load_url_from_bookmarks.sh index 704e106..d47d189 100755 --- a/examples/data/scripts/load_url_from_bookmarks.sh +++ b/examples/data/scripts/load_url_from_bookmarks.sh @@ -12,11 +12,11 @@ DMENU_OPTIONS="xmms vertical resize" if [ -z "$DMENU_HAS_VERTICAL" ]; then # because they are all after each other, just show the url, not their tags. - goto=$(awk '{print $1}' "$UZBL_BOOKMARKS_FILE" | $DMENU) + goto="$(awk '{print $1}' "$UZBL_BOOKMARKS_FILE" | $DMENU)" else # show tags as well - goto=$($DMENU < "$UZBL_BOOKMARKS_FILE" | awk '{print $1}') + goto="$($DMENU < "$UZBL_BOOKMARKS_FILE" | awk '{print $1}')" fi [ -n "$goto" ] && echo "uri $goto" > "$UZBL_FIFO" -#[ -n "$goto" ] && echo "uri $goto" | socat - unix-connect:"$UZBL_SOCKET" +#[ -n "$goto" ] && echo "uri $goto" | socat - "unix-connect:$UZBL_SOCKET" diff --git a/examples/data/scripts/load_url_from_history.sh b/examples/data/scripts/load_url_from_history.sh index 256a342..9cca356 100755 --- a/examples/data/scripts/load_url_from_history.sh +++ b/examples/data/scripts/load_url_from_history.sh @@ -11,13 +11,13 @@ DMENU_OPTIONS="xmms vertical resize" # choose from all entries, sorted and uniqued # goto=$(awk '{print $3}' $history_file | sort -u | dmenu -i) if [ -z "$DMENU_HAS_VERTICAL" ]; then - current=$(tail -n 1 "$UZBL_HISTORY_FILE" | awk '{print $3}'); - goto=$( (echo $current; awk '{print $3}' "$UZBL_HISTORY_FILE" | grep -v "^$current\$" | sort -u) | $DMENU) + current="$(tail -n 1 "$UZBL_HISTORY_FILE" | awk '{print $3}')" + goto="$( (echo "$current"; awk '{print $3}' "$UZBL_HISTORY_FILE" | grep -v "^$current\$" | sort -u) | $DMENU)" else # choose an item in reverse order, showing also the date and page titles # pick the last field from the first 3 fields. this way you can pick a url (prefixed with date & time) or type just a new url. - goto=$(tac "$UZBL_HISTORY_FILE" | $DMENU | cut -d ' ' -f -3 | awk '{print $NF}') + goto="$(tac "$UZBL_HISTORY_FILE" | $DMENU | cut -d ' ' -f -3 | awk '{print $NF}')" fi [ -n "$goto" ] && echo "uri $goto" > "$UZBL_FIFO" -#[ -n "$goto" ] && echo "uri $goto" | socat - unix-connect:"$UZBL_SOCKET" +#[ -n "$goto" ] && echo "uri $goto" | socat - "unix-connect:$UZBL_SOCKET" diff --git a/examples/data/scripts/session.sh b/examples/data/scripts/session.sh index 4466ef7..80c9744 100755 --- a/examples/data/scripts/session.sh +++ b/examples/data/scripts/session.sh @@ -18,19 +18,19 @@ if [ -z "$UZBL_UTIL_DIR" ]; then # we're being run standalone, we have to figure out where $UZBL_UTIL_DIR is # using the same logic as uzbl-browser does. - UZBL_UTIL_DIR=${XDG_DATA_HOME:-$HOME/.local/share}/uzbl/scripts/util + UZBL_UTIL_DIR="${XDG_DATA_HOME:-$HOME/.local/share}/uzbl/scripts/util" if ! [ -d "$UZBL_UTIL_DIR" ]; then - PREFIX=$(grep '^PREFIX' "$(which uzbl-browser)" | sed -e 's/.*=//') - UZBL_UTIL_DIR=$PREFIX/share/uzbl/examples/data/scripts/util + PREFIX="$(grep '^PREFIX' "$(which uzbl-browser)" | sed -e 's/.*=//')" + UZBL_UTIL_DIR="$PREFIX/share/uzbl/examples/data/scripts/util" fi fi . "$UZBL_UTIL_DIR/uzbl-dir.sh" [ -d "$UZBL_DATA_DIR" ] || exit 1 -UZBL="uzbl-browser -c $UZBL_CONFIG_FILE" # add custom flags and whatever here. +UZBL="uzbl-browser -c \"$UZBL_CONFIG_FILE\"" # add custom flags and whatever here. -scriptfile=$(readlink -f $0) # this script +scriptfile="$(readlink -f "$0")" # this script act="$1" if [ -z "$act" ]; then @@ -39,7 +39,7 @@ fi case $act in "launch" ) - urls=$(cat "$UZBL_SESSION_FILE") + urls="$(cat "$UZBL_SESSION_FILE")" if [ -z "$urls" ]; then $UZBL else @@ -60,7 +60,7 @@ case $act in ;; "endsession" ) - for fifo in "$UZBL_FIFO_DIR"/uzbl_fifo_*; do + for fifo in "$UZBL_FIFO_DIR/uzbl_fifo_*"; do if [ "$fifo" != "$UZBL_FIFO" ]; then echo "spawn $scriptfile endinstance" > "$fifo" fi diff --git a/examples/data/scripts/util/uzbl-dir.sh b/examples/data/scripts/util/uzbl-dir.sh index bb56954..3d28151 100644 --- a/examples/data/scripts/util/uzbl-dir.sh +++ b/examples/data/scripts/util/uzbl-dir.sh @@ -2,18 +2,18 @@ # Common directories and files used in scripts # Common things first -UZBL_DATA_DIR=${XDG_DATA_HOME:-$HOME/.local/share}/uzbl -UZBL_CONFIG_DIR=${XDG_CONFIG_DIR:-$HOME/.config}/uzbl +UZBL_DATA_DIR="${XDG_DATA_HOME:-$HOME/.local/share}/uzbl" +UZBL_CONFIG_DIR="${XDG_CONFIG_DIR:-$HOME/.config}/uzbl" UZBL_FIFO_DIR=/tmp UZBL_SOCKET_DIR=/tmp # Directories -UZBL_DOWNLOAD_DIR=${XDG_DOWNLOAD_DIR:-$HOME} -UZBL_FORMS_DIR=$UZBL_DATA_DIR/dforms +UZBL_DOWNLOAD_DIR="${XDG_DOWNLOAD_DIR:-$HOME}" +UZBL_FORMS_DIR="$UZBL_DATA_DIR/dforms" # Data files -UZBL_CONFIG_FILE=$UZBL_CONFIG_DIR/config -UZBL_COOKIE_FILE=$UZBL_DATA_DIR/cookies.txt -UZBL_BOOKMARKS_FILE=$UZBL_DATA_DIR/bookmarks -UZBL_HISTORY_FILE=$UZBL_DATA_DIR/history -UZBL_SESSION_FILE=$UZBL_DATA_DIR/browser-session +UZBL_CONFIG_FILE="$UZBL_CONFIG_DIR/config" +UZBL_COOKIE_FILE="$UZBL_DATA_DIR/cookies.txt" +UZBL_BOOKMARKS_FILE="$UZBL_DATA_DIR/bookmarks" +UZBL_HISTORY_FILE="$UZBL_DATA_DIR/history" +UZBL_SESSION_FILE="$UZBL_DATA_DIR/browser-session" diff --git a/examples/data/scripts/util/uzbl-window.sh b/examples/data/scripts/util/uzbl-window.sh index a7e92eb..35ce013 100644 --- a/examples/data/scripts/util/uzbl-window.sh +++ b/examples/data/scripts/util/uzbl-window.sh @@ -1,11 +1,11 @@ #!/bin/sh # uzbl window detection -UZBL_WIN_POS=$(xwininfo -id $UZBL_XID | \ - sed -ne 's/Corners:[ ]*[+-]\([0-9]*\)[+-]\([0-9]*\).*$/\1 \2/p') -UZBL_WIN_SIZE=$(xwininfo -id $UZBL_XID | \ - sed -ne 's/-geometry[ ]*\([0-9]*\)x\([0-9]*\).*$/\1 \2/p') -UZBL_WIN_POS_X=$(echo $UZBL_WIN_POS | cut -d\ -f1) -UZBL_WIN_POS_Y=$(echo $UZBL_WIN_POS | cut -d\ -f2) -UZBL_WIN_WIDTH=$(echo $UZBL_WIN_SIZE | cut -d\ -f1) -UZBL_WIN_HEIGHT=$(echo $UZBL_WIN_SIZE | cut -d\ -f2) +UZBL_WIN_POS="$(xwininfo -id $UZBL_XID | \ + sed -ne 's/Corners:[ ]*[+-]\([0-9]*\)[+-]\([0-9]*\).*$/\1 \2/p')" +UZBL_WIN_SIZE="$(xwininfo -id $UZBL_XID | \ + sed -ne 's/-geometry[ ]*\([0-9]*\)x\([0-9]*\).*$/\1 \2/p')" +UZBL_WIN_POS_X="$(echo "$UZBL_WIN_POS" | cut -d\ -f1)" +UZBL_WIN_POS_Y="$(echo "$UZBL_WIN_POS" | cut -d\ -f2)" +UZBL_WIN_WIDTH="$(echo "$UZBL_WIN_SIZE" | cut -d\ -f1)" +UZBL_WIN_HEIGHT="$(echo "$UZBL_WIN_SIZE" | cut -d\ -f2)" -- cgit v1.2.3 From db5213a116da236ff829ee4fa9a14c20867a852b Mon Sep 17 00:00:00 2001 From: Ben Boeckel Date: Thu, 10 Mar 2011 19:59:55 -0500 Subject: Remove the use of positional arguments Positional arguments should be given meaningful names. --- examples/data/scripts/follow.sh | 7 +++++-- examples/data/scripts/formfiller.sh | 1 + examples/data/scripts/load_cookies.sh | 1 + examples/data/scripts/session.sh | 1 + 4 files changed, 8 insertions(+), 2 deletions(-) diff --git a/examples/data/scripts/follow.sh b/examples/data/scripts/follow.sh index 3d0e992..83db395 100755 --- a/examples/data/scripts/follow.sh +++ b/examples/data/scripts/follow.sh @@ -3,14 +3,17 @@ # This script is just a wrapper around follow.js that lets us change uzbl's mode # after a link is selected. +keys="$1" +shift + # if socat is installed then we can change Uzbl's input mode once a link is # selected; otherwise we just select a link. if ! which socat >/dev/null 2>&1; then - echo "script @scripts_dir/follow.js \"@{follow_hint_keys} $1\"" > "$UZBL_FIFO" + echo "script @scripts_dir/follow.js \"@{follow_hint_keys} $keys\"" > "$UZBL_FIFO" exit fi -result="$(echo "script @scripts_dir/follow.js \"@{follow_hint_keys} $1\"" | socat - "unix-connect:$UZBL_SOCKET")" +result="$(echo "script @scripts_dir/follow.js \"@{follow_hint_keys} $keys\"" | socat - "unix-connect:$UZBL_SOCKET")" case $result in *XXXEMIT_FORM_ACTIVEXXX*) # a form element was selected diff --git a/examples/data/scripts/formfiller.sh b/examples/data/scripts/formfiller.sh index 9ce36b4..907ceef 100755 --- a/examples/data/scripts/formfiller.sh +++ b/examples/data/scripts/formfiller.sh @@ -54,6 +54,7 @@ MODELINE="> vim:ft=formfiller" [ -d "$UZBL_FORMS_DIR" ] || mkdir "$UZBL_FORMS_DIR" || exit 1 action="$1" +shift domain="$(echo "$UZBL_URI" | sed -e 's/\(http\|https\):\/\/\([^\/]\+\)\/.*/\2/')" diff --git a/examples/data/scripts/load_cookies.sh b/examples/data/scripts/load_cookies.sh index 65541b4..eff044b 100755 --- a/examples/data/scripts/load_cookies.sh +++ b/examples/data/scripts/load_cookies.sh @@ -2,6 +2,7 @@ if [ -n "$1" ]; then cookie_file="$1" + shift else cookie_file="${XDG_DATA_HOME:-$HOME/.local/share}/uzbl/cookies.txt" fi diff --git a/examples/data/scripts/session.sh b/examples/data/scripts/session.sh index 80c9744..73ee99b 100755 --- a/examples/data/scripts/session.sh +++ b/examples/data/scripts/session.sh @@ -32,6 +32,7 @@ UZBL="uzbl-browser -c \"$UZBL_CONFIG_FILE\"" # add custom flags and whatever her scriptfile="$(readlink -f "$0")" # this script act="$1" +shift if [ -z "$act" ]; then [ -f "$UZBL_SESSION_FILE" ] && act="launch" || act="endsession" -- cgit v1.2.3 From 6cb7be2b071f5e540c33ecc5e21ab22c81434834 Mon Sep 17 00:00:00 2001 From: Ben Boeckel Date: Thu, 10 Mar 2011 20:02:12 -0500 Subject: Reduce the complexity of the variable assignment --- examples/data/scripts/download.sh | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/examples/data/scripts/download.sh b/examples/data/scripts/download.sh index 561ac31..6bcd9d1 100755 --- a/examples/data/scripts/download.sh +++ b/examples/data/scripts/download.sh @@ -11,8 +11,10 @@ # the URL that is being downloaded uri="$1" +safe_uri="$(echo "$uri" | sed -e 's/\W/-/g')" + # a filename suggested by the server or based on the URL -suggested_filename="${2:-$(echo "$uri" | sed -e 's/\W/-/g')}" +suggested_filename="${2:-$safe_uri}" # the mimetype of the file being downloaded content_type="$3" -- cgit v1.2.3 From 03e2f59ec0959ba4dec30a903ac060d74e5fdac5 Mon Sep 17 00:00:00 2001 From: Ben Boeckel Date: Thu, 10 Mar 2011 20:48:54 -0500 Subject: Add padding inside of braces --- examples/data/scripts/download.sh | 2 +- examples/data/scripts/follow.sh | 2 +- examples/data/scripts/formfiller.sh | 24 ++++++++++++------------ examples/data/scripts/go_input.sh | 2 +- examples/data/scripts/insert_bookmark.sh | 2 +- examples/data/scripts/instance-select-wmii.sh | 14 +++++++------- examples/data/scripts/load_url_from_bookmarks.sh | 4 ++-- examples/data/scripts/load_url_from_history.sh | 7 +++---- examples/data/scripts/session.sh | 6 +++--- examples/data/scripts/util/uzbl-window.sh | 16 ++++++++-------- 10 files changed, 39 insertions(+), 40 deletions(-) diff --git a/examples/data/scripts/download.sh b/examples/data/scripts/download.sh index 6bcd9d1..7753bd6 100755 --- a/examples/data/scripts/download.sh +++ b/examples/data/scripts/download.sh @@ -11,7 +11,7 @@ # the URL that is being downloaded uri="$1" -safe_uri="$(echo "$uri" | sed -e 's/\W/-/g')" +safe_uri="$( echo "$uri" | sed -e 's/\W/-/g' )" # a filename suggested by the server or based on the URL suggested_filename="${2:-$safe_uri}" diff --git a/examples/data/scripts/follow.sh b/examples/data/scripts/follow.sh index 83db395..9754778 100755 --- a/examples/data/scripts/follow.sh +++ b/examples/data/scripts/follow.sh @@ -13,7 +13,7 @@ if ! which socat >/dev/null 2>&1; then exit fi -result="$(echo "script @scripts_dir/follow.js \"@{follow_hint_keys} $keys\"" | socat - "unix-connect:$UZBL_SOCKET")" +result="$( echo "script @scripts_dir/follow.js \"@{follow_hint_keys} $keys\"" | socat - "unix-connect:$UZBL_SOCKET" )" case $result in *XXXEMIT_FORM_ACTIVEXXX*) # a form element was selected diff --git a/examples/data/scripts/formfiller.sh b/examples/data/scripts/formfiller.sh index 907ceef..637a98f 100755 --- a/examples/data/scripts/formfiller.sh +++ b/examples/data/scripts/formfiller.sh @@ -47,16 +47,16 @@ DMENU_OPTIONS="vertical resize" . "$UZBL_UTIL_DIR/editor.sh" . "$UZBL_UTIL_DIR/uzbl-dir.sh" -RAND="$(dd if=/dev/urandom count=1 2> /dev/null | cksum | cut -c 1-5)" +RAND="$( dd if=/dev/urandom count=1 2>/dev/null | cksum | cut -c 1-5 )" MODELINE="> vim:ft=formfiller" -[ -d "$(dirname "$UZBL_FORMS_DIR")" ] || exit 1 +[ -d "$( dirname "$UZBL_FORMS_DIR" )" ] || exit 1 [ -d "$UZBL_FORMS_DIR" ] || mkdir "$UZBL_FORMS_DIR" || exit 1 action="$1" shift -domain="$(echo "$UZBL_URI" | sed -e 's/\(http\|https\):\/\/\([^\/]\+\)\/.*/\2/')" +domain="$( echo "$UZBL_URI" | sed -e 's/\(http\|https\):\/\/\([^\/]\+\)\/.*/\2/' )" if [ "$action" != 'edit' -a "$action" != 'new' -a "$action" != 'load' -a "$action" != 'add' -a "$action" != 'once' ]; then action="new" @@ -123,23 +123,23 @@ insertFunction="function insert(fname, ftype, fvalue, fchecked) { \ if [ "$action" = 'load' ]; then [ -e "$UZBL_FORMS_DIR/$domain" ] || exit 2 - if [ "$(cat "$UZBL_FORMS_DIR/$domain" | grep "!profile" | wc -l)" -gt 1 ]; then - menu="$(cat "$UZBL_FORMS_DIR/$domain" | \ - sed -n -e 's/^!profile=\([^[:blank:]]\+\)/\1/p')" - option="$(printf "$menu" | $DMENU)" + if [ "$( cat "$UZBL_FORMS_DIR/$domain" | grep "!profile" | wc -l )" -gt 1 ]; then + menu="$( cat "$UZBL_FORMS_DIR/$domain" | \ + sed -n -e 's/^!profile=\([^[:blank:]]\+\)/\1/p' )" + option="$( printf "$menu" | $DMENU )" fi # Remove comments sed -i -e '/^>/d' "$tmpfile" sed -i -e 's/^\([^{]\+\){\([^}]*\)}(\(radio\|checkbox\)):\(off\|no\|false\|unchecked\|0\|$\)/\1{\2}(\3):0/I;s/^\([^{]\+\){\([^}]*\)}(\(radio\|checkbox\)):[^0]\+/\1{\2}(\3):1/I' "$UZBL_FORMS_DIR/$domain" - fields="$(cat "$UZBL_FORMS_DIR/$domain" | \ + fields="$( cat "$UZBL_FORMS_DIR/$domain" | \ sed -n -e "/^!profile=${option}/,/^!profile=/p" | \ sed -e '/^!profile=/d' | \ sed -e 's/^\([^(]\+(\)\(radio\|checkbox\|text\|search\|textarea\|password\)):/%{>\1\2):<}%/' | \ sed -e 's/^\(.\+\)$/<{br}>\1/' | \ tr -d '\n' | \ - sed -e 's/<{br}>%{>\([^(]\+(\)\(radio\|checkbox\|text\|search\|textarea\|password\)):<}%/\\n\1\2):/g')" + sed -e 's/<{br}>%{>\([^(]\+(\)\(radio\|checkbox\|text\|search\|textarea\|password\)):<}%/\\n\1\2):/g' )" printf '%s\n' "${fields}" | \ sed -n -e "s/\([^(]\+\)(\(password\|text\|search\|textarea\)\+):[ ]*\(.\+\)/js $insertFunction; insert('\1', '\2', '\3', 0);/p" | \ sed -e 's/@/\\@/g;s/<{br}>/\\\\n/g' | socat - "unix-connect:$UZBL_SOCKET" @@ -147,7 +147,7 @@ if [ "$action" = 'load' ]; then sed -n -e "s/\([^{]\+\){\([^}]*\)}(\(radio\|checkbox\)):[ ]*\(.\+\)/js $insertFunction; insert('\1', '\3', '\2', \4);/p" | \ sed -e 's/@/\\@/g' | socat - "unix-connect:$UZBL_SOCKET" elif [ "$action" = "once" ]; then - tmpfile="$(mktemp)" + tmpfile="$( mktemp )" printf 'js %s dump(); \n' "$dumpFunction" | \ socat - "unix-connect:$UZBL_SOCKET" | \ sed -n -e '/^[^(]\+([^)]\+):/p' > "$tmpfile" @@ -160,11 +160,11 @@ elif [ "$action" = "once" ]; then sed -i -e '/^>/d' "$tmpfile" sed -i -e 's/^\([^{]\+\){\([^}]*\)}(\(radio\|checkbox\)):\(off\|no\|false\|unchecked\|0\|$\)/\1{\2}(\3):0/I;s/^\([^{]\+\){\([^}]*\)}(\(radio\|checkbox\)):[^0]\+/\1{\2}(\3):1/I' "$tmpfile" - fields="$(cat "$tmpfile" | \ + fields="$( cat "$tmpfile" | \ sed -e 's/^\([^(]\+(\)\(radio\|checkbox\|text\|search\|textarea\|password\)):/%{>\1\2):<}%/' | \ sed -e 's/^\(.\+\)$/<{br}>\1/' | \ tr -d '\n' | \ - sed -e 's/<{br}>%{>\([^(]\+(\)\(radio\|checkbox\|text\|search\|textarea\|password\)):<}%/\\n\1\2):/g')" + sed -e 's/<{br}>%{>\([^(]\+(\)\(radio\|checkbox\|text\|search\|textarea\|password\)):<}%/\\n\1\2):/g' )" printf '%s\n' "${fields}" | \ sed -n -e "s/\([^(]\+\)(\(password\|text\|search\|textarea\)\+):[ ]*\(.\+\)/js $insertFunction; insert('\1', '\2', '\3', 0);/p" | \ sed -e 's/@/\\@/g;s/<{br}>/\\\\n/g' | socat - "unix-connect:$UZBL_SOCKET" diff --git a/examples/data/scripts/go_input.sh b/examples/data/scripts/go_input.sh index a09c604..8d9ac84 100755 --- a/examples/data/scripts/go_input.sh +++ b/examples/data/scripts/go_input.sh @@ -1,5 +1,5 @@ #!/bin/sh -case "$(echo 'script @scripts_dir/go_input.js' | socat - "unix-connect:$UZBL_SOCKET")" in +case "$( echo 'script @scripts_dir/go_input.js' | socat - "unix-connect:$UZBL_SOCKET" )" in *XXXEMIT_FORM_ACTIVEXXX*) echo 'event FORM_ACTIVE' > "$UZBL_FIFO" ;; esac diff --git a/examples/data/scripts/insert_bookmark.sh b/examples/data/scripts/insert_bookmark.sh index 374bea0..b1ea07d 100755 --- a/examples/data/scripts/insert_bookmark.sh +++ b/examples/data/scripts/insert_bookmark.sh @@ -7,7 +7,7 @@ which zenity >/dev/null 2>&1 || exit 2 -tags="$(zenity --entry --text="Enter space-separated tags for bookmark $UZBL_URI:")" +tags="$( zenity --entry --text="Enter space-separated tags for bookmark $UZBL_URI:" )" exitstatus="$?" [ "$exitstatus" -eq 0 ] || exit "$exitstatus" diff --git a/examples/data/scripts/instance-select-wmii.sh b/examples/data/scripts/instance-select-wmii.sh index 57ef0cb..f0a7bef 100755 --- a/examples/data/scripts/instance-select-wmii.sh +++ b/examples/data/scripts/instance-select-wmii.sh @@ -18,24 +18,24 @@ case "$1" in "list" ) list="" # get window id's of uzbl clients. we could also get the label in one shot but it's pretty tricky - for i in $(wmiir read /tag/sel/index | grep uzbl |cut -d ' ' -f2); do - label="$(wmiir read /client/$i/label)" + for i in $( wmiir read /tag/sel/index | grep uzbl | cut -d ' ' -f2 ); do + label="$( wmiir read /client/$i/label )" list="$list$i : $label\n" done - window="$(printf "$list\n" | $DMENU | cut -d ' ' -f1)" + window="$( printf "$list\n" | $DMENU | cut -d ' ' -f1 )" wmiir xwrite /tag/sel/ctl "select client $window" ;; "next" ) - current="$(wmiir read /client/sel/ctl | head -n 1)" + current="$( wmiir read /client/sel/ctl | head -n 1 )" # find the next uzbl window and focus it - next="$(wmiir read /tag/sel/index | grep -A 10000 " $current " | grep -m 1 uzbl | cut -d ' ' -f2)" + next="$( wmiir read /tag/sel/index | grep -A 10000 " $current " | grep -m 1 uzbl | cut -d ' ' -f2 )" if [ -n "$next" ]; then wmiir xwrite /tag/sel/ctl "select client $next" fi ;; "prev" ) - current="$(wmiir read /client/sel/ctl | head -n 1)" - prev="$(wmiir read /tag/sel/index | grep -B 10000 " $current " | tac | grep -m 1 uzbl | cut -d ' ' -f2)" + current="$( wmiir read /client/sel/ctl | head -n 1 )" + prev="$( wmiir read /tag/sel/index | grep -B 10000 " $current " | tac | grep -m 1 uzbl | cut -d ' ' -f2 )" if [ -n "$prev" ]; then wmiir xwrite /tag/sel/ctl "select client $prev" fi diff --git a/examples/data/scripts/load_url_from_bookmarks.sh b/examples/data/scripts/load_url_from_bookmarks.sh index d47d189..5ba0d90 100755 --- a/examples/data/scripts/load_url_from_bookmarks.sh +++ b/examples/data/scripts/load_url_from_bookmarks.sh @@ -12,10 +12,10 @@ DMENU_OPTIONS="xmms vertical resize" if [ -z "$DMENU_HAS_VERTICAL" ]; then # because they are all after each other, just show the url, not their tags. - goto="$(awk '{print $1}' "$UZBL_BOOKMARKS_FILE" | $DMENU)" + goto="$( awk '{ print $1 }' "$UZBL_BOOKMARKS_FILE" | $DMENU )" else # show tags as well - goto="$($DMENU < "$UZBL_BOOKMARKS_FILE" | awk '{print $1}')" + goto="$( $DMENU < "$UZBL_BOOKMARKS_FILE" | awk '{ print $1 }' )" fi [ -n "$goto" ] && echo "uri $goto" > "$UZBL_FIFO" diff --git a/examples/data/scripts/load_url_from_history.sh b/examples/data/scripts/load_url_from_history.sh index 9cca356..5388680 100755 --- a/examples/data/scripts/load_url_from_history.sh +++ b/examples/data/scripts/load_url_from_history.sh @@ -9,14 +9,13 @@ DMENU_OPTIONS="xmms vertical resize" [ -r "$UZBL_HISTORY_FILE" ] || exit 1 # choose from all entries, sorted and uniqued -# goto=$(awk '{print $3}' $history_file | sort -u | dmenu -i) if [ -z "$DMENU_HAS_VERTICAL" ]; then - current="$(tail -n 1 "$UZBL_HISTORY_FILE" | awk '{print $3}')" - goto="$( (echo "$current"; awk '{print $3}' "$UZBL_HISTORY_FILE" | grep -v "^$current\$" | sort -u) | $DMENU)" + current="$( tail -n 1 "$UZBL_HISTORY_FILE" | awk '{ print $3 }' )" + goto="$( ( echo "$current"; awk '{ print $3 }' "$UZBL_HISTORY_FILE" | grep -v "^$current\$" | sort -u ) | $DMENU )" else # choose an item in reverse order, showing also the date and page titles # pick the last field from the first 3 fields. this way you can pick a url (prefixed with date & time) or type just a new url. - goto="$(tac "$UZBL_HISTORY_FILE" | $DMENU | cut -d ' ' -f -3 | awk '{print $NF}')" + goto="$( tac "$UZBL_HISTORY_FILE" | $DMENU | cut -d ' ' -f -3 | awk '{ print $NF }' )" fi [ -n "$goto" ] && echo "uri $goto" > "$UZBL_FIFO" diff --git a/examples/data/scripts/session.sh b/examples/data/scripts/session.sh index 73ee99b..ea84da5 100755 --- a/examples/data/scripts/session.sh +++ b/examples/data/scripts/session.sh @@ -20,7 +20,7 @@ if [ -z "$UZBL_UTIL_DIR" ]; then # using the same logic as uzbl-browser does. UZBL_UTIL_DIR="${XDG_DATA_HOME:-$HOME/.local/share}/uzbl/scripts/util" if ! [ -d "$UZBL_UTIL_DIR" ]; then - PREFIX="$(grep '^PREFIX' "$(which uzbl-browser)" | sed -e 's/.*=//')" + PREFIX="$( grep '^PREFIX' "$( which uzbl-browser )" | sed -e 's/.*=//' )" UZBL_UTIL_DIR="$PREFIX/share/uzbl/examples/data/scripts/util" fi fi @@ -30,7 +30,7 @@ fi UZBL="uzbl-browser -c \"$UZBL_CONFIG_FILE\"" # add custom flags and whatever here. -scriptfile="$(readlink -f "$0")" # this script +scriptfile="$( readlink -f "$0" )" # this script act="$1" shift @@ -40,7 +40,7 @@ fi case $act in "launch" ) - urls="$(cat "$UZBL_SESSION_FILE")" + urls="$( cat "$UZBL_SESSION_FILE" )" if [ -z "$urls" ]; then $UZBL else diff --git a/examples/data/scripts/util/uzbl-window.sh b/examples/data/scripts/util/uzbl-window.sh index 35ce013..077887b 100644 --- a/examples/data/scripts/util/uzbl-window.sh +++ b/examples/data/scripts/util/uzbl-window.sh @@ -1,11 +1,11 @@ #!/bin/sh # uzbl window detection -UZBL_WIN_POS="$(xwininfo -id $UZBL_XID | \ - sed -ne 's/Corners:[ ]*[+-]\([0-9]*\)[+-]\([0-9]*\).*$/\1 \2/p')" -UZBL_WIN_SIZE="$(xwininfo -id $UZBL_XID | \ - sed -ne 's/-geometry[ ]*\([0-9]*\)x\([0-9]*\).*$/\1 \2/p')" -UZBL_WIN_POS_X="$(echo "$UZBL_WIN_POS" | cut -d\ -f1)" -UZBL_WIN_POS_Y="$(echo "$UZBL_WIN_POS" | cut -d\ -f2)" -UZBL_WIN_WIDTH="$(echo "$UZBL_WIN_SIZE" | cut -d\ -f1)" -UZBL_WIN_HEIGHT="$(echo "$UZBL_WIN_SIZE" | cut -d\ -f2)" +UZBL_WIN_POS="$( xwininfo -id "$UZBL_XID" | \ + sed -n -e 's/Corners:[ ]*[+-]\([0-9]*\)[+-]\([0-9]*\).*$/\1 \2/p' )" +UZBL_WIN_SIZE="$( xwininfo -id "$UZBL_XID" | \ + sed -n -e 's/-geometry[ ]*\([0-9]*\)x\([0-9]*\).*$/\1 \2/p' )" +UZBL_WIN_POS_X="$( echo "$UZBL_WIN_POS" | cut -d\ -f1 )" +UZBL_WIN_POS_Y="$( echo "$UZBL_WIN_POS" | cut -d\ -f2 )" +UZBL_WIN_WIDTH="$( echo "$UZBL_WIN_SIZE" | cut -d\ -f1 )" +UZBL_WIN_HEIGHT="$( echo "$UZBL_WIN_SIZE" | cut -d\ -f2 )" -- cgit v1.2.3 From 7027c47d10d4f6595f8b926516fcbc90eb18d574 Mon Sep 17 00:00:00 2001 From: Ben Boeckel Date: Thu, 10 Mar 2011 20:49:56 -0500 Subject: Use cut over awk where possible --- examples/data/scripts/load_url_from_bookmarks.sh | 2 +- examples/data/scripts/load_url_from_history.sh | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/data/scripts/load_url_from_bookmarks.sh b/examples/data/scripts/load_url_from_bookmarks.sh index 5ba0d90..a03db4b 100755 --- a/examples/data/scripts/load_url_from_bookmarks.sh +++ b/examples/data/scripts/load_url_from_bookmarks.sh @@ -15,7 +15,7 @@ if [ -z "$DMENU_HAS_VERTICAL" ]; then goto="$( awk '{ print $1 }' "$UZBL_BOOKMARKS_FILE" | $DMENU )" else # show tags as well - goto="$( $DMENU < "$UZBL_BOOKMARKS_FILE" | awk '{ print $1 }' )" + goto="$( $DMENU < "$UZBL_BOOKMARKS_FILE" | cut -d ' ' -f 1 )" fi [ -n "$goto" ] && echo "uri $goto" > "$UZBL_FIFO" diff --git a/examples/data/scripts/load_url_from_history.sh b/examples/data/scripts/load_url_from_history.sh index 5388680..24bfdce 100755 --- a/examples/data/scripts/load_url_from_history.sh +++ b/examples/data/scripts/load_url_from_history.sh @@ -10,7 +10,7 @@ DMENU_OPTIONS="xmms vertical resize" # choose from all entries, sorted and uniqued if [ -z "$DMENU_HAS_VERTICAL" ]; then - current="$( tail -n 1 "$UZBL_HISTORY_FILE" | awk '{ print $3 }' )" + current="$( tail -n 1 "$UZBL_HISTORY_FILE" | cut -d ' ' -f 3 )" goto="$( ( echo "$current"; awk '{ print $3 }' "$UZBL_HISTORY_FILE" | grep -v "^$current\$" | sort -u ) | $DMENU )" else # choose an item in reverse order, showing also the date and page titles -- cgit v1.2.3 From 68b6074307106718c8e6cea9f280a81f3c42306c Mon Sep 17 00:00:00 2001 From: Ben Boeckel Date: Thu, 10 Mar 2011 20:51:33 -0500 Subject: Don't use cat when the recipient takes a file arg --- examples/data/scripts/formfiller.sh | 27 ++++++++++++--------------- 1 file changed, 12 insertions(+), 15 deletions(-) diff --git a/examples/data/scripts/formfiller.sh b/examples/data/scripts/formfiller.sh index 637a98f..f595eed 100755 --- a/examples/data/scripts/formfiller.sh +++ b/examples/data/scripts/formfiller.sh @@ -123,9 +123,8 @@ insertFunction="function insert(fname, ftype, fvalue, fchecked) { \ if [ "$action" = 'load' ]; then [ -e "$UZBL_FORMS_DIR/$domain" ] || exit 2 - if [ "$( cat "$UZBL_FORMS_DIR/$domain" | grep "!profile" | wc -l )" -gt 1 ]; then - menu="$( cat "$UZBL_FORMS_DIR/$domain" | \ - sed -n -e 's/^!profile=\([^[:blank:]]\+\)/\1/p' )" + if [ "$( grep "!profile" "$UZBL_FORMS_DIR/$domain" | wc -l )" -gt 1 ]; then + menu="$( sed -n -e 's/^!profile=\([^[:blank:]]\+\)/\1/p' "$UZBL_FORMS_DIR/$domain" )" option="$( printf "$menu" | $DMENU )" fi @@ -133,13 +132,12 @@ if [ "$action" = 'load' ]; then sed -i -e '/^>/d' "$tmpfile" sed -i -e 's/^\([^{]\+\){\([^}]*\)}(\(radio\|checkbox\)):\(off\|no\|false\|unchecked\|0\|$\)/\1{\2}(\3):0/I;s/^\([^{]\+\){\([^}]*\)}(\(radio\|checkbox\)):[^0]\+/\1{\2}(\3):1/I' "$UZBL_FORMS_DIR/$domain" - fields="$( cat "$UZBL_FORMS_DIR/$domain" | \ - sed -n -e "/^!profile=${option}/,/^!profile=/p" | \ - sed -e '/^!profile=/d' | \ - sed -e 's/^\([^(]\+(\)\(radio\|checkbox\|text\|search\|textarea\|password\)):/%{>\1\2):<}%/' | \ - sed -e 's/^\(.\+\)$/<{br}>\1/' | \ - tr -d '\n' | \ - sed -e 's/<{br}>%{>\([^(]\+(\)\(radio\|checkbox\|text\|search\|textarea\|password\)):<}%/\\n\1\2):/g' )" + fields="$( sed -n -e "/^!profile=${option}/,/^!profile=/p" "$UZBL_FORMS_DIR/$domain" | \ + sed -e '/^!profile=/d' | \ + sed -e 's/^\([^(]\+(\)\(radio\|checkbox\|text\|search\|textarea\|password\)):/%{>\1\2):<}%/' | \ + sed -e 's/^\(.\+\)$/<{br}>\1/' | \ + tr -d '\n' | \ + sed -e 's/<{br}>%{>\([^(]\+(\)\(radio\|checkbox\|text\|search\|textarea\|password\)):<}%/\\n\1\2):/g' )" printf '%s\n' "${fields}" | \ sed -n -e "s/\([^(]\+\)(\(password\|text\|search\|textarea\)\+):[ ]*\(.\+\)/js $insertFunction; insert('\1', '\2', '\3', 0);/p" | \ sed -e 's/@/\\@/g;s/<{br}>/\\\\n/g' | socat - "unix-connect:$UZBL_SOCKET" @@ -160,11 +158,10 @@ elif [ "$action" = "once" ]; then sed -i -e '/^>/d' "$tmpfile" sed -i -e 's/^\([^{]\+\){\([^}]*\)}(\(radio\|checkbox\)):\(off\|no\|false\|unchecked\|0\|$\)/\1{\2}(\3):0/I;s/^\([^{]\+\){\([^}]*\)}(\(radio\|checkbox\)):[^0]\+/\1{\2}(\3):1/I' "$tmpfile" - fields="$( cat "$tmpfile" | \ - sed -e 's/^\([^(]\+(\)\(radio\|checkbox\|text\|search\|textarea\|password\)):/%{>\1\2):<}%/' | \ - sed -e 's/^\(.\+\)$/<{br}>\1/' | \ - tr -d '\n' | \ - sed -e 's/<{br}>%{>\([^(]\+(\)\(radio\|checkbox\|text\|search\|textarea\|password\)):<}%/\\n\1\2):/g' )" + fields="$( sed -e 's/^\([^(]\+(\)\(radio\|checkbox\|text\|search\|textarea\|password\)):/%{>\1\2):<}%/' "$tmpfile" | \ + sed -e 's/^\(.\+\)$/<{br}>\1/' | \ + tr -d '\n' | \ + sed -e 's/<{br}>%{>\([^(]\+(\)\(radio\|checkbox\|text\|search\|textarea\|password\)):<}%/\\n\1\2):/g' )" printf '%s\n' "${fields}" | \ sed -n -e "s/\([^(]\+\)(\(password\|text\|search\|textarea\)\+):[ ]*\(.\+\)/js $insertFunction; insert('\1', '\2', '\3', 0);/p" | \ sed -e 's/@/\\@/g;s/<{br}>/\\\\n/g' | socat - "unix-connect:$UZBL_SOCKET" -- cgit v1.2.3 From 7ca2f68bf19b903cf93da5b5d153bee24a314aa5 Mon Sep 17 00:00:00 2001 From: Ben Boeckel Date: Thu, 10 Mar 2011 20:53:40 -0500 Subject: Use 4 space indentation for consistency --- examples/data/scripts/follow.sh | 14 ++++++++------ examples/data/scripts/go_input.sh | 4 +++- examples/data/scripts/load_cookies.sh | 14 +++++++------- 3 files changed, 18 insertions(+), 14 deletions(-) diff --git a/examples/data/scripts/follow.sh b/examples/data/scripts/follow.sh index 9754778..ba1bab4 100755 --- a/examples/data/scripts/follow.sh +++ b/examples/data/scripts/follow.sh @@ -15,10 +15,12 @@ fi result="$( echo "script @scripts_dir/follow.js \"@{follow_hint_keys} $keys\"" | socat - "unix-connect:$UZBL_SOCKET" )" case $result in - *XXXEMIT_FORM_ACTIVEXXX*) - # a form element was selected - echo 'event FORM_ACTIVE' > "$UZBL_FIFO" ;; - *XXXRESET_MODEXXX*) - # a link was selected, reset uzbl's input mode - echo 'set mode=' > "$UZBL_FIFO" ;; + *XXXEMIT_FORM_ACTIVEXXX*) + # a form element was selected + echo 'event FORM_ACTIVE' > "$UZBL_FIFO" + ;; + *XXXRESET_MODEXXX*) + # a link was selected, reset uzbl's input mode + echo 'set mode=' > "$UZBL_FIFO" + ;; esac diff --git a/examples/data/scripts/go_input.sh b/examples/data/scripts/go_input.sh index 8d9ac84..c3c966b 100755 --- a/examples/data/scripts/go_input.sh +++ b/examples/data/scripts/go_input.sh @@ -1,5 +1,7 @@ #!/bin/sh case "$( echo 'script @scripts_dir/go_input.js' | socat - "unix-connect:$UZBL_SOCKET" )" in - *XXXEMIT_FORM_ACTIVEXXX*) echo 'event FORM_ACTIVE' > "$UZBL_FIFO" ;; + *XXXEMIT_FORM_ACTIVEXXX*) + echo 'event FORM_ACTIVE' > "$UZBL_FIFO" + ;; esac diff --git a/examples/data/scripts/load_cookies.sh b/examples/data/scripts/load_cookies.sh index eff044b..c7fcc58 100755 --- a/examples/data/scripts/load_cookies.sh +++ b/examples/data/scripts/load_cookies.sh @@ -1,21 +1,21 @@ #!/bin/sh if [ -n "$1" ]; then - cookie_file="$1" - shift + cookie_file="$1" + shift else - cookie_file="${XDG_DATA_HOME:-$HOME/.local/share}/uzbl/cookies.txt" + cookie_file="${XDG_DATA_HOME:-$HOME/.local/share}/uzbl/cookies.txt" fi awk -F \\t ' BEGIN { - scheme["TRUE"] = "https"; - scheme["FALSE"] = "http"; + scheme["TRUE"] = "https"; + scheme["FALSE"] = "http"; } $0 ~ /^#HttpOnly_/ { -printf("add_cookie \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\"\n", substr($1,length("#HttpOnly_"),length($1)), $3, $6, $7, scheme[$4], $5) + printf("add_cookie \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\"\n", substr($1,length("#HttpOnly_"),length($1)), $3, $6, $7, scheme[$4], $5) } $0 !~ /^#/ { -printf("add_cookie \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\"\n", $1, $3, $6, $7, scheme[$4], $5) + printf("add_cookie \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\"\n", $1, $3, $6, $7, scheme[$4], $5) } ' "$cookie_file" -- cgit v1.2.3 From 0834c606592abddf889229826a8ed93190685f50 Mon Sep 17 00:00:00 2001 From: Ben Boeckel Date: Thu, 10 Mar 2011 20:55:52 -0500 Subject: Chain test commands together --- examples/data/scripts/formfiller.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/data/scripts/formfiller.sh b/examples/data/scripts/formfiller.sh index f595eed..b41faf4 100755 --- a/examples/data/scripts/formfiller.sh +++ b/examples/data/scripts/formfiller.sh @@ -58,7 +58,7 @@ shift domain="$( echo "$UZBL_URI" | sed -e 's/\(http\|https\):\/\/\([^\/]\+\)\/.*/\2/' )" -if [ "$action" != 'edit' -a "$action" != 'new' -a "$action" != 'load' -a "$action" != 'add' -a "$action" != 'once' ]; then +if [ "$action" != 'edit' ] && [ "$action" != 'new' ] && [ "$action" != 'load' ] && [ "$action" != 'add' ] && [ "$action" != 'once' ]; then action="new" [ -e "$UZBL_FORMS_DIR/$domain" ] && action="load" elif [ "$action" = 'edit' ] && [ ! -e "$UZBL_FORMS_DIR/$domain" ]; then -- cgit v1.2.3 From 183ddc0ea5c70df8a933cbe3bf83f0272f1c8855 Mon Sep 17 00:00:00 2001 From: Ben Boeckel Date: Thu, 10 Mar 2011 20:56:56 -0500 Subject: Don't put spaces before case matches --- examples/data/scripts/instance-select-wmii.sh | 6 +++--- examples/data/scripts/session.sh | 8 ++++---- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/examples/data/scripts/instance-select-wmii.sh b/examples/data/scripts/instance-select-wmii.sh index f0a7bef..565ff48 100755 --- a/examples/data/scripts/instance-select-wmii.sh +++ b/examples/data/scripts/instance-select-wmii.sh @@ -15,7 +15,7 @@ DMENU_SCHEME="wmii" . "$UZBL_UTIL_DIR/dmenu.sh" case "$1" in - "list" ) + "list") list="" # get window id's of uzbl clients. we could also get the label in one shot but it's pretty tricky for i in $( wmiir read /tag/sel/index | grep uzbl | cut -d ' ' -f2 ); do @@ -25,7 +25,7 @@ case "$1" in window="$( printf "$list\n" | $DMENU | cut -d ' ' -f1 )" wmiir xwrite /tag/sel/ctl "select client $window" ;; - "next" ) + "next") current="$( wmiir read /client/sel/ctl | head -n 1 )" # find the next uzbl window and focus it next="$( wmiir read /tag/sel/index | grep -A 10000 " $current " | grep -m 1 uzbl | cut -d ' ' -f2 )" @@ -33,7 +33,7 @@ case "$1" in wmiir xwrite /tag/sel/ctl "select client $next" fi ;; - "prev" ) + "prev") current="$( wmiir read /client/sel/ctl | head -n 1 )" prev="$( wmiir read /tag/sel/index | grep -B 10000 " $current " | tac | grep -m 1 uzbl | cut -d ' ' -f2 )" if [ -n "$prev" ]; then diff --git a/examples/data/scripts/session.sh b/examples/data/scripts/session.sh index ea84da5..c95a9e5 100755 --- a/examples/data/scripts/session.sh +++ b/examples/data/scripts/session.sh @@ -39,7 +39,7 @@ if [ -z "$act" ]; then fi case $act in - "launch" ) + "launch") urls="$( cat "$UZBL_SESSION_FILE" )" if [ -z "$urls" ]; then $UZBL @@ -51,7 +51,7 @@ case $act in fi ;; - "endinstance" ) + "endinstance") if [ -z "$UZBL_FIFO" ]; then echo "session manager: endinstance must be called from uzbl" exit 1 @@ -60,7 +60,7 @@ case $act in echo exit > "$UZBL_FIFO" ;; - "endsession" ) + "endsession") for fifo in "$UZBL_FIFO_DIR/uzbl_fifo_*"; do if [ "$fifo" != "$UZBL_FIFO" ]; then echo "spawn $scriptfile endinstance" > "$fifo" @@ -69,7 +69,7 @@ case $act in [ -z "$UZBL_FIFO" ] || echo "spawn $scriptfile endinstance" > "$UZBL_FIFO" ;; - * ) + *) echo "session manager: bad action" echo "Usage: $scriptfile [COMMAND] where commands are:" echo " launch - Restore a saved session or start a new one" -- cgit v1.2.3 From a501850008e061f10c744071ef035fa8d82fe535 Mon Sep 17 00:00:00 2001 From: Ben Boeckel Date: Thu, 10 Mar 2011 21:01:49 -0500 Subject: Store the path to the form file in a variable --- examples/data/scripts/formfiller.sh | 25 +++++++++++++------------ 1 file changed, 13 insertions(+), 12 deletions(-) diff --git a/examples/data/scripts/formfiller.sh b/examples/data/scripts/formfiller.sh index b41faf4..d34326f 100755 --- a/examples/data/scripts/formfiller.sh +++ b/examples/data/scripts/formfiller.sh @@ -57,11 +57,12 @@ action="$1" shift domain="$( echo "$UZBL_URI" | sed -e 's/\(http\|https\):\/\/\([^\/]\+\)\/.*/\2/' )" +form_file="$UZBL_FORMS_DIR/$domain" if [ "$action" != 'edit' ] && [ "$action" != 'new' ] && [ "$action" != 'load' ] && [ "$action" != 'add' ] && [ "$action" != 'once' ]; then action="new" - [ -e "$UZBL_FORMS_DIR/$domain" ] && action="load" -elif [ "$action" = 'edit' ] && [ ! -e "$UZBL_FORMS_DIR/$domain" ]; then + [ -e "$form_file" ] && action="load" +elif [ "$action" = 'edit' ] && [ ! -e "$form_file" ]; then action="new" fi @@ -122,17 +123,17 @@ insertFunction="function insert(fname, ftype, fvalue, fchecked) { \ };" if [ "$action" = 'load' ]; then - [ -e "$UZBL_FORMS_DIR/$domain" ] || exit 2 - if [ "$( grep "!profile" "$UZBL_FORMS_DIR/$domain" | wc -l )" -gt 1 ]; then - menu="$( sed -n -e 's/^!profile=\([^[:blank:]]\+\)/\1/p' "$UZBL_FORMS_DIR/$domain" )" + [ -e "$form_file" ] || exit 2 + if [ "$( grep "!profile" "$form_file" | wc -l )" -gt 1 ]; then + menu="$( sed -n -e 's/^!profile=\([^[:blank:]]\+\)/\1/p' "$form_file" )" option="$( printf "$menu" | $DMENU )" fi # Remove comments sed -i -e '/^>/d' "$tmpfile" - sed -i -e 's/^\([^{]\+\){\([^}]*\)}(\(radio\|checkbox\)):\(off\|no\|false\|unchecked\|0\|$\)/\1{\2}(\3):0/I;s/^\([^{]\+\){\([^}]*\)}(\(radio\|checkbox\)):[^0]\+/\1{\2}(\3):1/I' "$UZBL_FORMS_DIR/$domain" - fields="$( sed -n -e "/^!profile=${option}/,/^!profile=/p" "$UZBL_FORMS_DIR/$domain" | \ + sed -i -e 's/^\([^{]\+\){\([^}]*\)}(\(radio\|checkbox\)):\(off\|no\|false\|unchecked\|0\|$\)/\1{\2}(\3):0/I;s/^\([^{]\+\){\([^}]*\)}(\(radio\|checkbox\)):[^0]\+/\1{\2}(\3):1/I' "$form_file" + fields="$( sed -n -e "/^!profile=${option}/,/^!profile=/p" "$form_file" | \ sed -e '/^!profile=/d' | \ sed -e 's/^\([^(]\+(\)\(radio\|checkbox\|text\|search\|textarea\|password\)):/%{>\1\2):<}%/' | \ sed -e 's/^\(.\+\)$/<{br}>\1/' | \ @@ -171,8 +172,8 @@ elif [ "$action" = "once" ]; then rm -f "$tmpfile" else if [ "$action" = 'new' -o "$action" = 'add' ]; then - [ "$action" = 'new' ] && echo "$MODELINE" > "$UZBL_FORMS_DIR/$domain" - echo "!profile=NAME_THIS_PROFILE$RAND" >> "$UZBL_FORMS_DIR/$domain" + [ "$action" = 'new' ] && echo "$MODELINE" > "$form_file" + echo "!profile=NAME_THIS_PROFILE$RAND" >> "$form_file" # # 2. and 3. line (tr -d and sed) are because, on gmail login for example, # tag is splited into lines @@ -191,10 +192,10 @@ else # printf 'js %s dump(); \n' "$dumpFunction" | \ socat - "unix-connect:$UZBL_SOCKET" | \ - sed -n -e '/^[^(]\+([^)]\+):/p' >> "$UZBL_FORMS_DIR/$domain" + sed -n -e '/^[^(]\+([^)]\+):/p' >> "$form_file" fi - [ -e "$UZBL_FORMS_DIR/$domain" ] || exit 3 #this should never happen, but you never know. - $UZBL_EDITOR "$UZBL_FORMS_DIR/$domain" #TODO: if user aborts save in editor, the file is already overwritten + [ -e "$form_file" ] || exit 3 #this should never happen, but you never know. + $UZBL_EDITOR "$form_file" #TODO: if user aborts save in editor, the file is already overwritten fi # vim:fileencoding=utf-8:sw=4 -- cgit v1.2.3 From e417a25165fc1f6c8a0d96c3b7872e6e074f1840 Mon Sep 17 00:00:00 2001 From: Ben Boeckel Date: Thu, 10 Mar 2011 21:02:51 -0500 Subject: Normalize cut arguments --- examples/data/scripts/instance-select-wmii.sh | 8 ++++---- examples/data/scripts/util/uzbl-window.sh | 8 ++++---- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/examples/data/scripts/instance-select-wmii.sh b/examples/data/scripts/instance-select-wmii.sh index 565ff48..ec6a3c1 100755 --- a/examples/data/scripts/instance-select-wmii.sh +++ b/examples/data/scripts/instance-select-wmii.sh @@ -18,24 +18,24 @@ case "$1" in "list") list="" # get window id's of uzbl clients. we could also get the label in one shot but it's pretty tricky - for i in $( wmiir read /tag/sel/index | grep uzbl | cut -d ' ' -f2 ); do + for i in $( wmiir read /tag/sel/index | grep uzbl | cut -d ' ' -f 2 ); do label="$( wmiir read /client/$i/label )" list="$list$i : $label\n" done - window="$( printf "$list\n" | $DMENU | cut -d ' ' -f1 )" + window="$( printf "$list\n" | $DMENU | cut -d ' ' -f 1 )" wmiir xwrite /tag/sel/ctl "select client $window" ;; "next") current="$( wmiir read /client/sel/ctl | head -n 1 )" # find the next uzbl window and focus it - next="$( wmiir read /tag/sel/index | grep -A 10000 " $current " | grep -m 1 uzbl | cut -d ' ' -f2 )" + next="$( wmiir read /tag/sel/index | grep -A 10000 " $current " | grep -m 1 uzbl | cut -d ' ' -f 2 )" if [ -n "$next" ]; then wmiir xwrite /tag/sel/ctl "select client $next" fi ;; "prev") current="$( wmiir read /client/sel/ctl | head -n 1 )" - prev="$( wmiir read /tag/sel/index | grep -B 10000 " $current " | tac | grep -m 1 uzbl | cut -d ' ' -f2 )" + prev="$( wmiir read /tag/sel/index | grep -B 10000 " $current " | tac | grep -m 1 uzbl | cut -d ' ' -f 2 )" if [ -n "$prev" ]; then wmiir xwrite /tag/sel/ctl "select client $prev" fi diff --git a/examples/data/scripts/util/uzbl-window.sh b/examples/data/scripts/util/uzbl-window.sh index 077887b..351eff7 100644 --- a/examples/data/scripts/util/uzbl-window.sh +++ b/examples/data/scripts/util/uzbl-window.sh @@ -5,7 +5,7 @@ UZBL_WIN_POS="$( xwininfo -id "$UZBL_XID" | \ sed -n -e 's/Corners:[ ]*[+-]\([0-9]*\)[+-]\([0-9]*\).*$/\1 \2/p' )" UZBL_WIN_SIZE="$( xwininfo -id "$UZBL_XID" | \ sed -n -e 's/-geometry[ ]*\([0-9]*\)x\([0-9]*\).*$/\1 \2/p' )" -UZBL_WIN_POS_X="$( echo "$UZBL_WIN_POS" | cut -d\ -f1 )" -UZBL_WIN_POS_Y="$( echo "$UZBL_WIN_POS" | cut -d\ -f2 )" -UZBL_WIN_WIDTH="$( echo "$UZBL_WIN_SIZE" | cut -d\ -f1 )" -UZBL_WIN_HEIGHT="$( echo "$UZBL_WIN_SIZE" | cut -d\ -f2 )" +UZBL_WIN_POS_X="$( echo "$UZBL_WIN_POS" | cut -d ' ' -f 1 )" +UZBL_WIN_POS_Y="$( echo "$UZBL_WIN_POS" | cut -d ' ' -f 2 )" +UZBL_WIN_WIDTH="$( echo "$UZBL_WIN_SIZE" | cut -d ' ' -f 1 )" +UZBL_WIN_HEIGHT="$( echo "$UZBL_WIN_SIZE" | cut -d ' ' -f 2 )" -- cgit v1.2.3 From 23e8be89ff2a6be9237203b08167c644a7fe9cd6 Mon Sep 17 00:00:00 2001 From: Ben Boeckel Date: Thu, 10 Mar 2011 21:05:20 -0500 Subject: Clean up some printf calls --- examples/data/scripts/formfiller.sh | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/examples/data/scripts/formfiller.sh b/examples/data/scripts/formfiller.sh index d34326f..1a49e82 100755 --- a/examples/data/scripts/formfiller.sh +++ b/examples/data/scripts/formfiller.sh @@ -139,15 +139,15 @@ if [ "$action" = 'load' ]; then sed -e 's/^\(.\+\)$/<{br}>\1/' | \ tr -d '\n' | \ sed -e 's/<{br}>%{>\([^(]\+(\)\(radio\|checkbox\|text\|search\|textarea\|password\)):<}%/\\n\1\2):/g' )" - printf '%s\n' "${fields}" | \ + printf "%s\n" "${fields}" | \ sed -n -e "s/\([^(]\+\)(\(password\|text\|search\|textarea\)\+):[ ]*\(.\+\)/js $insertFunction; insert('\1', '\2', '\3', 0);/p" | \ sed -e 's/@/\\@/g;s/<{br}>/\\\\n/g' | socat - "unix-connect:$UZBL_SOCKET" - printf '%s\n' "${fields}" | \ + printf "%s\n" "${fields}" | \ sed -n -e "s/\([^{]\+\){\([^}]*\)}(\(radio\|checkbox\)):[ ]*\(.\+\)/js $insertFunction; insert('\1', '\3', '\2', \4);/p" | \ sed -e 's/@/\\@/g' | socat - "unix-connect:$UZBL_SOCKET" elif [ "$action" = "once" ]; then tmpfile="$( mktemp )" - printf 'js %s dump(); \n' "$dumpFunction" | \ + printf "js %s dump();\n" "$dumpFunction" | \ socat - "unix-connect:$UZBL_SOCKET" | \ sed -n -e '/^[^(]\+([^)]\+):/p' > "$tmpfile" echo "$MODELINE" >> "$tmpfile" @@ -163,10 +163,10 @@ elif [ "$action" = "once" ]; then sed -e 's/^\(.\+\)$/<{br}>\1/' | \ tr -d '\n' | \ sed -e 's/<{br}>%{>\([^(]\+(\)\(radio\|checkbox\|text\|search\|textarea\|password\)):<}%/\\n\1\2):/g' )" - printf '%s\n' "${fields}" | \ + printf "%s\n" "${fields}" | \ sed -n -e "s/\([^(]\+\)(\(password\|text\|search\|textarea\)\+):[ ]*\(.\+\)/js $insertFunction; insert('\1', '\2', '\3', 0);/p" | \ sed -e 's/@/\\@/g;s/<{br}>/\\\\n/g' | socat - "unix-connect:$UZBL_SOCKET" - printf '%s\n' "${fields}" | \ + printf "%s\n" "${fields}" | \ sed -n -e "s/\([^{]\+\){\([^}]*\)}(\(radio\|checkbox\)):[ ]*\(.\+\)/js $insertFunction; insert('\1', '\3', '\2', \4);/p" | \ sed -e 's/@/\\@/g' | socat - "unix-connect:$UZBL_SOCKET" rm -f "$tmpfile" @@ -190,7 +190,7 @@ else # login(text): # passwd(password): # - printf 'js %s dump(); \n' "$dumpFunction" | \ + printf "js %s dump();\n" "$dumpFunction" | \ socat - "unix-connect:$UZBL_SOCKET" | \ sed -n -e '/^[^(]\+([^)]\+):/p' >> "$form_file" fi -- cgit v1.2.3 From 8e1eee5059058a774ba3124ce18d5f0d52415202 Mon Sep 17 00:00:00 2001 From: Ben Boeckel Date: Thu, 10 Mar 2011 21:05:56 -0500 Subject: Remove extraneous sed call --- examples/data/scripts/formfiller.sh | 3 --- 1 file changed, 3 deletions(-) diff --git a/examples/data/scripts/formfiller.sh b/examples/data/scripts/formfiller.sh index 1a49e82..4b4fb4e 100755 --- a/examples/data/scripts/formfiller.sh +++ b/examples/data/scripts/formfiller.sh @@ -129,9 +129,6 @@ if [ "$action" = 'load' ]; then option="$( printf "$menu" | $DMENU )" fi - # Remove comments - sed -i -e '/^>/d' "$tmpfile" - sed -i -e 's/^\([^{]\+\){\([^}]*\)}(\(radio\|checkbox\)):\(off\|no\|false\|unchecked\|0\|$\)/\1{\2}(\3):0/I;s/^\([^{]\+\){\([^}]*\)}(\(radio\|checkbox\)):[^0]\+/\1{\2}(\3):1/I' "$form_file" fields="$( sed -n -e "/^!profile=${option}/,/^!profile=/p" "$form_file" | \ sed -e '/^!profile=/d' | \ -- cgit v1.2.3 From 5f2a6b9371fcf2ca78143cd255242e1cacac6ad1 Mon Sep 17 00:00:00 2001 From: Ben Boeckel Date: Thu, 10 Mar 2011 21:09:03 -0500 Subject: Use printf rather than echo --- examples/data/scripts/download.sh | 4 ++-- examples/data/scripts/follow.sh | 8 ++++---- examples/data/scripts/formfiller.sh | 6 +++--- examples/data/scripts/go_input.sh | 4 ++-- examples/data/scripts/history.sh | 2 +- examples/data/scripts/insert_bookmark.sh | 2 +- examples/data/scripts/instance-select-wmii.sh | 2 +- examples/data/scripts/load_url_from_bookmarks.sh | 4 ++-- examples/data/scripts/load_url_from_history.sh | 4 ++-- examples/data/scripts/session.sh | 20 ++++++++++---------- examples/data/scripts/util/uzbl-window.sh | 8 ++++---- 11 files changed, 32 insertions(+), 32 deletions(-) diff --git a/examples/data/scripts/download.sh b/examples/data/scripts/download.sh index 7753bd6..448e086 100755 --- a/examples/data/scripts/download.sh +++ b/examples/data/scripts/download.sh @@ -11,7 +11,7 @@ # the URL that is being downloaded uri="$1" -safe_uri="$( echo "$uri" | sed -e 's/\W/-/g' )" +safe_uri="$( printf "$uri" | sed -e 's/\W/-/g' )" # a filename suggested by the server or based on the URL suggested_filename="${2:-$safe_uri}" @@ -24,4 +24,4 @@ content_type="$3" total_size="$4" # just save the file to the default directory with the suggested name -echo "$UZBL_DOWNLOAD_DIR/$suggested_filename" +printf "$UZBL_DOWNLOAD_DIR/$suggested_filename\n" diff --git a/examples/data/scripts/follow.sh b/examples/data/scripts/follow.sh index ba1bab4..b038c12 100755 --- a/examples/data/scripts/follow.sh +++ b/examples/data/scripts/follow.sh @@ -9,18 +9,18 @@ shift # if socat is installed then we can change Uzbl's input mode once a link is # selected; otherwise we just select a link. if ! which socat >/dev/null 2>&1; then - echo "script @scripts_dir/follow.js \"@{follow_hint_keys} $keys\"" > "$UZBL_FIFO" + printf "script @scripts_dir/follow.js \"@{follow_hint_keys} $keys\"\n" > "$UZBL_FIFO" exit fi -result="$( echo "script @scripts_dir/follow.js \"@{follow_hint_keys} $keys\"" | socat - "unix-connect:$UZBL_SOCKET" )" +result="$( printf "script @scripts_dir/follow.js \"@{follow_hint_keys} $keys\"\n" | socat - "unix-connect:$UZBL_SOCKET" )" case $result in *XXXEMIT_FORM_ACTIVEXXX*) # a form element was selected - echo 'event FORM_ACTIVE' > "$UZBL_FIFO" + printf "event FORM_ACTIVE\n" > "$UZBL_FIFO" ;; *XXXRESET_MODEXXX*) # a link was selected, reset uzbl's input mode - echo 'set mode=' > "$UZBL_FIFO" + printf "set mode=\n" > "$UZBL_FIFO" ;; esac diff --git a/examples/data/scripts/formfiller.sh b/examples/data/scripts/formfiller.sh index 4b4fb4e..2895e5b 100755 --- a/examples/data/scripts/formfiller.sh +++ b/examples/data/scripts/formfiller.sh @@ -56,7 +56,7 @@ MODELINE="> vim:ft=formfiller" action="$1" shift -domain="$( echo "$UZBL_URI" | sed -e 's/\(http\|https\):\/\/\([^\/]\+\)\/.*/\2/' )" +domain="$( printf "$UZBL_URI\n" | sed -e 's/\(http\|https\):\/\/\([^\/]\+\)\/.*/\2/' )" form_file="$UZBL_FORMS_DIR/$domain" if [ "$action" != 'edit' ] && [ "$action" != 'new' ] && [ "$action" != 'load' ] && [ "$action" != 'add' ] && [ "$action" != 'once' ]; then @@ -147,7 +147,7 @@ elif [ "$action" = "once" ]; then printf "js %s dump();\n" "$dumpFunction" | \ socat - "unix-connect:$UZBL_SOCKET" | \ sed -n -e '/^[^(]\+([^)]\+):/p' > "$tmpfile" - echo "$MODELINE" >> "$tmpfile" + printf "$MODELINE\n" >> "$tmpfile" $UZBL_EDITOR "$tmpfile" [ -e "$tmpfile" ] || exit 2 @@ -170,7 +170,7 @@ elif [ "$action" = "once" ]; then else if [ "$action" = 'new' -o "$action" = 'add' ]; then [ "$action" = 'new' ] && echo "$MODELINE" > "$form_file" - echo "!profile=NAME_THIS_PROFILE$RAND" >> "$form_file" + printf "!profile=NAME_THIS_PROFILE$RAND\n" >> "$form_file" # # 2. and 3. line (tr -d and sed) are because, on gmail login for example, # tag is splited into lines diff --git a/examples/data/scripts/go_input.sh b/examples/data/scripts/go_input.sh index c3c966b..6574a83 100755 --- a/examples/data/scripts/go_input.sh +++ b/examples/data/scripts/go_input.sh @@ -1,7 +1,7 @@ #!/bin/sh -case "$( echo 'script @scripts_dir/go_input.js' | socat - "unix-connect:$UZBL_SOCKET" )" in +case "$( printf "script @scripts_dir/go_input.js\n" | socat - "unix-connect:$UZBL_SOCKET" )" in *XXXEMIT_FORM_ACTIVEXXX*) - echo 'event FORM_ACTIVE' > "$UZBL_FIFO" + printf "event FORM_ACTIVE\n" > "$UZBL_FIFO" ;; esac diff --git a/examples/data/scripts/history.sh b/examples/data/scripts/history.sh index bbef20a..4b660c3 100755 --- a/examples/data/scripts/history.sh +++ b/examples/data/scripts/history.sh @@ -4,4 +4,4 @@ [ -w "$UZBL_HISTORY_FILE" ] || [ ! -a "$UZBL_HISTORY_FILE" ] || exit 1 -echo "$( date +'%Y-%m-%d %H:%M:%S' ) $UZBL_URI $UZBL_TITLE" >> "$UZBL_HISTORY_FILE" +printf "$( date +'%Y-%m-%d %H:%M:%S' ) $UZBL_URI $UZBL_TITLE\n" >> "$UZBL_HISTORY_FILE" diff --git a/examples/data/scripts/insert_bookmark.sh b/examples/data/scripts/insert_bookmark.sh index b1ea07d..d4c6773 100755 --- a/examples/data/scripts/insert_bookmark.sh +++ b/examples/data/scripts/insert_bookmark.sh @@ -12,4 +12,4 @@ exitstatus="$?" [ "$exitstatus" -eq 0 ] || exit "$exitstatus" # TODO: check if already exists, if so, and tags are different: ask if you want to replace tags -echo "$UZBL_URI $tags" >> "$UZBL_BOOKMARKS_FILE" +printf "$UZBL_URI $tags\n" >> "$UZBL_BOOKMARKS_FILE" diff --git a/examples/data/scripts/instance-select-wmii.sh b/examples/data/scripts/instance-select-wmii.sh index ec6a3c1..c12f7b7 100755 --- a/examples/data/scripts/instance-select-wmii.sh +++ b/examples/data/scripts/instance-select-wmii.sh @@ -41,7 +41,7 @@ case "$1" in fi ;; * ) - echo "$1 not valid" >&2 + printf "$1 not valid\n" >&2 exit 2 ;; esac diff --git a/examples/data/scripts/load_url_from_bookmarks.sh b/examples/data/scripts/load_url_from_bookmarks.sh index a03db4b..d7bf104 100755 --- a/examples/data/scripts/load_url_from_bookmarks.sh +++ b/examples/data/scripts/load_url_from_bookmarks.sh @@ -18,5 +18,5 @@ else goto="$( $DMENU < "$UZBL_BOOKMARKS_FILE" | cut -d ' ' -f 1 )" fi -[ -n "$goto" ] && echo "uri $goto" > "$UZBL_FIFO" -#[ -n "$goto" ] && echo "uri $goto" | socat - "unix-connect:$UZBL_SOCKET" +[ -n "$goto" ] && printf "uri $goto\n" > "$UZBL_FIFO" +#[ -n "$goto" ] && printf "uri $goto\n" | socat - "unix-connect:$UZBL_SOCKET" diff --git a/examples/data/scripts/load_url_from_history.sh b/examples/data/scripts/load_url_from_history.sh index 24bfdce..3537b35 100755 --- a/examples/data/scripts/load_url_from_history.sh +++ b/examples/data/scripts/load_url_from_history.sh @@ -18,5 +18,5 @@ else goto="$( tac "$UZBL_HISTORY_FILE" | $DMENU | cut -d ' ' -f -3 | awk '{ print $NF }' )" fi -[ -n "$goto" ] && echo "uri $goto" > "$UZBL_FIFO" -#[ -n "$goto" ] && echo "uri $goto" | socat - "unix-connect:$UZBL_SOCKET" +[ -n "$goto" ] && printf "uri $goto\n" > "$UZBL_FIFO" +#[ -n "$goto" ] && printf "uri $goto\n" | socat - "unix-connect:$UZBL_SOCKET" diff --git a/examples/data/scripts/session.sh b/examples/data/scripts/session.sh index c95a9e5..e2f97fe 100755 --- a/examples/data/scripts/session.sh +++ b/examples/data/scripts/session.sh @@ -53,27 +53,27 @@ case $act in "endinstance") if [ -z "$UZBL_FIFO" ]; then - echo "session manager: endinstance must be called from uzbl" + printf "session manager: endinstance must be called from uzbl\n" exit 1 fi - [ "$UZBL_URI" != "(null)" ] && echo "$UZBL_URI" >> "$UZBL_SESSION_FILE" - echo exit > "$UZBL_FIFO" + [ "$UZBL_URI" != "(null)" ] && printf "$UZBL_URI\n" >> "$UZBL_SESSION_FILE" + printf "exit\n" > "$UZBL_FIFO" ;; "endsession") for fifo in "$UZBL_FIFO_DIR/uzbl_fifo_*"; do if [ "$fifo" != "$UZBL_FIFO" ]; then - echo "spawn $scriptfile endinstance" > "$fifo" + printf "spawn $scriptfile endinstance\n" > "$fifo" fi done - [ -z "$UZBL_FIFO" ] || echo "spawn $scriptfile endinstance" > "$UZBL_FIFO" + [ -z "$UZBL_FIFO" ] || printf "spawn $scriptfile endinstance\n" > "$UZBL_FIFO" ;; *) - echo "session manager: bad action" - echo "Usage: $scriptfile [COMMAND] where commands are:" - echo " launch - Restore a saved session or start a new one" - echo " endinstance - Quit the current instance. Must be called from uzbl" - echo " endsession - Quit the running session." + printf "session manager: bad action\n" + printf "Usage: $scriptfile [COMMAND] where commands are:\n" + printf " launch - Restore a saved session or start a new one\n" + printf " endinstance - Quit the current instance. Must be called from uzbl\n" + printf " endsession - Quit the running session.\n" ;; esac diff --git a/examples/data/scripts/util/uzbl-window.sh b/examples/data/scripts/util/uzbl-window.sh index 351eff7..279636a 100644 --- a/examples/data/scripts/util/uzbl-window.sh +++ b/examples/data/scripts/util/uzbl-window.sh @@ -5,7 +5,7 @@ UZBL_WIN_POS="$( xwininfo -id "$UZBL_XID" | \ sed -n -e 's/Corners:[ ]*[+-]\([0-9]*\)[+-]\([0-9]*\).*$/\1 \2/p' )" UZBL_WIN_SIZE="$( xwininfo -id "$UZBL_XID" | \ sed -n -e 's/-geometry[ ]*\([0-9]*\)x\([0-9]*\).*$/\1 \2/p' )" -UZBL_WIN_POS_X="$( echo "$UZBL_WIN_POS" | cut -d ' ' -f 1 )" -UZBL_WIN_POS_Y="$( echo "$UZBL_WIN_POS" | cut -d ' ' -f 2 )" -UZBL_WIN_WIDTH="$( echo "$UZBL_WIN_SIZE" | cut -d ' ' -f 1 )" -UZBL_WIN_HEIGHT="$( echo "$UZBL_WIN_SIZE" | cut -d ' ' -f 2 )" +UZBL_WIN_POS_X="$( printf "$UZBL_WIN_POS" | cut -d ' ' -f 1 )" +UZBL_WIN_POS_Y="$( printf "$UZBL_WIN_POS" | cut -d ' ' -f 2 )" +UZBL_WIN_WIDTH="$( printf "$UZBL_WIN_SIZE" | cut -d ' ' -f 1 )" +UZBL_WIN_HEIGHT="$( printf "$UZBL_WIN_SIZE" | cut -d ' ' -f 2 )" -- cgit v1.2.3 From 83a8c242f2cd350e0a8d0700179aa8c45a28ed20 Mon Sep 17 00:00:00 2001 From: Ben Boeckel Date: Thu, 10 Mar 2011 21:13:43 -0500 Subject: Use a better check for write permission --- examples/data/scripts/history.sh | 2 +- examples/data/scripts/insert_bookmark.sh | 3 +-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/examples/data/scripts/history.sh b/examples/data/scripts/history.sh index 4b660c3..4b4e970 100755 --- a/examples/data/scripts/history.sh +++ b/examples/data/scripts/history.sh @@ -2,6 +2,6 @@ . "$UZBL_UTIL_DIR/uzbl-dir.sh" -[ -w "$UZBL_HISTORY_FILE" ] || [ ! -a "$UZBL_HISTORY_FILE" ] || exit 1 +>> "$UZBL_HISTORY_FILE" || exit 1 printf "$( date +'%Y-%m-%d %H:%M:%S' ) $UZBL_URI $UZBL_TITLE\n" >> "$UZBL_HISTORY_FILE" diff --git a/examples/data/scripts/insert_bookmark.sh b/examples/data/scripts/insert_bookmark.sh index d4c6773..21a2aac 100755 --- a/examples/data/scripts/insert_bookmark.sh +++ b/examples/data/scripts/insert_bookmark.sh @@ -2,8 +2,7 @@ . "$UZBL_UTIL_DIR/uzbl-dir.sh" -[ -d "$UZBL_DATA_DIR" ] || exit 1 -[ -w "$UZBL_BOOKMARKS_FILE" ] || [ ! -a "$UZBL_BOOKMARKS_FILE" ] || exit 1 +>> "$UZBL_BOOKMARKS_FILE" || exit 1 which zenity >/dev/null 2>&1 || exit 2 -- cgit v1.2.3 From f43741a91218936749afb3242a6e473f76387684 Mon Sep 17 00:00:00 2001 From: Ben Boeckel Date: Thu, 10 Mar 2011 22:20:42 -0500 Subject: Add common utility script --- examples/data/scripts/util/uzbl-util.sh | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 examples/data/scripts/util/uzbl-util.sh diff --git a/examples/data/scripts/util/uzbl-util.sh b/examples/data/scripts/util/uzbl-util.sh new file mode 100644 index 0000000..4e010b7 --- /dev/null +++ b/examples/data/scripts/util/uzbl-util.sh @@ -0,0 +1,3 @@ +#!/bin/sh + +alias print="printf %s" -- cgit v1.2.3 From dcf3ffda8005c73c15f5142c61ee492f14af590a Mon Sep 17 00:00:00 2001 From: Ben Boeckel Date: Thu, 10 Mar 2011 22:23:36 -0500 Subject: Use print rather than printf printf chokes on $(printf "%DD") which may very well come up in an encoded URL. Avoid that with the print alias. --- examples/data/scripts/download.sh | 5 +++-- examples/data/scripts/follow.sh | 10 ++++++---- examples/data/scripts/formfiller.sh | 6 +++--- examples/data/scripts/go_input.sh | 6 ++++-- examples/data/scripts/history.sh | 2 +- examples/data/scripts/insert_bookmark.sh | 3 ++- examples/data/scripts/instance-select-wmii.sh | 5 +++-- examples/data/scripts/load_url_from_bookmarks.sh | 5 +++-- examples/data/scripts/load_url_from_history.sh | 5 +++-- examples/data/scripts/session.sh | 22 ++++++++++++---------- 10 files changed, 40 insertions(+), 29 deletions(-) diff --git a/examples/data/scripts/download.sh b/examples/data/scripts/download.sh index 448e086..8b4761f 100755 --- a/examples/data/scripts/download.sh +++ b/examples/data/scripts/download.sh @@ -7,11 +7,12 @@ # if nothing is printed to stdout, the download will be cancelled. . "$UZBL_UTIL_DIR/uzbl-dir.sh" +. "$UZBL_UTIL_DIR/uzbl-util.sh" # the URL that is being downloaded uri="$1" -safe_uri="$( printf "$uri" | sed -e 's/\W/-/g' )" +safe_uri="$( print "$uri" | sed -e 's/\W/-/g' )" # a filename suggested by the server or based on the URL suggested_filename="${2:-$safe_uri}" @@ -24,4 +25,4 @@ content_type="$3" total_size="$4" # just save the file to the default directory with the suggested name -printf "$UZBL_DOWNLOAD_DIR/$suggested_filename\n" +print "$UZBL_DOWNLOAD_DIR/$suggested_filename\n" diff --git a/examples/data/scripts/follow.sh b/examples/data/scripts/follow.sh index b038c12..ac5c6cb 100755 --- a/examples/data/scripts/follow.sh +++ b/examples/data/scripts/follow.sh @@ -3,24 +3,26 @@ # This script is just a wrapper around follow.js that lets us change uzbl's mode # after a link is selected. +. "$UZBL_UTIL_DIR/uzbl-util.sh" + keys="$1" shift # if socat is installed then we can change Uzbl's input mode once a link is # selected; otherwise we just select a link. if ! which socat >/dev/null 2>&1; then - printf "script @scripts_dir/follow.js \"@{follow_hint_keys} $keys\"\n" > "$UZBL_FIFO" + print "script @scripts_dir/follow.js \"@{follow_hint_keys} $keys\"\n" > "$UZBL_FIFO" exit fi -result="$( printf "script @scripts_dir/follow.js \"@{follow_hint_keys} $keys\"\n" | socat - "unix-connect:$UZBL_SOCKET" )" +result="$( print "script @scripts_dir/follow.js \"@{follow_hint_keys} $keys\"\n" | socat - "unix-connect:$UZBL_SOCKET" )" case $result in *XXXEMIT_FORM_ACTIVEXXX*) # a form element was selected - printf "event FORM_ACTIVE\n" > "$UZBL_FIFO" + print "event FORM_ACTIVE\n" > "$UZBL_FIFO" ;; *XXXRESET_MODEXXX*) # a link was selected, reset uzbl's input mode - printf "set mode=\n" > "$UZBL_FIFO" + print "set mode=\n" > "$UZBL_FIFO" ;; esac diff --git a/examples/data/scripts/formfiller.sh b/examples/data/scripts/formfiller.sh index 2895e5b..17634e2 100755 --- a/examples/data/scripts/formfiller.sh +++ b/examples/data/scripts/formfiller.sh @@ -56,7 +56,7 @@ MODELINE="> vim:ft=formfiller" action="$1" shift -domain="$( printf "$UZBL_URI\n" | sed -e 's/\(http\|https\):\/\/\([^\/]\+\)\/.*/\2/' )" +domain="$( print "$UZBL_URI\n" | sed -e 's/\(http\|https\):\/\/\([^\/]\+\)\/.*/\2/' )" form_file="$UZBL_FORMS_DIR/$domain" if [ "$action" != 'edit' ] && [ "$action" != 'new' ] && [ "$action" != 'load' ] && [ "$action" != 'add' ] && [ "$action" != 'once' ]; then @@ -126,7 +126,7 @@ if [ "$action" = 'load' ]; then [ -e "$form_file" ] || exit 2 if [ "$( grep "!profile" "$form_file" | wc -l )" -gt 1 ]; then menu="$( sed -n -e 's/^!profile=\([^[:blank:]]\+\)/\1/p' "$form_file" )" - option="$( printf "$menu" | $DMENU )" + option="$( print "$menu" | $DMENU )" fi sed -i -e 's/^\([^{]\+\){\([^}]*\)}(\(radio\|checkbox\)):\(off\|no\|false\|unchecked\|0\|$\)/\1{\2}(\3):0/I;s/^\([^{]\+\){\([^}]*\)}(\(radio\|checkbox\)):[^0]\+/\1{\2}(\3):1/I' "$form_file" @@ -170,7 +170,7 @@ elif [ "$action" = "once" ]; then else if [ "$action" = 'new' -o "$action" = 'add' ]; then [ "$action" = 'new' ] && echo "$MODELINE" > "$form_file" - printf "!profile=NAME_THIS_PROFILE$RAND\n" >> "$form_file" + print "!profile=NAME_THIS_PROFILE$RAND\n" >> "$form_file" # # 2. and 3. line (tr -d and sed) are because, on gmail login for example, # tag is splited into lines diff --git a/examples/data/scripts/go_input.sh b/examples/data/scripts/go_input.sh index 6574a83..ad236d1 100755 --- a/examples/data/scripts/go_input.sh +++ b/examples/data/scripts/go_input.sh @@ -1,7 +1,9 @@ #!/bin/sh -case "$( printf "script @scripts_dir/go_input.js\n" | socat - "unix-connect:$UZBL_SOCKET" )" in +. "$UZBL_UTIL_DIR/uzbl-util.sh" + +case "$( print "script @scripts_dir/go_input.js\n" | socat - "unix-connect:$UZBL_SOCKET" )" in *XXXEMIT_FORM_ACTIVEXXX*) - printf "event FORM_ACTIVE\n" > "$UZBL_FIFO" + print "event FORM_ACTIVE\n" > "$UZBL_FIFO" ;; esac diff --git a/examples/data/scripts/history.sh b/examples/data/scripts/history.sh index 4b4e970..d1e3c0f 100755 --- a/examples/data/scripts/history.sh +++ b/examples/data/scripts/history.sh @@ -4,4 +4,4 @@ >> "$UZBL_HISTORY_FILE" || exit 1 -printf "$( date +'%Y-%m-%d %H:%M:%S' ) $UZBL_URI $UZBL_TITLE\n" >> "$UZBL_HISTORY_FILE" +print "$( date +'%Y-%m-%d %H:%M:%S' ) $UZBL_URI $UZBL_TITLE\n" >> "$UZBL_HISTORY_FILE" diff --git a/examples/data/scripts/insert_bookmark.sh b/examples/data/scripts/insert_bookmark.sh index 21a2aac..5d41131 100755 --- a/examples/data/scripts/insert_bookmark.sh +++ b/examples/data/scripts/insert_bookmark.sh @@ -1,6 +1,7 @@ #!/bin/sh . "$UZBL_UTIL_DIR/uzbl-dir.sh" +. "$UZBL_UTIL_DIR/uzbl-util.sh" >> "$UZBL_BOOKMARKS_FILE" || exit 1 @@ -11,4 +12,4 @@ exitstatus="$?" [ "$exitstatus" -eq 0 ] || exit "$exitstatus" # TODO: check if already exists, if so, and tags are different: ask if you want to replace tags -printf "$UZBL_URI $tags\n" >> "$UZBL_BOOKMARKS_FILE" +print "$UZBL_URI $tags\n" >> "$UZBL_BOOKMARKS_FILE" diff --git a/examples/data/scripts/instance-select-wmii.sh b/examples/data/scripts/instance-select-wmii.sh index c12f7b7..d340dda 100755 --- a/examples/data/scripts/instance-select-wmii.sh +++ b/examples/data/scripts/instance-select-wmii.sh @@ -13,6 +13,7 @@ DMENU_SCHEME="wmii" . "$UZBL_UTIL_DIR/dmenu.sh" +. "$UZBL_UTIL_DIR/uzbl-util.sh" case "$1" in "list") @@ -22,7 +23,7 @@ case "$1" in label="$( wmiir read /client/$i/label )" list="$list$i : $label\n" done - window="$( printf "$list\n" | $DMENU | cut -d ' ' -f 1 )" + window="$( print "$list\n" | $DMENU | cut -d ' ' -f 1 )" wmiir xwrite /tag/sel/ctl "select client $window" ;; "next") @@ -41,7 +42,7 @@ case "$1" in fi ;; * ) - printf "$1 not valid\n" >&2 + print "$1 not valid\n" >&2 exit 2 ;; esac diff --git a/examples/data/scripts/load_url_from_bookmarks.sh b/examples/data/scripts/load_url_from_bookmarks.sh index d7bf104..30417f1 100755 --- a/examples/data/scripts/load_url_from_bookmarks.sh +++ b/examples/data/scripts/load_url_from_bookmarks.sh @@ -7,6 +7,7 @@ DMENU_OPTIONS="xmms vertical resize" . "$UZBL_UTIL_DIR/dmenu.sh" . "$UZBL_UTIL_DIR/uzbl-dir.sh" +. "$UZBL_UTIL_DIR/uzbl-util.sh" [ -r "$UZBL_BOOKMARKS_FILE" ] || exit 1 @@ -18,5 +19,5 @@ else goto="$( $DMENU < "$UZBL_BOOKMARKS_FILE" | cut -d ' ' -f 1 )" fi -[ -n "$goto" ] && printf "uri $goto\n" > "$UZBL_FIFO" -#[ -n "$goto" ] && printf "uri $goto\n" | socat - "unix-connect:$UZBL_SOCKET" +[ -n "$goto" ] && print "uri $goto\n" > "$UZBL_FIFO" +#[ -n "$goto" ] && print "uri $goto\n" | socat - "unix-connect:$UZBL_SOCKET" diff --git a/examples/data/scripts/load_url_from_history.sh b/examples/data/scripts/load_url_from_history.sh index 3537b35..0a6769a 100755 --- a/examples/data/scripts/load_url_from_history.sh +++ b/examples/data/scripts/load_url_from_history.sh @@ -5,6 +5,7 @@ DMENU_OPTIONS="xmms vertical resize" . "$UZBL_UTIL_DIR/dmenu.sh" . "$UZBL_UTIL_DIR/uzbl-dir.sh" +. "$UZBL_UTIL_DIR/uzbl-util.sh" [ -r "$UZBL_HISTORY_FILE" ] || exit 1 @@ -18,5 +19,5 @@ else goto="$( tac "$UZBL_HISTORY_FILE" | $DMENU | cut -d ' ' -f -3 | awk '{ print $NF }' )" fi -[ -n "$goto" ] && printf "uri $goto\n" > "$UZBL_FIFO" -#[ -n "$goto" ] && printf "uri $goto\n" | socat - "unix-connect:$UZBL_SOCKET" +[ -n "$goto" ] && print "uri $goto\n" > "$UZBL_FIFO" +#[ -n "$goto" ] && print "uri $goto\n" | socat - "unix-connect:$UZBL_SOCKET" diff --git a/examples/data/scripts/session.sh b/examples/data/scripts/session.sh index e2f97fe..d03554b 100755 --- a/examples/data/scripts/session.sh +++ b/examples/data/scripts/session.sh @@ -26,6 +26,8 @@ if [ -z "$UZBL_UTIL_DIR" ]; then fi . "$UZBL_UTIL_DIR/uzbl-dir.sh" +. "$UZBL_UTIL_DIR/uzbl-util.sh" + [ -d "$UZBL_DATA_DIR" ] || exit 1 UZBL="uzbl-browser -c \"$UZBL_CONFIG_FILE\"" # add custom flags and whatever here. @@ -53,27 +55,27 @@ case $act in "endinstance") if [ -z "$UZBL_FIFO" ]; then - printf "session manager: endinstance must be called from uzbl\n" + print "session manager: endinstance must be called from uzbl\n" exit 1 fi - [ "$UZBL_URI" != "(null)" ] && printf "$UZBL_URI\n" >> "$UZBL_SESSION_FILE" - printf "exit\n" > "$UZBL_FIFO" + [ "$UZBL_URI" != "(null)" ] && print "$UZBL_URI\n" >> "$UZBL_SESSION_FILE" + print "exit\n" > "$UZBL_FIFO" ;; "endsession") for fifo in "$UZBL_FIFO_DIR/uzbl_fifo_*"; do if [ "$fifo" != "$UZBL_FIFO" ]; then - printf "spawn $scriptfile endinstance\n" > "$fifo" + print "spawn $scriptfile endinstance\n" > "$fifo" fi done - [ -z "$UZBL_FIFO" ] || printf "spawn $scriptfile endinstance\n" > "$UZBL_FIFO" + [ -z "$UZBL_FIFO" ] || print "spawn $scriptfile endinstance\n" > "$UZBL_FIFO" ;; *) - printf "session manager: bad action\n" - printf "Usage: $scriptfile [COMMAND] where commands are:\n" - printf " launch - Restore a saved session or start a new one\n" - printf " endinstance - Quit the current instance. Must be called from uzbl\n" - printf " endsession - Quit the running session.\n" + print "session manager: bad action\n" + print "Usage: $scriptfile [COMMAND] where commands are:\n" + print " launch - Restore a saved session or start a new one\n" + print " endinstance - Quit the current instance. Must be called from uzbl\n" + print " endsession - Quit the running session.\n" ;; esac -- cgit v1.2.3 From 0e74fb167c23e9c80ed7a907e5d7e1dd0bc63d6e Mon Sep 17 00:00:00 2001 From: Ben Boeckel Date: Thu, 10 Mar 2011 22:24:43 -0500 Subject: Fix indentation --- examples/data/scripts/follow.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/data/scripts/follow.sh b/examples/data/scripts/follow.sh index ac5c6cb..4edab36 100755 --- a/examples/data/scripts/follow.sh +++ b/examples/data/scripts/follow.sh @@ -11,8 +11,8 @@ shift # if socat is installed then we can change Uzbl's input mode once a link is # selected; otherwise we just select a link. if ! which socat >/dev/null 2>&1; then - print "script @scripts_dir/follow.js \"@{follow_hint_keys} $keys\"\n" > "$UZBL_FIFO" - exit + print "script @scripts_dir/follow.js \"@{follow_hint_keys} $keys\"\n" > "$UZBL_FIFO" + exit 0 fi result="$( print "script @scripts_dir/follow.js \"@{follow_hint_keys} $keys\"\n" | socat - "unix-connect:$UZBL_SOCKET" )" -- cgit v1.2.3 From 39b930e8fdf82f8eefc04372f4edc03ffe55d738 Mon Sep 17 00:00:00 2001 From: Ben Boeckel Date: Fri, 11 Mar 2011 20:13:33 -0500 Subject: Use %b instead of %s in print alias --- examples/data/scripts/util/uzbl-util.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/data/scripts/util/uzbl-util.sh b/examples/data/scripts/util/uzbl-util.sh index 4e010b7..7e0bd99 100644 --- a/examples/data/scripts/util/uzbl-util.sh +++ b/examples/data/scripts/util/uzbl-util.sh @@ -1,3 +1,3 @@ #!/bin/sh -alias print="printf %s" +alias print="printf %b" -- cgit v1.2.3 From 07ef26f830a49833e49d0bb53f22a6ad25fa3c46 Mon Sep 17 00:00:00 2001 From: Ben Boeckel Date: Fri, 11 Mar 2011 20:13:56 -0500 Subject: Fix window geometry sed expression --- examples/data/scripts/util/uzbl-window.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/data/scripts/util/uzbl-window.sh b/examples/data/scripts/util/uzbl-window.sh index 279636a..b2f1d04 100644 --- a/examples/data/scripts/util/uzbl-window.sh +++ b/examples/data/scripts/util/uzbl-window.sh @@ -2,9 +2,9 @@ # uzbl window detection UZBL_WIN_POS="$( xwininfo -id "$UZBL_XID" | \ - sed -n -e 's/Corners:[ ]*[+-]\([0-9]*\)[+-]\([0-9]*\).*$/\1 \2/p' )" + sed -n -e '[ ]*s/Corners:[ ]*[+-]\([0-9]*\)[+-]\([0-9]*\).*$/\1 \2/p' )" UZBL_WIN_SIZE="$( xwininfo -id "$UZBL_XID" | \ - sed -n -e 's/-geometry[ ]*\([0-9]*\)x\([0-9]*\).*$/\1 \2/p' )" + sed -n -e '[ ]*s/-geometry[ ]*\([0-9]*\)x\([0-9]*\).*$/\1 \2/p' )" UZBL_WIN_POS_X="$( printf "$UZBL_WIN_POS" | cut -d ' ' -f 1 )" UZBL_WIN_POS_Y="$( printf "$UZBL_WIN_POS" | cut -d ' ' -f 2 )" UZBL_WIN_WIDTH="$( printf "$UZBL_WIN_SIZE" | cut -d ' ' -f 1 )" -- cgit v1.2.3 From 6c2890bbc664fb067bafda638417b92dc9fdd58d Mon Sep 17 00:00:00 2001 From: Ben Boeckel Date: Fri, 11 Mar 2011 20:14:43 -0500 Subject: Use print in uzbl-window util script --- examples/data/scripts/util/uzbl-window.sh | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/examples/data/scripts/util/uzbl-window.sh b/examples/data/scripts/util/uzbl-window.sh index b2f1d04..856e5fa 100644 --- a/examples/data/scripts/util/uzbl-window.sh +++ b/examples/data/scripts/util/uzbl-window.sh @@ -1,11 +1,13 @@ #!/bin/sh # uzbl window detection +. "$UZBL_UTIL_DIR/uzbl-util.sh" + UZBL_WIN_POS="$( xwininfo -id "$UZBL_XID" | \ sed -n -e '[ ]*s/Corners:[ ]*[+-]\([0-9]*\)[+-]\([0-9]*\).*$/\1 \2/p' )" UZBL_WIN_SIZE="$( xwininfo -id "$UZBL_XID" | \ sed -n -e '[ ]*s/-geometry[ ]*\([0-9]*\)x\([0-9]*\).*$/\1 \2/p' )" -UZBL_WIN_POS_X="$( printf "$UZBL_WIN_POS" | cut -d ' ' -f 1 )" -UZBL_WIN_POS_Y="$( printf "$UZBL_WIN_POS" | cut -d ' ' -f 2 )" -UZBL_WIN_WIDTH="$( printf "$UZBL_WIN_SIZE" | cut -d ' ' -f 1 )" -UZBL_WIN_HEIGHT="$( printf "$UZBL_WIN_SIZE" | cut -d ' ' -f 2 )" +UZBL_WIN_POS_X="$( print "$UZBL_WIN_POS" | cut -d ' ' -f 1 )" +UZBL_WIN_POS_Y="$( print "$UZBL_WIN_POS" | cut -d ' ' -f 2 )" +UZBL_WIN_WIDTH="$( print "$UZBL_WIN_SIZE" | cut -d ' ' -f 1 )" +UZBL_WIN_HEIGHT="$( print "$UZBL_WIN_SIZE" | cut -d ' ' -f 2 )" -- cgit v1.2.3 From 6b2a973e17a0cf4d3cdc88e71973624929018c78 Mon Sep 17 00:00:00 2001 From: Ben Boeckel Date: Fri, 11 Mar 2011 20:45:32 -0500 Subject: Allow the variable for follow.sh to be changed --- examples/config/config | 2 +- examples/data/scripts/follow.sh | 7 +++++-- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/examples/config/config b/examples/config/config index a2ecdb8..b5421da 100644 --- a/examples/config/config +++ b/examples/config/config @@ -309,7 +309,7 @@ set follow_hint_keys = 0123456789 #set follow_hint_keys = qwerty #set follow_hint_keys = asdfghjkl; #set follow_hint_keys = thsnd-rcgmvwb/;789aefijkopquxyz234 -@cbind fl* = spawn @scripts_dir/follow.sh "%s" +@cbind fl* = spawn @scripts_dir/follow.sh follow_hint_keys "%s" @cbind gi = spawn @scripts_dir/go_input.sh # Form filler binds diff --git a/examples/data/scripts/follow.sh b/examples/data/scripts/follow.sh index 4edab36..6401188 100755 --- a/examples/data/scripts/follow.sh +++ b/examples/data/scripts/follow.sh @@ -5,17 +5,20 @@ . "$UZBL_UTIL_DIR/uzbl-util.sh" +key_variable="$1" +shift + keys="$1" shift # if socat is installed then we can change Uzbl's input mode once a link is # selected; otherwise we just select a link. if ! which socat >/dev/null 2>&1; then - print "script @scripts_dir/follow.js \"@{follow_hint_keys} $keys\"\n" > "$UZBL_FIFO" + print "script @scripts_dir/follow.js \"@{$key_variable} $keys\"\n" > "$UZBL_FIFO" exit 0 fi -result="$( print "script @scripts_dir/follow.js \"@{follow_hint_keys} $keys\"\n" | socat - "unix-connect:$UZBL_SOCKET" )" +result="$( print "script @scripts_dir/follow.js \"@{$key_variable} $keys\"\n" | socat - "unix-connect:$UZBL_SOCKET" )" case $result in *XXXEMIT_FORM_ACTIVEXXX*) # a form element was selected -- cgit v1.2.3 From 32f6f8360684c0b583e613cf5727f0c102438bd2 Mon Sep 17 00:00:00 2001 From: Brendan Taylor Date: Sun, 13 Mar 2011 21:49:27 -0600 Subject: sh scripts: replace print with echo/printf we can safely use echo in many of the situations where 'print' is being used, and we can use printf directly in other places. --- examples/data/scripts/download.sh | 5 ++--- examples/data/scripts/go_input.sh | 6 ++---- examples/data/scripts/history.sh | 2 +- examples/data/scripts/insert_bookmark.sh | 3 +-- examples/data/scripts/instance-select-wmii.sh | 5 ++--- examples/data/scripts/load_url_from_bookmarks.sh | 5 ++--- examples/data/scripts/load_url_from_history.sh | 5 ++--- examples/data/scripts/session.sh | 21 ++++++++++----------- examples/data/scripts/util/uzbl-util.sh | 3 --- examples/data/scripts/util/uzbl-window.sh | 10 ++++------ 10 files changed, 26 insertions(+), 39 deletions(-) delete mode 100644 examples/data/scripts/util/uzbl-util.sh diff --git a/examples/data/scripts/download.sh b/examples/data/scripts/download.sh index 8b4761f..7753bd6 100755 --- a/examples/data/scripts/download.sh +++ b/examples/data/scripts/download.sh @@ -7,12 +7,11 @@ # if nothing is printed to stdout, the download will be cancelled. . "$UZBL_UTIL_DIR/uzbl-dir.sh" -. "$UZBL_UTIL_DIR/uzbl-util.sh" # the URL that is being downloaded uri="$1" -safe_uri="$( print "$uri" | sed -e 's/\W/-/g' )" +safe_uri="$( echo "$uri" | sed -e 's/\W/-/g' )" # a filename suggested by the server or based on the URL suggested_filename="${2:-$safe_uri}" @@ -25,4 +24,4 @@ content_type="$3" total_size="$4" # just save the file to the default directory with the suggested name -print "$UZBL_DOWNLOAD_DIR/$suggested_filename\n" +echo "$UZBL_DOWNLOAD_DIR/$suggested_filename" diff --git a/examples/data/scripts/go_input.sh b/examples/data/scripts/go_input.sh index ad236d1..9797788 100755 --- a/examples/data/scripts/go_input.sh +++ b/examples/data/scripts/go_input.sh @@ -1,9 +1,7 @@ #!/bin/sh -. "$UZBL_UTIL_DIR/uzbl-util.sh" - -case "$( print "script @scripts_dir/go_input.js\n" | socat - "unix-connect:$UZBL_SOCKET" )" in +case "$( echo "script @scripts_dir/go_input.js" | socat - "unix-connect:$UZBL_SOCKET" )" in *XXXEMIT_FORM_ACTIVEXXX*) - print "event FORM_ACTIVE\n" > "$UZBL_FIFO" + echo "event FORM_ACTIVE" > "$UZBL_FIFO" ;; esac diff --git a/examples/data/scripts/history.sh b/examples/data/scripts/history.sh index d1e3c0f..0709b5e 100755 --- a/examples/data/scripts/history.sh +++ b/examples/data/scripts/history.sh @@ -4,4 +4,4 @@ >> "$UZBL_HISTORY_FILE" || exit 1 -print "$( date +'%Y-%m-%d %H:%M:%S' ) $UZBL_URI $UZBL_TITLE\n" >> "$UZBL_HISTORY_FILE" +echo "$( date +'%Y-%m-%d %H:%M:%S' ) $UZBL_URI $UZBL_TITLE" >> "$UZBL_HISTORY_FILE" diff --git a/examples/data/scripts/insert_bookmark.sh b/examples/data/scripts/insert_bookmark.sh index 5d41131..f310e49 100755 --- a/examples/data/scripts/insert_bookmark.sh +++ b/examples/data/scripts/insert_bookmark.sh @@ -1,7 +1,6 @@ #!/bin/sh . "$UZBL_UTIL_DIR/uzbl-dir.sh" -. "$UZBL_UTIL_DIR/uzbl-util.sh" >> "$UZBL_BOOKMARKS_FILE" || exit 1 @@ -12,4 +11,4 @@ exitstatus="$?" [ "$exitstatus" -eq 0 ] || exit "$exitstatus" # TODO: check if already exists, if so, and tags are different: ask if you want to replace tags -print "$UZBL_URI $tags\n" >> "$UZBL_BOOKMARKS_FILE" +echo "$UZBL_URI $tags" >> "$UZBL_BOOKMARKS_FILE" diff --git a/examples/data/scripts/instance-select-wmii.sh b/examples/data/scripts/instance-select-wmii.sh index d340dda..b2aadbb 100755 --- a/examples/data/scripts/instance-select-wmii.sh +++ b/examples/data/scripts/instance-select-wmii.sh @@ -13,7 +13,6 @@ DMENU_SCHEME="wmii" . "$UZBL_UTIL_DIR/dmenu.sh" -. "$UZBL_UTIL_DIR/uzbl-util.sh" case "$1" in "list") @@ -23,7 +22,7 @@ case "$1" in label="$( wmiir read /client/$i/label )" list="$list$i : $label\n" done - window="$( print "$list\n" | $DMENU | cut -d ' ' -f 1 )" + window="$( echo "$list" | $DMENU | cut -d ' ' -f 1 )" wmiir xwrite /tag/sel/ctl "select client $window" ;; "next") @@ -42,7 +41,7 @@ case "$1" in fi ;; * ) - print "$1 not valid\n" >&2 + echo "$1 not valid" >&2 exit 2 ;; esac diff --git a/examples/data/scripts/load_url_from_bookmarks.sh b/examples/data/scripts/load_url_from_bookmarks.sh index 30417f1..a03db4b 100755 --- a/examples/data/scripts/load_url_from_bookmarks.sh +++ b/examples/data/scripts/load_url_from_bookmarks.sh @@ -7,7 +7,6 @@ DMENU_OPTIONS="xmms vertical resize" . "$UZBL_UTIL_DIR/dmenu.sh" . "$UZBL_UTIL_DIR/uzbl-dir.sh" -. "$UZBL_UTIL_DIR/uzbl-util.sh" [ -r "$UZBL_BOOKMARKS_FILE" ] || exit 1 @@ -19,5 +18,5 @@ else goto="$( $DMENU < "$UZBL_BOOKMARKS_FILE" | cut -d ' ' -f 1 )" fi -[ -n "$goto" ] && print "uri $goto\n" > "$UZBL_FIFO" -#[ -n "$goto" ] && print "uri $goto\n" | socat - "unix-connect:$UZBL_SOCKET" +[ -n "$goto" ] && echo "uri $goto" > "$UZBL_FIFO" +#[ -n "$goto" ] && echo "uri $goto" | socat - "unix-connect:$UZBL_SOCKET" diff --git a/examples/data/scripts/load_url_from_history.sh b/examples/data/scripts/load_url_from_history.sh index 0a6769a..24bfdce 100755 --- a/examples/data/scripts/load_url_from_history.sh +++ b/examples/data/scripts/load_url_from_history.sh @@ -5,7 +5,6 @@ DMENU_OPTIONS="xmms vertical resize" . "$UZBL_UTIL_DIR/dmenu.sh" . "$UZBL_UTIL_DIR/uzbl-dir.sh" -. "$UZBL_UTIL_DIR/uzbl-util.sh" [ -r "$UZBL_HISTORY_FILE" ] || exit 1 @@ -19,5 +18,5 @@ else goto="$( tac "$UZBL_HISTORY_FILE" | $DMENU | cut -d ' ' -f -3 | awk '{ print $NF }' )" fi -[ -n "$goto" ] && print "uri $goto\n" > "$UZBL_FIFO" -#[ -n "$goto" ] && print "uri $goto\n" | socat - "unix-connect:$UZBL_SOCKET" +[ -n "$goto" ] && echo "uri $goto" > "$UZBL_FIFO" +#[ -n "$goto" ] && echo "uri $goto" | socat - "unix-connect:$UZBL_SOCKET" diff --git a/examples/data/scripts/session.sh b/examples/data/scripts/session.sh index d03554b..4e7bfd1 100755 --- a/examples/data/scripts/session.sh +++ b/examples/data/scripts/session.sh @@ -26,7 +26,6 @@ if [ -z "$UZBL_UTIL_DIR" ]; then fi . "$UZBL_UTIL_DIR/uzbl-dir.sh" -. "$UZBL_UTIL_DIR/uzbl-util.sh" [ -d "$UZBL_DATA_DIR" ] || exit 1 @@ -55,27 +54,27 @@ case $act in "endinstance") if [ -z "$UZBL_FIFO" ]; then - print "session manager: endinstance must be called from uzbl\n" + echo "session manager: endinstance must be called from uzbl" exit 1 fi - [ "$UZBL_URI" != "(null)" ] && print "$UZBL_URI\n" >> "$UZBL_SESSION_FILE" - print "exit\n" > "$UZBL_FIFO" + [ "$UZBL_URI" != "(null)" ] && echo "$UZBL_URI" >> "$UZBL_SESSION_FILE" + echo "exit" > "$UZBL_FIFO" ;; "endsession") for fifo in "$UZBL_FIFO_DIR/uzbl_fifo_*"; do if [ "$fifo" != "$UZBL_FIFO" ]; then - print "spawn $scriptfile endinstance\n" > "$fifo" + echo "spawn $scriptfile endinstance" > "$fifo" fi done - [ -z "$UZBL_FIFO" ] || print "spawn $scriptfile endinstance\n" > "$UZBL_FIFO" + [ -z "$UZBL_FIFO" ] || echo "spawn $scriptfile endinstance" > "$UZBL_FIFO" ;; *) - print "session manager: bad action\n" - print "Usage: $scriptfile [COMMAND] where commands are:\n" - print " launch - Restore a saved session or start a new one\n" - print " endinstance - Quit the current instance. Must be called from uzbl\n" - print " endsession - Quit the running session.\n" + echo "session manager: bad action" + echo "Usage: $scriptfile [COMMAND] where commands are:" + echo " launch - Restore a saved session or start a new one" + echo " endinstance - Quit the current instance. Must be called from uzbl" + echo " endsession - Quit the running session." ;; esac diff --git a/examples/data/scripts/util/uzbl-util.sh b/examples/data/scripts/util/uzbl-util.sh deleted file mode 100644 index 7e0bd99..0000000 --- a/examples/data/scripts/util/uzbl-util.sh +++ /dev/null @@ -1,3 +0,0 @@ -#!/bin/sh - -alias print="printf %b" diff --git a/examples/data/scripts/util/uzbl-window.sh b/examples/data/scripts/util/uzbl-window.sh index 856e5fa..4b96372 100644 --- a/examples/data/scripts/util/uzbl-window.sh +++ b/examples/data/scripts/util/uzbl-window.sh @@ -1,13 +1,11 @@ #!/bin/sh # uzbl window detection -. "$UZBL_UTIL_DIR/uzbl-util.sh" - UZBL_WIN_POS="$( xwininfo -id "$UZBL_XID" | \ sed -n -e '[ ]*s/Corners:[ ]*[+-]\([0-9]*\)[+-]\([0-9]*\).*$/\1 \2/p' )" UZBL_WIN_SIZE="$( xwininfo -id "$UZBL_XID" | \ sed -n -e '[ ]*s/-geometry[ ]*\([0-9]*\)x\([0-9]*\).*$/\1 \2/p' )" -UZBL_WIN_POS_X="$( print "$UZBL_WIN_POS" | cut -d ' ' -f 1 )" -UZBL_WIN_POS_Y="$( print "$UZBL_WIN_POS" | cut -d ' ' -f 2 )" -UZBL_WIN_WIDTH="$( print "$UZBL_WIN_SIZE" | cut -d ' ' -f 1 )" -UZBL_WIN_HEIGHT="$( print "$UZBL_WIN_SIZE" | cut -d ' ' -f 2 )" +UZBL_WIN_POS_X="$( echo "$UZBL_WIN_POS" | cut -d ' ' -f 1 )" +UZBL_WIN_POS_Y="$( echo "$UZBL_WIN_POS" | cut -d ' ' -f 2 )" +UZBL_WIN_WIDTH="$( echo "$UZBL_WIN_SIZE" | cut -d ' ' -f 1 )" +UZBL_WIN_HEIGHT="$( echo "$UZBL_WIN_SIZE" | cut -d ' ' -f 2 )" -- cgit v1.2.3 From ac9ba58e63576adbf6aa5fbd956be7d4dbfd5aae Mon Sep 17 00:00:00 2001 From: Brendan Taylor Date: Sun, 13 Mar 2011 22:09:57 -0600 Subject: add 'hardcopy' (print page to printer) binding to example config --- examples/config/config | 3 +++ 1 file changed, 3 insertions(+) diff --git a/examples/config/config b/examples/config/config index bcd6d3e..6de0b59 100644 --- a/examples/config/config +++ b/examples/config/config @@ -267,6 +267,9 @@ set ebind = @mode_bind global,-insert @cbind n = search @cbind N = search_reverse +# Print pages to a printer +@cbind  p = hardcopy + # Web searching binds @cbind gg_ = uri http://www.google.com/search?q=\@\@ @cbind ddg_ = uri http://duckduckgo.com/?q=%s -- cgit v1.2.3 From 3cc75534065c0775dfea171b1b96cc3d2b7243a0 Mon Sep 17 00:00:00 2001 From: Ben Boeckel Date: Fri, 11 Mar 2011 20:55:57 -0500 Subject: Support -x flag without angle brackets as well --- examples/data/scripts/util/dmenu.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/data/scripts/util/dmenu.sh b/examples/data/scripts/util/dmenu.sh index 354d7d1..f0d1651 100644 --- a/examples/data/scripts/util/dmenu.sh +++ b/examples/data/scripts/util/dmenu.sh @@ -98,7 +98,7 @@ if dmenu --help 2>&1 | grep -q '\[-l <\?lines>\?\]'; then fi # Detect placement patch -if dmenu --help 2>&1 | grep -q '\[-x \]'; then +if dmenu --help 2>&1 | grep -q '\[-x <\?xoffset>\?\]'; then DMENU_PLACE_X="-x" DMENU_PLACE_Y="-y" DMENU_PLACE_WIDTH="-w" -- cgit v1.2.3 From 8572aefe9cfd0e58e3fa4021183285095670a6fa Mon Sep 17 00:00:00 2001 From: Ben Boeckel Date: Wed, 9 Mar 2011 23:23:59 -0500 Subject: Add a skeleton so users can improve downloads --- examples/data/scripts/download.sh | 36 ++++++++++++++++++++++++++++++------ 1 file changed, 30 insertions(+), 6 deletions(-) diff --git a/examples/data/scripts/download.sh b/examples/data/scripts/download.sh index 7753bd6..ca8728c 100755 --- a/examples/data/scripts/download.sh +++ b/examples/data/scripts/download.sh @@ -1,5 +1,4 @@ #!/bin/sh -# # uzbl's example configuration sets this script up as its download_handler. # when uzbl starts a download it runs this script. # if the script prints a file path to stdout, uzbl will save the download to @@ -10,18 +9,43 @@ # the URL that is being downloaded uri="$1" +shift safe_uri="$( echo "$uri" | sed -e 's/\W/-/g' )" # a filename suggested by the server or based on the URL -suggested_filename="${2:-$safe_uri}" +suggested_filename="${1:-$safe_uri}" +shift # the mimetype of the file being downloaded -content_type="$3" +content_type="$1" +shift # the size of the downloaded file in bytes. this is not always accurate, since # the server might not have sent a size with its response headers. -total_size="$4" +total_size="$1" +shift -# just save the file to the default directory with the suggested name -echo "$UZBL_DOWNLOAD_DIR/$suggested_filename" +case "$suggested_filename" in + # Default case + *) + path="$UZBL_DOWNLOAD_DIR/$suggested_filename" + ;; +esac + +# Do nothing if we don't want to save the file +[ -z "$path" ] && exit 0 + +# Check if the file exists +if [ ! -e "$path" ]; then + echo "$path" + exit 0 +fi + +# Try to make a unique filename +count=1 +while [ -e "$path.$count" ]; do + count=$(( $count + 1 )) +done + +echo "$path.$count" -- cgit v1.2.3 From ade2d7564e1e4687ed7d24ef09be29deb54081c7 Mon Sep 17 00:00:00 2001 From: Brendan Taylor Date: Sun, 13 Mar 2011 22:21:32 -0600 Subject: give an example in the new download skeleton --- examples/data/scripts/download.sh | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/examples/data/scripts/download.sh b/examples/data/scripts/download.sh index ca8728c..fe566ed 100755 --- a/examples/data/scripts/download.sh +++ b/examples/data/scripts/download.sh @@ -27,6 +27,10 @@ total_size="$1" shift case "$suggested_filename" in + # example: save torrents to a separate directory + #*.torrent) + # path="$UZBL_DOWNLOAD_DIR/torrents/$suggested_filename" + # ;; # Default case *) path="$UZBL_DOWNLOAD_DIR/$suggested_filename" -- cgit v1.2.3 From 7803561048966a88c4effe2466a4dc1e646d1e59 Mon Sep 17 00:00:00 2001 From: Brendan Taylor Date: Thu, 17 Mar 2011 07:06:03 -0600 Subject: parse events correctly in uzbl-tabbed --- examples/data/scripts/uzbl-tabbed | 44 ++++++++++++++++++++++++--------------- 1 file changed, 27 insertions(+), 17 deletions(-) diff --git a/examples/data/scripts/uzbl-tabbed b/examples/data/scripts/uzbl-tabbed index 1d64436..13e4e44 100755 --- a/examples/data/scripts/uzbl-tabbed +++ b/examples/data/scripts/uzbl-tabbed @@ -297,7 +297,6 @@ def escape(s): s = s.replace(split, glue) return s - class SocketClient: '''Represents a Uzbl instance, which is not necessarly linked with a UzblInstance''' @@ -443,18 +442,29 @@ class UzblInstance: if self._client: self._client.send('exit') + def unquote(self, s): + '''Removes quotation marks around strings if any and interprets + \\-escape sequences using `string_escape`''' + if s and s[0] == s[-1] and s[0] in ['"', "'"]: + s = s[1:-1] + return s.encode('utf-8').decode('string_escape').decode('utf-8') + + _splitquoted = re.compile("( |\"(?:\\\\.|[^\"])*?\"|'(?:\\\\.|[^'])*?')") + def parse_event(self, text): + '''Splits string on whitespace while respecting quotations''' + return [self.unquote(p) for p in self._splitquoted.split(text) if p.strip()] def parse_command(self, cmd): ''' Parse event givent by the Uzbl instance ''' - type, _, args = cmd.split(" ", 2) - if type == "EVENT": - type, args = args.split(" ", 1) + cmd = self.parse_event(cmd) + message, type, args = cmd[0], cmd[2], cmd[3:] + if message == "EVENT": if type == "TITLE_CHANGED": - self.title = args.strip() + self.title = args[0].strip() self.title_changed(False) elif type == "VARIABLE_SET": - var, _, val = args.split(" ", 2) + var, val = args[0], args[2] try: val = int(val) @@ -486,34 +496,34 @@ class UzblInstance: self.uri = val.strip() self.parent.update_tablist() elif type == "LOAD_COMMIT": - self.uri = args + self.uri = args[0] elif type == "NEW_TAB": - self.parent.new_tab(args) + self.parent.new_tab(args[0]) elif type == "NEW_BG_TAB": - self.parent.new_tab(args, '', 0) + self.parent.new_tab(args[0], '', 0) elif type == "NEW_TAB_NEXT": - self.parent.new_tab(args, next=True) + self.parent.new_tab(args[0], next=True) elif type == "NEW_BG_TAB_NEXT": - self.parent.new_tab(args, '', 0, next=True) + self.parent.new_tab(args[0], '', 0, next=True) elif type == "NEXT_TAB": - if args: - self.parent.next_tab(int(args)) + if args[0]: + self.parent.next_tab(int(args[0])) else: self.parent.next_tab() elif type == "PREV_TAB": - if args: - self.parent.prev_tab(int(args)) + if args[0]: + self.parent.prev_tab(int(args[0])) else: self.parent.prev_tab() elif type == "GOTO_TAB": - self.parent.goto_tab(int(args)) + self.parent.goto_tab(int(args[0])) elif type == "FIRST_TAB": self.parent.goto_tab(0) elif type == "LAST_TAB": self.parent.goto_tab(-1) elif type == "PRESET_TABS": - self.parent.parse_command(["preset"] + args.split()) + self.parent.parse_command(["preset"] + args) elif type == "BRING_TO_FRONT": self.parent.window.present() elif type == "CLEAN_TABS": -- cgit v1.2.3 From f54be5d0a91716d701d7abac74f69ff931665e3c Mon Sep 17 00:00:00 2001 From: "Klaus T. Aehlig" Date: Thu, 17 Mar 2011 07:19:21 -0600 Subject: add --socketdir and --fifodir options to uzbl-tabbed --- examples/data/scripts/uzbl-tabbed | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/examples/data/scripts/uzbl-tabbed b/examples/data/scripts/uzbl-tabbed index 0c347b5..2a5f481 100755 --- a/examples/data/scripts/uzbl-tabbed +++ b/examples/data/scripts/uzbl-tabbed @@ -1389,6 +1389,10 @@ if __name__ == "__main__": action='store_true', help="ignore session saving a loading.") parser.add_option('-v', '--verbose', dest='verbose', action='store_true', help='print verbose output.') + parser.add_option('-s', '--socketdir', dest='socketdir', + help="directory to create socket") + parser.add_option('-f', '--fifodir', dest='fifodir', + help="directory to create fifo") # Parse command line options (options, uris) = parser.parse_args() @@ -1403,6 +1407,12 @@ if __name__ == "__main__": import pprint sys.stderr.write("%s\n" % pprint.pformat(config)) + if options.socketdir: + config['socket_dir'] = options.socketdir + + if options.fifodir: + config['fifo_dir'] = options.fifodir + uzbl = UzblTabbed() # All extra arguments given to uzbl_tabbed.py are interpreted as -- cgit v1.2.3 From c4e594448095703a13dfa2556c78a55ed65d6f47 Mon Sep 17 00:00:00 2001 From: Brendan Taylor Date: Thu, 17 Mar 2011 07:25:48 -0600 Subject: add Klaus T. Aehlig to AUTHORS (and fix a typo) --- AUTHORS | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/AUTHORS b/AUTHORS index ff31818..fe97f86 100644 --- a/AUTHORS +++ b/AUTHORS @@ -53,6 +53,7 @@ In alphabetical order: Jason Woofenden (JasonWoof) - geometry=maximized, link following Jochen Sprickerhof - session.sh enhancements k0ral - split status bar, cleanup and bugfix patches + Klaus T. Aehlig - various patches Lars-Dominik Braun (PromyLOPh) - added ability to enable/disable the webkit page cache Laurence Withers (lwithers) - talk_to_socket Luca Bruno - bashims fixes @@ -84,7 +85,7 @@ In alphabetical order: Also, thanks to all people who've posted useful things to the mailing list and/or wiki. -Originaly based on http://trac.webkit.org/browser/trunk/WebKitTools/GtkLauncher/main.c +Originally based on http://trac.webkit.org/browser/trunk/WebKitTools/GtkLauncher/main.c Which is copyrighted: 2006, 2007 Apple Inc 2007 Alp Toker -- cgit v1.2.3 From 49ce876c744ee3d6a424c50d9f2db439acbe3f28 Mon Sep 17 00:00:00 2001 From: keis Date: Thu, 17 Mar 2011 20:24:02 +0100 Subject: fix clear_cookies warning --- src/uzbl-core.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/uzbl-core.c b/src/uzbl-core.c index c879602..ec2d347 100644 --- a/src/uzbl-core.c +++ b/src/uzbl-core.c @@ -732,10 +732,12 @@ clear_cookies(WebKitWebView *page, GArray *argv, GString *result) { (void) page; (void) argv; (void) result; // Replace the current cookie jar with a new empty jar - soup_session_remove_feature (uzbl.net.soup_session, uzbl.net.soup_cookie_jar); + soup_session_remove_feature (uzbl.net.soup_session, + SOUP_SESSION_FEATURE (uzbl.net.soup_cookie_jar)); g_object_unref (G_OBJECT (uzbl.net.soup_cookie_jar)); uzbl.net.soup_cookie_jar = uzbl_cookie_jar_new (); - soup_session_add_feature(uzbl.net.soup_session, uzbl.net.soup_cookie_jar); + soup_session_add_feature(uzbl.net.soup_session, + SOUP_SESSION_FEATURE (uzbl.net.soup_cookie_jar)); } void -- cgit v1.2.3 From 890f2f9b5ca2f23185976f5b04b5de51924122c5 Mon Sep 17 00:00:00 2001 From: Brendan Taylor Date: Thu, 17 Mar 2011 20:04:55 -0600 Subject: update .gitignore --- .gitignore | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index 2ddbb60..8c08dc0 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,8 @@ uzbl-core *.o +*.lo *.pyc +*.sw[a-z] *~ tags -uzbl-cookie-manager +sandbox -- cgit v1.2.3 From b266564f4a5fe6fc348992b28c9b31a42c7d86d8 Mon Sep 17 00:00:00 2001 From: Brendan Taylor Date: Thu, 17 Mar 2011 20:09:50 -0600 Subject: a hack to prevent the uzbl-tabbed window from expanding when the contents of the status bar are too long --- examples/data/scripts/uzbl-tabbed | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/examples/data/scripts/uzbl-tabbed b/examples/data/scripts/uzbl-tabbed index 2a5f481..4039096 100755 --- a/examples/data/scripts/uzbl-tabbed +++ b/examples/data/scripts/uzbl-tabbed @@ -578,6 +578,11 @@ class UzblTabbed: self.window.set_title("Uzbl Browser") self.window.set_border_width(0) + # this prevents the window from expanding if the contents of the + # statusbar are wider than the window. + # i suspect this is not the right way to do this. + self.window.set_geometry_hints(min_width=1) + # Set main window icon icon_path = config['icon_path'] if os.path.exists(icon_path): -- cgit v1.2.3 From fc9946d16ee7f2e1632e228c2b4734d8e636a76d Mon Sep 17 00:00:00 2001 From: keis Date: Fri, 18 Mar 2011 14:11:41 +0100 Subject: make elements with onclick followable --- examples/data/scripts/follow.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/data/scripts/follow.js b/examples/data/scripts/follow.js index 536256b..632bae6 100644 --- a/examples/data/scripts/follow.js +++ b/examples/data/scripts/follow.js @@ -211,7 +211,7 @@ uzbl.follow.followLinks = function(follow) { var s = follow.split(''); var linknr = this.labelToInt(follow); - var followable = 'a, area, textarea, select, input:not([type=hidden]), button'; + var followable = 'a, area, textarea, select, input:not([type=hidden]), button, *[onclick]'; var uri = 'a, area, frame, iframe'; //var focusable = 'a, area, textarea, select, input:not([type=hidden]), button, frame, iframe, applet, object'; //var desc = '*[title], img[alt], applet[alt], area[alt], input[alt]'; -- cgit v1.2.3 From acf2405edadd82746608e325a16044e831e1f6f9 Mon Sep 17 00:00:00 2001 From: keis Date: Fri, 18 Mar 2011 14:15:46 +0100 Subject: clear hints on Escape * add shortcut to clear all hints --- examples/config/config | 1 + examples/data/scripts/follow.js | 13 +++++++++---- 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/examples/config/config b/examples/config/config index 6de0b59..089fc8d 100644 --- a/examples/config/config +++ b/examples/config/config @@ -185,6 +185,7 @@ set ebind = @mode_bind global,-insert # Resets keycmd and returns to default mode. @on_event ESCAPE @set_mode @on_event ESCAPE event KEYCMD_CLEAR +@on_event ESCAPE js uzbl.follow.clearHints() @bind = event ESCAPE @bind [ = event ESCAPE diff --git a/examples/data/scripts/follow.js b/examples/data/scripts/follow.js index 632bae6..b7b0d82 100644 --- a/examples/data/scripts/follow.js +++ b/examples/data/scripts/follow.js @@ -98,12 +98,17 @@ uzbl.follow.elementInViewport = function(el) { } // Removes all hints/leftovers that might be generated -// by this script. -uzbl.follow.removeAllHints = function(doc) { +// by this script in the given document. +uzbl.follow.removeHints = function(doc) { var elements = doc.getElementById(uzbldivid); if (elements) elements.parentNode.removeChild(elements); } +// Clears all hints in every document +uzbl.follow.clearHints = function() { + this.documents().forEach(uzbl.follow.removeHints); +} + // Generate a hint for an element with the given label // Here you can play around with the style of the hints! uzbl.follow.generateHint = function(doc, el, label, top, left) { @@ -153,7 +158,7 @@ uzbl.follow.reDrawHints = function(elems, chars) { var positions = elements.map(uzbl.follow.elementPosition); this.documents().forEach(function(doc) { - uzbl.follow.removeAllHints(doc); + uzbl.follow.removeHints(doc); if (!doc.body) return; doc.hintdiv = doc.createElement('div'); doc.hintdiv.id = uzbldivid; @@ -230,7 +235,7 @@ uzbl.follow.followLinks = function(follow) { var el = elems[linknr]; // clear all of our hints - this.documents().forEach(uzbl.follow.removeAllHints); + this.clearHints(); if (newwindow) { // we're opening a new window using the URL attached to this element -- cgit v1.2.3 From a227c770d91fdc48245410cefc99aaf83851de00 Mon Sep 17 00:00:00 2001 From: Brendan Taylor Date: Sat, 19 Mar 2011 08:45:56 -0600 Subject: cleanup misc: remove unused files, fix bashisms --- misc/cleanprocs-files.sh | 10 ---------- misc/env.sh | 17 ++++++++++++----- misc/fifotest.sh | 20 -------------------- 3 files changed, 12 insertions(+), 35 deletions(-) delete mode 100755 misc/cleanprocs-files.sh delete mode 100755 misc/fifotest.sh diff --git a/misc/cleanprocs-files.sh b/misc/cleanprocs-files.sh deleted file mode 100755 index 463d1fb..0000000 --- a/misc/cleanprocs-files.sh +++ /dev/null @@ -1,10 +0,0 @@ -#!/bin/bash -killall uzbl; killall strace; -killall -9 uzbl; killall -9 strace - -rm -rf /tmp/uzbl_* - -echo "Uzbl processes:" -ps aux | grep uzbl | grep -v grep -echo "Uzbl /tmp entries:" -ls -alh /tmp/uzbl* 2>/dev/null diff --git a/misc/env.sh b/misc/env.sh index 68377f2..f815c44 100755 --- a/misc/env.sh +++ b/misc/env.sh @@ -10,14 +10,21 @@ # Maybe we should spawn processes from here with an 'exec' at the end? # Re-define our home location inside the sandbox dir. -export HOME=$(pwd)/sandbox/home +HOME=$(pwd)/sandbox/home +export HOME # Export default XDG_{DATA,CACHE,..}_HOME locations inside the sandbox # directory according to defaults in the xdg specification. # -export XDG_DATA_HOME=$HOME/.local/share -export XDG_CACHE_HOME=$HOME/.cache -export XDG_CONFIG_HOME=$HOME/.config +XDG_DATA_HOME=$HOME/.local/share +export XDG_DATA_HOME + +XDG_CACHE_HOME=$HOME/.cache +export XDG_CACHE_HOME + +XDG_CONFIG_HOME=$HOME/.config +export XDG_CONFIG_HOME # Needed to run uzbl-browser etc from here. -export PATH="$(pwd)/sandbox/usr/local/bin:$PATH" +PATH="$(pwd)/sandbox/usr/local/bin:$PATH" +export PATH diff --git a/misc/fifotest.sh b/misc/fifotest.sh deleted file mode 100755 index 8ad0593..0000000 --- a/misc/fifotest.sh +++ /dev/null @@ -1,20 +0,0 @@ -#!/bin/bash -if [ -z "$1" ] -then - echo "Need fifo filename!" >&2 - exit 2 -fi -while : -do - echo 'uri dns.be' - echo 'uri dns.be' > $1 - sleep 2 - echo 'uri www.archlinux.org' - echo 'uri www.archlinux.org' > $1 - sleep 2 - echo 'uri icanhascheezburger.com' - echo 'uri icanhascheezburger.com' > $1 - sleep 2 - echo 'back' - echo 'back' > $1 -done -- cgit v1.2.3 From 0c76d87b6006194ead35c8fb5cf1986fb0367e19 Mon Sep 17 00:00:00 2001 From: Brendan Taylor Date: Sat, 19 Mar 2011 08:46:09 -0600 Subject: fix bashisms in makefile --- Makefile | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/Makefile b/Makefile index 62bc9b5..91b66b6 100644 --- a/Makefile +++ b/Makefile @@ -74,7 +74,7 @@ test-uzbl-core-sandbox: uzbl-core make DESTDIR=./sandbox RUN_PREFIX=`pwd`/sandbox/usr/local install-uzbl-core make DESTDIR=./sandbox RUN_PREFIX=`pwd`/sandbox/usr/local install-example-data cp -np ./misc/env.sh ./sandbox/env.sh - source ./sandbox/env.sh && uzbl-core --uri http://www.uzbl.org --verbose + . ./sandbox/env.sh && uzbl-core --uri http://www.uzbl.org --verbose make DESTDIR=./sandbox uninstall rm -rf ./sandbox/usr @@ -83,9 +83,9 @@ test-uzbl-browser-sandbox: uzbl-browser make DESTDIR=./sandbox RUN_PREFIX=`pwd`/sandbox/usr/local install-uzbl-browser make DESTDIR=./sandbox RUN_PREFIX=`pwd`/sandbox/usr/local install-example-data cp -np ./misc/env.sh ./sandbox/env.sh - -source ./sandbox/env.sh && uzbl-event-manager restart -avv - source ./sandbox/env.sh && uzbl-browser --uri http://www.uzbl.org --verbose - source ./sandbox/env.sh && uzbl-event-manager stop -ivv + -. ./sandbox/env.sh && uzbl-event-manager restart -avv + . ./sandbox/env.sh && uzbl-browser --uri http://www.uzbl.org --verbose + . ./sandbox/env.sh && uzbl-event-manager stop -ivv make DESTDIR=./sandbox uninstall rm -rf ./sandbox/usr @@ -94,9 +94,9 @@ test-uzbl-tabbed-sandbox: uzbl-browser make DESTDIR=./sandbox RUN_PREFIX=`pwd`/sandbox/usr/local install-uzbl-browser make DESTDIR=./sandbox RUN_PREFIX=`pwd`/sandbox/usr/local install-example-data cp -np ./misc/env.sh ./sandbox/env.sh - -source ./sandbox/env.sh && uzbl-event-manager restart -avv - source ./sandbox/env.sh && ./sandbox/home/.local/share/uzbl/scripts/uzbl-tabbed - source ./sandbox/env.sh && uzbl-event-manager stop -ivv + -. ./sandbox/env.sh && uzbl-event-manager restart -avv + . ./sandbox/env.sh && ./sandbox/home/.local/share/uzbl/scripts/uzbl-tabbed + . ./sandbox/env.sh && uzbl-event-manager stop -ivv make DESTDIR=./sandbox uninstall rm -rf ./sandbox/usr -- cgit v1.2.3 From 931dd7496af6b3e6ad1d129335a7806ee245b14d Mon Sep 17 00:00:00 2001 From: Christer Sjöholm Date: Sun, 20 Mar 2011 11:37:57 +0100 Subject: Fixes NEXT_TAB and PREV_TAB in uzbl-tabbed. The detection of an argument was incorrect. --- examples/data/scripts/uzbl-tabbed | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/data/scripts/uzbl-tabbed b/examples/data/scripts/uzbl-tabbed index 4039096..0502951 100755 --- a/examples/data/scripts/uzbl-tabbed +++ b/examples/data/scripts/uzbl-tabbed @@ -510,12 +510,12 @@ class UzblInstance: self.parent.new_tab(args[0], '', 0, next=True) elif type == "NEXT_TAB": - if args[0]: + if args: self.parent.next_tab(int(args[0])) else: self.parent.next_tab() elif type == "PREV_TAB": - if args[0]: + if args: self.parent.prev_tab(int(args[0])) else: self.parent.prev_tab() -- cgit v1.2.3 From 23559dab4f44ccfef4edb7db19e2ec3e3671bf5a Mon Sep 17 00:00:00 2001 From: Christer Sjöholm Date: Sun, 20 Mar 2011 12:07:58 +0100 Subject: Fix for uzbl-tabbed new-tab. Some times the uri may be a unicode string, so we convert it to a str as required by gobject.spawn_async(). This happens when a page want to open an url in a new window. --- examples/data/scripts/uzbl-tabbed | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/data/scripts/uzbl-tabbed b/examples/data/scripts/uzbl-tabbed index 0502951..04635fc 100755 --- a/examples/data/scripts/uzbl-tabbed +++ b/examples/data/scripts/uzbl-tabbed @@ -1024,7 +1024,7 @@ class UzblTabbed: title = config['new_tab_title'] cmd = ['uzbl-browser', '-n', name, '-s', str(sid), - '--connect-socket', self.socket_path, '--uri', uri] + '--connect-socket', self.socket_path, '--uri', str(uri)] gobject.spawn_async(cmd, flags=gobject.SPAWN_SEARCH_PATH) uzbl = UzblInstance(self, tab, name, uri, title, switch) -- cgit v1.2.3 From 2d0e769245445eba8ec6f63c7bd122040d35f5e4 Mon Sep 17 00:00:00 2001 From: Christer Sjöholm Date: Sun, 20 Mar 2011 12:20:09 +0100 Subject: Allow NEW_TAB to be called without an URI The new instance tries to open the CWD, a blank page would be nicer. --- examples/data/scripts/uzbl-tabbed | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/examples/data/scripts/uzbl-tabbed b/examples/data/scripts/uzbl-tabbed index 04635fc..2d7d7c9 100755 --- a/examples/data/scripts/uzbl-tabbed +++ b/examples/data/scripts/uzbl-tabbed @@ -501,7 +501,10 @@ class UzblInstance: elif type == "LOAD_COMMIT": self.uri = args[0] elif type == "NEW_TAB": - self.parent.new_tab(args[0]) + if args: + self.parent.new_tab(args[0]) + else: + self.parent.new_tab() elif type == "NEW_BG_TAB": self.parent.new_tab(args[0], '', 0) elif type == "NEW_TAB_NEXT": -- cgit v1.2.3 From 2926b0f55122b131e0b9d2cf857d2b78d202c5ab Mon Sep 17 00:00:00 2001 From: Olof-Joachim Frahm Date: Mon, 21 Mar 2011 06:23:23 +0100 Subject: Fixed array bug. When e.g. spawn_sh modifies the array, invalid stuff is send to the python script, which then breaks while decoding them. --- src/uzbl-core.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/uzbl-core.c b/src/uzbl-core.c index c879602..ba062b6 100644 --- a/src/uzbl-core.c +++ b/src/uzbl-core.c @@ -1129,8 +1129,6 @@ spawn_sh_sync(WebKitWebView *web_view, GArray *argv, GString *result) { void run_parsed_command(const CommandInfo *c, GArray *a, GString *result) { - c->function(uzbl.gui.web_view, a, result); - /* send the COMMAND_EXECUTED event, except for set and event/request commands */ if(strcmp("set", c->key) && strcmp("event", c->key) && @@ -1141,12 +1139,18 @@ run_parsed_command(const CommandInfo *c, GArray *a, GString *result) { guint i = 0; while ((p = argv_idx(a, i++))) g_string_append_printf(param, " '%s'", p); + + /* might be destructive on array a */ + c->function(uzbl.gui.web_view, a, result); + send_event(COMMAND_EXECUTED, NULL, TYPE_NAME, c->key, TYPE_FORMATTEDSTR, param->str, NULL); g_string_free(param, TRUE); } + else + c->function(uzbl.gui.web_view, a, result); if(result) { g_free(uzbl.state.last_result); -- cgit v1.2.3 From bce29e41f55e74a65cdbd49a07811b2c9932bfc0 Mon Sep 17 00:00:00 2001 From: Brendan Taylor Date: Mon, 21 Mar 2011 18:12:33 -0600 Subject: add Olof-Joachim Frahm to AUTHORS --- AUTHORS | 1 + 1 file changed, 1 insertion(+) diff --git a/AUTHORS b/AUTHORS index fe97f86..f5f6414 100644 --- a/AUTHORS +++ b/AUTHORS @@ -67,6 +67,7 @@ In alphabetical order: Moritz Lenz - small doc fix Nicolas Pouillard - refactored scroll command Olivier Schwander - auto file:// prepend + Olof-Joachim Frahm - bugfixes Paul Tomak - formfiller.sh script, uzbl vim syntax Paweł Zuzelski (pawelz) - http auth handler, misc patches Peter Suschlik - backwards searching -- cgit v1.2.3 From f0bc65cfca369c5be69f798aa743138cd0c8942b Mon Sep 17 00:00:00 2001 From: Christer Sjöholm Date: Sun, 20 Mar 2011 11:37:57 +0100 Subject: Fixes NEXT_TAB and PREV_TAB in uzbl-tabbed. The detection of an argument was incorrect. --- examples/data/scripts/uzbl-tabbed | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/data/scripts/uzbl-tabbed b/examples/data/scripts/uzbl-tabbed index 13e4e44..c953062 100755 --- a/examples/data/scripts/uzbl-tabbed +++ b/examples/data/scripts/uzbl-tabbed @@ -507,12 +507,12 @@ class UzblInstance: self.parent.new_tab(args[0], '', 0, next=True) elif type == "NEXT_TAB": - if args[0]: + if args: self.parent.next_tab(int(args[0])) else: self.parent.next_tab() elif type == "PREV_TAB": - if args[0]: + if args: self.parent.prev_tab(int(args[0])) else: self.parent.prev_tab() -- cgit v1.2.3 From ee35babdd9ebfcb605d2c642357153850cb125e4 Mon Sep 17 00:00:00 2001 From: Christer Sjöholm Date: Sun, 20 Mar 2011 12:07:58 +0100 Subject: Fix for uzbl-tabbed new-tab. Some times the uri may be a unicode string, so we convert it to a str as required by gobject.spawn_async(). This happens when a page want to open an url in a new window. --- examples/data/scripts/uzbl-tabbed | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/data/scripts/uzbl-tabbed b/examples/data/scripts/uzbl-tabbed index c953062..d3cfe2f 100755 --- a/examples/data/scripts/uzbl-tabbed +++ b/examples/data/scripts/uzbl-tabbed @@ -1016,7 +1016,7 @@ class UzblTabbed: title = config['new_tab_title'] cmd = ['uzbl-browser', '-n', name, '-s', str(sid), - '--connect-socket', self.socket_path, '--uri', uri] + '--connect-socket', self.socket_path, '--uri', str(uri)] gobject.spawn_async(cmd, flags=gobject.SPAWN_SEARCH_PATH) uzbl = UzblInstance(self, tab, name, uri, title, switch) -- cgit v1.2.3 From 37fe833febdb26a03816e7a82c5b649fdc0984f3 Mon Sep 17 00:00:00 2001 From: Christer Sjöholm Date: Sun, 20 Mar 2011 12:20:09 +0100 Subject: Allow NEW_TAB to be called without an URI The new instance tries to open the CWD, a blank page would be nicer. --- examples/data/scripts/uzbl-tabbed | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/examples/data/scripts/uzbl-tabbed b/examples/data/scripts/uzbl-tabbed index d3cfe2f..72de00e 100755 --- a/examples/data/scripts/uzbl-tabbed +++ b/examples/data/scripts/uzbl-tabbed @@ -498,7 +498,10 @@ class UzblInstance: elif type == "LOAD_COMMIT": self.uri = args[0] elif type == "NEW_TAB": - self.parent.new_tab(args[0]) + if args: + self.parent.new_tab(args[0]) + else: + self.parent.new_tab() elif type == "NEW_BG_TAB": self.parent.new_tab(args[0], '', 0) elif type == "NEW_TAB_NEXT": -- cgit v1.2.3 From b7b7565b13e6b5e5192cb730b64f311fe5a51d71 Mon Sep 17 00:00:00 2001 From: Brendan Taylor Date: Mon, 21 Mar 2011 18:22:25 -0600 Subject: added Christer Sjöholm to AUTHORS MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- AUTHORS | 1 + 1 file changed, 1 insertion(+) diff --git a/AUTHORS b/AUTHORS index f5f6414..b3ce2e2 100644 --- a/AUTHORS +++ b/AUTHORS @@ -31,6 +31,7 @@ In alphabetical order: Cedric Staub - Javascript cookies Chris Mason - code snippets such as basic cookie handler Chris van Dijk (quigybo) - work on uzbl-tabbed + Christer Sjöholm - uzbl-tabbed bugfixes Ciprian Dorin, Craciun - patches Daiki Ueno (ueno) - fix for crash when opening image in new window Damien Leon - misc -- cgit v1.2.3 From 7c0d66962b044bf0001005e911aefe78bb10c95f Mon Sep 17 00:00:00 2001 From: Ben Boeckel Date: Thu, 24 Mar 2011 18:53:12 -0400 Subject: Allow for multiple characters to bound words Word deletion in URLs is a lot better when characters such as: \ -./&?= are considered to separate words. --- examples/config/config | 2 +- examples/data/plugins/keycmd.py | 14 ++++++++++---- 2 files changed, 11 insertions(+), 5 deletions(-) diff --git a/examples/config/config b/examples/config/config index ab690e0..a1a3494 100644 --- a/examples/config/config +++ b/examples/config/config @@ -194,7 +194,7 @@ set ebind = @mode_bind global,-insert @ebind = event KEYCMD_DELETE @ebind = event START_COMPLETION # Readline-ish bindings. -@ebind w = event KEYCMD_STRIP_WORD +@ebind w = event KEYCMD_STRIP_WORD \ -./&?= @ebind u = event SET_KEYCMD @ebind a = event SET_CURSOR_POS 0 @ebind e = event SET_CURSOR_POS -1 diff --git a/examples/data/plugins/keycmd.py b/examples/data/plugins/keycmd.py index 928c597..76e2d75 100644 --- a/examples/data/plugins/keycmd.py +++ b/examples/data/plugins/keycmd.py @@ -406,16 +406,22 @@ def append_keycmd(uzbl, keycmd): update_event(uzbl, k, False) -def keycmd_strip_word(uzbl, sep): +def keycmd_strip_word(uzbl, seps): ''' Removes the last word from the keycmd, similar to readline ^W ''' - sep = sep or ' ' + seps = seps or ' ' k = uzbl.keylet if not k.keycmd: return - head, tail = k.keycmd[:k.cursor].rstrip(sep), k.keycmd[k.cursor:] - rfind = head.rfind(sep) + head, tail = k.keycmd[:k.cursor].rstrip(seps), k.keycmd[k.cursor:] + rfind = -1 + for sep in seps: + p = head.rfind(sep) + if p >= 0 and rfind < p + 1: + rfind = p + 1 + if rfind == len(head) and head[-1] in seps: + rfind -= 1 head = head[:rfind] if rfind + 1 else '' k.keycmd = head + tail k.cursor = len(head) -- cgit v1.2.3 From 0aac27c1f1df8bdf19135c0b7271e3bca5d3cd2e Mon Sep 17 00:00:00 2001 From: Ben Boeckel Date: Thu, 24 Mar 2011 19:07:49 -0400 Subject: Add a binding to open a new window --- examples/config/config | 3 +++ 1 file changed, 3 insertions(+) diff --git a/examples/config/config b/examples/config/config index ab690e0..e4cfa24 100644 --- a/examples/config/config +++ b/examples/config/config @@ -296,6 +296,9 @@ set ebind = @mode_bind global,-insert # Hard-bound bookmarks @cbind gh = uri http://www.uzbl.org +# New window binds +@cbind gw = event REQ_NEW_WINDOW + # Yanking & pasting binds @cbind yu = sh 'echo -n "$UZBL_URI" | xclip' @cbind yU = sh 'echo -n "$1" | xclip' \@SELECTED_URI -- cgit v1.2.3 From 9e44a5085f8230a1eb0e88e0400fea3acb6795fb Mon Sep 17 00:00:00 2001 From: Ben Boeckel Date: Thu, 24 Mar 2011 19:08:03 -0400 Subject: Add bindings to switch to https version --- examples/config/config | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/examples/config/config b/examples/config/config index e4cfa24..9822789 100644 --- a/examples/config/config +++ b/examples/config/config @@ -299,6 +299,10 @@ set ebind = @mode_bind global,-insert # New window binds @cbind gw = event REQ_NEW_WINDOW +# SSL-ify bindings +@cbind zs = uri \@(echo "$UZBL_URI" | sed -e 's/^http:/https:/')\@ +@cbind zS = event REQ_NEW_WINDOW \@(echo "$UZBL_URI" | sed -e 's/^http:/https:/')\@ + # Yanking & pasting binds @cbind yu = sh 'echo -n "$UZBL_URI" | xclip' @cbind yU = sh 'echo -n "$1" | xclip' \@SELECTED_URI -- cgit v1.2.3 From ba7117ab362062f7cb0abdf6d0ee212f42d580ae Mon Sep 17 00:00:00 2001 From: Ben Boeckel Date: Sat, 26 Mar 2011 14:36:25 -0400 Subject: Update README for KEYCMD_STRIP_WORD event --- README | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README b/README index 3ac9a28..5ef791a 100644 --- a/README +++ b/README @@ -762,6 +762,8 @@ Events/requests which the EM and its plugins listens for keycmd. * `KEYCMD_STRIP_WORD`: Removes the last word from the keycmd, similar to readline `^W`. + - `request KEYCMD_STRIP_WORD `: The `` argument is a list of + characters that are considered to separate words. * `KEYCMD_EXEC_CURRENT`: (tries to) execute whatever is in the keycmd. * `SET_KEYCMD`: Allow setting of the keycmd externally. - `request SET_KEYCMD `: Set the keycmd to ``. -- cgit v1.2.3 From 2094a051902b3ba161a9a7aac9cde6b282c65f64 Mon Sep 17 00:00:00 2001 From: Brendan Taylor Date: Sat, 2 Apr 2011 07:57:51 -0600 Subject: changed the 'gi' example go_input binding to 'fi' it was shadowing an older example uzbl-tabbed binding --- examples/config/config | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/config/config b/examples/config/config index 750f2aa..e3e2080 100644 --- a/examples/config/config +++ b/examples/config/config @@ -344,7 +344,7 @@ set follow_hint_keys = 0123456789 #set follow_hint_keys = thsnd-rcgmvwb/;789aefijkopquxyz234 @cbind fl* = spawn @scripts_dir/follow.sh \@< uzbl.follow("\@follow_hint_keys", "%s", 0) >\@ @cbind Fl* = spawn @scripts_dir/follow.sh \@< uzbl.follow("\@follow_hint_keys", "%s", 1) >\@ -@cbind gi = spawn @scripts_dir/go_input.sh +@cbind fi = spawn @scripts_dir/go_input.sh # Form filler binds # This script allows you to configure (per domain) values to fill in form -- cgit v1.2.3 From ed1cfde1c8b0dc1fd4607a527cdbd2adcf7f4855 Mon Sep 17 00:00:00 2001 From: Brendan Taylor Date: Sat, 2 Apr 2011 07:58:17 -0600 Subject: disable an uzbl-tabbed binding that doesn't work --- examples/config/config | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/examples/config/config b/examples/config/config index e3e2080..272ba32 100644 --- a/examples/config/config +++ b/examples/config/config @@ -381,7 +381,8 @@ set preset = event PRESET_TABS @cbind gs_ = @preset save %s @cbind glo_ = @preset load %s @cbind gd_ = @preset del %s -@cbind gli = @preset list +# This doesn't work right now. +#@cbind gli = @preset list # === Context menu items ===================================================== -- cgit v1.2.3 From 46f5b42a6cd13608a447bed1d7e2e58c1a609dac Mon Sep 17 00:00:00 2001 From: Brendan Taylor Date: Sat, 2 Apr 2011 07:59:25 -0600 Subject: reworked uzbl-tabbed's event handling. it's easier to read and less busted now (i actually tested it this time). --- examples/data/scripts/uzbl-tabbed | 194 +++++++++++++++++++++++--------------- 1 file changed, 116 insertions(+), 78 deletions(-) diff --git a/examples/data/scripts/uzbl-tabbed b/examples/data/scripts/uzbl-tabbed index 2d7d7c9..e4a86bf 100755 --- a/examples/data/scripts/uzbl-tabbed +++ b/examples/data/scripts/uzbl-tabbed @@ -363,6 +363,116 @@ class SocketClient: map(source_remove, self._watchers) self._watchers = [] +class EventDispatcher: + def __init__(self, uzbl): + self.uzbl = uzbl + self.parent = self.uzbl.parent + + def dispatch(self, message_type, args): + method = getattr(self, message_type.lower(), None) + + if method is None: + return + + return method(*args) + + def title_changed(self, title): + self.uzbl.title = title.strip() + self.uzbl.title_changed(False) + + def variable_set(self, var, _type, val): + try: + val = int(val) + except: + pass + + if var in UZBL_TABBED_VARS: + if config[var] != val: + config[var] = val + if var == "show_gtk_tabs": + self.parent.notebook.set_show_tabs(bool(val)) + elif var == "show_tablist" or var == "tablist_top": + self.parent.update_tablist_display() + elif var == "gtk_tab_pos": + self.parent.update_gtk_tab_pos() + elif var == "status_background": + if config['status_background'].strip(): + try: + col = gtk.gdk.color_parse(config['status_background']) + self.parent.ebox.modify_bg(gtk.STATE_NORMAL, col) + except ValueError: + pass # got an invalid colour, just ignore it + elif var == "tab_titles" or var == "tab_indexes": + for tab in self.parent.notebook: + self.parent.tabs[tab].title_changed(True) + + self.parent.update_tablist() + else: + config[var] = val + + if var == "uri": + self.uzbl.uri = val.strip() + self.parent.update_tablist() + + def load_commit(self, uri): + self.uzbl.uri = uri + + def new_tab(self, uri = None): + if uri: + self.parent.new_tab(uri) + else: + self.parent.new_tab() + + def new_tab_bg(self, uri = None): + if uri: + self.parent.new_tab(uri, switch = False) + else: + self.parent.new_tab(switch = False) + + def new_tab_next(self, uri = None): + if uri: + self.parent.new_tab(uri, next=True) + else: + self.parent.new_tab(next=True) + + def new_bg_tab_next(self, uri = None): + if uri: + self.parent.new_tab(uri, switch = False, next = True) + else: + self.parent.new_tab(switch = False, next = True) + + def next_tab(self, step = None): + if step: + self.parent.next_tab(int(step)) + else: + self.parent.next_tab() + + def prev_tab(self, step = None): + if step: + self.parent.prev_tab(int(step)) + else: + self.parent.prev_tab() + + def goto_tab(self, index): + self.parent.goto_tab(int(index)) + + def first_tab(self): + self.parent.goto_tab(0) + + def last_tab(self): + self.parent.goto_tab(-1) + + def preset_tabs(self, *args): + self.parent.parse_command(["preset"] + [ a for a in args ]) + + def bring_to_front(self): + self.parent.window.present() + + def clean_tabs(self): + self.parent.clean_slate() + + def exit_all_tabs(self): + self.parent.quitrequest() class UzblInstance: '''Uzbl instance meta-data/meta-action object.''' @@ -371,10 +481,13 @@ class UzblInstance: self.parent = parent self.tab = tab + self.dispatcher = EventDispatcher(self) + self.name = name self.title = title self.tabtitle = "" self.uri = uri + self._client = None self._switch = switch # Switch to tab after loading ? self.title_changed() @@ -458,85 +571,10 @@ class UzblInstance: ''' Parse event givent by the Uzbl instance ''' cmd = self.parse_event(cmd) - message, type, args = cmd[0], cmd[2], cmd[3:] - if message == "EVENT": - if type == "TITLE_CHANGED": - self.title = args[0].strip() - self.title_changed(False) - elif type == "VARIABLE_SET": - var, val = args[0], args[2] - - try: - val = int(val) - except: - pass - - if var in UZBL_TABBED_VARS: - if config[var] != val: - config[var] = val - if var == "show_gtk_tabs": - self.parent.notebook.set_show_tabs(bool(val)) - elif var == "show_tablist" or var == "tablist_top": - self.parent.update_tablist_display() - elif var == "gtk_tab_pos": - self.parent.update_gtk_tab_pos() - elif var == "status_background": - if config['status_background'].strip(): - try: - col = gtk.gdk.color_parse(config['status_background']) - self.parent.ebox.modify_bg(gtk.STATE_NORMAL, col) - except ValueError: - pass # got an invalid colour, just ignore it - elif var == "tab_titles" or var == "tab_indexes": - for tab in self.parent.notebook: - self.parent.tabs[tab].title_changed(True) - - self.parent.update_tablist() - else: - config[var] = val - - if var == "uri": - self.uri = val.strip() - self.parent.update_tablist() - elif type == "LOAD_COMMIT": - self.uri = args[0] - elif type == "NEW_TAB": - if args: - self.parent.new_tab(args[0]) - else: - self.parent.new_tab() - elif type == "NEW_BG_TAB": - self.parent.new_tab(args[0], '', 0) - elif type == "NEW_TAB_NEXT": - self.parent.new_tab(args[0], next=True) - elif type == "NEW_BG_TAB_NEXT": - self.parent.new_tab(args[0], '', 0, next=True) - - elif type == "NEXT_TAB": - if args: - self.parent.next_tab(int(args[0])) - else: - self.parent.next_tab() - elif type == "PREV_TAB": - if args: - self.parent.prev_tab(int(args[0])) - else: - self.parent.prev_tab() - elif type == "GOTO_TAB": - self.parent.goto_tab(int(args[0])) - elif type == "FIRST_TAB": - self.parent.goto_tab(0) - elif type == "LAST_TAB": - self.parent.goto_tab(-1) - elif type == "PRESET_TABS": - self.parent.parse_command(["preset"] + args) - elif type == "BRING_TO_FRONT": - self.parent.window.present() - elif type == "CLEAN_TABS": - self.parent.clean_slate() - elif type == "EXIT_ALL_TABS": - self.parent.quitrequest() + message, message_type, args = cmd[0], cmd[2], cmd[3:] + if message == "EVENT": + self.dispatcher.dispatch(message_type, args) def close(self): '''The remote instance exited''' -- cgit v1.2.3 From fa73f8fd736ba4e2c535d887915f9aae3741f378 Mon Sep 17 00:00:00 2001 From: Brendan Taylor Date: Sat, 2 Apr 2011 07:59:49 -0600 Subject: add a fixme comment for uzbl-tabbed's preset listing --- examples/data/scripts/uzbl-tabbed | 2 ++ 1 file changed, 2 insertions(+) diff --git a/examples/data/scripts/uzbl-tabbed b/examples/data/scripts/uzbl-tabbed index e4a86bf..a15967a 100755 --- a/examples/data/scripts/uzbl-tabbed +++ b/examples/data/scripts/uzbl-tabbed @@ -1002,6 +1002,8 @@ class UzblTabbed: error("parse_command: preset %r does not exist." % path) elif cmd[1] == "list": + # FIXME: what argument is this supposed to be passed, + # and why? uzbl = self.get_tab_by_name(int(cmd[2])) if uzbl: if not os.path.isdir(config['saved_sessions_dir']): -- cgit v1.2.3 From e7578e27ccb638ca59ad250bc7a8049b3aa25df4 Mon Sep 17 00:00:00 2001 From: Brendan Taylor Date: Sat, 2 Apr 2011 08:14:56 -0600 Subject: fix returning to default encoding ("set current_encoding =") --- src/callbacks.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/callbacks.c b/src/callbacks.c index deda426..360b0c4 100644 --- a/src/callbacks.c +++ b/src/callbacks.c @@ -292,8 +292,11 @@ cmd_caret_browsing() { void set_current_encoding() { - webkit_web_view_set_custom_encoding(uzbl.gui.web_view, - uzbl.behave.current_encoding); + gchar *encoding = uzbl.behave.current_encoding; + if(strlen(encoding) == 0) + encoding = NULL; + + webkit_web_view_set_custom_encoding(uzbl.gui.web_view, encoding); } -- cgit v1.2.3 From c7a442bd9d0e07bc58f43e6263ccf1a2c1337960 Mon Sep 17 00:00:00 2001 From: Brendan Taylor Date: Mon, 11 Apr 2011 19:52:19 -0600 Subject: move style.css from examples/data to examples/config --- examples/config/config | 9 +++++---- examples/config/style.css | 25 +++++++++++++++++++++++++ examples/data/style.css | 25 ------------------------- 3 files changed, 30 insertions(+), 29 deletions(-) create mode 100644 examples/config/style.css delete mode 100644 examples/data/style.css diff --git a/examples/config/config b/examples/config/config index 272ba32..d049f0e 100644 --- a/examples/config/config +++ b/examples/config/config @@ -4,9 +4,10 @@ # === Core settings ========================================================== # common directory locations -set prefix = @(echo $PREFIX)@ -set data_home = @(echo $XDG_DATA_HOME)@ -set cache_home = @(echo $XDG_CACHE_HOME)@ +set prefix = @(echo $PREFIX)@ +set data_home = @(echo $XDG_DATA_HOME)@ +set cache_home = @(echo $XDG_CACHE_HOME)@ +set config_home = @(echo $XDG_CONFIG_HOME)@ # Interface paths. set fifo_dir = /tmp @@ -95,7 +96,7 @@ set download_handler = sync_spawn @scripts_dir/download.sh # === Behaviour and appearance =============================================== # Custom CSS can be defined here, including link follower hint styles -set stylesheet_uri = file://@data_home/uzbl/style.css +set stylesheet_uri = file://@config_home/uzbl/style.css set show_status = 1 set status_top = 0 diff --git a/examples/config/style.css b/examples/config/style.css new file mode 100644 index 0000000..ff055d1 --- /dev/null +++ b/examples/config/style.css @@ -0,0 +1,25 @@ +#uzbl_link_hints > span { + z-index: 1000 !important; + + background-color: #aaff00 !important; + border: 2px solid #556600 !important; + margin: 0 !important; + padding: 1px !important; + + color: black !important; + font-size: 9px !important; + line-height: 9px !important; + font-weight: bold !important; + font-variant: normal !important; + text-decoration: none !important; + + -webkit-transform: translate(-5px,-5px); + /* opacity: 0.7; */ +} + +/* we can have different colours for different types of hints! */ +#uzbl_link_hints.new-window > span { + background-color: #ffff00 !important; +} + +/* vim:set et ts=4: */ diff --git a/examples/data/style.css b/examples/data/style.css deleted file mode 100644 index ff055d1..0000000 --- a/examples/data/style.css +++ /dev/null @@ -1,25 +0,0 @@ -#uzbl_link_hints > span { - z-index: 1000 !important; - - background-color: #aaff00 !important; - border: 2px solid #556600 !important; - margin: 0 !important; - padding: 1px !important; - - color: black !important; - font-size: 9px !important; - line-height: 9px !important; - font-weight: bold !important; - font-variant: normal !important; - text-decoration: none !important; - - -webkit-transform: translate(-5px,-5px); - /* opacity: 0.7; */ -} - -/* we can have different colours for different types of hints! */ -#uzbl_link_hints.new-window > span { - background-color: #ffff00 !important; -} - -/* vim:set et ts=4: */ -- cgit v1.2.3 From 8126f371f3976a253d0b40e1788762ff68c273cb Mon Sep 17 00:00:00 2001 From: Brendan Taylor Date: Mon, 11 Apr 2011 19:52:49 -0600 Subject: autoinstall style.css --- src/uzbl-browser | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/uzbl-browser b/src/uzbl-browser index 81645ca..fb9a368 100755 --- a/src/uzbl-browser +++ b/src/uzbl-browser @@ -42,7 +42,7 @@ then echo "Error: Global config not found; please check if your distribution ships them separately" exit 3 fi - if ! cp "$EXAMPLES"/config/config "$XDG_CONFIG_HOME"/uzbl/config + if ! cp "$EXAMPLES"/config/* "$XDG_CONFIG_HOME"/uzbl/ then echo "Could not copy default config to $XDG_CONFIG_HOME/uzbl/config" >&2 # Run with the global config as a last resort -- cgit v1.2.3 From 54d90f3711abd0ad864fcb9767b27ca1f25541b2 Mon Sep 17 00:00:00 2001 From: Brendan Taylor Date: Mon, 11 Apr 2011 19:55:30 -0600 Subject: move src/uzbl-browser to bin/uzbl-browser --- Makefile | 4 +-- bin/uzbl-browser | 75 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/uzbl-browser | 75 -------------------------------------------------------- 3 files changed, 77 insertions(+), 77 deletions(-) create mode 100755 bin/uzbl-browser delete mode 100755 src/uzbl-browser diff --git a/Makefile b/Makefile index 91b66b6..a3597df 100644 --- a/Makefile +++ b/Makefile @@ -68,7 +68,7 @@ test-uzbl-core: uzbl-core ./uzbl-core --uri http://www.uzbl.org --verbose test-uzbl-browser: uzbl-browser - ./src/uzbl-browser --uri http://www.uzbl.org --verbose + ./bin/uzbl-browser --uri http://www.uzbl.org --verbose test-uzbl-core-sandbox: uzbl-core make DESTDIR=./sandbox RUN_PREFIX=`pwd`/sandbox/usr/local install-uzbl-core @@ -134,7 +134,7 @@ install-uzbl-core: all install-dirs install -m755 uzbl-core $(INSTALLDIR)/bin/uzbl-core install-uzbl-browser: install-dirs - install -m755 src/uzbl-browser $(INSTALLDIR)/bin/uzbl-browser + install -m755 bin/uzbl-browser $(INSTALLDIR)/bin/uzbl-browser install -m755 examples/data/scripts/uzbl-event-manager $(INSTALLDIR)/bin/uzbl-event-manager mv $(INSTALLDIR)/bin/uzbl-browser $(INSTALLDIR)/bin/uzbl-browser.bak sed 's#^PREFIX=.*#PREFIX=$(RUN_PREFIX)#' < $(INSTALLDIR)/bin/uzbl-browser.bak > $(INSTALLDIR)/bin/uzbl-browser diff --git a/bin/uzbl-browser b/bin/uzbl-browser new file mode 100755 index 0000000..fb9a368 --- /dev/null +++ b/bin/uzbl-browser @@ -0,0 +1,75 @@ +#!/bin/sh +# +# This script implements a more useful out-of-the-box "browsing experience". +# It does so by combining uzbl-core with a set of "recommended" tools and +# practices. See docs for more info. +# +# If you want to customize the behavior any of the helper tools, copy them +# to your $XDG_DATA_HOME/uzbl/scripts/ and edit them + +PREFIX=/usr/local +export PREFIX + +EXAMPLES=$PREFIX/share/uzbl/examples + +XDG_DATA_HOME=${XDG_DATA_HOME:-$HOME/.local/share} +export XDG_DATA_HOME + +XDG_CACHE_HOME=${XDG_CACHE_HOME:-$HOME/.cache} +export XDG_CACHE_HOME + +XDG_CONFIG_HOME=${XDG_CONFIG_HOME:-$HOME/.config} +export XDG_CONFIG_HOME + +# assure the relevant directories exist. +for dir in "$XDG_CACHE_HOME"/uzbl "$XDG_DATA_HOME"/uzbl "$XDG_CONFIG_HOME"/uzbl +do + if [ ! -d "$dir" ] + then + if ! mkdir -p "$dir" + then + echo "could not create $dir" >&2 + exit 2 + fi + fi +done + +# if no config exists yet in the recommended location, put the default (recommended) config there +if [ ! -f "$XDG_CONFIG_HOME"/uzbl/config ] +then + if [ ! -r "$EXAMPLES"/config/config ] + then + echo "Error: Global config not found; please check if your distribution ships them separately" + exit 3 + fi + if ! cp "$EXAMPLES"/config/* "$XDG_CONFIG_HOME"/uzbl/ + then + echo "Could not copy default config to $XDG_CONFIG_HOME/uzbl/config" >&2 + # Run with the global config as a last resort + config_file=$EXAMPLES/config/config + fi +fi + +# this variable is used by the default helper scripts as a location to +# load shared code from +if [ -z "$UZBL_UTIL_DIR" ] +then + if [ -d "$XDG_DATA_HOME"/uzbl/scripts/util ] + then + UZBL_UTIL_DIR=$XDG_DATA_HOME/uzbl/scripts/util + elif [ -d $EXAMPLES/data/scripts/util ] + then + UZBL_UTIL_DIR=$EXAMPLES/data/scripts/util + fi + export UZBL_UTIL_DIR +fi + +# uzbl-event-manager will exit if one is already running. +# we could also check if its pid file exists to avoid having to spawn it. +DAEMON_SOCKET="$XDG_CACHE_HOME"/uzbl/event_daemon +#if [ ! -f "$DAEMON_SOCKET".pid ] +#then + ${UZBL_EVENT_MANAGER:-uzbl-event-manager -va start} +#fi + +exec uzbl-core "$@" ${config_file:+--config "$config_file"} --connect-socket $DAEMON_SOCKET diff --git a/src/uzbl-browser b/src/uzbl-browser deleted file mode 100755 index fb9a368..0000000 --- a/src/uzbl-browser +++ /dev/null @@ -1,75 +0,0 @@ -#!/bin/sh -# -# This script implements a more useful out-of-the-box "browsing experience". -# It does so by combining uzbl-core with a set of "recommended" tools and -# practices. See docs for more info. -# -# If you want to customize the behavior any of the helper tools, copy them -# to your $XDG_DATA_HOME/uzbl/scripts/ and edit them - -PREFIX=/usr/local -export PREFIX - -EXAMPLES=$PREFIX/share/uzbl/examples - -XDG_DATA_HOME=${XDG_DATA_HOME:-$HOME/.local/share} -export XDG_DATA_HOME - -XDG_CACHE_HOME=${XDG_CACHE_HOME:-$HOME/.cache} -export XDG_CACHE_HOME - -XDG_CONFIG_HOME=${XDG_CONFIG_HOME:-$HOME/.config} -export XDG_CONFIG_HOME - -# assure the relevant directories exist. -for dir in "$XDG_CACHE_HOME"/uzbl "$XDG_DATA_HOME"/uzbl "$XDG_CONFIG_HOME"/uzbl -do - if [ ! -d "$dir" ] - then - if ! mkdir -p "$dir" - then - echo "could not create $dir" >&2 - exit 2 - fi - fi -done - -# if no config exists yet in the recommended location, put the default (recommended) config there -if [ ! -f "$XDG_CONFIG_HOME"/uzbl/config ] -then - if [ ! -r "$EXAMPLES"/config/config ] - then - echo "Error: Global config not found; please check if your distribution ships them separately" - exit 3 - fi - if ! cp "$EXAMPLES"/config/* "$XDG_CONFIG_HOME"/uzbl/ - then - echo "Could not copy default config to $XDG_CONFIG_HOME/uzbl/config" >&2 - # Run with the global config as a last resort - config_file=$EXAMPLES/config/config - fi -fi - -# this variable is used by the default helper scripts as a location to -# load shared code from -if [ -z "$UZBL_UTIL_DIR" ] -then - if [ -d "$XDG_DATA_HOME"/uzbl/scripts/util ] - then - UZBL_UTIL_DIR=$XDG_DATA_HOME/uzbl/scripts/util - elif [ -d $EXAMPLES/data/scripts/util ] - then - UZBL_UTIL_DIR=$EXAMPLES/data/scripts/util - fi - export UZBL_UTIL_DIR -fi - -# uzbl-event-manager will exit if one is already running. -# we could also check if its pid file exists to avoid having to spawn it. -DAEMON_SOCKET="$XDG_CACHE_HOME"/uzbl/event_daemon -#if [ ! -f "$DAEMON_SOCKET".pid ] -#then - ${UZBL_EVENT_MANAGER:-uzbl-event-manager -va start} -#fi - -exec uzbl-core "$@" ${config_file:+--config "$config_file"} --connect-socket $DAEMON_SOCKET -- cgit v1.2.3 From 3384703009e8190c8ad50821a4ace94c03733488 Mon Sep 17 00:00:00 2001 From: Brendan Taylor Date: Mon, 11 Apr 2011 19:58:03 -0600 Subject: move examples/data/scripts/uzbl-tabbed to bin/uzbl-tabbed --- Makefile | 5 +- bin/uzbl-tabbed | 1472 +++++++++++++++++++++++++++++++++++++ examples/data/scripts/uzbl-tabbed | 1472 ------------------------------------- 3 files changed, 1475 insertions(+), 1474 deletions(-) create mode 100755 bin/uzbl-tabbed delete mode 100755 examples/data/scripts/uzbl-tabbed diff --git a/Makefile b/Makefile index a3597df..df87c9e 100644 --- a/Makefile +++ b/Makefile @@ -92,10 +92,11 @@ test-uzbl-browser-sandbox: uzbl-browser test-uzbl-tabbed-sandbox: uzbl-browser make DESTDIR=./sandbox RUN_PREFIX=`pwd`/sandbox/usr/local install-uzbl-core make DESTDIR=./sandbox RUN_PREFIX=`pwd`/sandbox/usr/local install-uzbl-browser + make DESTDIR=./sandbox RUN_PREFIX=`pwd`/sandbox/usr/local install-uzbl-tabbed make DESTDIR=./sandbox RUN_PREFIX=`pwd`/sandbox/usr/local install-example-data cp -np ./misc/env.sh ./sandbox/env.sh -. ./sandbox/env.sh && uzbl-event-manager restart -avv - . ./sandbox/env.sh && ./sandbox/home/.local/share/uzbl/scripts/uzbl-tabbed + . ./sandbox/env.sh && uzbl-tabbed . ./sandbox/env.sh && uzbl-event-manager stop -ivv make DESTDIR=./sandbox uninstall rm -rf ./sandbox/usr @@ -146,7 +147,7 @@ install-uzbl-browser: install-dirs rm $(INSTALLDIR)/bin/uzbl-event-manager.bak install-uzbl-tabbed: install-dirs - install -m755 examples/data/scripts/uzbl-tabbed $(INSTALLDIR)/bin/uzbl-tabbed + install -m755 bin/uzbl-tabbed $(INSTALLDIR)/bin/uzbl-tabbed # you probably only want to do this manually when testing and/or to the sandbox. not meant for distributors install-example-data: diff --git a/bin/uzbl-tabbed b/bin/uzbl-tabbed new file mode 100755 index 0000000..a15967a --- /dev/null +++ b/bin/uzbl-tabbed @@ -0,0 +1,1472 @@ +#!/usr/bin/env python + +# Uzbl tabbing wrapper using a fifo socket interface +# Copyright (c) 2009, Tom Adams +# Copyright (c) 2009, Chris van Dijk +# Copyright (c) 2009, Mason Larobina +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + + +# Author(s): +# Tom Adams +# Wrote the original uzbl_tabbed.py as a proof of concept. +# +# Chris van Dijk (quigybo) +# Made signifigant headway on the old uzbl_tabbing.py script on the +# uzbl wiki +# +# Mason Larobina +# Rewrite of the uzbl_tabbing.py script to use a fifo socket interface +# and inherit configuration options from the user's uzbl config. +# +# Contributor(s): +# mxey +# uzbl_config path now honors XDG_CONFIG_HOME if it exists. +# +# Romain Bignon +# Fix for session restoration code. +# +# Jake Probst +# Wrote a patch that overflows tabs in the tablist on to new lines when +# running of room. +# +# Devon Jones +# Fifo command bring_to_front which brings the gtk window to focus. +# +# Simon Lipp (sloonz) +# Various + + +# Dependencies: +# pygtk - python bindings for gtk. +# pango - python bindings needed for text rendering & layout in gtk widgets. +# pygobject - GLib's GObject bindings for python. +# +# Note: I haven't included version numbers with this dependency list because +# I've only ever tested uzbl_tabbed.py on the latest stable versions of these +# packages in Gentoo's portage. Package names may vary on different systems. + + +# Configuration: +# Because this version of uzbl_tabbed is able to inherit options from your main +# uzbl configuration file you may wish to configure uzbl tabbed from there. +# Here is a list of configuration options that can be customised and some +# example values for each: +# +# General tabbing options: +# show_tablist = 1 +# show_gtk_tabs = 0 +# tablist_top = 1 +# gtk_tab_pos = (top|left|bottom|right) +# gtk_refresh = 1000 +# switch_to_new_tabs = 1 +# capture_new_windows = 1 +# multiline_tabs = 1 +# +# Tab title options: +# tab_titles = 1 +# tab_indexes = 1 +# new_tab_title = Loading +# max_title_len = 50 +# show_ellipsis = 1 +# +# Session options: +# save_session = 1 +# json_session = 0 +# session_file = $HOME/.local/share/uzbl/session +# +# Inherited uzbl options: +# fifo_dir = /tmp +# socket_dir = /tmp +# icon_path = $HOME/.local/share/uzbl/uzbl.png +# status_background = #303030 +# +# Misc options: +# window_size = 800,800 +# verbose = 0 +# +# And uzbl_tabbed.py takes care of the actual binding of the commands via each +# instances fifo socket. +# +# Custom tab styling: +# tab_colours = foreground = "#888" background = "#303030" +# tab_text_colours = foreground = "#bbb" +# selected_tab = foreground = "#fff" +# selected_tab_text = foreground = "green" +# tab_indicate_https = 1 +# https_colours = foreground = "#888" +# https_text_colours = foreground = "#9c8e2d" +# selected_https = foreground = "#fff" +# selected_https_text = foreground = "gold" +# +# How these styling values are used are soley defined by the syling policy +# handler below (the function in the config section). So you can for example +# turn the tab text colour Firetruck-Red in the event "error" appears in the +# tab title or some other arbitrary event. You may wish to make a trusted +# hosts file and turn tab titles of tabs visiting trusted hosts purple. + + +# Issues: +# - new windows are not caught and opened in a new tab. +# - when uzbl_tabbed.py crashes it takes all the children with it. +# - when a new tab is opened when using gtk tabs the tab button itself +# grabs focus from its child for a few seconds. +# - when switch_to_new_tabs is not selected the notebook page is +# maintained but the new window grabs focus (try as I might to stop it). + + +# Todo: +# - add command line options to use a different session file, not use a +# session file and or open a uri on starup. +# - ellipsize individual tab titles when the tab-list becomes over-crowded +# - add "<" & ">" arrows to tablist to indicate that only a subset of the +# currently open tabs are being displayed on the tablist. +# - add the small tab-list display when both gtk tabs and text vim-like +# tablist are hidden (I.e. [ 1 2 3 4 5 ]) +# - check spelling. +# - pass a uzbl socketid to uzbl_tabbed.py and have it assimilated into +# the collective. Resistance is futile! + + +import pygtk +import gtk +import subprocess +import os +import re +import time +import getopt +import pango +import select +import sys +import gobject +import socket +import random +import hashlib +import atexit +import types + +from gobject import io_add_watch, source_remove, timeout_add, IO_IN, IO_HUP +from signal import signal, SIGTERM, SIGINT +from optparse import OptionParser, OptionGroup +from traceback import print_exc + + +pygtk.require('2.0') + +_SCRIPTNAME = os.path.basename(sys.argv[0]) +def error(msg): + sys.stderr.write("%s: error: %s\n" % (_SCRIPTNAME, msg)) + +# ============================================================================ +# ::: Default configuration section :::::::::::::::::::::::::::::::::::::::::: +# ============================================================================ + +def xdghome(key, default): + '''Attempts to use the environ XDG_*_HOME paths if they exist otherwise + use $HOME and the default path.''' + + xdgkey = "XDG_%s_HOME" % key + if xdgkey in os.environ.keys() and os.environ[xdgkey]: + return os.environ[xdgkey] + + return os.path.join(os.environ['HOME'], default) + +# Setup xdg paths. +DATA_DIR = os.path.join(xdghome('DATA', '.local/share/'), 'uzbl/') + +# Ensure uzbl xdg paths exist +if not os.path.exists(DATA_DIR): + os.makedirs(DATA_DIR) + +# All of these settings can be inherited from your uzbl config file. +config = { + # Tab options + 'show_tablist': True, # Show text uzbl like statusbar tab-list + 'show_gtk_tabs': False, # Show gtk notebook tabs + 'tablist_top': True, # Display tab-list at top of window + 'gtk_tab_pos': 'top', # Gtk tab position (top|left|bottom|right) + 'gtk_refresh': 1000, # Tablist refresh millisecond interval + 'switch_to_new_tabs': True, # Upon opening a new tab switch to it + 'capture_new_windows': True, # Use uzbl_tabbed to catch new windows + 'multiline_tabs': True, # Tabs overflow onto new tablist lines. + + # Tab title options + 'tab_titles': True, # Display tab titles (else only tab-nums) + 'tab_indexes': True, # Display tab nums (else only tab titles) + 'new_tab_title': 'Loading', # New tab title + 'max_title_len': 50, # Truncate title at n characters + 'show_ellipsis': True, # Show ellipsis when truncating titles + + # Session options + 'save_session': True, # Save session in file when quit + 'saved_sessions_dir': os.path.join(DATA_DIR, 'sessions/'), + 'session_file': os.path.join(DATA_DIR, 'session'), + + # Inherited uzbl options + 'fifo_dir': '/tmp', # Path to look for uzbl fifo. + 'socket_dir': '/tmp', # Path to look for uzbl socket. + 'icon_path': os.path.join(DATA_DIR, 'uzbl.png'), + 'status_background': "#303030", # Default background for all panels. + + # Misc options + 'window_size': "800,800", # width,height in pixels. + 'verbose': False, # Print verbose output. + + # Add custom tab style definitions to be used by the tab colour policy + # handler here. Because these are added to the config dictionary like + # any other uzbl_tabbed configuration option remember that they can + # be superseeded from your main uzbl config file. + 'tab_colours': 'foreground = "#888" background = "#303030"', + 'tab_text_colours': 'foreground = "#bbb"', + 'selected_tab': 'foreground = "#fff"', + 'selected_tab_text': 'foreground = "green"', + 'tab_indicate_https': True, + 'https_colours': 'foreground = "#888"', + 'https_text_colours': 'foreground = "#9c8e2d"', + 'selected_https': 'foreground = "#fff"', + 'selected_https_text': 'foreground = "gold"', + +} # End of config dict. + +UZBL_TABBED_VARS = config.keys() + +# This is the tab style policy handler. Every time the tablist is updated +# this function is called to determine how to colourise that specific tab +# according the simple/complex rules as defined here. You may even wish to +# move this function into another python script and import it using: +# from mycustomtabbingconfig import colour_selector +# Remember to rename, delete or comment out this function if you do that. + +def colour_selector(tabindex, currentpage, uzbl): + '''Tablist styling policy handler. This function must return a tuple of + the form (tab style, text style).''' + + # Just as an example: + # if 'error' in uzbl.title: + # if tabindex == currentpage: + # return ('foreground="#fff"', 'foreground="red"') + # return ('foreground="#888"', 'foreground="red"') + + # Style tabs to indicate connected via https. + if config['tab_indicate_https'] and uzbl.uri.startswith("https://"): + if tabindex == currentpage: + return (config['selected_https'], config['selected_https_text']) + return (config['https_colours'], config['https_text_colours']) + + # Style to indicate selected. + if tabindex == currentpage: + return (config['selected_tab'], config['selected_tab_text']) + + # Default tab style. + return (config['tab_colours'], config['tab_text_colours']) + +# ============================================================================ +# ::: End of configuration section ::::::::::::::::::::::::::::::::::::::::::: +# ============================================================================ + +def echo(msg): + if config['verbose']: + sys.stderr.write("%s: %s\n" % (_SCRIPTNAME, msg)) + + +def counter(): + '''To infinity and beyond!''' + + i = 0 + while True: + i += 1 + yield i + + +def escape(s): + '''Replaces html markup in tab titles that screw around with pango.''' + + for (split, glue) in [('&','&'), ('<', '<'), ('>', '>')]: + s = s.replace(split, glue) + return s + +class SocketClient: + '''Represents a Uzbl instance, which is not necessarly linked with a UzblInstance''' + + # List of UzblInstance objects not already linked with a SocketClient + instances_queue = {} + + def __init__(self, socket): + self._buffer = "" + self._socket = socket + self._watchers = [io_add_watch(socket, IO_IN, self._socket_recv),\ + io_add_watch(socket, IO_HUP, self._socket_closed)] + self.uzbl = None + + + def _socket_recv(self, fd, condition): + '''Data available on socket, process it''' + + self._feed(self._socket.recv(1024)) #TODO: is io_add_watch edge or level-triggered ? + return True + + + def _socket_closed(self, fd, condition): + '''Remote client exited''' + self.uzbl.close() + return False + + + def _feed(self, data): + '''An Uzbl instance sent some data, parse it''' + + self._buffer += data + if self.uzbl: + if "\n" in self._buffer: + cmds = self._buffer.split("\n") + + if cmds[-1]: # Last command has been received incomplete, don't process it + self._buffer, cmds = cmds[-1], cmds[:-1] + else: + self._buffer = "" + + for cmd in cmds: + if cmd: + self.uzbl.parse_command(cmd) + else: + name = re.findall('^EVENT \[(\d+-\d+)\] INSTANCE_START \d+$', self._buffer, re.M) + uzbl = self.instances_queue.get(name[0]) + if uzbl: + del self.instances_queue[name[0]] + self.uzbl = uzbl + self.uzbl.got_socket(self) + self._feed("") + + def send(self, data): + '''Child socket send function.''' + + self._socket.send(data + "\n") + + def close(self): + '''Close the connection''' + + if self._socket: + self._socket.close() + self._socket = None + map(source_remove, self._watchers) + self._watchers = [] + +class EventDispatcher: + def __init__(self, uzbl): + self.uzbl = uzbl + self.parent = self.uzbl.parent + + def dispatch(self, message_type, args): + method = getattr(self, message_type.lower(), None) + + if method is None: + return + + return method(*args) + + def title_changed(self, title): + self.uzbl.title = title.strip() + self.uzbl.title_changed(False) + + def variable_set(self, var, _type, val): + try: + val = int(val) + except: + pass + + if var in UZBL_TABBED_VARS: + if config[var] != val: + config[var] = val + if var == "show_gtk_tabs": + self.parent.notebook.set_show_tabs(bool(val)) + elif var == "show_tablist" or var == "tablist_top": + self.parent.update_tablist_display() + elif var == "gtk_tab_pos": + self.parent.update_gtk_tab_pos() + elif var == "status_background": + if config['status_background'].strip(): + try: + col = gtk.gdk.color_parse(config['status_background']) + self.parent.ebox.modify_bg(gtk.STATE_NORMAL, col) + except ValueError: + pass # got an invalid colour, just ignore it + elif var == "tab_titles" or var == "tab_indexes": + for tab in self.parent.notebook: + self.parent.tabs[tab].title_changed(True) + + self.parent.update_tablist() + else: + config[var] = val + + if var == "uri": + self.uzbl.uri = val.strip() + self.parent.update_tablist() + + def load_commit(self, uri): + self.uzbl.uri = uri + + def new_tab(self, uri = None): + if uri: + self.parent.new_tab(uri) + else: + self.parent.new_tab() + + def new_tab_bg(self, uri = None): + if uri: + self.parent.new_tab(uri, switch = False) + else: + self.parent.new_tab(switch = False) + + def new_tab_next(self, uri = None): + if uri: + self.parent.new_tab(uri, next=True) + else: + self.parent.new_tab(next=True) + + def new_bg_tab_next(self, uri = None): + if uri: + self.parent.new_tab(uri, switch = False, next = True) + else: + self.parent.new_tab(switch = False, next = True) + + def next_tab(self, step = None): + if step: + self.parent.next_tab(int(step)) + else: + self.parent.next_tab() + + def prev_tab(self, step = None): + if step: + self.parent.prev_tab(int(step)) + else: + self.parent.prev_tab() + + def goto_tab(self, index): + self.parent.goto_tab(int(index)) + + def first_tab(self): + self.parent.goto_tab(0) + + def last_tab(self): + self.parent.goto_tab(-1) + + def preset_tabs(self, *args): + self.parent.parse_command(["preset"] + [ a for a in args ]) + + def bring_to_front(self): + self.parent.window.present() + + def clean_tabs(self): + self.parent.clean_slate() + + def exit_all_tabs(self): + self.parent.quitrequest() + +class UzblInstance: + '''Uzbl instance meta-data/meta-action object.''' + + def __init__(self, parent, tab, name, uri, title, switch): + + self.parent = parent + self.tab = tab + self.dispatcher = EventDispatcher(self) + + self.name = name + self.title = title + self.tabtitle = "" + self.uri = uri + + self._client = None + self._switch = switch # Switch to tab after loading ? + self.title_changed() + + + def got_socket(self, client): + '''Uzbl instance is now connected''' + + self._client = client + self.parent.config_uzbl(self) + if self._switch: + tabid = self.parent.notebook.page_num(self.tab) + self.parent.goto_tab(tabid) + + + def title_changed(self, gtk_only = True): # GTK-only is for indexes + '''self.title has changed, update the tabs list''' + + tab_titles = config['tab_titles'] + tab_indexes = config['tab_indexes'] + show_ellipsis = config['show_ellipsis'] + max_title_len = config['max_title_len'] + + # Unicode heavy strings do not like being truncated/sliced so by + # re-encoding the string sliced of limbs are removed. + self.tabtitle = self.title[:max_title_len + int(show_ellipsis)] + if type(self.tabtitle) != types.UnicodeType: + self.tabtitle = unicode(self.tabtitle, 'utf-8', 'ignore') + + self.tabtitle = self.tabtitle.encode('utf-8', 'ignore').strip() + + if show_ellipsis and len(self.tabtitle) != len(self.title): + self.tabtitle += "\xe2\x80\xa6" + + gtk_tab_format = "%d %s" + index = self.parent.notebook.page_num(self.tab) + if tab_titles and tab_indexes: + self.parent.notebook.set_tab_label_text(self.tab, + gtk_tab_format % (index, self.tabtitle)) + elif tab_titles: + self.parent.notebook.set_tab_label_text(self.tab, self.tabtitle) + else: + self.parent.notebook.set_tab_label_text(self.tab, str(index)) + + # If instance is current tab, update window title + if index == self.parent.notebook.get_current_page(): + title_format = "%s - Uzbl Browser" + self.parent.window.set_title(title_format % self.title) + + # Non-GTK tabs + if not gtk_only: + self.parent.update_tablist() + + + def set(self, key, val): + ''' Send the SET command to Uzbl ''' + + if self._client: + self._client.send('set %s = %s') #TODO: escape chars ? + + + def exit(self): + ''' Ask the Uzbl instance to close ''' + + if self._client: + self._client.send('exit') + + def unquote(self, s): + '''Removes quotation marks around strings if any and interprets + \\-escape sequences using `string_escape`''' + if s and s[0] == s[-1] and s[0] in ['"', "'"]: + s = s[1:-1] + return s.encode('utf-8').decode('string_escape').decode('utf-8') + + _splitquoted = re.compile("( |\"(?:\\\\.|[^\"])*?\"|'(?:\\\\.|[^'])*?')") + def parse_event(self, text): + '''Splits string on whitespace while respecting quotations''' + return [self.unquote(p) for p in self._splitquoted.split(text) if p.strip()] + + def parse_command(self, cmd): + ''' Parse event givent by the Uzbl instance ''' + + cmd = self.parse_event(cmd) + message, message_type, args = cmd[0], cmd[2], cmd[3:] + + if message == "EVENT": + self.dispatcher.dispatch(message_type, args) + + def close(self): + '''The remote instance exited''' + + if self._client: + self._client.close() + self._client = None + + +class UzblTabbed: + '''A tabbed version of uzbl using gtk.Notebook''' + + def __init__(self): + '''Create tablist, window and notebook.''' + + self._timers = {} + self._buffer = "" + self._killed = False + + # A list of the recently closed tabs + self._closed = [] + + # Holds metadata on the uzbl childen open. + self.tabs = {} + + # Uzbl sockets (socket => SocketClient) + self.clients = {} + + # Generates a unique id for uzbl socket filenames. + self.next_pid = counter().next + + # Create main window + self.window = gtk.Window() + try: + window_size = map(int, config['window_size'].split(',')) + self.window.set_default_size(*window_size) + + except: + print_exc() + error("Invalid value for default_size in config file.") + + self.window.set_title("Uzbl Browser") + self.window.set_border_width(0) + + # this prevents the window from expanding if the contents of the + # statusbar are wider than the window. + # i suspect this is not the right way to do this. + self.window.set_geometry_hints(min_width=1) + + # Set main window icon + icon_path = config['icon_path'] + if os.path.exists(icon_path): + self.window.set_icon(gtk.gdk.pixbuf_new_from_file(icon_path)) + + else: + icon_path = '/usr/share/uzbl/examples/data/uzbl.png' + if os.path.exists(icon_path): + self.window.set_icon(gtk.gdk.pixbuf_new_from_file(icon_path)) + + # Attach main window event handlers + self.window.connect("delete-event", self.quitrequest) + + # Create tab list + vbox = gtk.VBox() + self.vbox = vbox + self.window.add(vbox) + ebox = gtk.EventBox() + self.ebox = ebox + self.tablist = gtk.Label() + + self.tablist.set_use_markup(True) + self.tablist.set_justify(gtk.JUSTIFY_LEFT) + self.tablist.set_line_wrap(False) + self.tablist.set_selectable(False) + self.tablist.set_padding(2,2) + self.tablist.set_alignment(0,0) + self.tablist.set_ellipsize(pango.ELLIPSIZE_END) + self.tablist.set_text(" ") + self.tablist.show() + ebox.add(self.tablist) + ebox.show() + bgcolor = gtk.gdk.color_parse(config['status_background']) + ebox.modify_bg(gtk.STATE_NORMAL, bgcolor) + + # Create notebook + self.notebook = gtk.Notebook() + self.notebook.set_show_tabs(config['show_gtk_tabs']) + + # Set tab position + self.update_gtk_tab_pos() + + self.notebook.set_show_border(False) + self.notebook.set_scrollable(True) + self.notebook.set_border_width(0) + + self.notebook.connect("page-removed", self.tab_closed) + self.notebook.connect("switch-page", self.tab_changed) + self.notebook.connect("page-added", self.tab_opened) + self.notebook.connect("page-reordered", self.tab_reordered) + + self.notebook.show() + vbox.pack_start(self.notebook, True, True, 0) + vbox.reorder_child(self.notebook, 1) + self.update_tablist_display() + + self.vbox.show() + self.window.show() + self.wid = self.notebook.window.xid + + # Store information about the applications fifo and socket. + fifo_filename = 'uzbltabbed_%d.fifo' % os.getpid() + socket_filename = 'uzbltabbed_%d.socket' % os.getpid() + self._fifo = None + self._socket = None + self.fifo_path = os.path.join(config['fifo_dir'], fifo_filename) + self.socket_path = os.path.join(config['socket_dir'], socket_filename) + + # Now initialise the fifo and the socket + self.init_fifo() + self.init_socket() + + # If we are using sessions then load the last one if it exists. + if config['save_session']: + self.load_session() + + + def run(self): + '''UzblTabbed main function that calls the gtk loop.''' + + if not self.clients and not SocketClient.instances_queue and not self.tabs: + self.new_tab() + + gtk_refresh = int(config['gtk_refresh']) + if gtk_refresh < 100: + gtk_refresh = 100 + + # Make SIGTERM act orderly. + signal(SIGTERM, lambda signum, stack_frame: self.terminate(SIGTERM)) + + # Catch keyboard interrupts + signal(SIGINT, lambda signum, stack_frame: self.terminate(SIGINT)) + + try: + gtk.main() + + except: + print_exc() + error("encounted error %r" % sys.exc_info()[1]) + + # Unlink fifo socket + self.unlink_fifo() + self.close_socket() + + # Attempt to close all uzbl instances nicely. + self.quitrequest() + + # Allow time for all the uzbl instances to quit. + time.sleep(1) + + raise + + def terminate(self, termsig=None): + '''Handle termination signals and exit safely and cleanly.''' + + # Not required but at least it lets the user know what killed his + # browsing session. + if termsig == SIGTERM: + error("caught SIGTERM signal") + + elif termsig == SIGINT: + error("caught keyboard interrupt") + + else: + error("caught unknown signal") + + error("commencing infanticide!") + + # Sends the exit signal to all uzbl instances. + self.quitrequest() + + + def init_socket(self): + '''Create interprocess communication socket.''' + + def accept(sock, condition): + '''A new uzbl instance was created''' + + client, _ = sock.accept() + self.clients[client] = SocketClient(client) + + return True + + sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM) + sock.bind(self.socket_path) + sock.listen(1) + + # Add event handler for IO_IN event. + self._socket = (sock, io_add_watch(sock, IO_IN, accept)) + + echo("[socket] listening at %r" % self.socket_path) + + # Add atexit register to destroy the socket on program termination. + atexit.register(self.close_socket) + + + def close_socket(self): + '''Close the socket when closing the application''' + + if self._socket: + (fd, watcher) = self._socket + source_remove(watcher) + fd.close() + os.unlink(self.socket_path) + self._socket = None + + + def init_fifo(self): + '''Create interprocess communication fifo.''' + + if os.path.exists(self.fifo_path): + if not os.access(self.fifo_path, os.F_OK | os.R_OK | os.W_OK): + os.mkfifo(self.fifo_path) + + else: + basedir = os.path.dirname(self.fifo_path) + if not os.path.exists(basedir): + os.makedirs(basedir) + + os.mkfifo(self.fifo_path) + + # Add event handlers for IO_IN & IO_HUP events. + self.setup_fifo_watchers() + + echo("[fifo] listening at %r" % self.fifo_path) + + # Add atexit register to destroy the fifo on program termination. + atexit.register(self.unlink_fifo) + + + def unlink_fifo(self): + '''Unlink the fifo socket. Note: This function is called automatically + on exit by an atexit register.''' + + # Make sure the fifo fd is closed. + self.close_fifo() + + # And unlink if the real fifo exists. + if os.path.exists(self.fifo_path): + os.unlink(self.fifo_path) + echo("unlinked %r" % self.fifo_path) + + + def close_fifo(self): + '''Remove all event handlers watching the fifo and close the fd.''' + + # Already closed + if self._fifo is None: return + + (fd, watchers) = self._fifo + os.close(fd) + + # Stop all gobject io watchers watching the fifo. + for gid in watchers: + source_remove(gid) + + self._fifo = None + + + def setup_fifo_watchers(self): + '''Open fifo socket fd and setup gobject IO_IN & IO_HUP event + handlers.''' + + # Close currently open fifo fd and kill all watchers + self.close_fifo() + + fd = os.open(self.fifo_path, os.O_RDONLY | os.O_NONBLOCK) + + # Add gobject io event handlers to the fifo socket. + watchers = [io_add_watch(fd, IO_IN, self.main_fifo_read),\ + io_add_watch(fd, IO_HUP, self.main_fifo_hangup)] + + self._fifo = (fd, watchers) + + + def main_fifo_hangup(self, fd, cb_condition): + '''Handle main fifo socket hangups.''' + + # Close old fd, open new fifo socket and add io event handlers. + self.setup_fifo_watchers() + + # Kill the gobject event handler calling this handler function. + return False + + + def main_fifo_read(self, fd, cb_condition): + '''Read from main fifo socket.''' + + self._buffer = os.read(fd, 1024) + temp = self._buffer.split("\n") + self._buffer = temp.pop() + cmds = [s.strip().split() for s in temp if len(s.strip())] + + for cmd in cmds: + try: + #print cmd + self.parse_command(cmd) + + except: + print_exc() + error("parse_command: invalid command %s" % ' '.join(cmd)) + raise + + return True + + + def parse_command(self, cmd): + '''Parse instructions from uzbl child processes.''' + + # Commands ( [] = optional, {} = required ) + # new [uri] + # open new tab and head to optional uri. + # newbg [uri] + # open a new tab in the background + # close [tab-num] + # close current tab or close via tab id. + # next [n-tabs] + # open next tab or n tabs down. Supports negative indexing. + # prev [n-tabs] + # open prev tab or n tabs down. Supports negative indexing. + # goto {tab-n} + # goto tab n. + # first + # goto first tab. + # last + # goto last tab. + # title {pid} {document-title} + # updates tablist title. + # uri {pid} {document-location} + # updates tablist uri + # bring_to_front + # brings the gtk window to focus. + # exit + # exits uzbl_tabbed.py + + if cmd[0] == "new": + if len(cmd) == 2: + self.new_tab(cmd[1]) + + else: + self.new_tab() + + elif cmd[0] == "newbg": + if len(cmd) == 2: + self.new_tab(cmd[1], switch=False) + else: + self.new_tab(switch=False) + + elif cmd[0] == "newfromclip": + uri = subprocess.Popen(['xclip','-selection','clipboard','-o'],\ + stdout=subprocess.PIPE).communicate()[0] + if uri: + self.new_tab(uri) + + elif cmd[0] == "close": + if len(cmd) == 2: + self.close_tab(int(cmd[1])) + + else: + self.close_tab() + + elif cmd[0] == "next": + if len(cmd) == 2: + self.next_tab(int(cmd[1])) + + else: + self.next_tab() + + elif cmd[0] == "prev": + if len(cmd) == 2: + self.prev_tab(int(cmd[1])) + + else: + self.prev_tab() + + elif cmd[0] == "goto": + self.goto_tab(int(cmd[1])) + + elif cmd[0] == "first": + self.goto_tab(0) + + elif cmd[0] == "last": + self.goto_tab(-1) + + elif cmd[0] in ["title", "uri"]: + if len(cmd) > 2: + uzbl = self.get_tab_by_name(int(cmd[1])) + if uzbl: + old = getattr(uzbl, cmd[0]) + new = ' '.join(cmd[2:]) + setattr(uzbl, cmd[0], new) + if old != new: + self.update_tablist() + + else: + error("parse_command: no uzbl with name %r" % int(cmd[1])) + + elif cmd[0] == "preset": + if len(cmd) < 3: + error("parse_command: invalid preset command") + + elif cmd[1] == "save": + path = os.path.join(config['saved_sessions_dir'], cmd[2]) + self.save_session(path) + + elif cmd[1] == "load": + path = os.path.join(config['saved_sessions_dir'], cmd[2]) + self.load_session(path) + + elif cmd[1] == "del": + path = os.path.join(config['saved_sessions_dir'], cmd[2]) + if os.path.isfile(path): + os.remove(path) + + else: + error("parse_command: preset %r does not exist." % path) + + elif cmd[1] == "list": + # FIXME: what argument is this supposed to be passed, + # and why? + uzbl = self.get_tab_by_name(int(cmd[2])) + if uzbl: + if not os.path.isdir(config['saved_sessions_dir']): + js = "js alert('No saved presets.');" + uzbl._client.send(js) + + else: + listdir = os.listdir(config['saved_sessions_dir']) + listdir = "\\n".join(listdir) + js = "js alert('Session presets:\\n\\n%s');" % listdir + uzbl._client.send(js) + + else: + error("parse_command: unknown tab name.") + + else: + error("parse_command: unknown parse command %r"\ + % ' '.join(cmd)) + + elif cmd[0] == "bring_to_front": + self.window.present() + + elif cmd[0] == "clean": + self.clean_slate() + + elif cmd[0] == "exit": + self.quitrequest() + + else: + error("parse_command: unknown command %r" % ' '.join(cmd)) + + + def get_tab_by_name(self, name): + '''Return uzbl instance by name.''' + + for (tab, uzbl) in self.tabs.items(): + if uzbl.name == name: + return uzbl + + return False + + + def new_tab(self, uri='', title='', switch=None, next=False): + '''Add a new tab to the notebook and start a new instance of uzbl. + Use the switch option to negate config['switch_to_new_tabs'] option + when you need to load multiple tabs at a time (I.e. like when + restoring a session from a file).''' + + tab = gtk.Socket() + tab.show() + self.notebook.insert_page(tab, position=next and self.notebook.get_current_page() + 1 or -1) + self.notebook.set_tab_reorderable(tab, True) + sid = tab.get_id() + uri = uri.strip() + name = "%d-%d" % (os.getpid(), self.next_pid()) + + if switch is None: + switch = config['switch_to_new_tabs'] + + if not title: + title = config['new_tab_title'] + + cmd = ['uzbl-browser', '-n', name, '-s', str(sid), + '--connect-socket', self.socket_path, '--uri', str(uri)] + gobject.spawn_async(cmd, flags=gobject.SPAWN_SEARCH_PATH) + + uzbl = UzblInstance(self, tab, name, uri, title, switch) + SocketClient.instances_queue[name] = uzbl + self.tabs[tab] = uzbl + + + def clean_slate(self): + '''Close all open tabs and open a fresh brand new one.''' + + self.new_tab() + tabs = self.tabs.keys() + for tab in list(self.notebook)[:-1]: + if tab not in tabs: continue + uzbl = self.tabs[tab] + uzbl.exit() + + + def config_uzbl(self, uzbl): + '''Send bind commands for tab new/close/next/prev to a uzbl + instance.''' + + # Set definitions here + # set(key, command back to fifo) + if config['capture_new_windows']: + uzbl.set("new_window", r'new $8') + + + def goto_tab(self, index): + '''Goto tab n (supports negative indexing).''' + + title_format = "%s - Uzbl Browser" + + tabs = list(self.notebook) + if 0 <= index < len(tabs): + self.notebook.set_current_page(index) + uzbl = self.tabs[self.notebook.get_nth_page(index)] + self.window.set_title(title_format % uzbl.title) + self.update_tablist() + return None + + try: + tab = tabs[index] + # Update index because index might have previously been a + # negative index. + index = tabs.index(tab) + self.notebook.set_current_page(index) + uzbl = self.tabs[self.notebook.get_nth_page(index)] + self.window.set_title(title_format % uzbl.title) + self.update_tablist() + + except IndexError: + pass + + + def next_tab(self, step=1): + '''Switch to next tab or n tabs right.''' + + if step < 1: + error("next_tab: invalid step %r" % step) + return None + + ntabs = self.notebook.get_n_pages() + tabn = (self.notebook.get_current_page() + step) % ntabs + self.goto_tab(tabn) + + + def prev_tab(self, step=1): + '''Switch to prev tab or n tabs left.''' + + if step < 1: + error("prev_tab: invalid step %r" % step) + return None + + ntabs = self.notebook.get_n_pages() + tabn = self.notebook.get_current_page() - step + while tabn < 0: tabn += ntabs + self.goto_tab(tabn) + + + def close_tab(self, tabn=None): + '''Closes current tab. Supports negative indexing.''' + + if tabn is None: + tabn = self.notebook.get_current_page() + + else: + try: + tab = list(self.notebook)[tabn] + + except IndexError: + error("close_tab: invalid index %r" % tabn) + return None + + self.notebook.remove_page(tabn) + + + def tab_opened(self, notebook, tab, index): + '''Called upon tab creation. Called by page-added signal.''' + + if config['switch_to_new_tabs']: + self.notebook.set_focus_child(tab) + + else: + oldindex = self.notebook.get_current_page() + oldtab = self.notebook.get_nth_page(oldindex) + self.notebook.set_focus_child(oldtab) + + + def tab_closed(self, notebook, tab, index): + '''Close the window if no tabs are left. Called by page-removed + signal.''' + + if tab in self.tabs.keys(): + uzbl = self.tabs[tab] + uzbl.close() + + self._closed.append((uzbl.uri, uzbl.title)) + self._closed = self._closed[-10:] + del self.tabs[tab] + + if self.notebook.get_n_pages() == 0: + if not self._killed and config['save_session']: + if os.path.exists(config['session_file']): + os.remove(config['session_file']) + + self.quit() + + for tab in self.notebook: + self.tabs[tab].title_changed(True) + self.update_tablist() + + return True + + + def tab_changed(self, notebook, page, index): + '''Refresh tab list. Called by switch-page signal.''' + + tab = self.notebook.get_nth_page(index) + self.notebook.set_focus_child(tab) + self.update_tablist(index) + return True + + + def tab_reordered(self, notebook, page, index): + '''Refresh tab titles. Called by page-reordered signal.''' + + for tab in self.notebook: + self.tabs[tab].title_changed(True) + return True + + + def update_tablist_display(self): + '''Called when show_tablist or tablist_top has changed''' + + if self.ebox in self.vbox.get_children(): + self.vbox.remove(self.ebox) + + if config['show_tablist']: + self.vbox.pack_start(self.ebox, False, False, 0) + if config['tablist_top']: + self.vbox.reorder_child(self.ebox, 0) + else: + self.vbox.reorder_child(self.ebox, 2) + + def update_gtk_tab_pos(self): + ''' Called when gtk_tab_pos has changed ''' + + allposes = {'left': gtk.POS_LEFT, 'right':gtk.POS_RIGHT, + 'top':gtk.POS_TOP, 'bottom':gtk.POS_BOTTOM} + if config['gtk_tab_pos'] in allposes.keys(): + self.notebook.set_tab_pos(allposes[config['gtk_tab_pos']]) + + + def update_tablist(self, curpage=None): + '''Upate tablist status bar.''' + + if not config['show_tablist']: + return True + + tab_titles = config['tab_titles'] + tab_indexes = config['tab_indexes'] + multiline_tabs = config['multiline_tabs'] + + if multiline_tabs: + multiline = [] + + tabs = self.tabs.keys() + if curpage is None: + curpage = self.notebook.get_current_page() + + pango = "" + normal = (config['tab_colours'], config['tab_text_colours']) + selected = (config['selected_tab'], config['selected_tab_text']) + + if tab_titles and tab_indexes: + tab_format = " [ %(index)d %(title)s ] " + elif tab_titles: + tab_format = " [ %(title)s ] " + else: + tab_format = " [ %(index)d ] " + + for index, tab in enumerate(self.notebook): + if tab not in tabs: continue + uzbl = self.tabs[tab] + title = escape(uzbl.tabtitle) + + style = colour_selector(index, curpage, uzbl) + (tabc, textc) = style + + if multiline_tabs: + opango = pango + + pango += tab_format % locals() + + self.tablist.set_markup(pango) + listwidth = self.tablist.get_layout().get_pixel_size()[0] + winwidth = self.window.get_size()[0] + + if listwidth > (winwidth - 20): + multiline.append(opango) + pango = tab_format % locals() + else: + pango += tab_format % locals() + + if multiline_tabs: + multiline.append(pango) + self.tablist.set_markup(' '.join(multiline)) + + else: + self.tablist.set_markup(pango) + + return True + + + def save_session(self, session_file=None): + '''Save the current session to file for restoration on next load.''' + + if session_file is None: + session_file = config['session_file'] + + tabs = self.tabs.keys() + lines = "curtab = %d\n" % self.notebook.get_current_page() + for tab in list(self.notebook): + if tab not in tabs: + continue + + uzbl = self.tabs[tab] + if not uzbl.uri: + continue + + lines += "%s %s\n" % (uzbl.uri, uzbl.title) + + if not os.path.isfile(session_file): + dirname = os.path.dirname(session_file) + if not os.path.isdir(dirname): + os.makedirs(dirname) + + fh = open(session_file, 'w') + fh.write(lines) + fh.close() + + + def load_session(self, session_file=None): + '''Load a saved session from file.''' + + default_path = False + delete_loaded = False + + if session_file is None: + default_path = True + delete_loaded = True + session_file = config['session_file'] + + if not os.path.isfile(session_file): + return False + + fh = open(session_file, 'r') + raw = fh.read() + fh.close() + + tabs = [] + curtab = 0 + + lines = filter(None, map(str.strip, raw.split('\n'))) + if len(lines) < 2: + error("Error: The session file %r looks invalid." % session_file) + if delete_loaded and os.path.exists(session_file): + os.remove(session_file) + + return None + + try: + for line in lines: + if line.startswith("curtab"): + curtab = int(line.split()[-1]) + + else: + uri, title = map(str.strip, line.split(" ", 1)) + tabs += [(uri, title),] + + except: + print_exc() + error("Warning: failed to load session file %r" % session_file) + return None + + # Now populate notebook with the loaded session. + for (index, (uri, title)) in enumerate(tabs): + self.new_tab(uri=uri, title=title, switch=(curtab==index)) + + # A saved session has been loaded now delete it. + if delete_loaded and os.path.exists(session_file): + os.remove(session_file) + + + def quitrequest(self, *args): + '''Attempt to close all uzbl instances nicely and exit.''' + + self._killed = True + + if config['save_session']: + if len(list(self.notebook)) > 1: + self.save_session() + + else: + # Notebook has one page open so delete the session file. + if os.path.isfile(config['session_file']): + os.remove(config['session_file']) + + for (tab, uzbl) in self.tabs.items(): + uzbl.exit() + + # Add a gobject timer to make sure the application force-quits after a + # reasonable period. Calling quit when all the tabs haven't had time to + # close should be a last resort. + timer = "force-quit" + timerid = timeout_add(5000, self.quit, timer) + self._timers[timer] = timerid + + + def quit(self, *args): + '''Cleanup and quit. Called by delete-event signal.''' + + # Close the fifo socket, remove any gobject io event handlers and + # delete socket. + self.unlink_fifo() + self.close_socket() + + # Remove all gobject timers that are still ticking. + for (timerid, gid) in self._timers.items(): + source_remove(gid) + del self._timers[timerid] + + try: + gtk.main_quit() + + except: + pass + + +if __name__ == "__main__": + + # Build command line parser + usage = "usage: %prog [OPTIONS] {URIS}..." + parser = OptionParser(usage=usage) + parser.add_option('-n', '--no-session', dest='nosession', + action='store_true', help="ignore session saving a loading.") + parser.add_option('-v', '--verbose', dest='verbose', + action='store_true', help='print verbose output.') + parser.add_option('-s', '--socketdir', dest='socketdir', + help="directory to create socket") + parser.add_option('-f', '--fifodir', dest='fifodir', + help="directory to create fifo") + + # Parse command line options + (options, uris) = parser.parse_args() + + if options.nosession: + config['save_session'] = False + + if options.verbose: + config['verbose'] = True + + if config['verbose']: + import pprint + sys.stderr.write("%s\n" % pprint.pformat(config)) + + if options.socketdir: + config['socket_dir'] = options.socketdir + + if options.fifodir: + config['fifo_dir'] = options.fifodir + + uzbl = UzblTabbed() + + # All extra arguments given to uzbl_tabbed.py are interpreted as + # web-locations to opened in new tabs. + lasturi = len(uris)-1 + for (index,uri) in enumerate(uris): + uzbl.new_tab(uri, switch=(index==lasturi)) + + uzbl.run() diff --git a/examples/data/scripts/uzbl-tabbed b/examples/data/scripts/uzbl-tabbed deleted file mode 100755 index a15967a..0000000 --- a/examples/data/scripts/uzbl-tabbed +++ /dev/null @@ -1,1472 +0,0 @@ -#!/usr/bin/env python - -# Uzbl tabbing wrapper using a fifo socket interface -# Copyright (c) 2009, Tom Adams -# Copyright (c) 2009, Chris van Dijk -# Copyright (c) 2009, Mason Larobina -# -# This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program. If not, see . - - -# Author(s): -# Tom Adams -# Wrote the original uzbl_tabbed.py as a proof of concept. -# -# Chris van Dijk (quigybo) -# Made signifigant headway on the old uzbl_tabbing.py script on the -# uzbl wiki -# -# Mason Larobina -# Rewrite of the uzbl_tabbing.py script to use a fifo socket interface -# and inherit configuration options from the user's uzbl config. -# -# Contributor(s): -# mxey -# uzbl_config path now honors XDG_CONFIG_HOME if it exists. -# -# Romain Bignon -# Fix for session restoration code. -# -# Jake Probst -# Wrote a patch that overflows tabs in the tablist on to new lines when -# running of room. -# -# Devon Jones -# Fifo command bring_to_front which brings the gtk window to focus. -# -# Simon Lipp (sloonz) -# Various - - -# Dependencies: -# pygtk - python bindings for gtk. -# pango - python bindings needed for text rendering & layout in gtk widgets. -# pygobject - GLib's GObject bindings for python. -# -# Note: I haven't included version numbers with this dependency list because -# I've only ever tested uzbl_tabbed.py on the latest stable versions of these -# packages in Gentoo's portage. Package names may vary on different systems. - - -# Configuration: -# Because this version of uzbl_tabbed is able to inherit options from your main -# uzbl configuration file you may wish to configure uzbl tabbed from there. -# Here is a list of configuration options that can be customised and some -# example values for each: -# -# General tabbing options: -# show_tablist = 1 -# show_gtk_tabs = 0 -# tablist_top = 1 -# gtk_tab_pos = (top|left|bottom|right) -# gtk_refresh = 1000 -# switch_to_new_tabs = 1 -# capture_new_windows = 1 -# multiline_tabs = 1 -# -# Tab title options: -# tab_titles = 1 -# tab_indexes = 1 -# new_tab_title = Loading -# max_title_len = 50 -# show_ellipsis = 1 -# -# Session options: -# save_session = 1 -# json_session = 0 -# session_file = $HOME/.local/share/uzbl/session -# -# Inherited uzbl options: -# fifo_dir = /tmp -# socket_dir = /tmp -# icon_path = $HOME/.local/share/uzbl/uzbl.png -# status_background = #303030 -# -# Misc options: -# window_size = 800,800 -# verbose = 0 -# -# And uzbl_tabbed.py takes care of the actual binding of the commands via each -# instances fifo socket. -# -# Custom tab styling: -# tab_colours = foreground = "#888" background = "#303030" -# tab_text_colours = foreground = "#bbb" -# selected_tab = foreground = "#fff" -# selected_tab_text = foreground = "green" -# tab_indicate_https = 1 -# https_colours = foreground = "#888" -# https_text_colours = foreground = "#9c8e2d" -# selected_https = foreground = "#fff" -# selected_https_text = foreground = "gold" -# -# How these styling values are used are soley defined by the syling policy -# handler below (the function in the config section). So you can for example -# turn the tab text colour Firetruck-Red in the event "error" appears in the -# tab title or some other arbitrary event. You may wish to make a trusted -# hosts file and turn tab titles of tabs visiting trusted hosts purple. - - -# Issues: -# - new windows are not caught and opened in a new tab. -# - when uzbl_tabbed.py crashes it takes all the children with it. -# - when a new tab is opened when using gtk tabs the tab button itself -# grabs focus from its child for a few seconds. -# - when switch_to_new_tabs is not selected the notebook page is -# maintained but the new window grabs focus (try as I might to stop it). - - -# Todo: -# - add command line options to use a different session file, not use a -# session file and or open a uri on starup. -# - ellipsize individual tab titles when the tab-list becomes over-crowded -# - add "<" & ">" arrows to tablist to indicate that only a subset of the -# currently open tabs are being displayed on the tablist. -# - add the small tab-list display when both gtk tabs and text vim-like -# tablist are hidden (I.e. [ 1 2 3 4 5 ]) -# - check spelling. -# - pass a uzbl socketid to uzbl_tabbed.py and have it assimilated into -# the collective. Resistance is futile! - - -import pygtk -import gtk -import subprocess -import os -import re -import time -import getopt -import pango -import select -import sys -import gobject -import socket -import random -import hashlib -import atexit -import types - -from gobject import io_add_watch, source_remove, timeout_add, IO_IN, IO_HUP -from signal import signal, SIGTERM, SIGINT -from optparse import OptionParser, OptionGroup -from traceback import print_exc - - -pygtk.require('2.0') - -_SCRIPTNAME = os.path.basename(sys.argv[0]) -def error(msg): - sys.stderr.write("%s: error: %s\n" % (_SCRIPTNAME, msg)) - -# ============================================================================ -# ::: Default configuration section :::::::::::::::::::::::::::::::::::::::::: -# ============================================================================ - -def xdghome(key, default): - '''Attempts to use the environ XDG_*_HOME paths if they exist otherwise - use $HOME and the default path.''' - - xdgkey = "XDG_%s_HOME" % key - if xdgkey in os.environ.keys() and os.environ[xdgkey]: - return os.environ[xdgkey] - - return os.path.join(os.environ['HOME'], default) - -# Setup xdg paths. -DATA_DIR = os.path.join(xdghome('DATA', '.local/share/'), 'uzbl/') - -# Ensure uzbl xdg paths exist -if not os.path.exists(DATA_DIR): - os.makedirs(DATA_DIR) - -# All of these settings can be inherited from your uzbl config file. -config = { - # Tab options - 'show_tablist': True, # Show text uzbl like statusbar tab-list - 'show_gtk_tabs': False, # Show gtk notebook tabs - 'tablist_top': True, # Display tab-list at top of window - 'gtk_tab_pos': 'top', # Gtk tab position (top|left|bottom|right) - 'gtk_refresh': 1000, # Tablist refresh millisecond interval - 'switch_to_new_tabs': True, # Upon opening a new tab switch to it - 'capture_new_windows': True, # Use uzbl_tabbed to catch new windows - 'multiline_tabs': True, # Tabs overflow onto new tablist lines. - - # Tab title options - 'tab_titles': True, # Display tab titles (else only tab-nums) - 'tab_indexes': True, # Display tab nums (else only tab titles) - 'new_tab_title': 'Loading', # New tab title - 'max_title_len': 50, # Truncate title at n characters - 'show_ellipsis': True, # Show ellipsis when truncating titles - - # Session options - 'save_session': True, # Save session in file when quit - 'saved_sessions_dir': os.path.join(DATA_DIR, 'sessions/'), - 'session_file': os.path.join(DATA_DIR, 'session'), - - # Inherited uzbl options - 'fifo_dir': '/tmp', # Path to look for uzbl fifo. - 'socket_dir': '/tmp', # Path to look for uzbl socket. - 'icon_path': os.path.join(DATA_DIR, 'uzbl.png'), - 'status_background': "#303030", # Default background for all panels. - - # Misc options - 'window_size': "800,800", # width,height in pixels. - 'verbose': False, # Print verbose output. - - # Add custom tab style definitions to be used by the tab colour policy - # handler here. Because these are added to the config dictionary like - # any other uzbl_tabbed configuration option remember that they can - # be superseeded from your main uzbl config file. - 'tab_colours': 'foreground = "#888" background = "#303030"', - 'tab_text_colours': 'foreground = "#bbb"', - 'selected_tab': 'foreground = "#fff"', - 'selected_tab_text': 'foreground = "green"', - 'tab_indicate_https': True, - 'https_colours': 'foreground = "#888"', - 'https_text_colours': 'foreground = "#9c8e2d"', - 'selected_https': 'foreground = "#fff"', - 'selected_https_text': 'foreground = "gold"', - -} # End of config dict. - -UZBL_TABBED_VARS = config.keys() - -# This is the tab style policy handler. Every time the tablist is updated -# this function is called to determine how to colourise that specific tab -# according the simple/complex rules as defined here. You may even wish to -# move this function into another python script and import it using: -# from mycustomtabbingconfig import colour_selector -# Remember to rename, delete or comment out this function if you do that. - -def colour_selector(tabindex, currentpage, uzbl): - '''Tablist styling policy handler. This function must return a tuple of - the form (tab style, text style).''' - - # Just as an example: - # if 'error' in uzbl.title: - # if tabindex == currentpage: - # return ('foreground="#fff"', 'foreground="red"') - # return ('foreground="#888"', 'foreground="red"') - - # Style tabs to indicate connected via https. - if config['tab_indicate_https'] and uzbl.uri.startswith("https://"): - if tabindex == currentpage: - return (config['selected_https'], config['selected_https_text']) - return (config['https_colours'], config['https_text_colours']) - - # Style to indicate selected. - if tabindex == currentpage: - return (config['selected_tab'], config['selected_tab_text']) - - # Default tab style. - return (config['tab_colours'], config['tab_text_colours']) - -# ============================================================================ -# ::: End of configuration section ::::::::::::::::::::::::::::::::::::::::::: -# ============================================================================ - -def echo(msg): - if config['verbose']: - sys.stderr.write("%s: %s\n" % (_SCRIPTNAME, msg)) - - -def counter(): - '''To infinity and beyond!''' - - i = 0 - while True: - i += 1 - yield i - - -def escape(s): - '''Replaces html markup in tab titles that screw around with pango.''' - - for (split, glue) in [('&','&'), ('<', '<'), ('>', '>')]: - s = s.replace(split, glue) - return s - -class SocketClient: - '''Represents a Uzbl instance, which is not necessarly linked with a UzblInstance''' - - # List of UzblInstance objects not already linked with a SocketClient - instances_queue = {} - - def __init__(self, socket): - self._buffer = "" - self._socket = socket - self._watchers = [io_add_watch(socket, IO_IN, self._socket_recv),\ - io_add_watch(socket, IO_HUP, self._socket_closed)] - self.uzbl = None - - - def _socket_recv(self, fd, condition): - '''Data available on socket, process it''' - - self._feed(self._socket.recv(1024)) #TODO: is io_add_watch edge or level-triggered ? - return True - - - def _socket_closed(self, fd, condition): - '''Remote client exited''' - self.uzbl.close() - return False - - - def _feed(self, data): - '''An Uzbl instance sent some data, parse it''' - - self._buffer += data - if self.uzbl: - if "\n" in self._buffer: - cmds = self._buffer.split("\n") - - if cmds[-1]: # Last command has been received incomplete, don't process it - self._buffer, cmds = cmds[-1], cmds[:-1] - else: - self._buffer = "" - - for cmd in cmds: - if cmd: - self.uzbl.parse_command(cmd) - else: - name = re.findall('^EVENT \[(\d+-\d+)\] INSTANCE_START \d+$', self._buffer, re.M) - uzbl = self.instances_queue.get(name[0]) - if uzbl: - del self.instances_queue[name[0]] - self.uzbl = uzbl - self.uzbl.got_socket(self) - self._feed("") - - def send(self, data): - '''Child socket send function.''' - - self._socket.send(data + "\n") - - def close(self): - '''Close the connection''' - - if self._socket: - self._socket.close() - self._socket = None - map(source_remove, self._watchers) - self._watchers = [] - -class EventDispatcher: - def __init__(self, uzbl): - self.uzbl = uzbl - self.parent = self.uzbl.parent - - def dispatch(self, message_type, args): - method = getattr(self, message_type.lower(), None) - - if method is None: - return - - return method(*args) - - def title_changed(self, title): - self.uzbl.title = title.strip() - self.uzbl.title_changed(False) - - def variable_set(self, var, _type, val): - try: - val = int(val) - except: - pass - - if var in UZBL_TABBED_VARS: - if config[var] != val: - config[var] = val - if var == "show_gtk_tabs": - self.parent.notebook.set_show_tabs(bool(val)) - elif var == "show_tablist" or var == "tablist_top": - self.parent.update_tablist_display() - elif var == "gtk_tab_pos": - self.parent.update_gtk_tab_pos() - elif var == "status_background": - if config['status_background'].strip(): - try: - col = gtk.gdk.color_parse(config['status_background']) - self.parent.ebox.modify_bg(gtk.STATE_NORMAL, col) - except ValueError: - pass # got an invalid colour, just ignore it - elif var == "tab_titles" or var == "tab_indexes": - for tab in self.parent.notebook: - self.parent.tabs[tab].title_changed(True) - - self.parent.update_tablist() - else: - config[var] = val - - if var == "uri": - self.uzbl.uri = val.strip() - self.parent.update_tablist() - - def load_commit(self, uri): - self.uzbl.uri = uri - - def new_tab(self, uri = None): - if uri: - self.parent.new_tab(uri) - else: - self.parent.new_tab() - - def new_tab_bg(self, uri = None): - if uri: - self.parent.new_tab(uri, switch = False) - else: - self.parent.new_tab(switch = False) - - def new_tab_next(self, uri = None): - if uri: - self.parent.new_tab(uri, next=True) - else: - self.parent.new_tab(next=True) - - def new_bg_tab_next(self, uri = None): - if uri: - self.parent.new_tab(uri, switch = False, next = True) - else: - self.parent.new_tab(switch = False, next = True) - - def next_tab(self, step = None): - if step: - self.parent.next_tab(int(step)) - else: - self.parent.next_tab() - - def prev_tab(self, step = None): - if step: - self.parent.prev_tab(int(step)) - else: - self.parent.prev_tab() - - def goto_tab(self, index): - self.parent.goto_tab(int(index)) - - def first_tab(self): - self.parent.goto_tab(0) - - def last_tab(self): - self.parent.goto_tab(-1) - - def preset_tabs(self, *args): - self.parent.parse_command(["preset"] + [ a for a in args ]) - - def bring_to_front(self): - self.parent.window.present() - - def clean_tabs(self): - self.parent.clean_slate() - - def exit_all_tabs(self): - self.parent.quitrequest() - -class UzblInstance: - '''Uzbl instance meta-data/meta-action object.''' - - def __init__(self, parent, tab, name, uri, title, switch): - - self.parent = parent - self.tab = tab - self.dispatcher = EventDispatcher(self) - - self.name = name - self.title = title - self.tabtitle = "" - self.uri = uri - - self._client = None - self._switch = switch # Switch to tab after loading ? - self.title_changed() - - - def got_socket(self, client): - '''Uzbl instance is now connected''' - - self._client = client - self.parent.config_uzbl(self) - if self._switch: - tabid = self.parent.notebook.page_num(self.tab) - self.parent.goto_tab(tabid) - - - def title_changed(self, gtk_only = True): # GTK-only is for indexes - '''self.title has changed, update the tabs list''' - - tab_titles = config['tab_titles'] - tab_indexes = config['tab_indexes'] - show_ellipsis = config['show_ellipsis'] - max_title_len = config['max_title_len'] - - # Unicode heavy strings do not like being truncated/sliced so by - # re-encoding the string sliced of limbs are removed. - self.tabtitle = self.title[:max_title_len + int(show_ellipsis)] - if type(self.tabtitle) != types.UnicodeType: - self.tabtitle = unicode(self.tabtitle, 'utf-8', 'ignore') - - self.tabtitle = self.tabtitle.encode('utf-8', 'ignore').strip() - - if show_ellipsis and len(self.tabtitle) != len(self.title): - self.tabtitle += "\xe2\x80\xa6" - - gtk_tab_format = "%d %s" - index = self.parent.notebook.page_num(self.tab) - if tab_titles and tab_indexes: - self.parent.notebook.set_tab_label_text(self.tab, - gtk_tab_format % (index, self.tabtitle)) - elif tab_titles: - self.parent.notebook.set_tab_label_text(self.tab, self.tabtitle) - else: - self.parent.notebook.set_tab_label_text(self.tab, str(index)) - - # If instance is current tab, update window title - if index == self.parent.notebook.get_current_page(): - title_format = "%s - Uzbl Browser" - self.parent.window.set_title(title_format % self.title) - - # Non-GTK tabs - if not gtk_only: - self.parent.update_tablist() - - - def set(self, key, val): - ''' Send the SET command to Uzbl ''' - - if self._client: - self._client.send('set %s = %s') #TODO: escape chars ? - - - def exit(self): - ''' Ask the Uzbl instance to close ''' - - if self._client: - self._client.send('exit') - - def unquote(self, s): - '''Removes quotation marks around strings if any and interprets - \\-escape sequences using `string_escape`''' - if s and s[0] == s[-1] and s[0] in ['"', "'"]: - s = s[1:-1] - return s.encode('utf-8').decode('string_escape').decode('utf-8') - - _splitquoted = re.compile("( |\"(?:\\\\.|[^\"])*?\"|'(?:\\\\.|[^'])*?')") - def parse_event(self, text): - '''Splits string on whitespace while respecting quotations''' - return [self.unquote(p) for p in self._splitquoted.split(text) if p.strip()] - - def parse_command(self, cmd): - ''' Parse event givent by the Uzbl instance ''' - - cmd = self.parse_event(cmd) - message, message_type, args = cmd[0], cmd[2], cmd[3:] - - if message == "EVENT": - self.dispatcher.dispatch(message_type, args) - - def close(self): - '''The remote instance exited''' - - if self._client: - self._client.close() - self._client = None - - -class UzblTabbed: - '''A tabbed version of uzbl using gtk.Notebook''' - - def __init__(self): - '''Create tablist, window and notebook.''' - - self._timers = {} - self._buffer = "" - self._killed = False - - # A list of the recently closed tabs - self._closed = [] - - # Holds metadata on the uzbl childen open. - self.tabs = {} - - # Uzbl sockets (socket => SocketClient) - self.clients = {} - - # Generates a unique id for uzbl socket filenames. - self.next_pid = counter().next - - # Create main window - self.window = gtk.Window() - try: - window_size = map(int, config['window_size'].split(',')) - self.window.set_default_size(*window_size) - - except: - print_exc() - error("Invalid value for default_size in config file.") - - self.window.set_title("Uzbl Browser") - self.window.set_border_width(0) - - # this prevents the window from expanding if the contents of the - # statusbar are wider than the window. - # i suspect this is not the right way to do this. - self.window.set_geometry_hints(min_width=1) - - # Set main window icon - icon_path = config['icon_path'] - if os.path.exists(icon_path): - self.window.set_icon(gtk.gdk.pixbuf_new_from_file(icon_path)) - - else: - icon_path = '/usr/share/uzbl/examples/data/uzbl.png' - if os.path.exists(icon_path): - self.window.set_icon(gtk.gdk.pixbuf_new_from_file(icon_path)) - - # Attach main window event handlers - self.window.connect("delete-event", self.quitrequest) - - # Create tab list - vbox = gtk.VBox() - self.vbox = vbox - self.window.add(vbox) - ebox = gtk.EventBox() - self.ebox = ebox - self.tablist = gtk.Label() - - self.tablist.set_use_markup(True) - self.tablist.set_justify(gtk.JUSTIFY_LEFT) - self.tablist.set_line_wrap(False) - self.tablist.set_selectable(False) - self.tablist.set_padding(2,2) - self.tablist.set_alignment(0,0) - self.tablist.set_ellipsize(pango.ELLIPSIZE_END) - self.tablist.set_text(" ") - self.tablist.show() - ebox.add(self.tablist) - ebox.show() - bgcolor = gtk.gdk.color_parse(config['status_background']) - ebox.modify_bg(gtk.STATE_NORMAL, bgcolor) - - # Create notebook - self.notebook = gtk.Notebook() - self.notebook.set_show_tabs(config['show_gtk_tabs']) - - # Set tab position - self.update_gtk_tab_pos() - - self.notebook.set_show_border(False) - self.notebook.set_scrollable(True) - self.notebook.set_border_width(0) - - self.notebook.connect("page-removed", self.tab_closed) - self.notebook.connect("switch-page", self.tab_changed) - self.notebook.connect("page-added", self.tab_opened) - self.notebook.connect("page-reordered", self.tab_reordered) - - self.notebook.show() - vbox.pack_start(self.notebook, True, True, 0) - vbox.reorder_child(self.notebook, 1) - self.update_tablist_display() - - self.vbox.show() - self.window.show() - self.wid = self.notebook.window.xid - - # Store information about the applications fifo and socket. - fifo_filename = 'uzbltabbed_%d.fifo' % os.getpid() - socket_filename = 'uzbltabbed_%d.socket' % os.getpid() - self._fifo = None - self._socket = None - self.fifo_path = os.path.join(config['fifo_dir'], fifo_filename) - self.socket_path = os.path.join(config['socket_dir'], socket_filename) - - # Now initialise the fifo and the socket - self.init_fifo() - self.init_socket() - - # If we are using sessions then load the last one if it exists. - if config['save_session']: - self.load_session() - - - def run(self): - '''UzblTabbed main function that calls the gtk loop.''' - - if not self.clients and not SocketClient.instances_queue and not self.tabs: - self.new_tab() - - gtk_refresh = int(config['gtk_refresh']) - if gtk_refresh < 100: - gtk_refresh = 100 - - # Make SIGTERM act orderly. - signal(SIGTERM, lambda signum, stack_frame: self.terminate(SIGTERM)) - - # Catch keyboard interrupts - signal(SIGINT, lambda signum, stack_frame: self.terminate(SIGINT)) - - try: - gtk.main() - - except: - print_exc() - error("encounted error %r" % sys.exc_info()[1]) - - # Unlink fifo socket - self.unlink_fifo() - self.close_socket() - - # Attempt to close all uzbl instances nicely. - self.quitrequest() - - # Allow time for all the uzbl instances to quit. - time.sleep(1) - - raise - - def terminate(self, termsig=None): - '''Handle termination signals and exit safely and cleanly.''' - - # Not required but at least it lets the user know what killed his - # browsing session. - if termsig == SIGTERM: - error("caught SIGTERM signal") - - elif termsig == SIGINT: - error("caught keyboard interrupt") - - else: - error("caught unknown signal") - - error("commencing infanticide!") - - # Sends the exit signal to all uzbl instances. - self.quitrequest() - - - def init_socket(self): - '''Create interprocess communication socket.''' - - def accept(sock, condition): - '''A new uzbl instance was created''' - - client, _ = sock.accept() - self.clients[client] = SocketClient(client) - - return True - - sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM) - sock.bind(self.socket_path) - sock.listen(1) - - # Add event handler for IO_IN event. - self._socket = (sock, io_add_watch(sock, IO_IN, accept)) - - echo("[socket] listening at %r" % self.socket_path) - - # Add atexit register to destroy the socket on program termination. - atexit.register(self.close_socket) - - - def close_socket(self): - '''Close the socket when closing the application''' - - if self._socket: - (fd, watcher) = self._socket - source_remove(watcher) - fd.close() - os.unlink(self.socket_path) - self._socket = None - - - def init_fifo(self): - '''Create interprocess communication fifo.''' - - if os.path.exists(self.fifo_path): - if not os.access(self.fifo_path, os.F_OK | os.R_OK | os.W_OK): - os.mkfifo(self.fifo_path) - - else: - basedir = os.path.dirname(self.fifo_path) - if not os.path.exists(basedir): - os.makedirs(basedir) - - os.mkfifo(self.fifo_path) - - # Add event handlers for IO_IN & IO_HUP events. - self.setup_fifo_watchers() - - echo("[fifo] listening at %r" % self.fifo_path) - - # Add atexit register to destroy the fifo on program termination. - atexit.register(self.unlink_fifo) - - - def unlink_fifo(self): - '''Unlink the fifo socket. Note: This function is called automatically - on exit by an atexit register.''' - - # Make sure the fifo fd is closed. - self.close_fifo() - - # And unlink if the real fifo exists. - if os.path.exists(self.fifo_path): - os.unlink(self.fifo_path) - echo("unlinked %r" % self.fifo_path) - - - def close_fifo(self): - '''Remove all event handlers watching the fifo and close the fd.''' - - # Already closed - if self._fifo is None: return - - (fd, watchers) = self._fifo - os.close(fd) - - # Stop all gobject io watchers watching the fifo. - for gid in watchers: - source_remove(gid) - - self._fifo = None - - - def setup_fifo_watchers(self): - '''Open fifo socket fd and setup gobject IO_IN & IO_HUP event - handlers.''' - - # Close currently open fifo fd and kill all watchers - self.close_fifo() - - fd = os.open(self.fifo_path, os.O_RDONLY | os.O_NONBLOCK) - - # Add gobject io event handlers to the fifo socket. - watchers = [io_add_watch(fd, IO_IN, self.main_fifo_read),\ - io_add_watch(fd, IO_HUP, self.main_fifo_hangup)] - - self._fifo = (fd, watchers) - - - def main_fifo_hangup(self, fd, cb_condition): - '''Handle main fifo socket hangups.''' - - # Close old fd, open new fifo socket and add io event handlers. - self.setup_fifo_watchers() - - # Kill the gobject event handler calling this handler function. - return False - - - def main_fifo_read(self, fd, cb_condition): - '''Read from main fifo socket.''' - - self._buffer = os.read(fd, 1024) - temp = self._buffer.split("\n") - self._buffer = temp.pop() - cmds = [s.strip().split() for s in temp if len(s.strip())] - - for cmd in cmds: - try: - #print cmd - self.parse_command(cmd) - - except: - print_exc() - error("parse_command: invalid command %s" % ' '.join(cmd)) - raise - - return True - - - def parse_command(self, cmd): - '''Parse instructions from uzbl child processes.''' - - # Commands ( [] = optional, {} = required ) - # new [uri] - # open new tab and head to optional uri. - # newbg [uri] - # open a new tab in the background - # close [tab-num] - # close current tab or close via tab id. - # next [n-tabs] - # open next tab or n tabs down. Supports negative indexing. - # prev [n-tabs] - # open prev tab or n tabs down. Supports negative indexing. - # goto {tab-n} - # goto tab n. - # first - # goto first tab. - # last - # goto last tab. - # title {pid} {document-title} - # updates tablist title. - # uri {pid} {document-location} - # updates tablist uri - # bring_to_front - # brings the gtk window to focus. - # exit - # exits uzbl_tabbed.py - - if cmd[0] == "new": - if len(cmd) == 2: - self.new_tab(cmd[1]) - - else: - self.new_tab() - - elif cmd[0] == "newbg": - if len(cmd) == 2: - self.new_tab(cmd[1], switch=False) - else: - self.new_tab(switch=False) - - elif cmd[0] == "newfromclip": - uri = subprocess.Popen(['xclip','-selection','clipboard','-o'],\ - stdout=subprocess.PIPE).communicate()[0] - if uri: - self.new_tab(uri) - - elif cmd[0] == "close": - if len(cmd) == 2: - self.close_tab(int(cmd[1])) - - else: - self.close_tab() - - elif cmd[0] == "next": - if len(cmd) == 2: - self.next_tab(int(cmd[1])) - - else: - self.next_tab() - - elif cmd[0] == "prev": - if len(cmd) == 2: - self.prev_tab(int(cmd[1])) - - else: - self.prev_tab() - - elif cmd[0] == "goto": - self.goto_tab(int(cmd[1])) - - elif cmd[0] == "first": - self.goto_tab(0) - - elif cmd[0] == "last": - self.goto_tab(-1) - - elif cmd[0] in ["title", "uri"]: - if len(cmd) > 2: - uzbl = self.get_tab_by_name(int(cmd[1])) - if uzbl: - old = getattr(uzbl, cmd[0]) - new = ' '.join(cmd[2:]) - setattr(uzbl, cmd[0], new) - if old != new: - self.update_tablist() - - else: - error("parse_command: no uzbl with name %r" % int(cmd[1])) - - elif cmd[0] == "preset": - if len(cmd) < 3: - error("parse_command: invalid preset command") - - elif cmd[1] == "save": - path = os.path.join(config['saved_sessions_dir'], cmd[2]) - self.save_session(path) - - elif cmd[1] == "load": - path = os.path.join(config['saved_sessions_dir'], cmd[2]) - self.load_session(path) - - elif cmd[1] == "del": - path = os.path.join(config['saved_sessions_dir'], cmd[2]) - if os.path.isfile(path): - os.remove(path) - - else: - error("parse_command: preset %r does not exist." % path) - - elif cmd[1] == "list": - # FIXME: what argument is this supposed to be passed, - # and why? - uzbl = self.get_tab_by_name(int(cmd[2])) - if uzbl: - if not os.path.isdir(config['saved_sessions_dir']): - js = "js alert('No saved presets.');" - uzbl._client.send(js) - - else: - listdir = os.listdir(config['saved_sessions_dir']) - listdir = "\\n".join(listdir) - js = "js alert('Session presets:\\n\\n%s');" % listdir - uzbl._client.send(js) - - else: - error("parse_command: unknown tab name.") - - else: - error("parse_command: unknown parse command %r"\ - % ' '.join(cmd)) - - elif cmd[0] == "bring_to_front": - self.window.present() - - elif cmd[0] == "clean": - self.clean_slate() - - elif cmd[0] == "exit": - self.quitrequest() - - else: - error("parse_command: unknown command %r" % ' '.join(cmd)) - - - def get_tab_by_name(self, name): - '''Return uzbl instance by name.''' - - for (tab, uzbl) in self.tabs.items(): - if uzbl.name == name: - return uzbl - - return False - - - def new_tab(self, uri='', title='', switch=None, next=False): - '''Add a new tab to the notebook and start a new instance of uzbl. - Use the switch option to negate config['switch_to_new_tabs'] option - when you need to load multiple tabs at a time (I.e. like when - restoring a session from a file).''' - - tab = gtk.Socket() - tab.show() - self.notebook.insert_page(tab, position=next and self.notebook.get_current_page() + 1 or -1) - self.notebook.set_tab_reorderable(tab, True) - sid = tab.get_id() - uri = uri.strip() - name = "%d-%d" % (os.getpid(), self.next_pid()) - - if switch is None: - switch = config['switch_to_new_tabs'] - - if not title: - title = config['new_tab_title'] - - cmd = ['uzbl-browser', '-n', name, '-s', str(sid), - '--connect-socket', self.socket_path, '--uri', str(uri)] - gobject.spawn_async(cmd, flags=gobject.SPAWN_SEARCH_PATH) - - uzbl = UzblInstance(self, tab, name, uri, title, switch) - SocketClient.instances_queue[name] = uzbl - self.tabs[tab] = uzbl - - - def clean_slate(self): - '''Close all open tabs and open a fresh brand new one.''' - - self.new_tab() - tabs = self.tabs.keys() - for tab in list(self.notebook)[:-1]: - if tab not in tabs: continue - uzbl = self.tabs[tab] - uzbl.exit() - - - def config_uzbl(self, uzbl): - '''Send bind commands for tab new/close/next/prev to a uzbl - instance.''' - - # Set definitions here - # set(key, command back to fifo) - if config['capture_new_windows']: - uzbl.set("new_window", r'new $8') - - - def goto_tab(self, index): - '''Goto tab n (supports negative indexing).''' - - title_format = "%s - Uzbl Browser" - - tabs = list(self.notebook) - if 0 <= index < len(tabs): - self.notebook.set_current_page(index) - uzbl = self.tabs[self.notebook.get_nth_page(index)] - self.window.set_title(title_format % uzbl.title) - self.update_tablist() - return None - - try: - tab = tabs[index] - # Update index because index might have previously been a - # negative index. - index = tabs.index(tab) - self.notebook.set_current_page(index) - uzbl = self.tabs[self.notebook.get_nth_page(index)] - self.window.set_title(title_format % uzbl.title) - self.update_tablist() - - except IndexError: - pass - - - def next_tab(self, step=1): - '''Switch to next tab or n tabs right.''' - - if step < 1: - error("next_tab: invalid step %r" % step) - return None - - ntabs = self.notebook.get_n_pages() - tabn = (self.notebook.get_current_page() + step) % ntabs - self.goto_tab(tabn) - - - def prev_tab(self, step=1): - '''Switch to prev tab or n tabs left.''' - - if step < 1: - error("prev_tab: invalid step %r" % step) - return None - - ntabs = self.notebook.get_n_pages() - tabn = self.notebook.get_current_page() - step - while tabn < 0: tabn += ntabs - self.goto_tab(tabn) - - - def close_tab(self, tabn=None): - '''Closes current tab. Supports negative indexing.''' - - if tabn is None: - tabn = self.notebook.get_current_page() - - else: - try: - tab = list(self.notebook)[tabn] - - except IndexError: - error("close_tab: invalid index %r" % tabn) - return None - - self.notebook.remove_page(tabn) - - - def tab_opened(self, notebook, tab, index): - '''Called upon tab creation. Called by page-added signal.''' - - if config['switch_to_new_tabs']: - self.notebook.set_focus_child(tab) - - else: - oldindex = self.notebook.get_current_page() - oldtab = self.notebook.get_nth_page(oldindex) - self.notebook.set_focus_child(oldtab) - - - def tab_closed(self, notebook, tab, index): - '''Close the window if no tabs are left. Called by page-removed - signal.''' - - if tab in self.tabs.keys(): - uzbl = self.tabs[tab] - uzbl.close() - - self._closed.append((uzbl.uri, uzbl.title)) - self._closed = self._closed[-10:] - del self.tabs[tab] - - if self.notebook.get_n_pages() == 0: - if not self._killed and config['save_session']: - if os.path.exists(config['session_file']): - os.remove(config['session_file']) - - self.quit() - - for tab in self.notebook: - self.tabs[tab].title_changed(True) - self.update_tablist() - - return True - - - def tab_changed(self, notebook, page, index): - '''Refresh tab list. Called by switch-page signal.''' - - tab = self.notebook.get_nth_page(index) - self.notebook.set_focus_child(tab) - self.update_tablist(index) - return True - - - def tab_reordered(self, notebook, page, index): - '''Refresh tab titles. Called by page-reordered signal.''' - - for tab in self.notebook: - self.tabs[tab].title_changed(True) - return True - - - def update_tablist_display(self): - '''Called when show_tablist or tablist_top has changed''' - - if self.ebox in self.vbox.get_children(): - self.vbox.remove(self.ebox) - - if config['show_tablist']: - self.vbox.pack_start(self.ebox, False, False, 0) - if config['tablist_top']: - self.vbox.reorder_child(self.ebox, 0) - else: - self.vbox.reorder_child(self.ebox, 2) - - def update_gtk_tab_pos(self): - ''' Called when gtk_tab_pos has changed ''' - - allposes = {'left': gtk.POS_LEFT, 'right':gtk.POS_RIGHT, - 'top':gtk.POS_TOP, 'bottom':gtk.POS_BOTTOM} - if config['gtk_tab_pos'] in allposes.keys(): - self.notebook.set_tab_pos(allposes[config['gtk_tab_pos']]) - - - def update_tablist(self, curpage=None): - '''Upate tablist status bar.''' - - if not config['show_tablist']: - return True - - tab_titles = config['tab_titles'] - tab_indexes = config['tab_indexes'] - multiline_tabs = config['multiline_tabs'] - - if multiline_tabs: - multiline = [] - - tabs = self.tabs.keys() - if curpage is None: - curpage = self.notebook.get_current_page() - - pango = "" - normal = (config['tab_colours'], config['tab_text_colours']) - selected = (config['selected_tab'], config['selected_tab_text']) - - if tab_titles and tab_indexes: - tab_format = " [ %(index)d %(title)s ] " - elif tab_titles: - tab_format = " [ %(title)s ] " - else: - tab_format = " [ %(index)d ] " - - for index, tab in enumerate(self.notebook): - if tab not in tabs: continue - uzbl = self.tabs[tab] - title = escape(uzbl.tabtitle) - - style = colour_selector(index, curpage, uzbl) - (tabc, textc) = style - - if multiline_tabs: - opango = pango - - pango += tab_format % locals() - - self.tablist.set_markup(pango) - listwidth = self.tablist.get_layout().get_pixel_size()[0] - winwidth = self.window.get_size()[0] - - if listwidth > (winwidth - 20): - multiline.append(opango) - pango = tab_format % locals() - else: - pango += tab_format % locals() - - if multiline_tabs: - multiline.append(pango) - self.tablist.set_markup(' '.join(multiline)) - - else: - self.tablist.set_markup(pango) - - return True - - - def save_session(self, session_file=None): - '''Save the current session to file for restoration on next load.''' - - if session_file is None: - session_file = config['session_file'] - - tabs = self.tabs.keys() - lines = "curtab = %d\n" % self.notebook.get_current_page() - for tab in list(self.notebook): - if tab not in tabs: - continue - - uzbl = self.tabs[tab] - if not uzbl.uri: - continue - - lines += "%s %s\n" % (uzbl.uri, uzbl.title) - - if not os.path.isfile(session_file): - dirname = os.path.dirname(session_file) - if not os.path.isdir(dirname): - os.makedirs(dirname) - - fh = open(session_file, 'w') - fh.write(lines) - fh.close() - - - def load_session(self, session_file=None): - '''Load a saved session from file.''' - - default_path = False - delete_loaded = False - - if session_file is None: - default_path = True - delete_loaded = True - session_file = config['session_file'] - - if not os.path.isfile(session_file): - return False - - fh = open(session_file, 'r') - raw = fh.read() - fh.close() - - tabs = [] - curtab = 0 - - lines = filter(None, map(str.strip, raw.split('\n'))) - if len(lines) < 2: - error("Error: The session file %r looks invalid." % session_file) - if delete_loaded and os.path.exists(session_file): - os.remove(session_file) - - return None - - try: - for line in lines: - if line.startswith("curtab"): - curtab = int(line.split()[-1]) - - else: - uri, title = map(str.strip, line.split(" ", 1)) - tabs += [(uri, title),] - - except: - print_exc() - error("Warning: failed to load session file %r" % session_file) - return None - - # Now populate notebook with the loaded session. - for (index, (uri, title)) in enumerate(tabs): - self.new_tab(uri=uri, title=title, switch=(curtab==index)) - - # A saved session has been loaded now delete it. - if delete_loaded and os.path.exists(session_file): - os.remove(session_file) - - - def quitrequest(self, *args): - '''Attempt to close all uzbl instances nicely and exit.''' - - self._killed = True - - if config['save_session']: - if len(list(self.notebook)) > 1: - self.save_session() - - else: - # Notebook has one page open so delete the session file. - if os.path.isfile(config['session_file']): - os.remove(config['session_file']) - - for (tab, uzbl) in self.tabs.items(): - uzbl.exit() - - # Add a gobject timer to make sure the application force-quits after a - # reasonable period. Calling quit when all the tabs haven't had time to - # close should be a last resort. - timer = "force-quit" - timerid = timeout_add(5000, self.quit, timer) - self._timers[timer] = timerid - - - def quit(self, *args): - '''Cleanup and quit. Called by delete-event signal.''' - - # Close the fifo socket, remove any gobject io event handlers and - # delete socket. - self.unlink_fifo() - self.close_socket() - - # Remove all gobject timers that are still ticking. - for (timerid, gid) in self._timers.items(): - source_remove(gid) - del self._timers[timerid] - - try: - gtk.main_quit() - - except: - pass - - -if __name__ == "__main__": - - # Build command line parser - usage = "usage: %prog [OPTIONS] {URIS}..." - parser = OptionParser(usage=usage) - parser.add_option('-n', '--no-session', dest='nosession', - action='store_true', help="ignore session saving a loading.") - parser.add_option('-v', '--verbose', dest='verbose', - action='store_true', help='print verbose output.') - parser.add_option('-s', '--socketdir', dest='socketdir', - help="directory to create socket") - parser.add_option('-f', '--fifodir', dest='fifodir', - help="directory to create fifo") - - # Parse command line options - (options, uris) = parser.parse_args() - - if options.nosession: - config['save_session'] = False - - if options.verbose: - config['verbose'] = True - - if config['verbose']: - import pprint - sys.stderr.write("%s\n" % pprint.pformat(config)) - - if options.socketdir: - config['socket_dir'] = options.socketdir - - if options.fifodir: - config['fifo_dir'] = options.fifodir - - uzbl = UzblTabbed() - - # All extra arguments given to uzbl_tabbed.py are interpreted as - # web-locations to opened in new tabs. - lasturi = len(uris)-1 - for (index,uri) in enumerate(uris): - uzbl.new_tab(uri, switch=(index==lasturi)) - - uzbl.run() -- cgit v1.2.3 From 841914c050bc00a39d9313c05856568696e58a23 Mon Sep 17 00:00:00 2001 From: Brendan Taylor Date: Mon, 11 Apr 2011 19:59:51 -0600 Subject: move examples/data/scripts/uzbl-event-manager to bin/uzbl-event-manager --- Makefile | 2 +- bin/uzbl-event-manager | 991 +++++++++++++++++++++++++++++++ examples/data/scripts/uzbl-event-manager | 991 ------------------------------- 3 files changed, 992 insertions(+), 992 deletions(-) create mode 100755 bin/uzbl-event-manager delete mode 100755 examples/data/scripts/uzbl-event-manager diff --git a/Makefile b/Makefile index df87c9e..dad7e61 100644 --- a/Makefile +++ b/Makefile @@ -136,7 +136,7 @@ install-uzbl-core: all install-dirs install-uzbl-browser: install-dirs install -m755 bin/uzbl-browser $(INSTALLDIR)/bin/uzbl-browser - install -m755 examples/data/scripts/uzbl-event-manager $(INSTALLDIR)/bin/uzbl-event-manager + install -m755 bin/uzbl-event-manager $(INSTALLDIR)/bin/uzbl-event-manager mv $(INSTALLDIR)/bin/uzbl-browser $(INSTALLDIR)/bin/uzbl-browser.bak sed 's#^PREFIX=.*#PREFIX=$(RUN_PREFIX)#' < $(INSTALLDIR)/bin/uzbl-browser.bak > $(INSTALLDIR)/bin/uzbl-browser chmod 755 $(INSTALLDIR)/bin/uzbl-browser diff --git a/bin/uzbl-event-manager b/bin/uzbl-event-manager new file mode 100755 index 0000000..cb462c7 --- /dev/null +++ b/bin/uzbl-event-manager @@ -0,0 +1,991 @@ +#!/usr/bin/env python + +# Event Manager for Uzbl +# Copyright (c) 2009-2010, Mason Larobina +# Copyright (c) 2009, Dieter Plaetinck +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +''' + +E V E N T _ M A N A G E R . P Y +=============================== + +Event manager for uzbl written in python. + +''' + +import atexit +import imp +import logging +import os +import socket +import sys +import time +import weakref +import re +from collections import defaultdict +from functools import partial +from glob import glob +from itertools import count +from optparse import OptionParser +from select import select +from signal import signal, SIGTERM, SIGINT +from socket import socket, AF_UNIX, SOCK_STREAM +from traceback import format_exc + +def xdghome(key, default): + '''Attempts to use the environ XDG_*_HOME paths if they exist otherwise + use $HOME and the default path.''' + + xdgkey = "XDG_%s_HOME" % key + if xdgkey in os.environ.keys() and os.environ[xdgkey]: + return os.environ[xdgkey] + + return os.path.join(os.environ['HOME'], default) + +# `make install` will put the correct value here for your system +PREFIX = '/usr/local/' + +# Setup xdg paths. +DATA_DIR = os.path.join(xdghome('DATA', '.local/share/'), 'uzbl/') +CACHE_DIR = os.path.join(xdghome('CACHE', '.cache/'), 'uzbl/') + +# Define some globals. +SCRIPTNAME = os.path.basename(sys.argv[0]) + +def get_exc(): + '''Format `format_exc` for logging.''' + return "\n%s" % format_exc().rstrip() + +def expandpath(path): + '''Expand and realpath paths.''' + return os.path.realpath(os.path.expandvars(path)) + +def ascii(u): + '''Convert unicode strings into ascii for transmission over + ascii-only streams/sockets/devices.''' + return u.encode('utf-8') + + +def daemonize(): + '''Daemonize the process using the Stevens' double-fork magic.''' + + logger.info('entering daemon mode') + + try: + if os.fork(): + os._exit(0) + + except OSError: + logger.critical(get_exc()) + sys.exit(1) + + os.chdir('/') + os.setsid() + os.umask(0) + + try: + if os.fork(): + os._exit(0) + + except OSError: + logger.critical(get_exc()) + sys.exit(1) + + if sys.stdout.isatty(): + sys.stdout.flush() + sys.stderr.flush() + + devnull = '/dev/null' + stdin = file(devnull, 'r') + stdout = file(devnull, 'a+') + stderr = file(devnull, 'a+', 0) + + os.dup2(stdin.fileno(), sys.stdin.fileno()) + os.dup2(stdout.fileno(), sys.stdout.fileno()) + os.dup2(stderr.fileno(), sys.stderr.fileno()) + + logger.info('entered daemon mode') + + +def make_dirs(path): + '''Make all basedirs recursively as required.''' + + try: + dirname = os.path.dirname(path) + if not os.path.isdir(dirname): + logger.debug('creating directories %r' % dirname) + os.makedirs(dirname) + + except OSError: + logger.error(get_exc()) + + +class EventHandler(object): + '''Event handler class. Used to store args and kwargs which are merged + come time to call the callback with the event args and kwargs.''' + + nextid = count().next + + def __init__(self, plugin, event, callback, args, kwargs): + self.id = self.nextid() + self.plugin = plugin + self.event = event + self.callback = callback + self.args = args + self.kwargs = kwargs + + + def __repr__(self): + elems = ['id=%d' % self.id, 'event=%s' % self.event, + 'callback=%r' % self.callback] + + if self.args: + elems.append('args=%s' % repr(self.args)) + + if self.kwargs: + elems.append('kwargs=%s' % repr(self.kwargs)) + + elems.append('plugin=%s' % self.plugin.name) + return u'' % ', '.join(elems) + + + def call(self, uzbl, *args, **kwargs): + '''Execute the handler function and merge argument lists.''' + + args = args + self.args + kwargs = dict(self.kwargs.items() + kwargs.items()) + self.callback(uzbl, *args, **kwargs) + + + + + +class Plugin(object): + '''Plugin module wrapper object.''' + + # Special functions exported from the Plugin instance to the + # plugin namespace. + special_functions = ['require', 'export', 'export_dict', 'connect', + 'connect_dict', 'logger', 'unquote', 'splitquoted'] + + + def __init__(self, parent, name, path, plugin): + self.parent = parent + self.name = name + self.path = path + self.plugin = plugin + self.logger = get_logger('plugin.%s' % name) + + # Weakrefs to all handlers created by this plugin + self.handlers = set([]) + + # Plugins init hook + init = getattr(plugin, 'init', None) + self.init = init if callable(init) else None + + # Plugins optional after hook + after = getattr(plugin, 'after', None) + self.after = after if callable(after) else None + + # Plugins optional cleanup hook + cleanup = getattr(plugin, 'cleanup', None) + self.cleanup = cleanup if callable(cleanup) else None + + assert init or after or cleanup, "missing hooks in plugin" + + # Export plugin's instance methods to plugin namespace + for attr in self.special_functions: + plugin.__dict__[attr] = getattr(self, attr) + + + def __repr__(self): + return u'' % self.plugin + + + def export(self, uzbl, attr, object, prepend=True): + '''Attach `object` to `uzbl` instance. This is the preferred method + of sharing functionality, functions, data and objects between + plugins. + + If the object is callable you may wish to turn the callable object + in to a meta-instance-method by prepending `uzbl` to the call stack. + You can change this behaviour with the `prepend` argument. + ''' + + assert attr not in uzbl.exports, "attr %r already exported by %r" %\ + (attr, uzbl.exports[attr][0]) + + prepend = True if prepend and callable(object) else False + uzbl.__dict__[attr] = partial(object, uzbl) if prepend else object + uzbl.exports[attr] = (self, object, prepend) + uzbl.logger.info('exported %r to %r by plugin %r, prepended %r' + % (object, 'uzbl.%s' % attr, self.name, prepend)) + + + def export_dict(self, uzbl, exports): + for (attr, object) in exports.items(): + self.export(uzbl, attr, object) + + + def find_handler(self, event, callback, args, kwargs): + '''Check if a handler with the identical callback and arguments + exists and return it.''' + + # Remove dead refs + self.handlers -= set(filter(lambda ref: not ref(), self.handlers)) + + # Find existing identical handler + for handler in [ref() for ref in self.handlers]: + if handler.event == event and handler.callback == callback \ + and handler.args == args and handler.kwargs == kwargs: + return handler + + + def connect(self, uzbl, event, callback, *args, **kwargs): + '''Create an event handler object which handles `event` events. + + Arguments passed to the connect function (`args` and `kwargs`) are + stored in the handler object and merged with the event arguments + come handler execution. + + All handler functions must behave like a `uzbl` instance-method (that + means `uzbl` is prepended to the callback call arguments).''' + + # Sanitise and check event name + event = event.upper().strip() + assert event and ' ' not in event + + assert callable(callback), 'callback must be callable' + + # Check if an identical handler already exists + handler = self.find_handler(event, callback, args, kwargs) + if not handler: + # Create a new handler + handler = EventHandler(self, event, callback, args, kwargs) + self.handlers.add(weakref.ref(handler)) + self.logger.info('new %r' % handler) + + uzbl.handlers[event].append(handler) + uzbl.logger.info('connected %r' % handler) + return handler + + + def connect_dict(self, uzbl, connects): + for (event, callback) in connects.items(): + self.connect(uzbl, event, callback) + + + def require(self, plugin): + '''Check that plugin with name `plugin` has been loaded. Use this to + ensure that your plugins dependencies have been met.''' + + assert plugin in self.parent.plugins, self.logger.critical( + 'plugin %r required by plugin %r' (plugin, self.name)) + + @classmethod + def unquote(cls, s): + '''Removes quotation marks around strings if any and interprets + \\-escape sequences using `string_escape`''' + if s and s[0] == s[-1] and s[0] in ['"', "'"]: + s = s[1:-1] + return s.encode('utf-8').decode('string_escape').decode('utf-8') + + _splitquoted = re.compile("( |\"(?:\\\\.|[^\"])*?\"|'(?:\\\\.|[^'])*?')") + @classmethod + def splitquoted(cls, text): + '''Splits string on whitespace while respecting quotations''' + return [cls.unquote(p) for p in cls._splitquoted.split(text) if p.strip()] + + +class Uzbl(object): + def __init__(self, parent, child_socket): + self.opts = opts + self.parent = parent + self.child_socket = child_socket + self.time = time.time() + self.pid = None + self.name = None + + # Flag if the instance has raised the INSTANCE_START event. + self.instance_start = False + + # Use name "unknown" until name is discovered. + self.logger = get_logger('uzbl-instance[]') + + # Track plugin event handlers and exported functions. + self.exports = {} + self.handlers = defaultdict(list) + + # Internal vars + self._depth = 0 + self._buffer = '' + + + def __repr__(self): + return '' % ', '.join([ + 'pid=%s' % (self.pid if self.pid else "Unknown"), + 'name=%s' % ('%r' % self.name if self.name else "Unknown"), + 'uptime=%f' % (time.time()-self.time), + '%d exports' % len(self.exports.keys()), + '%d handlers' % sum([len(l) for l in self.handlers.values()])]) + + + def init_plugins(self): + '''Call the init and after hooks in all loaded plugins for this + instance.''' + + # Initialise each plugin with the current uzbl instance. + for plugin in self.parent.plugins.values(): + if plugin.init: + self.logger.debug('calling %r plugin init hook' % plugin.name) + plugin.init(self) + + # Allow plugins to use exported features of other plugins by calling an + # optional `after` function in the plugins namespace. + for plugin in self.parent.plugins.values(): + if plugin.after: + self.logger.debug('calling %r plugin after hook'%plugin.name) + plugin.after(self) + + + def send(self, msg): + '''Send a command to the uzbl instance via the child socket + instance.''' + + msg = msg.strip() + assert self.child_socket, "socket inactive" + + if opts.print_events: + print ascii(u'%s<-- %s' % (' ' * self._depth, msg)) + + self.child_socket.send(ascii("%s\n" % msg)) + + + def read(self): + '''Read data from the child socket and pass lines to the parse_msg + function.''' + + try: + raw = unicode(self.child_socket.recv(8192), 'utf-8', 'ignore') + if not raw: + self.logger.debug('read null byte') + return self.close() + + except: + self.logger.error(get_exc()) + return self.close() + + lines = (self._buffer + raw).split('\n') + self._buffer = lines.pop() + + for line in filter(None, map(unicode.strip, lines)): + try: + self.parse_msg(line.strip()) + + except: + self.logger.error(get_exc()) + self.logger.error('erroneous event: %r' % line) + + + def parse_msg(self, line): + '''Parse an incoming message from a uzbl instance. Event strings + will be parsed into `self.event(event, args)`.''' + + # Split by spaces (and fill missing with nulls) + elems = (line.split(' ', 3) + ['',]*3)[:4] + + # Ignore non-event messages. + if elems[0] != 'EVENT': + logger.info('non-event message: %r' % line) + if opts.print_events: + print '--- %s' % ascii(line) + return + + # Check event string elements + (name, event, args) = elems[1:] + assert name and event, 'event string missing elements' + if not self.name: + self.name = name + self.logger = get_logger('uzbl-instance%s' % name) + self.logger.info('found instance name %r' % name) + + assert self.name == name, 'instance name mismatch' + + # Handle the event with the event handlers through the event method + self.event(event, args) + + + def event(self, event, *args, **kargs): + '''Raise an event.''' + + event = event.upper() + + if not opts.daemon_mode and opts.print_events: + elems = [event,] + if args: elems.append(unicode(args)) + if kargs: elems.append(unicode(kargs)) + print ascii(u'%s--> %s' % (' ' * self._depth, ' '.join(elems))) + + if event == "INSTANCE_START" and args: + assert not self.instance_start, 'instance already started' + + self.pid = int(args[0]) + self.logger.info('found instance pid %r' % self.pid) + + self.init_plugins() + + elif event == "INSTANCE_EXIT": + self.logger.info('uzbl instance exit') + self.close() + + if event not in self.handlers: + return + + for handler in self.handlers[event]: + self._depth += 1 + try: + handler.call(self, *args, **kargs) + + except: + self.logger.error(get_exc()) + + self._depth -= 1 + + + def close_connection(self, child_socket): + '''Close child socket and delete the uzbl instance created for that + child socket connection.''' + + + def close(self): + '''Close the client socket and call the plugin cleanup hooks.''' + + self.logger.debug('called close method') + + # Remove self from parent uzbls dict. + if self.child_socket in self.parent.uzbls: + self.logger.debug('removing self from uzbls list') + del self.parent.uzbls[self.child_socket] + + try: + if self.child_socket: + self.logger.debug('closing child socket') + self.child_socket.close() + + except: + self.logger.error(get_exc()) + + finally: + self.child_socket = None + + # Call plugins cleanup hooks. + for plugin in self.parent.plugins.values(): + if plugin.cleanup: + self.logger.debug('calling %r plugin cleanup hook' + % plugin.name) + plugin.cleanup(self) + + logger.info('removed %r' % self) + + +class UzblEventDaemon(object): + def __init__(self): + self.opts = opts + self.server_socket = None + self._quit = False + + # Hold uzbl instances + # {child socket: Uzbl instance, ..} + self.uzbls = {} + + # Hold plugins + # {plugin name: Plugin instance, ..} + self.plugins = {} + + # Register that the event daemon server has started by creating the + # pid file. + make_pid_file(opts.pid_file) + + # Register a function to clean up the socket and pid file on exit. + atexit.register(self.quit) + + # Add signal handlers. + for sigint in [SIGTERM, SIGINT]: + signal(sigint, self.quit) + + # Load plugins into self.plugins + self.load_plugins(opts.plugins) + + + def load_plugins(self, plugins): + '''Load event manager plugins.''' + + for path in plugins: + logger.debug('loading plugin %r' % path) + (dir, file) = os.path.split(path) + name = file[:-3] if file.lower().endswith('.py') else file + + info = imp.find_module(name, [dir,]) + module = imp.load_module(name, *info) + + # Check if the plugin has a callable hook. + hooks = filter(callable, [getattr(module, attr, None) \ + for attr in ['init', 'after', 'cleanup']]) + assert hooks, "no hooks in plugin %r" % module + + logger.debug('creating plugin instance for %r plugin' % name) + plugin = Plugin(self, name, path, module) + self.plugins[name] = plugin + logger.info('new %r' % plugin) + + + def create_server_socket(self): + '''Create the event manager daemon socket for uzbl instance duplex + communication.''' + + # Close old socket. + self.close_server_socket() + + sock = socket(AF_UNIX, SOCK_STREAM) + sock.bind(opts.server_socket) + sock.listen(5) + + self.server_socket = sock + logger.debug('bound server socket to %r' % opts.server_socket) + + + def run(self): + '''Main event daemon loop.''' + + logger.debug('entering main loop') + + # Create and listen on the server socket + self.create_server_socket() + + if opts.daemon_mode: + # Daemonize the process + daemonize() + + # Update the pid file + make_pid_file(opts.pid_file) + + try: + # Accept incoming connections and listen for incoming data + self.listen() + + except: + if not self._quit: + logger.critical(get_exc()) + + # Clean up and exit + self.quit() + + logger.debug('exiting main loop') + + + def listen(self): + '''Accept incoming connections and constantly poll instance sockets + for incoming data.''' + + logger.info('listening on %r' % opts.server_socket) + + # Count accepted connections + connections = 0 + + while (self.uzbls or not connections) or (not opts.auto_close): + socks = [self.server_socket] + self.uzbls.keys() + reads, _, errors = select(socks, [], socks, 1) + + if self.server_socket in reads: + reads.remove(self.server_socket) + + # Accept connection and create uzbl instance. + child_socket = self.server_socket.accept()[0] + self.uzbls[child_socket] = Uzbl(self, child_socket) + connections += 1 + + for uzbl in [self.uzbls[s] for s in reads]: + uzbl.read() + + for uzbl in [self.uzbls[s] for s in errors]: + uzbl.logger.error('socket read error') + uzbl.close() + + logger.info('auto closing') + + + def close_server_socket(self): + '''Close and delete the server socket.''' + + try: + if self.server_socket: + logger.debug('closing server socket') + self.server_socket.close() + self.server_socket = None + + if os.path.exists(opts.server_socket): + logger.info('unlinking %r' % opts.server_socket) + os.unlink(opts.server_socket) + + except: + logger.error(get_exc()) + + + def quit(self, sigint=None, *args): + '''Close all instance socket objects, server socket and delete the + pid file.''' + + if sigint == SIGTERM: + logger.critical('caught SIGTERM, exiting') + + elif sigint == SIGINT: + logger.critical('caught SIGINT, exiting') + + elif not self._quit: + logger.debug('shutting down event manager') + + self.close_server_socket() + + for uzbl in self.uzbls.values(): + uzbl.close() + + del_pid_file(opts.pid_file) + + if not self._quit: + logger.info('event manager shut down') + self._quit = True + + +def make_pid_file(pid_file): + '''Creates a pid file at `pid_file`, fails silently.''' + + try: + logger.debug('creating pid file %r' % pid_file) + make_dirs(pid_file) + pid = os.getpid() + fileobj = open(pid_file, 'w') + fileobj.write('%d' % pid) + fileobj.close() + logger.info('created pid file %r with pid %d' % (pid_file, pid)) + + except: + logger.error(get_exc()) + + +def del_pid_file(pid_file): + '''Deletes a pid file at `pid_file`, fails silently.''' + + if os.path.isfile(pid_file): + try: + logger.debug('deleting pid file %r' % pid_file) + os.remove(pid_file) + logger.info('deleted pid file %r' % pid_file) + + except: + logger.error(get_exc()) + + +def get_pid(pid_file): + '''Reads a pid from pid file `pid_file`, fails None.''' + + try: + logger.debug('reading pid file %r' % pid_file) + fileobj = open(pid_file, 'r') + pid = int(fileobj.read()) + fileobj.close() + logger.info('read pid %d from pid file %r' % (pid, pid_file)) + return pid + + except (IOError, ValueError): + logger.error(get_exc()) + return None + + +def pid_running(pid): + '''Checks if a process with a pid `pid` is running.''' + + try: + os.kill(pid, 0) + except OSError: + return False + else: + return True + + +def term_process(pid): + '''Asks nicely then forces process with pid `pid` to exit.''' + + try: + logger.info('sending SIGTERM to process with pid %r' % pid) + os.kill(pid, SIGTERM) + + except OSError: + logger.error(get_exc()) + + logger.debug('waiting for process with pid %r to exit' % pid) + start = time.time() + while True: + if not pid_running(pid): + logger.debug('process with pid %d exit' % pid) + return True + + if (time.time()-start) > 5: + logger.warning('process with pid %d failed to exit' % pid) + logger.info('sending SIGKILL to process with pid %d' % pid) + try: + os.kill(pid, SIGKILL) + except: + logger.critical(get_exc()) + raise + + if (time.time()-start) > 10: + logger.critical('unable to kill process with pid %d' % pid) + raise OSError + + time.sleep(0.25) + + +def stop_action(): + '''Stop the event manager daemon.''' + + pid_file = opts.pid_file + if not os.path.isfile(pid_file): + logger.error('could not find running event manager with pid file %r' + % opts.pid_file) + return + + pid = get_pid(pid_file) + if not pid_running(pid): + logger.debug('no process with pid %r' % pid) + del_pid_file(pid_file) + return + + logger.debug('terminating process with pid %r' % pid) + term_process(pid) + del_pid_file(pid_file) + logger.info('stopped event manager process with pid %d' % pid) + + +def start_action(): + '''Start the event manager daemon.''' + + pid_file = opts.pid_file + if os.path.isfile(pid_file): + pid = get_pid(pid_file) + if pid_running(pid): + logger.error('event manager already started with pid %d' % pid) + return + + logger.info('no process with pid %d' % pid) + del_pid_file(pid_file) + + UzblEventDaemon().run() + + +def restart_action(): + '''Restart the event manager daemon.''' + + stop_action() + start_action() + + +def list_action(): + '''List all the plugins that would be loaded in the current search + dirs.''' + + names = {} + for plugin in opts.plugins: + (head, tail) = os.path.split(plugin) + if tail not in names: + names[tail] = plugin + + for plugin in sorted(names.values()): + print plugin + + +if __name__ == "__main__": + parser = OptionParser('usage: %prog [options] {start|stop|restart|list}') + add = parser.add_option + + add('-v', '--verbose', + dest='verbose', default=2, action='count', + help='increase verbosity') + + add('-d', '--plugin-dir', + dest='plugin_dirs', action='append', metavar="DIR", default=[], + help='add extra plugin search dir, same as `-l "DIR/*.py"`') + + add('-l', '--load-plugin', + dest='load_plugins', action='append', metavar="PLUGIN", default=[], + help='load plugin, loads before plugins in search dirs') + + socket_location = os.path.join(CACHE_DIR, 'event_daemon') + add('-s', '--server-socket', + dest='server_socket', metavar="SOCKET", default=socket_location, + help='server AF_UNIX socket location') + + add('-p', '--pid-file', + metavar="FILE", dest='pid_file', + help='pid file location, defaults to server socket + .pid') + + add('-n', '--no-daemon', + dest='daemon_mode', action='store_false', default=True, + help='do not daemonize the process') + + add('-a', '--auto-close', + dest='auto_close', action='store_true', default=False, + help='auto close after all instances disconnect') + + add('-i', '--no-default-dirs', + dest='default_dirs', action='store_false', default=True, + help='ignore the default plugin search dirs') + + add('-o', '--log-file', + dest='log_file', metavar='FILE', + help='write logging output to a file, defaults to server socket +' + ' .log') + + add('-q', '--quiet-events', + dest='print_events', action="store_false", default=True, + help="silence the printing of events to stdout") + + (opts, args) = parser.parse_args() + + opts.server_socket = expandpath(opts.server_socket) + + # Set default pid file location + if not opts.pid_file: + opts.pid_file = "%s.pid" % opts.server_socket + + else: + opts.pid_file = expandpath(opts.pid_file) + + # Set default log file location + if not opts.log_file: + opts.log_file = "%s.log" % opts.server_socket + + else: + opts.log_file = expandpath(opts.log_file) + + # Logging setup + log_level = logging.CRITICAL - opts.verbose*10 + + # Console logging handler + ch = logging.StreamHandler() + ch.setLevel(max(log_level+10, 10)) + ch.setFormatter(logging.Formatter( + '%(name)s: %(levelname)s: %(message)s')) + + # File logging handler + fh = logging.FileHandler(opts.log_file, 'w', 'utf-8', 1) + fh.setLevel(max(log_level, 10)) + fh.setFormatter(logging.Formatter( + '[%(created)f] %(name)s: %(levelname)s: %(message)s')) + + # logging.getLogger wrapper which sets the levels and adds the + # file and console handlers automagically + def get_logger(name): + handlers = [ch, fh] + level = [max(log_level, 10),] + logger = logging.getLogger(name) + logger.setLevel(level[0]) + for handler in handlers: + logger.addHandler(handler) + + return logger + + # Get main logger + logger = get_logger(SCRIPTNAME) + logger.info('logging to %r' % opts.log_file) + + plugins = {} + + # Load all `opts.load_plugins` into the plugins list + for path in opts.load_plugins: + path = expandpath(path) + matches = glob(path) + if not matches: + parser.error('cannot find plugin(s): %r' % path) + + for plugin in matches: + (head, tail) = os.path.split(plugin) + if tail not in plugins: + logger.debug('found plugin: %r' % plugin) + plugins[tail] = plugin + + else: + logger.debug('ignoring plugin: %r' % plugin) + + # Add default plugin locations + if opts.default_dirs: + logger.debug('adding default plugin dirs to plugin dirs list') + opts.plugin_dirs += [os.path.join(DATA_DIR, 'plugins/'), + os.path.join(PREFIX, 'share/uzbl/examples/data/plugins/')] + + else: + logger.debug('ignoring default plugin dirs') + + # Load all plugins in `opts.plugin_dirs` into the plugins list + for dir in opts.plugin_dirs: + dir = expandpath(dir) + logger.debug('searching plugin dir: %r' % dir) + for plugin in glob(os.path.join(dir, '*.py')): + (head, tail) = os.path.split(plugin) + if tail not in plugins: + logger.debug('found plugin: %r' % plugin) + plugins[tail] = plugin + + else: + logger.debug('ignoring plugin: %r' % plugin) + + plugins = plugins.values() + + # Check all the paths in the plugins list are files + for plugin in plugins: + if not os.path.isfile(plugin): + parser.error('plugin not a file: %r' % plugin) + + if opts.auto_close: logger.debug('will auto close') + else: logger.debug('will not auto close') + + if opts.daemon_mode: logger.debug('will daemonize') + else: logger.debug('will not daemonize') + + opts.plugins = plugins + + # init like {start|stop|..} daemon actions + daemon_actions = {'start': start_action, 'stop': stop_action, + 'restart': restart_action, 'list': list_action} + + if len(args) == 1: + action = args[0] + if action not in daemon_actions: + parser.error('invalid action: %r' % action) + + elif not args: + logger.warning('no daemon action given, assuming %r' % 'start') + action = 'start' + + else: + parser.error('invalid action argument: %r' % args) + + logger.info('daemon action %r' % action) + # Do action + daemon_actions[action]() + + logger.debug('process CPU time: %f' % time.clock()) + +# vi: set et ts=4: diff --git a/examples/data/scripts/uzbl-event-manager b/examples/data/scripts/uzbl-event-manager deleted file mode 100755 index cb462c7..0000000 --- a/examples/data/scripts/uzbl-event-manager +++ /dev/null @@ -1,991 +0,0 @@ -#!/usr/bin/env python - -# Event Manager for Uzbl -# Copyright (c) 2009-2010, Mason Larobina -# Copyright (c) 2009, Dieter Plaetinck -# -# This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program. If not, see . - -''' - -E V E N T _ M A N A G E R . P Y -=============================== - -Event manager for uzbl written in python. - -''' - -import atexit -import imp -import logging -import os -import socket -import sys -import time -import weakref -import re -from collections import defaultdict -from functools import partial -from glob import glob -from itertools import count -from optparse import OptionParser -from select import select -from signal import signal, SIGTERM, SIGINT -from socket import socket, AF_UNIX, SOCK_STREAM -from traceback import format_exc - -def xdghome(key, default): - '''Attempts to use the environ XDG_*_HOME paths if they exist otherwise - use $HOME and the default path.''' - - xdgkey = "XDG_%s_HOME" % key - if xdgkey in os.environ.keys() and os.environ[xdgkey]: - return os.environ[xdgkey] - - return os.path.join(os.environ['HOME'], default) - -# `make install` will put the correct value here for your system -PREFIX = '/usr/local/' - -# Setup xdg paths. -DATA_DIR = os.path.join(xdghome('DATA', '.local/share/'), 'uzbl/') -CACHE_DIR = os.path.join(xdghome('CACHE', '.cache/'), 'uzbl/') - -# Define some globals. -SCRIPTNAME = os.path.basename(sys.argv[0]) - -def get_exc(): - '''Format `format_exc` for logging.''' - return "\n%s" % format_exc().rstrip() - -def expandpath(path): - '''Expand and realpath paths.''' - return os.path.realpath(os.path.expandvars(path)) - -def ascii(u): - '''Convert unicode strings into ascii for transmission over - ascii-only streams/sockets/devices.''' - return u.encode('utf-8') - - -def daemonize(): - '''Daemonize the process using the Stevens' double-fork magic.''' - - logger.info('entering daemon mode') - - try: - if os.fork(): - os._exit(0) - - except OSError: - logger.critical(get_exc()) - sys.exit(1) - - os.chdir('/') - os.setsid() - os.umask(0) - - try: - if os.fork(): - os._exit(0) - - except OSError: - logger.critical(get_exc()) - sys.exit(1) - - if sys.stdout.isatty(): - sys.stdout.flush() - sys.stderr.flush() - - devnull = '/dev/null' - stdin = file(devnull, 'r') - stdout = file(devnull, 'a+') - stderr = file(devnull, 'a+', 0) - - os.dup2(stdin.fileno(), sys.stdin.fileno()) - os.dup2(stdout.fileno(), sys.stdout.fileno()) - os.dup2(stderr.fileno(), sys.stderr.fileno()) - - logger.info('entered daemon mode') - - -def make_dirs(path): - '''Make all basedirs recursively as required.''' - - try: - dirname = os.path.dirname(path) - if not os.path.isdir(dirname): - logger.debug('creating directories %r' % dirname) - os.makedirs(dirname) - - except OSError: - logger.error(get_exc()) - - -class EventHandler(object): - '''Event handler class. Used to store args and kwargs which are merged - come time to call the callback with the event args and kwargs.''' - - nextid = count().next - - def __init__(self, plugin, event, callback, args, kwargs): - self.id = self.nextid() - self.plugin = plugin - self.event = event - self.callback = callback - self.args = args - self.kwargs = kwargs - - - def __repr__(self): - elems = ['id=%d' % self.id, 'event=%s' % self.event, - 'callback=%r' % self.callback] - - if self.args: - elems.append('args=%s' % repr(self.args)) - - if self.kwargs: - elems.append('kwargs=%s' % repr(self.kwargs)) - - elems.append('plugin=%s' % self.plugin.name) - return u'' % ', '.join(elems) - - - def call(self, uzbl, *args, **kwargs): - '''Execute the handler function and merge argument lists.''' - - args = args + self.args - kwargs = dict(self.kwargs.items() + kwargs.items()) - self.callback(uzbl, *args, **kwargs) - - - - - -class Plugin(object): - '''Plugin module wrapper object.''' - - # Special functions exported from the Plugin instance to the - # plugin namespace. - special_functions = ['require', 'export', 'export_dict', 'connect', - 'connect_dict', 'logger', 'unquote', 'splitquoted'] - - - def __init__(self, parent, name, path, plugin): - self.parent = parent - self.name = name - self.path = path - self.plugin = plugin - self.logger = get_logger('plugin.%s' % name) - - # Weakrefs to all handlers created by this plugin - self.handlers = set([]) - - # Plugins init hook - init = getattr(plugin, 'init', None) - self.init = init if callable(init) else None - - # Plugins optional after hook - after = getattr(plugin, 'after', None) - self.after = after if callable(after) else None - - # Plugins optional cleanup hook - cleanup = getattr(plugin, 'cleanup', None) - self.cleanup = cleanup if callable(cleanup) else None - - assert init or after or cleanup, "missing hooks in plugin" - - # Export plugin's instance methods to plugin namespace - for attr in self.special_functions: - plugin.__dict__[attr] = getattr(self, attr) - - - def __repr__(self): - return u'' % self.plugin - - - def export(self, uzbl, attr, object, prepend=True): - '''Attach `object` to `uzbl` instance. This is the preferred method - of sharing functionality, functions, data and objects between - plugins. - - If the object is callable you may wish to turn the callable object - in to a meta-instance-method by prepending `uzbl` to the call stack. - You can change this behaviour with the `prepend` argument. - ''' - - assert attr not in uzbl.exports, "attr %r already exported by %r" %\ - (attr, uzbl.exports[attr][0]) - - prepend = True if prepend and callable(object) else False - uzbl.__dict__[attr] = partial(object, uzbl) if prepend else object - uzbl.exports[attr] = (self, object, prepend) - uzbl.logger.info('exported %r to %r by plugin %r, prepended %r' - % (object, 'uzbl.%s' % attr, self.name, prepend)) - - - def export_dict(self, uzbl, exports): - for (attr, object) in exports.items(): - self.export(uzbl, attr, object) - - - def find_handler(self, event, callback, args, kwargs): - '''Check if a handler with the identical callback and arguments - exists and return it.''' - - # Remove dead refs - self.handlers -= set(filter(lambda ref: not ref(), self.handlers)) - - # Find existing identical handler - for handler in [ref() for ref in self.handlers]: - if handler.event == event and handler.callback == callback \ - and handler.args == args and handler.kwargs == kwargs: - return handler - - - def connect(self, uzbl, event, callback, *args, **kwargs): - '''Create an event handler object which handles `event` events. - - Arguments passed to the connect function (`args` and `kwargs`) are - stored in the handler object and merged with the event arguments - come handler execution. - - All handler functions must behave like a `uzbl` instance-method (that - means `uzbl` is prepended to the callback call arguments).''' - - # Sanitise and check event name - event = event.upper().strip() - assert event and ' ' not in event - - assert callable(callback), 'callback must be callable' - - # Check if an identical handler already exists - handler = self.find_handler(event, callback, args, kwargs) - if not handler: - # Create a new handler - handler = EventHandler(self, event, callback, args, kwargs) - self.handlers.add(weakref.ref(handler)) - self.logger.info('new %r' % handler) - - uzbl.handlers[event].append(handler) - uzbl.logger.info('connected %r' % handler) - return handler - - - def connect_dict(self, uzbl, connects): - for (event, callback) in connects.items(): - self.connect(uzbl, event, callback) - - - def require(self, plugin): - '''Check that plugin with name `plugin` has been loaded. Use this to - ensure that your plugins dependencies have been met.''' - - assert plugin in self.parent.plugins, self.logger.critical( - 'plugin %r required by plugin %r' (plugin, self.name)) - - @classmethod - def unquote(cls, s): - '''Removes quotation marks around strings if any and interprets - \\-escape sequences using `string_escape`''' - if s and s[0] == s[-1] and s[0] in ['"', "'"]: - s = s[1:-1] - return s.encode('utf-8').decode('string_escape').decode('utf-8') - - _splitquoted = re.compile("( |\"(?:\\\\.|[^\"])*?\"|'(?:\\\\.|[^'])*?')") - @classmethod - def splitquoted(cls, text): - '''Splits string on whitespace while respecting quotations''' - return [cls.unquote(p) for p in cls._splitquoted.split(text) if p.strip()] - - -class Uzbl(object): - def __init__(self, parent, child_socket): - self.opts = opts - self.parent = parent - self.child_socket = child_socket - self.time = time.time() - self.pid = None - self.name = None - - # Flag if the instance has raised the INSTANCE_START event. - self.instance_start = False - - # Use name "unknown" until name is discovered. - self.logger = get_logger('uzbl-instance[]') - - # Track plugin event handlers and exported functions. - self.exports = {} - self.handlers = defaultdict(list) - - # Internal vars - self._depth = 0 - self._buffer = '' - - - def __repr__(self): - return '' % ', '.join([ - 'pid=%s' % (self.pid if self.pid else "Unknown"), - 'name=%s' % ('%r' % self.name if self.name else "Unknown"), - 'uptime=%f' % (time.time()-self.time), - '%d exports' % len(self.exports.keys()), - '%d handlers' % sum([len(l) for l in self.handlers.values()])]) - - - def init_plugins(self): - '''Call the init and after hooks in all loaded plugins for this - instance.''' - - # Initialise each plugin with the current uzbl instance. - for plugin in self.parent.plugins.values(): - if plugin.init: - self.logger.debug('calling %r plugin init hook' % plugin.name) - plugin.init(self) - - # Allow plugins to use exported features of other plugins by calling an - # optional `after` function in the plugins namespace. - for plugin in self.parent.plugins.values(): - if plugin.after: - self.logger.debug('calling %r plugin after hook'%plugin.name) - plugin.after(self) - - - def send(self, msg): - '''Send a command to the uzbl instance via the child socket - instance.''' - - msg = msg.strip() - assert self.child_socket, "socket inactive" - - if opts.print_events: - print ascii(u'%s<-- %s' % (' ' * self._depth, msg)) - - self.child_socket.send(ascii("%s\n" % msg)) - - - def read(self): - '''Read data from the child socket and pass lines to the parse_msg - function.''' - - try: - raw = unicode(self.child_socket.recv(8192), 'utf-8', 'ignore') - if not raw: - self.logger.debug('read null byte') - return self.close() - - except: - self.logger.error(get_exc()) - return self.close() - - lines = (self._buffer + raw).split('\n') - self._buffer = lines.pop() - - for line in filter(None, map(unicode.strip, lines)): - try: - self.parse_msg(line.strip()) - - except: - self.logger.error(get_exc()) - self.logger.error('erroneous event: %r' % line) - - - def parse_msg(self, line): - '''Parse an incoming message from a uzbl instance. Event strings - will be parsed into `self.event(event, args)`.''' - - # Split by spaces (and fill missing with nulls) - elems = (line.split(' ', 3) + ['',]*3)[:4] - - # Ignore non-event messages. - if elems[0] != 'EVENT': - logger.info('non-event message: %r' % line) - if opts.print_events: - print '--- %s' % ascii(line) - return - - # Check event string elements - (name, event, args) = elems[1:] - assert name and event, 'event string missing elements' - if not self.name: - self.name = name - self.logger = get_logger('uzbl-instance%s' % name) - self.logger.info('found instance name %r' % name) - - assert self.name == name, 'instance name mismatch' - - # Handle the event with the event handlers through the event method - self.event(event, args) - - - def event(self, event, *args, **kargs): - '''Raise an event.''' - - event = event.upper() - - if not opts.daemon_mode and opts.print_events: - elems = [event,] - if args: elems.append(unicode(args)) - if kargs: elems.append(unicode(kargs)) - print ascii(u'%s--> %s' % (' ' * self._depth, ' '.join(elems))) - - if event == "INSTANCE_START" and args: - assert not self.instance_start, 'instance already started' - - self.pid = int(args[0]) - self.logger.info('found instance pid %r' % self.pid) - - self.init_plugins() - - elif event == "INSTANCE_EXIT": - self.logger.info('uzbl instance exit') - self.close() - - if event not in self.handlers: - return - - for handler in self.handlers[event]: - self._depth += 1 - try: - handler.call(self, *args, **kargs) - - except: - self.logger.error(get_exc()) - - self._depth -= 1 - - - def close_connection(self, child_socket): - '''Close child socket and delete the uzbl instance created for that - child socket connection.''' - - - def close(self): - '''Close the client socket and call the plugin cleanup hooks.''' - - self.logger.debug('called close method') - - # Remove self from parent uzbls dict. - if self.child_socket in self.parent.uzbls: - self.logger.debug('removing self from uzbls list') - del self.parent.uzbls[self.child_socket] - - try: - if self.child_socket: - self.logger.debug('closing child socket') - self.child_socket.close() - - except: - self.logger.error(get_exc()) - - finally: - self.child_socket = None - - # Call plugins cleanup hooks. - for plugin in self.parent.plugins.values(): - if plugin.cleanup: - self.logger.debug('calling %r plugin cleanup hook' - % plugin.name) - plugin.cleanup(self) - - logger.info('removed %r' % self) - - -class UzblEventDaemon(object): - def __init__(self): - self.opts = opts - self.server_socket = None - self._quit = False - - # Hold uzbl instances - # {child socket: Uzbl instance, ..} - self.uzbls = {} - - # Hold plugins - # {plugin name: Plugin instance, ..} - self.plugins = {} - - # Register that the event daemon server has started by creating the - # pid file. - make_pid_file(opts.pid_file) - - # Register a function to clean up the socket and pid file on exit. - atexit.register(self.quit) - - # Add signal handlers. - for sigint in [SIGTERM, SIGINT]: - signal(sigint, self.quit) - - # Load plugins into self.plugins - self.load_plugins(opts.plugins) - - - def load_plugins(self, plugins): - '''Load event manager plugins.''' - - for path in plugins: - logger.debug('loading plugin %r' % path) - (dir, file) = os.path.split(path) - name = file[:-3] if file.lower().endswith('.py') else file - - info = imp.find_module(name, [dir,]) - module = imp.load_module(name, *info) - - # Check if the plugin has a callable hook. - hooks = filter(callable, [getattr(module, attr, None) \ - for attr in ['init', 'after', 'cleanup']]) - assert hooks, "no hooks in plugin %r" % module - - logger.debug('creating plugin instance for %r plugin' % name) - plugin = Plugin(self, name, path, module) - self.plugins[name] = plugin - logger.info('new %r' % plugin) - - - def create_server_socket(self): - '''Create the event manager daemon socket for uzbl instance duplex - communication.''' - - # Close old socket. - self.close_server_socket() - - sock = socket(AF_UNIX, SOCK_STREAM) - sock.bind(opts.server_socket) - sock.listen(5) - - self.server_socket = sock - logger.debug('bound server socket to %r' % opts.server_socket) - - - def run(self): - '''Main event daemon loop.''' - - logger.debug('entering main loop') - - # Create and listen on the server socket - self.create_server_socket() - - if opts.daemon_mode: - # Daemonize the process - daemonize() - - # Update the pid file - make_pid_file(opts.pid_file) - - try: - # Accept incoming connections and listen for incoming data - self.listen() - - except: - if not self._quit: - logger.critical(get_exc()) - - # Clean up and exit - self.quit() - - logger.debug('exiting main loop') - - - def listen(self): - '''Accept incoming connections and constantly poll instance sockets - for incoming data.''' - - logger.info('listening on %r' % opts.server_socket) - - # Count accepted connections - connections = 0 - - while (self.uzbls or not connections) or (not opts.auto_close): - socks = [self.server_socket] + self.uzbls.keys() - reads, _, errors = select(socks, [], socks, 1) - - if self.server_socket in reads: - reads.remove(self.server_socket) - - # Accept connection and create uzbl instance. - child_socket = self.server_socket.accept()[0] - self.uzbls[child_socket] = Uzbl(self, child_socket) - connections += 1 - - for uzbl in [self.uzbls[s] for s in reads]: - uzbl.read() - - for uzbl in [self.uzbls[s] for s in errors]: - uzbl.logger.error('socket read error') - uzbl.close() - - logger.info('auto closing') - - - def close_server_socket(self): - '''Close and delete the server socket.''' - - try: - if self.server_socket: - logger.debug('closing server socket') - self.server_socket.close() - self.server_socket = None - - if os.path.exists(opts.server_socket): - logger.info('unlinking %r' % opts.server_socket) - os.unlink(opts.server_socket) - - except: - logger.error(get_exc()) - - - def quit(self, sigint=None, *args): - '''Close all instance socket objects, server socket and delete the - pid file.''' - - if sigint == SIGTERM: - logger.critical('caught SIGTERM, exiting') - - elif sigint == SIGINT: - logger.critical('caught SIGINT, exiting') - - elif not self._quit: - logger.debug('shutting down event manager') - - self.close_server_socket() - - for uzbl in self.uzbls.values(): - uzbl.close() - - del_pid_file(opts.pid_file) - - if not self._quit: - logger.info('event manager shut down') - self._quit = True - - -def make_pid_file(pid_file): - '''Creates a pid file at `pid_file`, fails silently.''' - - try: - logger.debug('creating pid file %r' % pid_file) - make_dirs(pid_file) - pid = os.getpid() - fileobj = open(pid_file, 'w') - fileobj.write('%d' % pid) - fileobj.close() - logger.info('created pid file %r with pid %d' % (pid_file, pid)) - - except: - logger.error(get_exc()) - - -def del_pid_file(pid_file): - '''Deletes a pid file at `pid_file`, fails silently.''' - - if os.path.isfile(pid_file): - try: - logger.debug('deleting pid file %r' % pid_file) - os.remove(pid_file) - logger.info('deleted pid file %r' % pid_file) - - except: - logger.error(get_exc()) - - -def get_pid(pid_file): - '''Reads a pid from pid file `pid_file`, fails None.''' - - try: - logger.debug('reading pid file %r' % pid_file) - fileobj = open(pid_file, 'r') - pid = int(fileobj.read()) - fileobj.close() - logger.info('read pid %d from pid file %r' % (pid, pid_file)) - return pid - - except (IOError, ValueError): - logger.error(get_exc()) - return None - - -def pid_running(pid): - '''Checks if a process with a pid `pid` is running.''' - - try: - os.kill(pid, 0) - except OSError: - return False - else: - return True - - -def term_process(pid): - '''Asks nicely then forces process with pid `pid` to exit.''' - - try: - logger.info('sending SIGTERM to process with pid %r' % pid) - os.kill(pid, SIGTERM) - - except OSError: - logger.error(get_exc()) - - logger.debug('waiting for process with pid %r to exit' % pid) - start = time.time() - while True: - if not pid_running(pid): - logger.debug('process with pid %d exit' % pid) - return True - - if (time.time()-start) > 5: - logger.warning('process with pid %d failed to exit' % pid) - logger.info('sending SIGKILL to process with pid %d' % pid) - try: - os.kill(pid, SIGKILL) - except: - logger.critical(get_exc()) - raise - - if (time.time()-start) > 10: - logger.critical('unable to kill process with pid %d' % pid) - raise OSError - - time.sleep(0.25) - - -def stop_action(): - '''Stop the event manager daemon.''' - - pid_file = opts.pid_file - if not os.path.isfile(pid_file): - logger.error('could not find running event manager with pid file %r' - % opts.pid_file) - return - - pid = get_pid(pid_file) - if not pid_running(pid): - logger.debug('no process with pid %r' % pid) - del_pid_file(pid_file) - return - - logger.debug('terminating process with pid %r' % pid) - term_process(pid) - del_pid_file(pid_file) - logger.info('stopped event manager process with pid %d' % pid) - - -def start_action(): - '''Start the event manager daemon.''' - - pid_file = opts.pid_file - if os.path.isfile(pid_file): - pid = get_pid(pid_file) - if pid_running(pid): - logger.error('event manager already started with pid %d' % pid) - return - - logger.info('no process with pid %d' % pid) - del_pid_file(pid_file) - - UzblEventDaemon().run() - - -def restart_action(): - '''Restart the event manager daemon.''' - - stop_action() - start_action() - - -def list_action(): - '''List all the plugins that would be loaded in the current search - dirs.''' - - names = {} - for plugin in opts.plugins: - (head, tail) = os.path.split(plugin) - if tail not in names: - names[tail] = plugin - - for plugin in sorted(names.values()): - print plugin - - -if __name__ == "__main__": - parser = OptionParser('usage: %prog [options] {start|stop|restart|list}') - add = parser.add_option - - add('-v', '--verbose', - dest='verbose', default=2, action='count', - help='increase verbosity') - - add('-d', '--plugin-dir', - dest='plugin_dirs', action='append', metavar="DIR", default=[], - help='add extra plugin search dir, same as `-l "DIR/*.py"`') - - add('-l', '--load-plugin', - dest='load_plugins', action='append', metavar="PLUGIN", default=[], - help='load plugin, loads before plugins in search dirs') - - socket_location = os.path.join(CACHE_DIR, 'event_daemon') - add('-s', '--server-socket', - dest='server_socket', metavar="SOCKET", default=socket_location, - help='server AF_UNIX socket location') - - add('-p', '--pid-file', - metavar="FILE", dest='pid_file', - help='pid file location, defaults to server socket + .pid') - - add('-n', '--no-daemon', - dest='daemon_mode', action='store_false', default=True, - help='do not daemonize the process') - - add('-a', '--auto-close', - dest='auto_close', action='store_true', default=False, - help='auto close after all instances disconnect') - - add('-i', '--no-default-dirs', - dest='default_dirs', action='store_false', default=True, - help='ignore the default plugin search dirs') - - add('-o', '--log-file', - dest='log_file', metavar='FILE', - help='write logging output to a file, defaults to server socket +' - ' .log') - - add('-q', '--quiet-events', - dest='print_events', action="store_false", default=True, - help="silence the printing of events to stdout") - - (opts, args) = parser.parse_args() - - opts.server_socket = expandpath(opts.server_socket) - - # Set default pid file location - if not opts.pid_file: - opts.pid_file = "%s.pid" % opts.server_socket - - else: - opts.pid_file = expandpath(opts.pid_file) - - # Set default log file location - if not opts.log_file: - opts.log_file = "%s.log" % opts.server_socket - - else: - opts.log_file = expandpath(opts.log_file) - - # Logging setup - log_level = logging.CRITICAL - opts.verbose*10 - - # Console logging handler - ch = logging.StreamHandler() - ch.setLevel(max(log_level+10, 10)) - ch.setFormatter(logging.Formatter( - '%(name)s: %(levelname)s: %(message)s')) - - # File logging handler - fh = logging.FileHandler(opts.log_file, 'w', 'utf-8', 1) - fh.setLevel(max(log_level, 10)) - fh.setFormatter(logging.Formatter( - '[%(created)f] %(name)s: %(levelname)s: %(message)s')) - - # logging.getLogger wrapper which sets the levels and adds the - # file and console handlers automagically - def get_logger(name): - handlers = [ch, fh] - level = [max(log_level, 10),] - logger = logging.getLogger(name) - logger.setLevel(level[0]) - for handler in handlers: - logger.addHandler(handler) - - return logger - - # Get main logger - logger = get_logger(SCRIPTNAME) - logger.info('logging to %r' % opts.log_file) - - plugins = {} - - # Load all `opts.load_plugins` into the plugins list - for path in opts.load_plugins: - path = expandpath(path) - matches = glob(path) - if not matches: - parser.error('cannot find plugin(s): %r' % path) - - for plugin in matches: - (head, tail) = os.path.split(plugin) - if tail not in plugins: - logger.debug('found plugin: %r' % plugin) - plugins[tail] = plugin - - else: - logger.debug('ignoring plugin: %r' % plugin) - - # Add default plugin locations - if opts.default_dirs: - logger.debug('adding default plugin dirs to plugin dirs list') - opts.plugin_dirs += [os.path.join(DATA_DIR, 'plugins/'), - os.path.join(PREFIX, 'share/uzbl/examples/data/plugins/')] - - else: - logger.debug('ignoring default plugin dirs') - - # Load all plugins in `opts.plugin_dirs` into the plugins list - for dir in opts.plugin_dirs: - dir = expandpath(dir) - logger.debug('searching plugin dir: %r' % dir) - for plugin in glob(os.path.join(dir, '*.py')): - (head, tail) = os.path.split(plugin) - if tail not in plugins: - logger.debug('found plugin: %r' % plugin) - plugins[tail] = plugin - - else: - logger.debug('ignoring plugin: %r' % plugin) - - plugins = plugins.values() - - # Check all the paths in the plugins list are files - for plugin in plugins: - if not os.path.isfile(plugin): - parser.error('plugin not a file: %r' % plugin) - - if opts.auto_close: logger.debug('will auto close') - else: logger.debug('will not auto close') - - if opts.daemon_mode: logger.debug('will daemonize') - else: logger.debug('will not daemonize') - - opts.plugins = plugins - - # init like {start|stop|..} daemon actions - daemon_actions = {'start': start_action, 'stop': stop_action, - 'restart': restart_action, 'list': list_action} - - if len(args) == 1: - action = args[0] - if action not in daemon_actions: - parser.error('invalid action: %r' % action) - - elif not args: - logger.warning('no daemon action given, assuming %r' % 'start') - action = 'start' - - else: - parser.error('invalid action argument: %r' % args) - - logger.info('daemon action %r' % action) - # Do action - daemon_actions[action]() - - logger.debug('process CPU time: %f' % time.clock()) - -# vi: set et ts=4: -- cgit v1.2.3 From ed8f45d6eb21e5a931d55235708bcc73a2191771 Mon Sep 17 00:00:00 2001 From: Brendan Taylor Date: Mon, 11 Apr 2011 20:08:30 -0600 Subject: make link hints look way cooler --- examples/config/style.css | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/examples/config/style.css b/examples/config/style.css index ff055d1..a368aa0 100644 --- a/examples/config/style.css +++ b/examples/config/style.css @@ -1,12 +1,11 @@ #uzbl_link_hints > span { z-index: 1000 !important; - background-color: #aaff00 !important; - border: 2px solid #556600 !important; - margin: 0 !important; - padding: 1px !important; + background-color: #333 !important; + margin: 0 !important; + padding: 3px !important; - color: black !important; + color: #ccc !important; font-size: 9px !important; line-height: 9px !important; font-weight: bold !important; @@ -14,12 +13,16 @@ text-decoration: none !important; -webkit-transform: translate(-5px,-5px); - /* opacity: 0.7; */ + opacity: 0.8; + -webkit-border-radius: 6px !important; + /* Play around with this, pretty fun things to do :) */ + /* -webkit-transform: scale(1) rotate(0deg) translate(-6px,-5px) !important; */ } /* we can have different colours for different types of hints! */ #uzbl_link_hints.new-window > span { background-color: #ffff00 !important; + color: black !important; } /* vim:set et ts=4: */ -- cgit v1.2.3 From eb00f99bc300fc902beaeaa5385f5994ce904cdc Mon Sep 17 00:00:00 2001 From: Ben Boeckel Date: Mon, 7 Mar 2011 13:19:18 -0500 Subject: Add utils to load/save temporary URLs for later --- examples/config/config | 4 ++++ examples/data/scripts/insert_temp.sh | 8 ++++++++ examples/data/scripts/load_url_from_temps.sh | 23 +++++++++++++++++++++++ examples/data/scripts/util/dmenu.sh | 7 +++++++ examples/data/scripts/util/uzbl-dir.sh | 1 + 5 files changed, 43 insertions(+) create mode 100755 examples/data/scripts/insert_temp.sh create mode 100755 examples/data/scripts/load_url_from_temps.sh diff --git a/examples/config/config b/examples/config/config index d049f0e..7a4c685 100644 --- a/examples/config/config +++ b/examples/config/config @@ -337,6 +337,10 @@ set ebind = @mode_bind global,-insert @cbind U = spawn @scripts_dir/load_url_from_history.sh @cbind u = spawn @scripts_dir/load_url_from_bookmarks.sh +# Temporary bookmarks +@cbind d = spawn @scripts_dir/insert_temp.sh +@cbind D = spawn @scripts_dir/load_url_from_temps.sh + # Link following (similar to vimperator and konqueror) # Set custom keys you wish to use for navigation. Some common examples: set follow_hint_keys = 0123456789 diff --git a/examples/data/scripts/insert_temp.sh b/examples/data/scripts/insert_temp.sh new file mode 100755 index 0000000..a67b645 --- /dev/null +++ b/examples/data/scripts/insert_temp.sh @@ -0,0 +1,8 @@ +#!/bin/sh + +. "$UZBL_UTIL_DIR/uzbl-dir.sh" +. "$UZBL_UTIL_DIR/uzbl-util.sh" + +>> "$UZBL_TEMPS_FILE" || exit 1 + +print "$UZBL_URI $UZBL_TITLE\n" >> "$UZBL_TEMPS_FILE" diff --git a/examples/data/scripts/load_url_from_temps.sh b/examples/data/scripts/load_url_from_temps.sh new file mode 100755 index 0000000..9788b0f --- /dev/null +++ b/examples/data/scripts/load_url_from_temps.sh @@ -0,0 +1,23 @@ +#!/bin/sh + +DMENU_SCHEME="temps" +DMENU_OPTIONS="xmms vertical resize" + +. "$UZBL_UTIL_DIR/dmenu.sh" +. "$UZBL_UTIL_DIR/uzbl-dir.sh" +. "$UZBL_UTIL_DIR/uzbl-util.sh" + +[ -r "$UZBL_TEMPS_FILE" ] || exit 1 + +if [ -z "$DMENU_HAS_VERTICAL" ]; then + # because they are all after each other, just show the url, not their titles. + goto=$( awk '{ print $1 }' "$UZBL_TEMPS_FILE" | $DMENU ) +else + # show titles + goto=$( $DMENU < "$UZBL_TEMPS_FILE" | cut -d ' ' -f 1 ) +fi + +sed -i -e "\<^$goto "$UZBL_FIFO" +#[ -n "$goto" ] && print "uri $goto\n" | socat - "unix-connect:$UZBL_SOCKET" diff --git a/examples/data/scripts/util/dmenu.sh b/examples/data/scripts/util/dmenu.sh index f0d1651..0b7272e 100644 --- a/examples/data/scripts/util/dmenu.sh +++ b/examples/data/scripts/util/dmenu.sh @@ -30,6 +30,13 @@ case "$DMENU_SCHEME" in SB="#ccffaa" SF="#303030" ;; + # Temps + "temps" ) + NB="#303030" + NF="khaki" + SB="#ccffaa" + SF="#303030" + ;; # Default * ) NB="#303030" diff --git a/examples/data/scripts/util/uzbl-dir.sh b/examples/data/scripts/util/uzbl-dir.sh index 3d28151..82510d8 100644 --- a/examples/data/scripts/util/uzbl-dir.sh +++ b/examples/data/scripts/util/uzbl-dir.sh @@ -15,5 +15,6 @@ UZBL_FORMS_DIR="$UZBL_DATA_DIR/dforms" UZBL_CONFIG_FILE="$UZBL_CONFIG_DIR/config" UZBL_COOKIE_FILE="$UZBL_DATA_DIR/cookies.txt" UZBL_BOOKMARKS_FILE="$UZBL_DATA_DIR/bookmarks" +UZBL_TEMPS_FILE="$UZBL_DATA_DIR/temps" UZBL_HISTORY_FILE="$UZBL_DATA_DIR/history" UZBL_SESSION_FILE="$UZBL_DATA_DIR/browser-session" -- cgit v1.2.3 From cd737560c394196a2fff99afe5acc8d5c4ccb93a Mon Sep 17 00:00:00 2001 From: Brendan Taylor Date: Tue, 12 Apr 2011 21:16:07 -0600 Subject: use 'echo' instead of 'print' in examples/data/scripts/*temp*.sh --- examples/data/scripts/insert_temp.sh | 3 +-- examples/data/scripts/load_url_from_temps.sh | 5 ++--- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/examples/data/scripts/insert_temp.sh b/examples/data/scripts/insert_temp.sh index a67b645..7ed8d22 100755 --- a/examples/data/scripts/insert_temp.sh +++ b/examples/data/scripts/insert_temp.sh @@ -1,8 +1,7 @@ #!/bin/sh . "$UZBL_UTIL_DIR/uzbl-dir.sh" -. "$UZBL_UTIL_DIR/uzbl-util.sh" >> "$UZBL_TEMPS_FILE" || exit 1 -print "$UZBL_URI $UZBL_TITLE\n" >> "$UZBL_TEMPS_FILE" +echo "$UZBL_URI $UZBL_TITLE" >> "$UZBL_TEMPS_FILE" diff --git a/examples/data/scripts/load_url_from_temps.sh b/examples/data/scripts/load_url_from_temps.sh index 9788b0f..b46687b 100755 --- a/examples/data/scripts/load_url_from_temps.sh +++ b/examples/data/scripts/load_url_from_temps.sh @@ -5,7 +5,6 @@ DMENU_OPTIONS="xmms vertical resize" . "$UZBL_UTIL_DIR/dmenu.sh" . "$UZBL_UTIL_DIR/uzbl-dir.sh" -. "$UZBL_UTIL_DIR/uzbl-util.sh" [ -r "$UZBL_TEMPS_FILE" ] || exit 1 @@ -19,5 +18,5 @@ fi sed -i -e "\<^$goto "$UZBL_FIFO" -#[ -n "$goto" ] && print "uri $goto\n" | socat - "unix-connect:$UZBL_SOCKET" +[ -n "$goto" ] && echo "uri $goto" > "$UZBL_FIFO" +#[ -n "$goto" ] && echo "uri $goto" | socat - "unix-connect:$UZBL_SOCKET" -- cgit v1.2.3 From e2b2a4831be5f682a5a59b642fde1ba1f1caa308 Mon Sep 17 00:00:00 2001 From: Ben Boeckel Date: Tue, 12 Apr 2011 23:33:31 -0400 Subject: Match form field types exactly --- examples/data/scripts/formfiller.sh | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/examples/data/scripts/formfiller.sh b/examples/data/scripts/formfiller.sh index 3dc9dc4..435a114 100755 --- a/examples/data/scripts/formfiller.sh +++ b/examples/data/scripts/formfiller.sh @@ -66,15 +66,15 @@ ParseFields () field = $0 sub ( /[^:]*:/, "", field ) - if ( parts[2] ~ /(text|password|search)/ ) + if ( parts[2] ~ /^(text|password|search)$/ ) printf( "js uzbl.formfiller.insert(\"%s\",\"%s\",\"%s\",0);\n", parts[1], parts[2], field ) - else if ( parts[2] ~ /(checkbox|radio)/ ) + else if ( parts[2] ~ /^(checkbox|radio)$/ ) 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 -- cgit v1.2.3 From e1bb5b44c16636b4ffc1cc14dbe1e23c0b0e63de Mon Sep 17 00:00:00 2001 From: Ben Boeckel Date: Tue, 12 Apr 2011 23:33:46 -0400 Subject: Properly escape newlines --- examples/data/scripts/formfiller.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/data/scripts/formfiller.sh b/examples/data/scripts/formfiller.sh index 435a114..14853c7 100755 --- a/examples/data/scripts/formfiller.sh +++ b/examples/data/scripts/formfiller.sh @@ -81,7 +81,7 @@ ParseFields () sub ( /^\\/, "" ) gsub ( /"/, "\\\"" ) gsub ( /\\/, "\\\\" ) - field = field $0 "\\n" + field = field $0 "\\\\n" } printf( "js uzbl.formfiller.insert(\"%s\",\"%s\",\"%s\",0);\n", parts[1], parts[2], field ) -- cgit v1.2.3 From ea192bba46f6f40bb67faf7f561260d7da286191 Mon Sep 17 00:00:00 2001 From: Ben Boeckel Date: Tue, 12 Apr 2011 23:37:42 -0400 Subject: Update bindings to formfiller to match reality --- examples/config/config | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/config/config b/examples/config/config index d049f0e..7efbb22 100644 --- a/examples/config/config +++ b/examples/config/config @@ -353,10 +353,10 @@ set follow_hint_keys = 0123456789 # This implementation allows you to save multiple profiles for each form # (think about multiple accounts on some website). set formfiller = spawn @scripts_dir/formfiller.sh -@cbind za = @formfiller add @cbind ze = @formfiller edit @cbind zn = @formfiller new @cbind zl = @formfiller load +@cbind zo = @formfiller once # --- Uzbl tabbed binds ------------------------------------------------------ -- cgit v1.2.3 From 1a7bfc9471fcc46135b1099629675f085af7407a Mon Sep 17 00:00:00 2001 From: Ben Boeckel Date: Tue, 12 Apr 2011 23:45:27 -0400 Subject: Fix sed typo --- examples/data/scripts/formfiller.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/data/scripts/formfiller.sh b/examples/data/scripts/formfiller.sh index 14853c7..b69ab60 100755 --- a/examples/data/scripts/formfiller.sh +++ b/examples/data/scripts/formfiller.sh @@ -132,7 +132,7 @@ Once () test -e "$tmpfile" && ParseFields < "$tmpfile" \ - | sed 's/@/\\@' \ + | sed 's/@/\\@/' \ > "$UZBL_FIFO" } -- cgit v1.2.3 From d5b71e85e1b13c79a6de488254406ec690c9efe7 Mon Sep 17 00:00:00 2001 From: Ben Boeckel Date: Tue, 12 Apr 2011 23:58:48 -0400 Subject: Escape all @ characters --- examples/data/scripts/formfiller.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/data/scripts/formfiller.sh b/examples/data/scripts/formfiller.sh index b69ab60..c1171a0 100755 --- a/examples/data/scripts/formfiller.sh +++ b/examples/data/scripts/formfiller.sh @@ -116,7 +116,7 @@ Load () ParseProfile $option < "$file" \ | ParseFields \ - | sed 's/@/\\@/' \ + | sed 's/@/\\@/g' \ > "$UZBL_FIFO" } @@ -132,7 +132,7 @@ Once () test -e "$tmpfile" && ParseFields < "$tmpfile" \ - | sed 's/@/\\@/' \ + | sed 's/@/\\@/g' \ > "$UZBL_FIFO" } -- cgit v1.2.3 From 1282b9cf99be29db65529eec3bfb14f6685b393b Mon Sep 17 00:00:00 2001 From: Brendan Taylor Date: Tue, 12 Apr 2011 22:00:35 -0600 Subject: add a 'download' command that can download the current url or an arbitrary url --- src/uzbl-core.c | 19 ++++++++++++++++++- src/uzbl-core.h | 1 + 2 files changed, 19 insertions(+), 1 deletion(-) diff --git a/src/uzbl-core.c b/src/uzbl-core.c index e498762..3a96482 100644 --- a/src/uzbl-core.c +++ b/src/uzbl-core.c @@ -552,7 +552,8 @@ CommandInfo cmdlist[] = { "show_inspector", show_inspector, 0 }, { "add_cookie", add_cookie, 0 }, { "delete_cookie", delete_cookie, 0 }, - { "clear_cookies", clear_cookies, 0 } + { "clear_cookies", clear_cookies, 0 }, + { "download", download, 0 } }; void @@ -740,6 +741,22 @@ clear_cookies(WebKitWebView *page, GArray *argv, GString *result) { SOUP_SESSION_FEATURE (uzbl.net.soup_cookie_jar)); } +void +download(WebKitWebView *web_view, GArray *argv, GString *result) { + (void) result; + + const gchar *uri = NULL; + + if(argv->len > 0) + uri = argv_idx(argv, 0); + else + uri = uzbl.state.uri; + + WebKitNetworkRequest *req = webkit_network_request_new(uri); + webkit_web_view_request_download(web_view, req); + g_object_unref(req); +} + void act_dump_config() { dump_config(); diff --git a/src/uzbl-core.h b/src/uzbl-core.h index affd334..be8fccd 100644 --- a/src/uzbl-core.h +++ b/src/uzbl-core.h @@ -325,6 +325,7 @@ void show_inspector(WebKitWebView *page, GArray *argv, GString *result); void add_cookie(WebKitWebView *page, GArray *argv, GString *result); 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 builtins(); typedef void (*Command)(WebKitWebView*, GArray *argv, GString *result); -- cgit v1.2.3 From bdfb2fb35c4d6fa407361dcc99aefb00ff185e6d Mon Sep 17 00:00:00 2001 From: Brendan Taylor Date: Tue, 12 Apr 2011 22:35:42 -0600 Subject: allow a second argument to the 'download' command that specifies a destination path --- examples/data/scripts/download.sh | 14 +++++++++++--- src/callbacks.c | 8 ++++++++ src/uzbl-core.c | 18 ++++++++++++------ 3 files changed, 31 insertions(+), 9 deletions(-) diff --git a/examples/data/scripts/download.sh b/examples/data/scripts/download.sh index fe566ed..dbc9caf 100755 --- a/examples/data/scripts/download.sh +++ b/examples/data/scripts/download.sh @@ -1,9 +1,17 @@ #!/bin/sh # uzbl's example configuration sets this script up as its download_handler. -# when uzbl starts a download it runs this script. +# this script is run when uzbl encounters a URL that it can't display, and when +# a download is requested using the 'download' command. +# # if the script prints a file path to stdout, uzbl will save the download to -# that path. -# if nothing is printed to stdout, the download will be cancelled. +# that path using it's internal downloader. +# +# if nothing is printed to stdout, the internal download will be cancelled. +# you could do your own download handling in your script that way. + +# if $5 is set, it is the path that was passed to uzbl's "download" command. +# we want to use that if it's available. +[ -n "$5" ] && echo "$5" && exit . "$UZBL_UTIL_DIR/uzbl-dir.sh" diff --git a/src/callbacks.c b/src/callbacks.c index 360b0c4..703107b 100644 --- a/src/callbacks.c +++ b/src/callbacks.c @@ -837,6 +837,11 @@ download_cb(WebKitWebView *web_view, WebKitDownload *download, gpointer user_dat /* get the URI being downloaded */ const gchar *uri = webkit_download_get_uri(download); + /* get the destination path, if specified. + * this is only intended to be set when this function is trigger by an + * explicit download using uzbl's 'download' action. */ + const gchar *destination = user_data; + if (uzbl.state.verbose) printf("Download requested -> %s\n", uri); @@ -883,6 +888,9 @@ download_cb(WebKitWebView *web_view, WebKitDownload *download, gpointer user_dat gchar *total_size_s = g_strdup_printf("%d", total_size); g_array_append_val(a, total_size_s); + if(destination) + g_array_append_val(a, destination); + GString *result = g_string_new (""); run_parsed_command(c, a, result); diff --git a/src/uzbl-core.c b/src/uzbl-core.c index 3a96482..204c89c 100644 --- a/src/uzbl-core.c +++ b/src/uzbl-core.c @@ -745,15 +745,21 @@ void download(WebKitWebView *web_view, GArray *argv, GString *result) { (void) result; - const gchar *uri = NULL; + const gchar *uri = argv_idx(argv, 0); + const gchar *destination = NULL; + if(argv->len > 1) + destination = argv_idx(argv, 1); - if(argv->len > 0) - uri = argv_idx(argv, 0); + WebKitNetworkRequest *req = webkit_network_request_new(uri); + WebKitDownload *download = webkit_download_new(req); + + download_cb(web_view, download, destination); + + if(webkit_download_get_destination_uri(download)) + webkit_download_start(download); else - uri = uzbl.state.uri; + g_object_unref(download); - WebKitNetworkRequest *req = webkit_network_request_new(uri); - webkit_web_view_request_download(web_view, req); g_object_unref(req); } -- cgit v1.2.3 From a3154b72aa2b3e3ad02178cab9049546d769bb67 Mon Sep 17 00:00:00 2001 From: Brendan Taylor Date: Tue, 12 Apr 2011 22:44:39 -0600 Subject: document the download command and the change to download_handler's arguments --- README | 23 ++++++++++++++++------- 1 file changed, 16 insertions(+), 7 deletions(-) diff --git a/README b/README index 6709bf5..cfc9a87 100644 --- a/README +++ b/README @@ -257,11 +257,14 @@ The following commands are recognized: - Show the WebInspector * `add_cookie ` - Adds a new cookie to the cookie jar -* 'delete_cookie [ ]` - - Deletes a matching cookie from the cookie jar. scheme and expire time - is currently not considered when matching. -* 'clear_cookies` - - Clears all cookies from the cookie jar +* `delete_cookie [ ]` + - Deletes a matching cookie from the cookie jar. scheme and expire time + is currently not considered when matching. +* `clear_cookies` + - Clears all cookies from the cookie jar +* `download []` + - Starts a download using the given uri. A destination file path can be given + to specify where the download should be written to. ### VARIABLES AND CONSTANTS @@ -506,9 +509,15 @@ Handler scripts (`download_handler`, `cookie_handler`, `scheme_handler` and * download handler - `$1 url`: The URL of the item to be downloaded. - - `$2 suggested_filename`: A filename suggested by the server or based on the URL. + - `$2 suggested_filename`: A filename suggested by the server or based on the + URL. - `$3 content_type`: The mimetype of the file to be downloaded. - - `$4 total_size`: The size of the file to be downloaded in bytes. This may be inaccurate. + - `$4 total_size`: The size of the file to be downloaded in bytes. This may be + inaccurate. + - `$5 destination_path`: This is only present if the download was started + explicitly using the `download` command. If it is present, this is the path + that the file should be saved to. A download handler using WebKit's internal + downloader can just echo this path and exit when this argument is present. * cookie handler -- cgit v1.2.3 From de2f2544c5d59d3974d3c77a3bcaf82bbb95a8ef Mon Sep 17 00:00:00 2001 From: Ben Boeckel Date: Wed, 13 Apr 2011 23:30:08 -0400 Subject: Avoid division by zero error Addresses bug #252. --- examples/config/config | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/config/config b/examples/config/config index d049f0e..ab7a7da 100644 --- a/examples/config/config +++ b/examples/config/config @@ -91,7 +91,7 @@ set download_handler = sync_spawn @scripts_dir/download.sh #@on_event CONFIG_CHANGED print Config changed: %1 = %2 # Scroll percentage calculation -@on_event SCROLL_VERT set scroll_message = \@<(function(){var p='--';if(%3!=%2){p=(%1/(%3-%4));p=Math.round(10000*p)/100;};return p+'%';})()>\@ +@on_event SCROLL_VERT set scroll_message = \@<(function(){var p='--';if(%3!=%2){p=(%1/(%3-%2));p=Math.round(10000*p)/100;};return p+'%';})()>\@ # === Behaviour and appearance =============================================== -- cgit v1.2.3 From 726e105a1269a9202690281471e5fa243223809b Mon Sep 17 00:00:00 2001 From: Ben Boeckel Date: Thu, 14 Apr 2011 00:20:20 -0400 Subject: Avoid --name which GTK uses internally Addresses #170. --- src/uzbl-core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/uzbl-core.c b/src/uzbl-core.c index e498762..e918451 100644 --- a/src/uzbl-core.c +++ b/src/uzbl-core.c @@ -47,7 +47,7 @@ GOptionEntry entries[] = { "Uri to load at startup (equivalent to 'uzbl ' or 'set uri = URI' after uzbl has launched)", "URI" }, { "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, + { "named", 'n', 0, G_OPTION_ARG_STRING, &uzbl.state.instance_name, "Name of the current instance (defaults to Xorg window id or random for GtkSocket mode)", "NAME" }, { "config", 'c', 0, G_OPTION_ARG_STRING, &uzbl.state.config_file, "Path to config file or '-' for stdin", "FILE" }, -- cgit v1.2.3 From 05b7422a9fcbb1cadf1beaff5ec0cea8b5b7a828 Mon Sep 17 00:00:00 2001 From: Ben Boeckel Date: Thu, 14 Apr 2011 00:22:49 -0400 Subject: Update documentation --- README | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/README b/README index 6709bf5..431694e 100644 --- a/README +++ b/README @@ -104,7 +104,7 @@ There are several interfaces to interact with Uzbl: When `uzbl` forks a new instance (eg "open in new window") it will use the same command line arguments (eg the same `--config `), except `--uri` and -`--name`. If you made changes to the configuration at runtime, these are not +`--named`. If you made changes to the configuration at runtime, these are not passed on to the child. #### Uzbl-browser @@ -258,8 +258,8 @@ The following commands are recognized: * `add_cookie ` - Adds a new cookie to the cookie jar * 'delete_cookie [ ]` - - Deletes a matching cookie from the cookie jar. scheme and expire time - is currently not considered when matching. + - Deletes a matching cookie from the cookie jar. scheme and expire time + is currently not considered when matching. * 'clear_cookies` - Clears all cookies from the cookie jar @@ -793,7 +793,7 @@ where `arguments` and `uri` are both optional. `arguments` can be: * `-u`, `--uri=URI`: URI to load at startup. Equivalent to `uzbl ` or `set uri = URI` after `uzbl` has launched. * `-v`, `--verbose`: Whether to print all messages or just errors. -* `-n`, `--name=NAME`: Name of the current instance (defaults to Xorg window +* `-n`, `--named=NAME`: Name of the current instance (defaults to Xorg window id or random for GtkSocket mode). * `-c`, `--config=FILE`: Path to config file or `-` for stdin. * `-s`, `--socket=SOCKET`: Xembed socket ID. -- cgit v1.2.3 From 76f8d42568b7985de3c256f10d6d40ebd0dfd697 Mon Sep 17 00:00:00 2001 From: Brendan Taylor Date: Thu, 14 Apr 2011 20:17:45 -0600 Subject: use /usr/bin/env consistently in example script #!s --- examples/data/scripts/auth.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/data/scripts/auth.py b/examples/data/scripts/auth.py index 592a2c6..49fa41e 100755 --- a/examples/data/scripts/auth.py +++ b/examples/data/scripts/auth.py @@ -1,4 +1,4 @@ -#!/usr/bin/python +#!/usr/bin/env python import gtk import sys -- cgit v1.2.3 From 13f4f27d4d4ff12440729ff4e738b2679371215b Mon Sep 17 00:00:00 2001 From: Ben Boeckel Date: Thu, 14 Apr 2011 23:03:11 -0400 Subject: Use the correct variable %2 is the top of the scrollbar; %4 is the page size. --- examples/config/config | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/config/config b/examples/config/config index ab7a7da..e6eac34 100644 --- a/examples/config/config +++ b/examples/config/config @@ -91,7 +91,7 @@ set download_handler = sync_spawn @scripts_dir/download.sh #@on_event CONFIG_CHANGED print Config changed: %1 = %2 # Scroll percentage calculation -@on_event SCROLL_VERT set scroll_message = \@<(function(){var p='--';if(%3!=%2){p=(%1/(%3-%2));p=Math.round(10000*p)/100;};return p+'%';})()>\@ +@on_event SCROLL_VERT set scroll_message = \@<(function(){var p='--';if(%3<=%4){p=(%1/(%3-%4));p=Math.round(10000*p)/100;};return p+'%';})()>\@ # === Behaviour and appearance =============================================== -- cgit v1.2.3 From 4b106c13eb642f865c4bed2bc149c703e3fe7534 Mon Sep 17 00:00:00 2001 From: Rob Date: Fri, 19 Feb 2010 11:09:21 +0100 Subject: added modifier mask to key_press/release events --- src/callbacks.c | 4 ++-- src/events.c | 48 +++++++++++++++++++++++++++++++++++++++++++----- src/events.h | 2 +- 3 files changed, 46 insertions(+), 8 deletions(-) diff --git a/src/callbacks.c b/src/callbacks.c index 703107b..c0064ec 100644 --- a/src/callbacks.c +++ b/src/callbacks.c @@ -549,7 +549,7 @@ key_press_cb (GtkWidget* window, GdkEventKey* event) { (void) window; if(event->type == GDK_KEY_PRESS) - key_to_event(event->keyval, GDK_KEY_PRESS); + key_to_event(event->keyval, event->is_modifier?0:event->state, GDK_KEY_PRESS); return uzbl.behave.forward_keys ? FALSE : TRUE; } @@ -559,7 +559,7 @@ key_release_cb (GtkWidget* window, GdkEventKey* event) { (void) window; if(event->type == GDK_KEY_RELEASE) - key_to_event(event->keyval, GDK_KEY_RELEASE); + key_to_event(event->keyval, event->is_modifier?0:event->state, GDK_KEY_RELEASE); return uzbl.behave.forward_keys ? FALSE : TRUE; } diff --git a/src/events.c b/src/events.c index 58dddfc..45b2ef1 100644 --- a/src/events.c +++ b/src/events.c @@ -202,11 +202,46 @@ send_event(int type, const gchar *custom_event, ...) { /* Transform gdk key events to our own events */ void -key_to_event(guint keyval, gint mode) { +key_to_event(guint keyval, guint state, gint mode) { gchar ucs[7]; gint ulen; gchar *keyname; guint32 ukval = gdk_keyval_to_unicode(keyval); + GString *modifiers = g_string_new(""); + gchar *details; + + /* check modifier state*/ + if(state & GDK_MODIFIER_MASK) { + if(state & GDK_SHIFT_MASK) + g_string_append(modifiers, "Shift|"); + if(state & GDK_LOCK_MASK) + g_string_append(modifiers, "ScrollLock|"); + if(state & GDK_CONTROL_MASK) + g_string_append(modifiers, "Ctrl|"); + if(state & GDK_MOD1_MASK) + g_string_append(modifiers,"Mod1|"); + if(state & GDK_MOD2_MASK) + g_string_append(modifiers,"Mod2|"); + if(state & GDK_MOD3_MASK) + g_string_append(modifiers,"Mod3|"); + if(state & GDK_MOD4_MASK) + g_string_append(modifiers,"Mod4|"); + if(state & GDK_MOD5_MASK) + g_string_append(modifiers,"Mod5|"); + if(state & GDK_BUTTON1_MASK) + g_string_append(modifiers,"Button1|"); + if(state & GDK_BUTTON2_MASK) + g_string_append(modifiers,"Button2|"); + if(state & GDK_BUTTON3_MASK) + g_string_append(modifiers,"Button3|"); + if(state & GDK_BUTTON4_MASK) + g_string_append(modifiers,"Button4|"); + if(state & GDK_BUTTON5_MASK) + g_string_append(modifiers,"Button5|"); + + if(modifiers->str[modifiers->len-1] == '|') + g_string_overwrite(modifiers, modifiers->len-1, " "); + } /* check for printable unicode char */ /* TODO: Pass the keyvals through a GtkIMContext so that @@ -216,15 +251,18 @@ key_to_event(guint keyval, gint mode) { ulen = g_unichar_to_utf8(ukval, ucs); ucs[ulen] = 0; - send_event(mode == GDK_KEY_PRESS ? KEY_PRESS : KEY_RELEASE, - NULL, TYPE_FORMATTEDSTR, ucs, NULL); + send_event(mode == GDK_KEY_PRESS ? KEY_PRESS : KEY_RELEASE, NULL, + TYPE_STR, modifiers->str, TYPE_FORMATTEDSTR, ucs, NULL); } /* send keysym for non-printable chars */ else if((keyname = gdk_keyval_name(keyval))){ - send_event(mode == GDK_KEY_PRESS ? KEY_PRESS : KEY_RELEASE, - NULL, TYPE_NAME, keyname , NULL); + send_event(mode == GDK_KEY_PRESS ? KEY_PRESS : KEY_RELEASE, NULL, + TYPE_STR, modifiers->str, TYPE_NAME, keyname , NULL); } + g_string_free(modifiers, TRUE); + g_free(details); + } /* vi: set et ts=4: */ diff --git a/src/events.h b/src/events.h index bd519a6..97ed0a0 100644 --- a/src/events.h +++ b/src/events.h @@ -42,6 +42,6 @@ void send_event(int type, const gchar *custom_event, ...) G_GNUC_NULL_TERMINATED; void -key_to_event(guint keyval, gint mode); +key_to_event(guint keyval, guint state, int mode); #endif -- cgit v1.2.3 From 60b4e20512df7b29e19aa3bb17532fd177928d4d Mon Sep 17 00:00:00 2001 From: Rob Date: Fri, 19 Feb 2010 12:44:37 +0100 Subject: added MOD_PRESS/RELEASE events that denote X modifier keys --- src/callbacks.c | 4 ++-- src/events.c | 15 +++++++++------ src/events.h | 5 +++-- 3 files changed, 14 insertions(+), 10 deletions(-) diff --git a/src/callbacks.c b/src/callbacks.c index c0064ec..4c150ec 100644 --- a/src/callbacks.c +++ b/src/callbacks.c @@ -549,7 +549,7 @@ key_press_cb (GtkWidget* window, GdkEventKey* event) { (void) window; if(event->type == GDK_KEY_PRESS) - key_to_event(event->keyval, event->is_modifier?0:event->state, GDK_KEY_PRESS); + key_to_event(event->keyval, event->is_modifier?0:event->state, event->is_modifier, GDK_KEY_PRESS); return uzbl.behave.forward_keys ? FALSE : TRUE; } @@ -559,7 +559,7 @@ key_release_cb (GtkWidget* window, GdkEventKey* event) { (void) window; if(event->type == GDK_KEY_RELEASE) - key_to_event(event->keyval, event->is_modifier?0:event->state, GDK_KEY_RELEASE); + key_to_event(event->keyval, event->is_modifier?0:event->state, event->is_modifier, GDK_KEY_RELEASE); return uzbl.behave.forward_keys ? FALSE : TRUE; } diff --git a/src/events.c b/src/events.c index 45b2ef1..013bd85 100644 --- a/src/events.c +++ b/src/events.c @@ -23,6 +23,8 @@ const char *event_table[LAST_EVENT] = { "REQUEST_STARTING" , "KEY_PRESS" , "KEY_RELEASE" , + "MOD_PRESS" , + "MOD_RELEASE" , "COMMAND_EXECUTED" , "LINK_HOVER" , "TITLE_CHANGED" , @@ -202,13 +204,12 @@ send_event(int type, const gchar *custom_event, ...) { /* Transform gdk key events to our own events */ void -key_to_event(guint keyval, guint state, gint mode) { +key_to_event(guint keyval, guint state, guint is_modifier, gint mode) { gchar ucs[7]; gint ulen; gchar *keyname; guint32 ukval = gdk_keyval_to_unicode(keyval); GString *modifiers = g_string_new(""); - gchar *details; /* check modifier state*/ if(state & GDK_MODIFIER_MASK) { @@ -256,13 +257,15 @@ key_to_event(guint keyval, guint state, gint mode) { } /* send keysym for non-printable chars */ else if((keyname = gdk_keyval_name(keyval))){ - send_event(mode == GDK_KEY_PRESS ? KEY_PRESS : KEY_RELEASE, NULL, - TYPE_STR, modifiers->str, TYPE_NAME, keyname , NULL); + if(is_modifier) + send_event(mode == GDK_KEY_PRESS ? MOD_PRESS : MOD_RELEASE, NULL, + TYPE_STR, modifiers->str, TYPE_NAME, keyname , NULL); + else + send_event(mode == GDK_KEY_PRESS ? KEY_PRESS : KEY_RELEASE, NULL, + TYPE_STR, modifiers->str, TYPE_NAME, keyname , NULL); } g_string_free(modifiers, TRUE); - g_free(details); - } /* vi: set et ts=4: */ diff --git a/src/events.h b/src/events.h index 97ed0a0..35e0ecd 100644 --- a/src/events.h +++ b/src/events.h @@ -13,7 +13,8 @@ enum event_type { LOAD_START, LOAD_COMMIT, LOAD_FINISH, LOAD_ERROR, REQUEST_STARTING, - KEY_PRESS, KEY_RELEASE, COMMAND_EXECUTED, + KEY_PRESS, KEY_RELEASE, MOD_PRESS, MOD_RELEASE, + COMMAND_EXECUTED, LINK_HOVER, TITLE_CHANGED, GEOMETRY_CHANGED, WEBINSPECTOR, NEW_WINDOW, SELECTION_CHANGED, VARIABLE_SET, FIFO_SET, SOCKET_SET, @@ -42,6 +43,6 @@ void send_event(int type, const gchar *custom_event, ...) G_GNUC_NULL_TERMINATED; void -key_to_event(guint keyval, guint state, int mode); +key_to_event(guint keyval, guint state, guint is_modifier, int mode); #endif -- cgit v1.2.3 From 5a46390e61faaea2d88ec49a1a81997672f4150b Mon Sep 17 00:00:00 2001 From: Rob Date: Mon, 22 Feb 2010 09:03:15 +0100 Subject: show modmask on MOD_PRESS/RELEASE --- src/callbacks.c | 4 ++-- src/events.c | 33 +++++++++++++++++++++------------ src/events.h | 3 +++ 3 files changed, 26 insertions(+), 14 deletions(-) diff --git a/src/callbacks.c b/src/callbacks.c index 4c150ec..6821700 100644 --- a/src/callbacks.c +++ b/src/callbacks.c @@ -549,7 +549,7 @@ key_press_cb (GtkWidget* window, GdkEventKey* event) { (void) window; if(event->type == GDK_KEY_PRESS) - key_to_event(event->keyval, event->is_modifier?0:event->state, event->is_modifier, GDK_KEY_PRESS); + key_to_event(event->keyval, event->state, event->is_modifier, GDK_KEY_PRESS); return uzbl.behave.forward_keys ? FALSE : TRUE; } @@ -559,7 +559,7 @@ key_release_cb (GtkWidget* window, GdkEventKey* event) { (void) window; if(event->type == GDK_KEY_RELEASE) - key_to_event(event->keyval, event->is_modifier?0:event->state, event->is_modifier, GDK_KEY_RELEASE); + key_to_event(event->keyval, event->state, event->is_modifier, GDK_KEY_RELEASE); return uzbl.behave.forward_keys ? FALSE : TRUE; } diff --git a/src/events.c b/src/events.c index 013bd85..12f9d83 100644 --- a/src/events.c +++ b/src/events.c @@ -202,16 +202,10 @@ send_event(int type, const gchar *custom_event, ...) { va_end (vargs); } -/* Transform gdk key events to our own events */ -void -key_to_event(guint keyval, guint state, guint is_modifier, gint mode) { - gchar ucs[7]; - gint ulen; - gchar *keyname; - guint32 ukval = gdk_keyval_to_unicode(keyval); +gchar * +get_modifier_mask(guint state) { GString *modifiers = g_string_new(""); - /* check modifier state*/ if(state & GDK_MODIFIER_MASK) { if(state & GDK_SHIFT_MASK) g_string_append(modifiers, "Shift|"); @@ -244,6 +238,21 @@ key_to_event(guint keyval, guint state, guint is_modifier, gint mode) { g_string_overwrite(modifiers, modifiers->len-1, " "); } + return g_string_free(modifiers, FALSE); +} + +/* Transform gdk key events to our own events */ +void +key_to_event(guint keyval, guint state, guint is_modifier, gint mode) { + gchar ucs[7]; + gint ulen; + gchar *keyname; + guint32 ukval = gdk_keyval_to_unicode(keyval); + gchar *modifiers = NULL; + + /* check modifier state*/ + modifiers = get_modifier_mask(state); + /* check for printable unicode char */ /* TODO: Pass the keyvals through a GtkIMContext so that * we also get combining chars right @@ -253,19 +262,19 @@ key_to_event(guint keyval, guint state, guint is_modifier, gint mode) { ucs[ulen] = 0; send_event(mode == GDK_KEY_PRESS ? KEY_PRESS : KEY_RELEASE, NULL, - TYPE_STR, modifiers->str, TYPE_FORMATTEDSTR, ucs, NULL); + TYPE_STR, modifiers, TYPE_FORMATTEDSTR, ucs, NULL); } /* send keysym for non-printable chars */ else if((keyname = gdk_keyval_name(keyval))){ if(is_modifier) send_event(mode == GDK_KEY_PRESS ? MOD_PRESS : MOD_RELEASE, NULL, - TYPE_STR, modifiers->str, TYPE_NAME, keyname , NULL); + TYPE_STR, modifiers, TYPE_NAME, keyname , NULL); else send_event(mode == GDK_KEY_PRESS ? KEY_PRESS : KEY_RELEASE, NULL, - TYPE_STR, modifiers->str, TYPE_NAME, keyname , NULL); + TYPE_STR, modifiers, TYPE_NAME, keyname , NULL); } - g_string_free(modifiers, TRUE); + g_free(modifiers); } /* vi: set et ts=4: */ diff --git a/src/events.h b/src/events.h index 35e0ecd..0c40206 100644 --- a/src/events.h +++ b/src/events.h @@ -42,6 +42,9 @@ vsend_event(int type, const gchar *custom_event, va_list vargs); void send_event(int type, const gchar *custom_event, ...) G_GNUC_NULL_TERMINATED; +gchar * +get_modifier_mask(guint state); + void key_to_event(guint keyval, guint state, guint is_modifier, int mode); -- cgit v1.2.3 From a49a73acf5355145e45fb08e8bae824e8e429453 Mon Sep 17 00:00:00 2001 From: keis Date: Tue, 14 Dec 2010 12:31:03 +0100 Subject: Make the work with the new key events --- examples/data/plugins/keycmd.py | 111 ++++++++++++++-------------------------- 1 file changed, 37 insertions(+), 74 deletions(-) diff --git a/examples/data/plugins/keycmd.py b/examples/data/plugins/keycmd.py index 76e2d75..7a889cb 100644 --- a/examples/data/plugins/keycmd.py +++ b/examples/data/plugins/keycmd.py @@ -65,28 +65,6 @@ class Keylet(object): return key - def find_addition(self, modkey): - '''Key has just been pressed, check if this key + the held list - results in a modkey addition. Return that addition and remove all - modkeys that created it.''' - - # Intersection of (held list + modkey) and additions. - added = (self.held | set([modkey])) & set(self.additions.keys()) - for key in added: - if key == modkey or modkey in self.additions[key]: - self.held -= self.additions[key] - return key - - # Held list + ignored list + modkey. - modkeys = self.held | self.ignored | set([modkey]) - for (key, value) in self.additions.items(): - if modkeys.issuperset(value): - self.held -= value - return key - - return modkey - - def key_ignored(self, key): '''Check if the given key is ignored by any ignore rules.''' @@ -132,10 +110,7 @@ def add_modmap(uzbl, key, map): assert len(key) modmaps = uzbl.keylet.modmaps - if key[0] == "<" and key[-1] == ">": - key = key[1:-1] - - modmaps[key] = map + modmaps[key.strip('<>')] = map.strip('<>') uzbl.event("NEW_MODMAP", key, map) @@ -244,23 +219,17 @@ def clear_current(uzbl): clear_keycmd(uzbl) -def focus_changed(uzbl, *args): - '''Focus to the uzbl instance has now been lost which means all currently - held keys in the held list will not get a KEY_RELEASE event so clear the - entire held list.''' - - clear_modcmd(uzbl, clear_held=True) - - def update_event(uzbl, k, execute=True): '''Raise keycmd & modcmd update events.''' keycmd, modcmd = k.get_keycmd(), k.get_modcmd() if k.is_modcmd: + logger.debug('modcmd_update, %s' % modcmd) uzbl.event('MODCMD_UPDATE', k) else: + logger.debug('keycmd_update, %s' % keycmd) uzbl.event('KEYCMD_UPDATE', k) if uzbl.config.get('modcmd_updates', '1') == '1': @@ -293,31 +262,19 @@ def inject_str(str, index, inj): return "%s%s%s" % (str[:index], inj, str[index:]) -def get_keylet_and_key(uzbl, key, add=True): - '''Return the keylet and apply any transformations to the key as defined - by the modmapping or modkey addition rules. Return None if the key is - ignored.''' - +def parse_key_event(uzbl, key): + ''' Build a set from the modstate part of the event, and pass all keys through modmap ''' keylet = uzbl.keylet - key = keylet.modmap_key(key) - if len(key) == 1: - return (keylet, key) - - modkey = "<%s>" % key.strip("<>") - - if keylet.key_ignored(modkey): - if add: - keylet.ignored.add(modkey) - - elif modkey in keylet.ignored: - keylet.ignored.remove(modkey) - modkey = keylet.find_addition(modkey) - - if keylet.key_ignored(modkey): - return (keylet, None) - - return (keylet, modkey) + # Get the modstate part of the event if present + if ' ' in key: + modstate, key = key.split(' ') + modstate = set(['<%s>' % keylet.modmap_key(k) for k in modstate.split('|')]) + else: + modstate = set() + + key = keylet.modmap_key(key) + return modstate, key def key_press(uzbl, key): @@ -330,17 +287,18 @@ def key_press(uzbl, key): 5. If in modcmd mode the pressed key is added to the held keys list. 6. Keycmd is updated and events raised if anything is changed.''' - (k, key) = get_keylet_and_key(uzbl, key.strip()) - if not key: - return + k = uzbl.keylet + modstate, key = parse_key_event(uzbl, key) + modstate = set([m for m in modstate if not k.key_ignored(m)]) - if key.lower() == '' and not k.held and k.keycmd: + logger.debug('key press modstate=%s' % str(modstate)) + if key.lower() == 'space' and not modstate and k.keycmd: k.keycmd = inject_str(k.keycmd, k.cursor, ' ') k.cursor += 1 - elif not k.held and len(key) == 1: - + elif not modstate and len(key) == 1: if uzbl.config.get('keycmd_events', '1') != '1': + # TODO, make a note on what's going on here k.keycmd = '' k.cursor = 0 del uzbl.config['keycmd'] @@ -349,14 +307,17 @@ def key_press(uzbl, key): k.keycmd = inject_str(k.keycmd, k.cursor, key) k.cursor += 1 - elif len(key) > 1: - k.is_modcmd = True - if key not in k.held: - k.held.add(key) + elif len(key) == 1: + k.modcmd += key else: + if not k.key_ignored('<%s>' % key): + modstate.add('<%s>' % key) + + if len(modstate) > 0: k.is_modcmd = True - k.modcmd += key + + k.held = modstate update_event(uzbl, k) @@ -368,14 +329,16 @@ def key_release(uzbl, key): 2. If in a mod-command then raise a MODCMD_EXEC. 3. Check if any modkey is held, if so set modcmd mode. 4. Update the keycmd uzbl variable if anything changed.''' + k = uzbl.keylet + modstate, key = parse_key_event(uzbl, key) + modstate = set([m for m in modstate if not k.key_ignored(m)]) - (k, key) = get_keylet_and_key(uzbl, key.strip(), add=False) - - if key in k.held: + if len(key) > 1: if k.is_modcmd: + modstate.remove('<%s>' % key) + k.held = modstate uzbl.event('MODCMD_EXEC', k) - k.held.remove(key) clear_modcmd(uzbl) @@ -491,8 +454,6 @@ def init(uzbl): connect_dict(uzbl, { 'APPEND_KEYCMD': append_keycmd, - 'FOCUS_GAINED': focus_changed, - 'FOCUS_LOST': focus_changed, 'IGNORE_KEY': add_key_ignore, 'INJECT_KEYCMD': inject_keycmd, 'KEYCMD_BACKSPACE': keycmd_backspace, @@ -502,6 +463,8 @@ def init(uzbl): 'KEYCMD_CLEAR': clear_keycmd, 'KEY_PRESS': key_press, 'KEY_RELEASE': key_release, + 'MOD_PRESS': key_press, + 'MOD_RELEASE': key_release, 'MODKEY_ADDITION': modkey_addition_parse, 'MODMAP': modmap_parse, 'SET_CURSOR_POS': set_cursor_pos, -- cgit v1.2.3 From 46fa282a849e5a7dd6352438cb4cd07df4417a0e Mon Sep 17 00:00:00 2001 From: keis Date: Sun, 13 Feb 2011 15:02:30 +0100 Subject: remove some unused code --- examples/config/config | 6 +----- examples/data/plugins/keycmd.py | 44 ----------------------------------------- 2 files changed, 1 insertion(+), 49 deletions(-) diff --git a/examples/config/config b/examples/config/config index 1a09d65..aafa7dc 100644 --- a/examples/config/config +++ b/examples/config/config @@ -154,15 +154,11 @@ set useragent = Uzbl (Webkit @{WEBKIT_MAJOR}.@{WEBKIT_MINOR}) (@(+uname @modmap @modmap -#modkey_addition -@modkey_addition -@modkey_addition -@modkey_addition - #ignore_key @ignore_key @ignore_key @ignore_key +@ignore_key # --- Bind aliases ----------------------------------------------------------- diff --git a/examples/data/plugins/keycmd.py b/examples/data/plugins/keycmd.py index 7a889cb..bd65213 100644 --- a/examples/data/plugins/keycmd.py +++ b/examples/data/plugins/keycmd.py @@ -23,7 +23,6 @@ class Keylet(object): def __init__(self): # Modcmd tracking self.held = set() - self.ignored = set() self.modcmd = '' self.is_modcmd = False @@ -33,7 +32,6 @@ class Keylet(object): self.modmaps = {} self.ignores = {} - self.additions = {} def get_keycmd(self): @@ -146,45 +144,6 @@ def add_key_ignore(uzbl, glob): uzbl.event('NEW_KEY_IGNORE', glob) -def add_modkey_addition(uzbl, modkeys, result): - '''Add a modkey addition definition. - - Examples: - set mod_addition = request MODKEY_ADDITION - @mod_addition - @mod_addition - @mod_addition - ... - - Then: - @bind = - @bind o = - ... - ''' - - additions = uzbl.keylet.additions - modkeys = set(modkeys) - - assert len(modkeys) and result and result not in modkeys - - for (existing_result, existing_modkeys) in additions.items(): - if existing_result != result: - assert modkeys != existing_modkeys - - additions[result] = modkeys - uzbl.event('NEW_MODKEY_ADDITION', modkeys, result) - - -def modkey_addition_parse(uzbl, modkeys): - '''Parse modkey addition definition.''' - - keys = filter(None, map(unicode.strip, modkeys.split(" "))) - keys = ['<%s>' % key.strip("<>") for key in keys if key.strip("<>")] - - assert len(keys) > 1 - add_modkey_addition(uzbl, keys[:-1], keys[-1]) - - def clear_keycmd(uzbl, *args): '''Clear the keycmd for this uzbl instance.''' @@ -202,7 +161,6 @@ def clear_modcmd(uzbl, clear_held=False): k.modcmd = '' k.is_modcmd = False if clear_held: - k.ignored = set() k.held = set() del uzbl.config['modcmd'] @@ -465,7 +423,6 @@ def init(uzbl): 'KEY_RELEASE': key_release, 'MOD_PRESS': key_press, 'MOD_RELEASE': key_release, - 'MODKEY_ADDITION': modkey_addition_parse, 'MODMAP': modmap_parse, 'SET_CURSOR_POS': set_cursor_pos, 'SET_KEYCMD': set_keycmd, @@ -473,7 +430,6 @@ def init(uzbl): export_dict(uzbl, { 'add_key_ignore': add_key_ignore, - 'add_modkey_addition': add_modkey_addition, 'add_modmap': add_modmap, 'append_keycmd': append_keycmd, 'clear_current': clear_current, -- cgit v1.2.3 From bb65b56be88e8da15435205b3d1a9afbb48cad02 Mon Sep 17 00:00:00 2001 From: keis Date: Sun, 13 Feb 2011 15:11:52 +0100 Subject: stop tracking held keys in keylet --- examples/data/plugins/bind.py | 8 ++++---- examples/data/plugins/keycmd.py | 44 ++++++++++++++++------------------------- 2 files changed, 21 insertions(+), 31 deletions(-) diff --git a/examples/data/plugins/bind.py b/examples/data/plugins/bind.py index 69fd863..fc8b392 100644 --- a/examples/data/plugins/bind.py +++ b/examples/data/plugins/bind.py @@ -372,11 +372,11 @@ def mode_changed(uzbl, mode): uzbl.bindlet.reset() -def match_and_exec(uzbl, bind, depth, keylet, bindlet): +def match_and_exec(uzbl, bind, depth, modstate, keylet, bindlet): (on_exec, has_args, mod_cmd, glob, more) = bind[depth] cmd = keylet.modcmd if mod_cmd else keylet.keycmd - if mod_cmd and keylet.held != mod_cmd: + if mod_cmd and modstate != mod_cmd: return False if has_args: @@ -415,7 +415,7 @@ def match_and_exec(uzbl, bind, depth, keylet, bindlet): return True -def key_event(uzbl, keylet, mod_cmd=False, on_exec=False): +def key_event(uzbl, modstate, keylet, mod_cmd=False, on_exec=False): bindlet = uzbl.bindlet depth = bindlet.depth for bind in bindlet.get_binds(): @@ -423,7 +423,7 @@ def key_event(uzbl, keylet, mod_cmd=False, on_exec=False): if (bool(t[MOD_CMD]) != mod_cmd) or (t[ON_EXEC] != on_exec): continue - if match_and_exec(uzbl, bind, depth, keylet, bindlet): + if match_and_exec(uzbl, bind, depth, modstate, keylet, bindlet): return bindlet.after() diff --git a/examples/data/plugins/keycmd.py b/examples/data/plugins/keycmd.py index bd65213..8c5b458 100644 --- a/examples/data/plugins/keycmd.py +++ b/examples/data/plugins/keycmd.py @@ -17,12 +17,10 @@ def uzbl_escape(str): class Keylet(object): - '''Small per-instance object that tracks all the keys held and characters - typed.''' + '''Small per-instance object that tracks characters typed.''' def __init__(self): # Modcmd tracking - self.held = set() self.modcmd = '' self.is_modcmd = False @@ -46,7 +44,7 @@ class Keylet(object): if not self.is_modcmd: return '' - return ''.join(self.held) + self.modcmd + return self.modcmd def modmap_key(self, key): @@ -80,9 +78,6 @@ class Keylet(object): if self.is_modcmd: l.append('modcmd=%r' % self.get_modcmd()) - elif self.held: - l.append('held=%r' % ''.join(sorted(self.held))) - if self.keycmd: l.append('keycmd=%r' % self.get_keycmd()) @@ -154,14 +149,12 @@ def clear_keycmd(uzbl, *args): uzbl.event('KEYCMD_CLEARED') -def clear_modcmd(uzbl, clear_held=False): +def clear_modcmd(uzbl): '''Clear the modcmd for this uzbl instance.''' k = uzbl.keylet k.modcmd = '' k.is_modcmd = False - if clear_held: - k.held = set() del uzbl.config['modcmd'] uzbl.event('MODCMD_CLEARED') @@ -177,21 +170,21 @@ def clear_current(uzbl): clear_keycmd(uzbl) -def update_event(uzbl, k, execute=True): +def update_event(uzbl, modstate, k, execute=True): '''Raise keycmd & modcmd update events.''' - keycmd, modcmd = k.get_keycmd(), k.get_modcmd() + keycmd, modcmd = k.get_keycmd(), ''.join(modstate) + k.get_modcmd() if k.is_modcmd: logger.debug('modcmd_update, %s' % modcmd) - uzbl.event('MODCMD_UPDATE', k) + uzbl.event('MODCMD_UPDATE', modstate, k) else: logger.debug('keycmd_update, %s' % keycmd) - uzbl.event('KEYCMD_UPDATE', k) + uzbl.event('KEYCMD_UPDATE', modstate, k) if uzbl.config.get('modcmd_updates', '1') == '1': - new_modcmd = k.get_modcmd() + new_modcmd = ''.join(modstate) + k.get_modcmd() if not new_modcmd: del uzbl.config['modcmd'] @@ -275,9 +268,7 @@ def key_press(uzbl, key): if len(modstate) > 0: k.is_modcmd = True - k.held = modstate - - update_event(uzbl, k) + update_event(uzbl, modstate, k) def key_release(uzbl, key): @@ -294,8 +285,7 @@ def key_release(uzbl, key): if len(key) > 1: if k.is_modcmd: modstate.remove('<%s>' % key) - k.held = modstate - uzbl.event('MODCMD_EXEC', k) + uzbl.event('MODCMD_EXEC', modstate, k) clear_modcmd(uzbl) @@ -306,7 +296,7 @@ def set_keycmd(uzbl, keycmd): k = uzbl.keylet k.keycmd = keycmd k.cursor = len(keycmd) - update_event(uzbl, k, False) + update_event(uzbl, set(), k, False) def inject_keycmd(uzbl, keycmd): @@ -315,7 +305,7 @@ def inject_keycmd(uzbl, keycmd): k = uzbl.keylet k.keycmd = inject_str(k.keycmd, k.cursor, keycmd) k.cursor += len(keycmd) - update_event(uzbl, k, False) + update_event(uzbl, set(), k, False) def append_keycmd(uzbl, keycmd): @@ -324,7 +314,7 @@ def append_keycmd(uzbl, keycmd): k = uzbl.keylet k.keycmd += keycmd k.cursor = len(k.keycmd) - update_event(uzbl, k, False) + update_event(uzbl, set(), k, False) def keycmd_strip_word(uzbl, seps): @@ -346,7 +336,7 @@ def keycmd_strip_word(uzbl, seps): head = head[:rfind] if rfind + 1 else '' k.keycmd = head + tail k.cursor = len(head) - update_event(uzbl, k, False) + update_event(uzbl, set(), k, False) def keycmd_backspace(uzbl, *args): @@ -358,7 +348,7 @@ def keycmd_backspace(uzbl, *args): k.keycmd = k.keycmd[:k.cursor-1] + k.keycmd[k.cursor:] k.cursor -= 1 - update_event(uzbl, k, False) + update_event(uzbl, set(), k, False) def keycmd_delete(uzbl, *args): @@ -369,7 +359,7 @@ def keycmd_delete(uzbl, *args): return k.keycmd = k.keycmd[:k.cursor] + k.keycmd[k.cursor+1:] - update_event(uzbl, k, False) + update_event(uzbl, set(), k, False) def keycmd_exec_current(uzbl, *args): @@ -403,7 +393,7 @@ def set_cursor_pos(uzbl, index): cursor = len(k.keycmd) k.cursor = cursor - update_event(uzbl, k, False) + update_event(uzbl, set(), k, False) # plugin init hook -- cgit v1.2.3 From 891786d26677ba535d454839e40b0660636b7039 Mon Sep 17 00:00:00 2001 From: keis Date: Fri, 11 Mar 2011 22:41:39 +0100 Subject: drop extra whitespace in key events --- src/events.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/events.c b/src/events.c index 12f9d83..a6b1776 100644 --- a/src/events.c +++ b/src/events.c @@ -235,7 +235,7 @@ get_modifier_mask(guint state) { g_string_append(modifiers,"Button5|"); if(modifiers->str[modifiers->len-1] == '|') - g_string_overwrite(modifiers, modifiers->len-1, " "); + g_string_truncate(modifiers, modifiers->len-1); } return g_string_free(modifiers, FALSE); -- cgit v1.2.3 From 06c8a781c660b573ac64eb40cace7aa81add3312 Mon Sep 17 00:00:00 2001 From: keis Date: Fri, 11 Mar 2011 22:41:55 +0100 Subject: use splitquoted to parse key event --- examples/data/plugins/keycmd.py | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/examples/data/plugins/keycmd.py b/examples/data/plugins/keycmd.py index 8c5b458..5e3776f 100644 --- a/examples/data/plugins/keycmd.py +++ b/examples/data/plugins/keycmd.py @@ -217,12 +217,8 @@ def parse_key_event(uzbl, key): ''' Build a set from the modstate part of the event, and pass all keys through modmap ''' keylet = uzbl.keylet - # Get the modstate part of the event if present - if ' ' in key: - modstate, key = key.split(' ') - modstate = set(['<%s>' % keylet.modmap_key(k) for k in modstate.split('|')]) - else: - modstate = set() + modstate, key = splitquoted(key) + modstate = set(['<%s>' % keylet.modmap_key(k) for k in modstate.split('|')]) key = keylet.modmap_key(key) return modstate, key -- cgit v1.2.3 From 16f10abea2c634b462ba7157e63383b076b75bcc Mon Sep 17 00:00:00 2001 From: keis Date: Mon, 14 Mar 2011 19:55:17 +0100 Subject: handle the case of no modkeys held --- examples/data/plugins/keycmd.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/data/plugins/keycmd.py b/examples/data/plugins/keycmd.py index 5e3776f..952fbac 100644 --- a/examples/data/plugins/keycmd.py +++ b/examples/data/plugins/keycmd.py @@ -218,7 +218,7 @@ def parse_key_event(uzbl, key): keylet = uzbl.keylet modstate, key = splitquoted(key) - modstate = set(['<%s>' % keylet.modmap_key(k) for k in modstate.split('|')]) + modstate = set(['<%s>' % keylet.modmap_key(k) for k in modstate.split('|') if k]) key = keylet.modmap_key(key) return modstate, key -- cgit v1.2.3 From 354d530231cb06fb8aa046b1a6442586aec8847f Mon Sep 17 00:00:00 2001 From: keis Date: Mon, 14 Mar 2011 20:53:31 +0100 Subject: keycmd comments and docs --- README | 12 ++++++------ docs/README.uzbl-event-manager | 27 ++++++++++++++++++++++++--- examples/data/plugins/keycmd.py | 13 +++++-------- 3 files changed, 35 insertions(+), 17 deletions(-) diff --git a/README b/README index c5d353b..08c6356 100644 --- a/README +++ b/README @@ -677,10 +677,14 @@ Events have this format: `uri`. * `EVENT [uzbl_instance_name] LINK_UNHOVER uri`: The mouse leaves the link `uri`. -* `EVENT [uzbl_instance_name] KEY_PRESS key_name`: The key (or mouse button) +* `EVENT [uzbl_instance_name] KEY_PRESS 'mod_state' key_name`: The key (or mouse button) `key_name` is pressed. -* `EVENT [uzbl_instance_name] KEY_RELEASE key_name`: The key (or mouse button) +* `EVENT [uzbl_instance_name] KEY_RELEASE 'mod_state' key_name`: The key (or mouse button) `key_name` is released. +* `EVENT [uzbl_instance_name] MOD_PRESS 'mod_state' mod_name`: A key mapped to + `mod_name` is pressed. +* `EVENT [uzbl_instance_name] MOD_RELEASE 'mod_state' mod_name`: A key mapped to + `mod_name` is released. * `EVENT [uzbl_instance_name] SELECTION_CHANGED selected_text`: When text is selected in the `uzbl` window. * `EVENT [uzbl_instance_name] NEW_WINDOW uri`: Request to creation of new `uzbl` window, @@ -758,10 +762,6 @@ Events/requests which the EM and its plugins listens for when the `` key or button is pressed. * `IGNORE_KEY`: Ignore a key pattern, specified by ``. - `request IGNORE_KEY ` -* `MODKEY_ADDITION`: Create a compound modkey from multiple individual keys. - - `request MODKEY_ADDITION `: The modkey - `` is considered pressed when all of ``, ``, and - `` are pressed. * `TOGGLE_MODES` - `request TOGGLE_MODES ... ` * `APPEND_KEYCMD`: Append a string to the current keycmd. diff --git a/docs/README.uzbl-event-manager b/docs/README.uzbl-event-manager index 23e185c..da26847 100644 --- a/docs/README.uzbl-event-manager +++ b/docs/README.uzbl-event-manager @@ -26,15 +26,36 @@ MODE_CHANGE ### keycmd.py ### - Tracks the currently entered command -- Connects To: FOCUS_GAINED, FOCUS_LOST, KEY_PRESS, KEY_RELEASE, (APPEND_KEYCMD, +- Connects To: KEY_PRESS, KEY_RELEASE, MOD_PRESS, MOD_RELEASE, (APPEND_KEYCMD, IGNORE_KEY, INJECT_KEYCMD, KEYCMD_BACKSPACE, KEYCMD_DELETE, - KEYCMD_EXEC_CURRENT, KEYCMD_STRIP_WORD, MODKEY_ADDITION, MODMAP, + KEYCMD_EXEC_CURRENT, KEYCMD_STRIP_WORD, KEYCMD_CLEAR, MODMAP, SET_CURSOR_POS, SET_KEYCMD) -- Emits: KEYCMD_UPDATE, KEYCMD_EXEC, MODCMD_UPDATE, MODCMD_EXEC +- Emits: KEYCMD_UPDATE, KEYCMD_EXEC, MODCMD_UPDATE, MODCMD_EXEC, KEYCMD_CLEARED + MODCMD_CLEARED Maintains a command line that is manipulated by simple keypresses and a number of events. +APPEND_KEYCMD + Appends `str` to the end of the keycmd + +INJECT_KEYCMD + Inserts `str` at the cursor position + +KEYCMD_BACKSPACE + Removes the character at the cursor position in the keycmd + +KEYCMD_DELETE + Removes the character after the cursor position in the keycmd + +KEYCMD_EXEC_CURRENT + Raise a KEYCMD_EXEC with the current keylet and then clear the keycmd + +KEYCMD_STRIP_WORD [] + Removes the last word from the keycmd, similar to readline ^W + +KEYCMD_CLEAR + Clears the keycmd and raises KEYCMD_CLEARED ### bind.py ### - Provides support for key bindings diff --git a/examples/data/plugins/keycmd.py b/examples/data/plugins/keycmd.py index 952fbac..99f92af 100644 --- a/examples/data/plugins/keycmd.py +++ b/examples/data/plugins/keycmd.py @@ -228,11 +228,10 @@ def key_press(uzbl, key): '''Handle KEY_PRESS events. Things done by this function include: 1. Ignore all shift key presses (shift can be detected by capital chars) - 3. In non-modcmd mode: + 2. In non-modcmd mode: a. append char to keycmd - 4. If not in modcmd mode and a modkey was pressed set modcmd mode. - 5. If in modcmd mode the pressed key is added to the held keys list. - 6. Keycmd is updated and events raised if anything is changed.''' + 3. If not in modcmd mode and a modkey was pressed set modcmd mode. + 4. Keycmd is updated and events raised if anything is changed.''' k = uzbl.keylet modstate, key = parse_key_event(uzbl, key) @@ -270,10 +269,8 @@ def key_press(uzbl, key): def key_release(uzbl, key): '''Respond to KEY_RELEASE event. Things done by this function include: - 1. Remove the key from the keylet held list. - 2. If in a mod-command then raise a MODCMD_EXEC. - 3. Check if any modkey is held, if so set modcmd mode. - 4. Update the keycmd uzbl variable if anything changed.''' + 1. If in a mod-command then raise a MODCMD_EXEC. + 2. Update the keycmd uzbl variable if anything changed.''' k = uzbl.keylet modstate, key = parse_key_event(uzbl, key) modstate = set([m for m in modstate if not k.key_ignored(m)]) -- cgit v1.2.3 From 3f8b387500eca9f108883b5c3fbf68099f5abbe6 Mon Sep 17 00:00:00 2001 From: keis Date: Tue, 15 Mar 2011 17:56:08 +0100 Subject: placeholder translation of keyval to mod --- src/events.c | 41 ++++++++++++++++++++++++++++++++++------- 1 file changed, 34 insertions(+), 7 deletions(-) diff --git a/src/events.c b/src/events.c index a6b1776..5ff9a52 100644 --- a/src/events.c +++ b/src/events.c @@ -241,6 +241,30 @@ get_modifier_mask(guint state) { return g_string_free(modifiers, FALSE); } +guint key_to_modifier(guint keyval) { + /* FIXME + * Should really use XGetModifierMapping and/or Xkb to get actual mod keys + */ + switch(keyval) { + case GDK_KEY_Shift_L: + case GDK_KEY_Shift_R: + return GDK_SHIFT_MASK; + case GDK_KEY_Control_L: + case GDK_KEY_Control_R: + return GDK_CONTROL_MASK; + case GDK_KEY_Alt_L: + case GDK_KEY_Alt_R: + return GDK_MOD1_MASK; + case GDK_KEY_Super_L: + case GDK_KEY_Super_R: + return GDK_MOD4_MASK; + case GDK_KEY_ISO_Level3_Shift: + return GDK_MOD5_MASK; + default: + return 0; + } +} + /* Transform gdk key events to our own events */ void key_to_event(guint keyval, guint state, guint is_modifier, gint mode) { @@ -249,15 +273,22 @@ key_to_event(guint keyval, guint state, guint is_modifier, gint mode) { gchar *keyname; guint32 ukval = gdk_keyval_to_unicode(keyval); gchar *modifiers = NULL; + guint mod; /* check modifier state*/ modifiers = get_modifier_mask(state); + if(is_modifier && (mod = key_to_modifier (keyval))) { + send_event(mode == GDK_KEY_PRESS ? MOD_PRESS : MOD_RELEASE, NULL, + TYPE_STR, modifiers, + TYPE_NAME, get_modifier_mask (mod), + NULL); + } /* check for printable unicode char */ /* TODO: Pass the keyvals through a GtkIMContext so that * we also get combining chars right */ - if(g_unichar_isgraph(ukval)) { + else if(g_unichar_isgraph(ukval)) { ulen = g_unichar_to_utf8(ukval, ucs); ucs[ulen] = 0; @@ -266,12 +297,8 @@ key_to_event(guint keyval, guint state, guint is_modifier, gint mode) { } /* send keysym for non-printable chars */ else if((keyname = gdk_keyval_name(keyval))){ - if(is_modifier) - send_event(mode == GDK_KEY_PRESS ? MOD_PRESS : MOD_RELEASE, NULL, - TYPE_STR, modifiers, TYPE_NAME, keyname , NULL); - else - send_event(mode == GDK_KEY_PRESS ? KEY_PRESS : KEY_RELEASE, NULL, - TYPE_STR, modifiers, TYPE_NAME, keyname , NULL); + send_event(mode == GDK_KEY_PRESS ? KEY_PRESS : KEY_RELEASE, NULL, + TYPE_STR, modifiers, TYPE_NAME, keyname, NULL); } g_free(modifiers); -- cgit v1.2.3 From 3813b1885e478e3c2a178cbf3136ce597c2d77f1 Mon Sep 17 00:00:00 2001 From: keis Date: Wed, 16 Mar 2011 19:32:17 +0100 Subject: replace alt with mod1 in config --- examples/config/config | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/config/config b/examples/config/config index aafa7dc..146d515 100644 --- a/examples/config/config +++ b/examples/config/config @@ -286,8 +286,8 @@ set ebind = @mode_bind global,-insert # Use socat to directly inject commands into uzbl-core and view events # raised by uzbl-core: -@cbind t = sh 'xterm -e "socat unix-connect:\"$UZBL_SOCKET\" -"' -#@cbind t = sh 'urxvt -e socat unix-connect:"$UZBL_SOCKET" -' +@cbind t = sh 'xterm -e "socat unix-connect:\"$UZBL_SOCKET\" -"' +#@cbind t = sh 'urxvt -e socat unix-connect:"$UZBL_SOCKET" -' # Uri opening prompts @cbind o_ = uri %s -- cgit v1.2.3 From d2c7da7a03c8f9b76f78636a2374f439dae5c72d Mon Sep 17 00:00:00 2001 From: keis Date: Wed, 16 Mar 2011 19:42:22 +0100 Subject: use updated modstate for key events --- examples/data/plugins/keycmd.py | 2 -- src/events.c | 8 ++++---- 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/examples/data/plugins/keycmd.py b/examples/data/plugins/keycmd.py index 99f92af..5fb7e8a 100644 --- a/examples/data/plugins/keycmd.py +++ b/examples/data/plugins/keycmd.py @@ -273,11 +273,9 @@ def key_release(uzbl, key): 2. Update the keycmd uzbl variable if anything changed.''' k = uzbl.keylet modstate, key = parse_key_event(uzbl, key) - modstate = set([m for m in modstate if not k.key_ignored(m)]) if len(key) > 1: if k.is_modcmd: - modstate.remove('<%s>' % key) uzbl.event('MODCMD_EXEC', modstate, k) clear_modcmd(uzbl) diff --git a/src/events.c b/src/events.c index 5ff9a52..c588729 100644 --- a/src/events.c +++ b/src/events.c @@ -273,12 +273,12 @@ key_to_event(guint keyval, guint state, guint is_modifier, gint mode) { gchar *keyname; guint32 ukval = gdk_keyval_to_unicode(keyval); gchar *modifiers = NULL; - guint mod; + guint mod = key_to_modifier (keyval); - /* check modifier state*/ - modifiers = get_modifier_mask(state); + /* Get modifier state including this key press/release */ + modifiers = get_modifier_mask(mode == GDK_KEY_PRESS ? state | mod : state & ~mod); - if(is_modifier && (mod = key_to_modifier (keyval))) { + if(is_modifier && mod) { send_event(mode == GDK_KEY_PRESS ? MOD_PRESS : MOD_RELEASE, NULL, TYPE_STR, modifiers, TYPE_NAME, get_modifier_mask (mod), -- cgit v1.2.3 From d09026aa3c9a4e8b4fefc114fb9cf126a454d01f Mon Sep 17 00:00:00 2001 From: keis Date: Fri, 18 Mar 2011 16:15:48 +0100 Subject: Ignored keys don't enter modcmd but works in modcmd * Makes Shift+Insert bind work without breaking normal shift functionality. --- examples/config/config | 2 +- examples/data/plugins/keycmd.py | 12 +++++------- 2 files changed, 6 insertions(+), 8 deletions(-) diff --git a/examples/config/config b/examples/config/config index 146d515..8c706df 100644 --- a/examples/config/config +++ b/examples/config/config @@ -322,7 +322,7 @@ set ebind = @mode_bind global,-insert # Start a new uzbl instance from the page in primary selection @cbind 'p = sh 'echo "event REQ_NEW_WINDOW $(xclip -o)" > "$UZBL_FIFO"' # paste primary selection into keycmd at the cursor position -@bind = sh 'echo "event INJECT_KEYCMD $(xclip -o | sed s/\\\@/%40/g)" > "$UZBL_FIFO"' +@bind = sh 'echo "event INJECT_KEYCMD $(xclip -o | sed s/\\\@/%40/g)" > "$UZBL_FIFO"' # Bookmark inserting binds @cbind b_ = sh 'echo `printf "$UZBL_URI %s"` >> "$XDG_DATA_HOME"/uzbl/bookmarks' diff --git a/examples/data/plugins/keycmd.py b/examples/data/plugins/keycmd.py index 5fb7e8a..198b859 100644 --- a/examples/data/plugins/keycmd.py +++ b/examples/data/plugins/keycmd.py @@ -185,7 +185,7 @@ def update_event(uzbl, modstate, k, execute=True): if uzbl.config.get('modcmd_updates', '1') == '1': new_modcmd = ''.join(modstate) + k.get_modcmd() - if not new_modcmd: + if not new_modcmd or not k.is_modcmd: del uzbl.config['modcmd'] elif new_modcmd == modcmd: @@ -235,14 +235,14 @@ def key_press(uzbl, key): k = uzbl.keylet modstate, key = parse_key_event(uzbl, key) - modstate = set([m for m in modstate if not k.key_ignored(m)]) + k.is_modcmd = any(not k.key_ignored(m) for m in modstate) logger.debug('key press modstate=%s' % str(modstate)) - if key.lower() == 'space' and not modstate and k.keycmd: + if key.lower() == 'space' and not k.is_modcmd and k.keycmd: k.keycmd = inject_str(k.keycmd, k.cursor, ' ') k.cursor += 1 - elif not modstate and len(key) == 1: + elif not k.is_modcmd and len(key) == 1: if uzbl.config.get('keycmd_events', '1') != '1': # TODO, make a note on what's going on here k.keycmd = '' @@ -259,9 +259,7 @@ def key_press(uzbl, key): else: if not k.key_ignored('<%s>' % key): modstate.add('<%s>' % key) - - if len(modstate) > 0: - k.is_modcmd = True + k.is_modcmd = True update_event(uzbl, modstate, k) -- cgit v1.2.3 From d17aa83d99e3189a7efd04e4a250643c469d8298 Mon Sep 17 00:00:00 2001 From: Brendan Taylor Date: Mon, 18 Apr 2011 19:51:00 -0600 Subject: bind.py expects KEYCMD_EXEC to include a modstate parameter --- examples/data/plugins/history.py | 2 +- examples/data/plugins/keycmd.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/data/plugins/history.py b/examples/data/plugins/history.py index 5e9e4e1..f42f86f 100644 --- a/examples/data/plugins/history.py +++ b/examples/data/plugins/history.py @@ -83,7 +83,7 @@ class History(object): def __str__(self): return "(History %s, %s)" % (self.cursor, self.prompt) -def keycmd_exec(uzbl, keylet): +def keycmd_exec(uzbl, modstate, keylet): cmd = keylet.get_keycmd() if cmd: uzbl.history.add(cmd) diff --git a/examples/data/plugins/keycmd.py b/examples/data/plugins/keycmd.py index 198b859..1bb70e3 100644 --- a/examples/data/plugins/keycmd.py +++ b/examples/data/plugins/keycmd.py @@ -355,7 +355,7 @@ def keycmd_exec_current(uzbl, *args): '''Raise a KEYCMD_EXEC with the current keylet and then clear the keycmd.''' - uzbl.event('KEYCMD_EXEC', uzbl.keylet) + uzbl.event('KEYCMD_EXEC', set(), uzbl.keylet) clear_keycmd(uzbl) -- cgit v1.2.3 From 169f53f110ca096d78c986402b5f9237924b8fbc Mon Sep 17 00:00:00 2001 From: Brendan Taylor Date: Mon, 18 Apr 2011 20:11:10 -0600 Subject: escape ' in KEY_PRESS/RELEASE events --- src/events.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/events.c b/src/events.c index c588729..62d6414 100644 --- a/src/events.c +++ b/src/events.c @@ -160,11 +160,13 @@ vsend_event(int type, const gchar *custom_event, va_list vargs) { g_string_append_printf (event_message, "%d", va_arg (vargs, int)); break; case TYPE_STR: + /* a string that needs to be escaped */ g_string_append_c (event_message, '\''); append_escaped (event_message, va_arg (vargs, char*)); g_string_append_c (event_message, '\''); break; case TYPE_FORMATTEDSTR: + /* a string has already been escaped */ g_string_append (event_message, va_arg (vargs, char*)); break; case TYPE_NAME: @@ -293,7 +295,7 @@ key_to_event(guint keyval, guint state, guint is_modifier, gint mode) { ucs[ulen] = 0; send_event(mode == GDK_KEY_PRESS ? KEY_PRESS : KEY_RELEASE, NULL, - TYPE_STR, modifiers, TYPE_FORMATTEDSTR, ucs, NULL); + TYPE_STR, modifiers, TYPE_STR, ucs, NULL); } /* send keysym for non-printable chars */ else if((keyname = gdk_keyval_name(keyval))){ -- cgit v1.2.3 From d0b919ed5fb7fd42f6f4851443790e5c87116128 Mon Sep 17 00:00:00 2001 From: Brendan Taylor Date: Sun, 24 Apr 2011 00:48:53 -0600 Subject: allow processes other than uzbl-tabbed to start uzbl-browser instances that appear in -tabbed not entirely sure that this is useful yet. --- bin/uzbl-tabbed | 47 ++++++++++++++++++++++++++++++++--------------- src/uzbl-core.c | 8 ++++++-- src/uzbl-core.h | 1 + 3 files changed, 39 insertions(+), 17 deletions(-) diff --git a/bin/uzbl-tabbed b/bin/uzbl-tabbed index a15967a..d63d6de 100755 --- a/bin/uzbl-tabbed +++ b/bin/uzbl-tabbed @@ -303,12 +303,13 @@ class SocketClient: # List of UzblInstance objects not already linked with a SocketClient instances_queue = {} - def __init__(self, socket): + def __init__(self, socket, uzbl_tabbed): self._buffer = "" self._socket = socket self._watchers = [io_add_watch(socket, IO_IN, self._socket_recv),\ io_add_watch(socket, IO_HUP, self._socket_closed)] self.uzbl = None + self.uzbl_tabbed = uzbl_tabbed def _socket_recv(self, fd, condition): @@ -341,13 +342,17 @@ class SocketClient: if cmd: self.uzbl.parse_command(cmd) else: - name = re.findall('^EVENT \[(\d+-\d+)\] INSTANCE_START \d+$', self._buffer, re.M) + name = re.findall('^EVENT \[([^]]+)\] INSTANCE_START \d+$', self._buffer, re.M) uzbl = self.instances_queue.get(name[0]) if uzbl: + # we've found the uzbl we were waiting for del self.instances_queue[name[0]] - self.uzbl = uzbl - self.uzbl.got_socket(self) - self._feed("") + else: + # an unsolicited uzbl has connected, how exciting! + uzbl = UzblInstance(self.uzbl_tabbed, None, '', '', False) + self.uzbl = uzbl + self.uzbl.got_socket(self) + self._feed("") def send(self, data): '''Child socket send function.''' @@ -376,6 +381,12 @@ class EventDispatcher: return method(*args) + def plug_created(self, plug_id): + if not self.uzbl.tab: + tab = self.parent.create_tab() + tab.add_id(int(plug_id)) + self.uzbl.set_tab(tab) + def title_changed(self, title): self.uzbl.title = title.strip() self.uzbl.title_changed(False) @@ -477,10 +488,10 @@ class EventDispatcher: class UzblInstance: '''Uzbl instance meta-data/meta-action object.''' - def __init__(self, parent, tab, name, uri, title, switch): + def __init__(self, parent, name, uri, title, switch): self.parent = parent - self.tab = tab + self.tab = None self.dispatcher = EventDispatcher(self) self.name = name @@ -490,8 +501,11 @@ class UzblInstance: self._client = None self._switch = switch # Switch to tab after loading ? - self.title_changed() + def set_tab(self, tab): + self.tab = tab + self.title_changed() + self.parent.tabs[self.tab] = self def got_socket(self, client): '''Uzbl instance is now connected''' @@ -763,7 +777,7 @@ class UzblTabbed: '''A new uzbl instance was created''' client, _ = sock.accept() - self.clients[client] = SocketClient(client) + self.clients[client] = SocketClient(client, self) return True @@ -1045,6 +1059,12 @@ class UzblTabbed: return False + def create_tab(self, next = False): + tab = gtk.Socket() + tab.show() + self.notebook.insert_page(tab, position=next and self.notebook.get_current_page() + 1 or -1) + self.notebook.set_tab_reorderable(tab, True) + return tab def new_tab(self, uri='', title='', switch=None, next=False): '''Add a new tab to the notebook and start a new instance of uzbl. @@ -1052,10 +1072,7 @@ class UzblTabbed: when you need to load multiple tabs at a time (I.e. like when restoring a session from a file).''' - tab = gtk.Socket() - tab.show() - self.notebook.insert_page(tab, position=next and self.notebook.get_current_page() + 1 or -1) - self.notebook.set_tab_reorderable(tab, True) + tab = self.create_tab(next) sid = tab.get_id() uri = uri.strip() name = "%d-%d" % (os.getpid(), self.next_pid()) @@ -1070,9 +1087,9 @@ class UzblTabbed: '--connect-socket', self.socket_path, '--uri', str(uri)] gobject.spawn_async(cmd, flags=gobject.SPAWN_SEARCH_PATH) - uzbl = UzblInstance(self, tab, name, uri, title, switch) + uzbl = UzblInstance(self, name, uri, title, switch) + uzbl.set_tab(tab) SocketClient.instances_queue[name] = uzbl - self.tabs[tab] = uzbl def clean_slate(self): diff --git a/src/uzbl-core.c b/src/uzbl-core.c index c095a7f..e461a4c 100644 --- a/src/uzbl-core.c +++ b/src/uzbl-core.c @@ -51,8 +51,11 @@ GOptionEntry entries[] = { "Name of the current instance (defaults to Xorg window id or random for GtkSocket mode)", "NAME" }, { "config", 'c', 0, G_OPTION_ARG_STRING, &uzbl.state.config_file, "Path to config file or '-' for stdin", "FILE" }, + /* TODO: explain the difference between these two options */ { "socket", 's', 0, G_OPTION_ARG_INT, &uzbl.state.socket_id, - "Xembed Socket ID", "SOCKET" }, + "Xembed socket ID, this window should embed itself", "SOCKET" }, + { "embed", 'e', 0, G_OPTION_ARG_NONE, &uzbl.state.embed, + "Whether this window should expect to be embedded", NULL }, { "connect-socket", 0, 0, G_OPTION_ARG_STRING_ARRAY, &uzbl.state.connect_socket_names, "Connect to server socket for event managing", "CSOCKET" }, { "print-events", 'p', 0, G_OPTION_ARG_NONE, &uzbl.state.events_stdout, @@ -1540,6 +1543,7 @@ create_window() { GtkPlug* create_plug() { + if(uzbl.state.embed) uzbl.state.socket_id = 0; GtkPlug* plug = GTK_PLUG (gtk_plug_new (uzbl.state.socket_id)); g_signal_connect (G_OBJECT (plug), "destroy", G_CALLBACK (destroy_cb), NULL); g_signal_connect (G_OBJECT (plug), "key-press-event", G_CALLBACK (key_press_cb), NULL); @@ -1746,7 +1750,7 @@ initialize(int argc, char** argv) { } /* Embedded mode */ - if (uzbl.state.socket_id) + if (uzbl.state.socket_id || uzbl.state.embed) uzbl.state.plug_mode = TRUE; if (!g_thread_supported()) diff --git a/src/uzbl-core.h b/src/uzbl-core.h index be8fccd..07b6f99 100644 --- a/src/uzbl-core.h +++ b/src/uzbl-core.h @@ -109,6 +109,7 @@ typedef struct { gchar* executable_path; gchar* searchtx; gboolean verbose; + gboolean embed; GdkEventButton* last_button; gchar* last_result; gboolean plug_mode; -- cgit v1.2.3 From 8a184cdb2dc5c3f6cb907beeaa82287a2d782b6a Mon Sep 17 00:00:00 2001 From: Brendan Taylor Date: Sun, 24 Apr 2011 02:15:40 -0600 Subject: uzbl-tabbed: refactor the SocketClient class --- bin/uzbl-tabbed | 209 +++++++++++++++++++++++++++++--------------------------- 1 file changed, 107 insertions(+), 102 deletions(-) diff --git a/bin/uzbl-tabbed b/bin/uzbl-tabbed index d63d6de..889793a 100755 --- a/bin/uzbl-tabbed +++ b/bin/uzbl-tabbed @@ -298,7 +298,7 @@ def escape(s): return s class SocketClient: - '''Represents a Uzbl instance, which is not necessarly linked with a UzblInstance''' + '''Represents a connection to the uzbl-tabbed socket.''' # List of UzblInstance objects not already linked with a SocketClient instances_queue = {} @@ -308,8 +308,10 @@ class SocketClient: self._socket = socket self._watchers = [io_add_watch(socket, IO_IN, self._socket_recv),\ io_add_watch(socket, IO_HUP, self._socket_closed)] + self.uzbl = None self.uzbl_tabbed = uzbl_tabbed + self.dispatcher = GlobalEventDispatcher(uzbl_tabbed) def _socket_recv(self, fd, condition): @@ -329,24 +331,38 @@ class SocketClient: '''An Uzbl instance sent some data, parse it''' self._buffer += data - if self.uzbl: - if "\n" in self._buffer: - cmds = self._buffer.split("\n") - if cmds[-1]: # Last command has been received incomplete, don't process it - self._buffer, cmds = cmds[-1], cmds[:-1] - else: - self._buffer = "" + if "\n" in self._buffer: + cmds = self._buffer.split("\n") - for cmd in cmds: - if cmd: - self.uzbl.parse_command(cmd) - else: - name = re.findall('^EVENT \[([^]]+)\] INSTANCE_START \d+$', self._buffer, re.M) - uzbl = self.instances_queue.get(name[0]) + if cmds[-1]: # Last command has been received incomplete, don't process it + self._buffer, cmds = cmds[-1], cmds[:-1] + else: + self._buffer = "" + + for cmd in cmds: + if cmd: + self.handle_event(cmd) + + def handle_event(self, cmd): + cmd = parse_event(cmd) + message, instance_name, message_type = cmd[0:3] + args = cmd[3:] + + if not message == "EVENT": + next + + # strip the surrounding [] + instance_name = instance_name[1:-1] + + if self.uzbl: + if not self.dispatcher.dispatch(message_type, args): + self.uzbl.dispatcher.dispatch(message_type, args) + elif message_type == 'INSTANCE_START': + uzbl = self.instances_queue.get(instance_name) if uzbl: # we've found the uzbl we were waiting for - del self.instances_queue[name[0]] + del self.instances_queue[instance_name] else: # an unsolicited uzbl has connected, how exciting! uzbl = UzblInstance(self.uzbl_tabbed, None, '', '', False) @@ -368,18 +384,78 @@ class SocketClient: map(source_remove, self._watchers) self._watchers = [] -class EventDispatcher: - def __init__(self, uzbl): - self.uzbl = uzbl - self.parent = self.uzbl.parent +def unquote(s): + '''Removes quotation marks around strings if any and interprets + \\-escape sequences using `string_escape`''' + if s and s[0] == s[-1] and s[0] in ['"', "'"]: + s = s[1:-1] + return s.encode('utf-8').decode('string_escape').decode('utf-8') + +_splitquoted = re.compile("( |\"(?:\\\\.|[^\"])*?\"|'(?:\\\\.|[^'])*?')") +def parse_event(text): + '''Splits string on whitespace while respecting quotations''' + return [unquote(p) for p in _splitquoted.split(text) if p.strip()] + +class EventDispatcher: def dispatch(self, message_type, args): + '''Returns True if the message was handled, False otherwise.''' + method = getattr(self, message_type.lower(), None) if method is None: - return + return False + + method(*args) + return True + +class GlobalEventDispatcher(EventDispatcher): + def __init__(self, uzbl_tabbed): + self.uzbl_tabbed = uzbl_tabbed + + def new_tab(self, uri = ''): + self.uzbl_tabbed.new_tab(uri) + + def new_tab_bg(self, uri = ''): + self.uzbl_tabbed.new_tab(uri, switch = False) + + def new_tab_next(self, uri = ''): + self.uzbl_tabbed.new_tab(uri, next=True) - return method(*args) + def new_bg_tab_next(self, uri = ''): + self.uzbl_tabbed.new_tab(uri, switch = False, next = True) + + def next_tab(self, step = 1): + self.uzbl_tabbed.next_tab(int(step)) + + def prev_tab(self, step = 1): + self.uzbl_tabbed.prev_tab(int(step)) + + def goto_tab(self, index): + self.uzbl_tabbed.goto_tab(int(index)) + + def first_tab(self): + self.uzbl_tabbed.goto_tab(0) + + def last_tab(self): + self.uzbl_tabbed.goto_tab(-1) + + def preset_tabs(self, *args): + self.uzbl_tabbed.parse_command(["preset"] + [ a for a in args ]) + + def bring_to_front(self): + self.uzbl_tabbed.window.present() + + def clean_tabs(self): + self.uzbl_tabbed.clean_slate() + + def exit_all_tabs(self): + self.uzbl_tabbed.quitrequest() + +class InstanceEventDispatcher(EventDispatcher): + def __init__(self, uzbl): + self.uzbl = uzbl + self.parent = self.uzbl.parent def plug_created(self, plug_id): if not self.uzbl.tab: @@ -428,63 +504,6 @@ class EventDispatcher: def load_commit(self, uri): self.uzbl.uri = uri - def new_tab(self, uri = None): - if uri: - self.parent.new_tab(uri) - else: - self.parent.new_tab() - - def new_tab_bg(self, uri = None): - if uri: - self.parent.new_tab(uri, switch = False) - else: - self.parent.new_tab(switch = False) - - def new_tab_next(self, uri = None): - if uri: - self.parent.new_tab(uri, next=True) - else: - self.parent.new_tab(next=True) - - def new_bg_tab_next(self, uri = None): - if uri: - self.parent.new_tab(uri, switch = False, next = True) - else: - self.parent.new_tab(switch = False, next = True) - - def next_tab(self, step = None): - if step: - self.parent.next_tab(int(step)) - else: - self.parent.next_tab() - - def prev_tab(self, step = None): - if step: - self.parent.prev_tab(int(step)) - else: - self.parent.prev_tab() - - def goto_tab(self, index): - self.parent.goto_tab(int(index)) - - def first_tab(self): - self.parent.goto_tab(0) - - def last_tab(self): - self.parent.goto_tab(-1) - - def preset_tabs(self, *args): - self.parent.parse_command(["preset"] + [ a for a in args ]) - - def bring_to_front(self): - self.parent.window.present() - - def clean_tabs(self): - self.parent.clean_slate() - - def exit_all_tabs(self): - self.parent.quitrequest() - class UzblInstance: '''Uzbl instance meta-data/meta-action object.''' @@ -492,7 +511,7 @@ class UzblInstance: self.parent = parent self.tab = None - self.dispatcher = EventDispatcher(self) + self.dispatcher = InstanceEventDispatcher(self) self.name = name self.title = title @@ -569,27 +588,6 @@ class UzblInstance: if self._client: self._client.send('exit') - def unquote(self, s): - '''Removes quotation marks around strings if any and interprets - \\-escape sequences using `string_escape`''' - if s and s[0] == s[-1] and s[0] in ['"', "'"]: - s = s[1:-1] - return s.encode('utf-8').decode('string_escape').decode('utf-8') - - _splitquoted = re.compile("( |\"(?:\\\\.|[^\"])*?\"|'(?:\\\\.|[^'])*?')") - def parse_event(self, text): - '''Splits string on whitespace while respecting quotations''' - return [self.unquote(p) for p in self._splitquoted.split(text) if p.strip()] - - def parse_command(self, cmd): - ''' Parse event givent by the Uzbl instance ''' - - cmd = self.parse_event(cmd) - message, message_type, args = cmd[0], cmd[2], cmd[3:] - - if message == "EVENT": - self.dispatcher.dispatch(message_type, args) - def close(self): '''The remote instance exited''' @@ -1059,10 +1057,16 @@ class UzblTabbed: return False - def create_tab(self, next = False): + def create_tab(self, beside = False): tab = gtk.Socket() tab.show() - self.notebook.insert_page(tab, position=next and self.notebook.get_current_page() + 1 or -1) + + if beside: + pos = self.notebook.get_current_page() + 1 + self.notebook.insert_page(tab, position=pos) + else: + self.notebook.append_page(tab) + self.notebook.set_tab_reorderable(tab, True) return tab @@ -1089,6 +1093,7 @@ class UzblTabbed: uzbl = UzblInstance(self, name, uri, title, switch) uzbl.set_tab(tab) + SocketClient.instances_queue[name] = uzbl -- cgit v1.2.3 From e13915d1eb4ef40fcb2e18ea0781a76ec32bd1df Mon Sep 17 00:00:00 2001 From: Brendan Taylor Date: Sun, 24 Apr 2011 21:55:58 -0600 Subject: uzbl-browsers started by uzbl-tabbed should use uzbl-tabbed's socket_dir. this is a quick hack to make the socket location predictable for uzbl-tabbed users --- bin/uzbl-tabbed | 35 +++++++++++++++++++++++------------ 1 file changed, 23 insertions(+), 12 deletions(-) diff --git a/bin/uzbl-tabbed b/bin/uzbl-tabbed index 889793a..4e832fd 100755 --- a/bin/uzbl-tabbed +++ b/bin/uzbl-tabbed @@ -88,8 +88,6 @@ # session_file = $HOME/.local/share/uzbl/session # # Inherited uzbl options: -# fifo_dir = /tmp -# socket_dir = /tmp # icon_path = $HOME/.local/share/uzbl/uzbl.png # status_background = #303030 # @@ -215,8 +213,6 @@ config = { 'session_file': os.path.join(DATA_DIR, 'session'), # Inherited uzbl options - 'fifo_dir': '/tmp', # Path to look for uzbl fifo. - 'socket_dir': '/tmp', # Path to look for uzbl socket. 'icon_path': os.path.join(DATA_DIR, 'uzbl.png'), 'status_background': "#303030", # Default background for all panels. @@ -579,7 +575,8 @@ class UzblInstance: ''' Send the SET command to Uzbl ''' if self._client: - self._client.send('set %s = %s') #TODO: escape chars ? + line = 'set %s = %s' % (key, val) #TODO: escape chars ? + self._client.send(line) def exit(self): @@ -618,6 +615,13 @@ class UzblTabbed: # Generates a unique id for uzbl socket filenames. self.next_pid = counter().next + # Whether to reconfigure new uzbl instances + self.force_socket_dir = False + self.force_fifo_dir = False + + self.fifo_dir = '/tmp' # Path to look for uzbl fifo. + self.socket_dir = '/tmp' # Path to look for uzbl socket. + # Create main window self.window = gtk.Window() try: @@ -699,10 +703,10 @@ class UzblTabbed: # Store information about the applications fifo and socket. fifo_filename = 'uzbltabbed_%d.fifo' % os.getpid() socket_filename = 'uzbltabbed_%d.socket' % os.getpid() - self._fifo = None + self._fifo = None self._socket = None - self.fifo_path = os.path.join(config['fifo_dir'], fifo_filename) - self.socket_path = os.path.join(config['socket_dir'], socket_filename) + self.fifo_path = os.path.join(self.fifo_dir, fifo_filename) + self.socket_path = os.path.join(self.socket_dir, socket_filename) # Now initialise the fifo and the socket self.init_fifo() @@ -1117,6 +1121,11 @@ class UzblTabbed: if config['capture_new_windows']: uzbl.set("new_window", r'new $8') + if self.force_socket_dir: + uzbl.set("socket_dir", self.socket_dir) + + if self.force_fifo_dir: + uzbl.set("fifo_dir", self.fifo_dir) def goto_tab(self, index): '''Goto tab n (supports negative indexing).''' @@ -1477,13 +1486,15 @@ if __name__ == "__main__": import pprint sys.stderr.write("%s\n" % pprint.pformat(config)) + uzbl = UzblTabbed() + if options.socketdir: - config['socket_dir'] = options.socketdir + uzbl.socket_dir = options.socketdir + uzbl.force_socket_dir = True if options.fifodir: - config['fifo_dir'] = options.fifodir - - uzbl = UzblTabbed() + uzbl.fifo_dir = options.fifodir + uzbl.force_fifo_dir = True # All extra arguments given to uzbl_tabbed.py are interpreted as # web-locations to opened in new tabs. -- cgit v1.2.3 From dbc8a823b1bd3fd2d59254c75b235e05d18c7ea8 Mon Sep 17 00:00:00 2001 From: Brendan Taylor Date: Sun, 24 Apr 2011 23:32:26 -0600 Subject: uzbl-tabbed: remove the broken 'capture_new_windows' option --- bin/uzbl-tabbed | 8 -------- 1 file changed, 8 deletions(-) diff --git a/bin/uzbl-tabbed b/bin/uzbl-tabbed index 4e832fd..8635108 100755 --- a/bin/uzbl-tabbed +++ b/bin/uzbl-tabbed @@ -72,7 +72,6 @@ # gtk_tab_pos = (top|left|bottom|right) # gtk_refresh = 1000 # switch_to_new_tabs = 1 -# capture_new_windows = 1 # multiline_tabs = 1 # # Tab title options: @@ -197,7 +196,6 @@ config = { 'gtk_tab_pos': 'top', # Gtk tab position (top|left|bottom|right) 'gtk_refresh': 1000, # Tablist refresh millisecond interval 'switch_to_new_tabs': True, # Upon opening a new tab switch to it - 'capture_new_windows': True, # Use uzbl_tabbed to catch new windows 'multiline_tabs': True, # Tabs overflow onto new tablist lines. # Tab title options @@ -1111,16 +1109,10 @@ class UzblTabbed: uzbl = self.tabs[tab] uzbl.exit() - def config_uzbl(self, uzbl): '''Send bind commands for tab new/close/next/prev to a uzbl instance.''' - # Set definitions here - # set(key, command back to fifo) - if config['capture_new_windows']: - uzbl.set("new_window", r'new $8') - if self.force_socket_dir: uzbl.set("socket_dir", self.socket_dir) -- cgit v1.2.3 From d568fcf4b569d5715a1b13e520b87e3737cb6e82 Mon Sep 17 00:00:00 2001 From: Brendan Taylor Date: Sun, 24 Apr 2011 23:37:44 -0600 Subject: uzbl-tabbed: remove the undocumented uzbl-tabbed fifo --- bin/uzbl-tabbed | 275 +++++++------------------------------------------------- 1 file changed, 33 insertions(+), 242 deletions(-) diff --git a/bin/uzbl-tabbed b/bin/uzbl-tabbed index 8635108..4e860d2 100755 --- a/bin/uzbl-tabbed +++ b/bin/uzbl-tabbed @@ -435,7 +435,7 @@ class GlobalEventDispatcher(EventDispatcher): self.uzbl_tabbed.goto_tab(-1) def preset_tabs(self, *args): - self.uzbl_tabbed.parse_command(["preset"] + [ a for a in args ]) + self.uzbl_tabbed.run_preset_cmd(*args) def bring_to_front(self): self.uzbl_tabbed.window.present() @@ -698,16 +698,13 @@ class UzblTabbed: self.window.show() self.wid = self.notebook.window.xid - # Store information about the applications fifo and socket. - fifo_filename = 'uzbltabbed_%d.fifo' % os.getpid() + # Store information about the application's socket. socket_filename = 'uzbltabbed_%d.socket' % os.getpid() - self._fifo = None self._socket = None self.fifo_path = os.path.join(self.fifo_dir, fifo_filename) self.socket_path = os.path.join(self.socket_dir, socket_filename) - # Now initialise the fifo and the socket - self.init_fifo() + # Now initialise the the socket self.init_socket() # If we are using sessions then load the last one if it exists. @@ -738,8 +735,7 @@ class UzblTabbed: print_exc() error("encounted error %r" % sys.exc_info()[1]) - # Unlink fifo socket - self.unlink_fifo() + # Unlink socket self.close_socket() # Attempt to close all uzbl instances nicely. @@ -805,249 +801,45 @@ class UzblTabbed: self._socket = None - def init_fifo(self): - '''Create interprocess communication fifo.''' + def run_preset_command(self, cmd, *args): + if len(args) < 1: + error("parse_command: invalid preset command") - if os.path.exists(self.fifo_path): - if not os.access(self.fifo_path, os.F_OK | os.R_OK | os.W_OK): - os.mkfifo(self.fifo_path) + elif cmd == "save": + path = os.path.join(config['saved_sessions_dir'], args[0]) + self.save_session(path) - else: - basedir = os.path.dirname(self.fifo_path) - if not os.path.exists(basedir): - os.makedirs(basedir) - - os.mkfifo(self.fifo_path) - - # Add event handlers for IO_IN & IO_HUP events. - self.setup_fifo_watchers() - - echo("[fifo] listening at %r" % self.fifo_path) - - # Add atexit register to destroy the fifo on program termination. - atexit.register(self.unlink_fifo) - - - def unlink_fifo(self): - '''Unlink the fifo socket. Note: This function is called automatically - on exit by an atexit register.''' - - # Make sure the fifo fd is closed. - self.close_fifo() - - # And unlink if the real fifo exists. - if os.path.exists(self.fifo_path): - os.unlink(self.fifo_path) - echo("unlinked %r" % self.fifo_path) - - - def close_fifo(self): - '''Remove all event handlers watching the fifo and close the fd.''' - - # Already closed - if self._fifo is None: return - - (fd, watchers) = self._fifo - os.close(fd) - - # Stop all gobject io watchers watching the fifo. - for gid in watchers: - source_remove(gid) - - self._fifo = None - - - def setup_fifo_watchers(self): - '''Open fifo socket fd and setup gobject IO_IN & IO_HUP event - handlers.''' - - # Close currently open fifo fd and kill all watchers - self.close_fifo() - - fd = os.open(self.fifo_path, os.O_RDONLY | os.O_NONBLOCK) - - # Add gobject io event handlers to the fifo socket. - watchers = [io_add_watch(fd, IO_IN, self.main_fifo_read),\ - io_add_watch(fd, IO_HUP, self.main_fifo_hangup)] - - self._fifo = (fd, watchers) - - - def main_fifo_hangup(self, fd, cb_condition): - '''Handle main fifo socket hangups.''' - - # Close old fd, open new fifo socket and add io event handlers. - self.setup_fifo_watchers() - - # Kill the gobject event handler calling this handler function. - return False - - - def main_fifo_read(self, fd, cb_condition): - '''Read from main fifo socket.''' - - self._buffer = os.read(fd, 1024) - temp = self._buffer.split("\n") - self._buffer = temp.pop() - cmds = [s.strip().split() for s in temp if len(s.strip())] - - for cmd in cmds: - try: - #print cmd - self.parse_command(cmd) - - except: - print_exc() - error("parse_command: invalid command %s" % ' '.join(cmd)) - raise - - return True - - - def parse_command(self, cmd): - '''Parse instructions from uzbl child processes.''' - - # Commands ( [] = optional, {} = required ) - # new [uri] - # open new tab and head to optional uri. - # newbg [uri] - # open a new tab in the background - # close [tab-num] - # close current tab or close via tab id. - # next [n-tabs] - # open next tab or n tabs down. Supports negative indexing. - # prev [n-tabs] - # open prev tab or n tabs down. Supports negative indexing. - # goto {tab-n} - # goto tab n. - # first - # goto first tab. - # last - # goto last tab. - # title {pid} {document-title} - # updates tablist title. - # uri {pid} {document-location} - # updates tablist uri - # bring_to_front - # brings the gtk window to focus. - # exit - # exits uzbl_tabbed.py - - if cmd[0] == "new": - if len(cmd) == 2: - self.new_tab(cmd[1]) - - else: - self.new_tab() - - elif cmd[0] == "newbg": - if len(cmd) == 2: - self.new_tab(cmd[1], switch=False) - else: - self.new_tab(switch=False) - - elif cmd[0] == "newfromclip": - uri = subprocess.Popen(['xclip','-selection','clipboard','-o'],\ - stdout=subprocess.PIPE).communicate()[0] - if uri: - self.new_tab(uri) - - elif cmd[0] == "close": - if len(cmd) == 2: - self.close_tab(int(cmd[1])) - - else: - self.close_tab() - - elif cmd[0] == "next": - if len(cmd) == 2: - self.next_tab(int(cmd[1])) - - else: - self.next_tab() - - elif cmd[0] == "prev": - if len(cmd) == 2: - self.prev_tab(int(cmd[1])) + elif cmd == "load": + path = os.path.join(config['saved_sessions_dir'], args[0]) + self.load_session(path) + elif cmd == "del": + path = os.path.join(config['saved_sessions_dir'], args[0]) + if os.path.isfile(path): + os.remove(path) else: - self.prev_tab() + error("parse_command: preset %r does not exist." % path) - elif cmd[0] == "goto": - self.goto_tab(int(cmd[1])) - - elif cmd[0] == "first": - self.goto_tab(0) - - elif cmd[0] == "last": - self.goto_tab(-1) - - elif cmd[0] in ["title", "uri"]: - if len(cmd) > 2: - uzbl = self.get_tab_by_name(int(cmd[1])) - if uzbl: - old = getattr(uzbl, cmd[0]) - new = ' '.join(cmd[2:]) - setattr(uzbl, cmd[0], new) - if old != new: - self.update_tablist() - - else: - error("parse_command: no uzbl with name %r" % int(cmd[1])) - - elif cmd[0] == "preset": - if len(cmd) < 3: - error("parse_command: invalid preset command") - - elif cmd[1] == "save": - path = os.path.join(config['saved_sessions_dir'], cmd[2]) - self.save_session(path) - - elif cmd[1] == "load": - path = os.path.join(config['saved_sessions_dir'], cmd[2]) - self.load_session(path) - - elif cmd[1] == "del": - path = os.path.join(config['saved_sessions_dir'], cmd[2]) - if os.path.isfile(path): - os.remove(path) - - else: - error("parse_command: preset %r does not exist." % path) - - elif cmd[1] == "list": - # FIXME: what argument is this supposed to be passed, - # and why? - uzbl = self.get_tab_by_name(int(cmd[2])) - if uzbl: - if not os.path.isdir(config['saved_sessions_dir']): - js = "js alert('No saved presets.');" - uzbl._client.send(js) - - else: - listdir = os.listdir(config['saved_sessions_dir']) - listdir = "\\n".join(listdir) - js = "js alert('Session presets:\\n\\n%s');" % listdir - uzbl._client.send(js) + elif cmd == "list": + # FIXME: what argument is this supposed to be passed, + # and why? + uzbl = self.get_tab_by_name(int(args[0])) + if uzbl: + if not os.path.isdir(config['saved_sessions_dir']): + js = "js alert('No saved presets.');" + uzbl._client.send(js) else: - error("parse_command: unknown tab name.") + listdir = os.listdir(config['saved_sessions_dir']) + listdir = "\\n".join(listdir) + js = "js alert('Session presets:\\n\\n%s');" % listdir + uzbl._client.send(js) else: - error("parse_command: unknown parse command %r"\ - % ' '.join(cmd)) - - elif cmd[0] == "bring_to_front": - self.window.present() - - elif cmd[0] == "clean": - self.clean_slate() - - elif cmd[0] == "exit": - self.quitrequest() + error("parse_command: unknown tab name.") else: - error("parse_command: unknown command %r" % ' '.join(cmd)) + error("parse_command: unknown parse command %r" % cmd) def get_tab_by_name(self, name): @@ -1434,9 +1226,8 @@ class UzblTabbed: def quit(self, *args): '''Cleanup and quit. Called by delete-event signal.''' - # Close the fifo socket, remove any gobject io event handlers and + # Close the socket, remove any gobject io event handlers and # delete socket. - self.unlink_fifo() self.close_socket() # Remove all gobject timers that are still ticking. -- cgit v1.2.3 From 90e76a16bbd46fe7bd3505e8df8f870d5b1c29be Mon Sep 17 00:00:00 2001 From: Brendan Taylor Date: Mon, 25 Apr 2011 09:44:39 -0600 Subject: it seems my python is getting rusty. --- bin/uzbl-tabbed | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/bin/uzbl-tabbed b/bin/uzbl-tabbed index 4e860d2..03c2ffa 100755 --- a/bin/uzbl-tabbed +++ b/bin/uzbl-tabbed @@ -344,7 +344,7 @@ class SocketClient: args = cmd[3:] if not message == "EVENT": - next + return # strip the surrounding [] instance_name = instance_name[1:-1] @@ -533,6 +533,9 @@ class UzblInstance: def title_changed(self, gtk_only = True): # GTK-only is for indexes '''self.title has changed, update the tabs list''' + if not self.tab: + return + tab_titles = config['tab_titles'] tab_indexes = config['tab_indexes'] show_ellipsis = config['show_ellipsis'] -- cgit v1.2.3 From 7b75f8084db1a004a264b45b1ea3de98de4acc98 Mon Sep 17 00:00:00 2001 From: Brendan Taylor Date: Mon, 25 Apr 2011 09:57:46 -0600 Subject: i could have sworn i tested it this time --- bin/uzbl-tabbed | 1 - 1 file changed, 1 deletion(-) diff --git a/bin/uzbl-tabbed b/bin/uzbl-tabbed index 03c2ffa..772c9c2 100755 --- a/bin/uzbl-tabbed +++ b/bin/uzbl-tabbed @@ -704,7 +704,6 @@ class UzblTabbed: # Store information about the application's socket. socket_filename = 'uzbltabbed_%d.socket' % os.getpid() self._socket = None - self.fifo_path = os.path.join(self.fifo_dir, fifo_filename) self.socket_path = os.path.join(self.socket_dir, socket_filename) # Now initialise the the socket -- cgit v1.2.3 From cd7ff839afd2af2ec78868d91eca7fd4a2d4f117 Mon Sep 17 00:00:00 2001 From: Brendan Taylor Date: Mon, 25 Apr 2011 16:03:55 -0600 Subject: my kingdom for an automated test suite --- bin/uzbl-tabbed | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bin/uzbl-tabbed b/bin/uzbl-tabbed index 772c9c2..1a65788 100755 --- a/bin/uzbl-tabbed +++ b/bin/uzbl-tabbed @@ -435,7 +435,7 @@ class GlobalEventDispatcher(EventDispatcher): self.uzbl_tabbed.goto_tab(-1) def preset_tabs(self, *args): - self.uzbl_tabbed.run_preset_cmd(*args) + self.uzbl_tabbed.run_preset_command(*args) def bring_to_front(self): self.uzbl_tabbed.window.present() -- cgit v1.2.3