about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--Functions/Zle/url-quote-magic148
1 files changed, 148 insertions, 0 deletions
diff --git a/Functions/Zle/url-quote-magic b/Functions/Zle/url-quote-magic
new file mode 100644
index 000000000..826d26d09
--- /dev/null
+++ b/Functions/Zle/url-quote-magic
@@ -0,0 +1,148 @@
+# Functions to make it easier to type URLs as command line arguments.  As
+# you type, the input character is analyzed and, if it may need quoting,
+# the current word is checked for a URI scheme.  If one is found and the
+# current word is not already in quotes, a backslash is inserted before
+# the input character.
+
+# Setup:
+#       autoload -U url-quote-magic
+#       zle -N self-insert url-quote-magic
+
+# A number of zstyles may be set to control the quoting behavior.
+#
+# url-metas
+#  This style is looked up in the context :url-quote-magic:SCHEME (where
+#  SCHEME is that of the current URL, e.g. "ftp").  The value is a string
+#  listing the characters to be treated as globbing metacharacters when
+#  appearing in a URL using that scheme.  The default is to quote all zsh
+#  extended globbing characters, excluding '<' and '>' but including
+#  braces (as in brace expansion).  See also url-seps.
+#
+# url-seps
+#  Like url-metas, but lists characters that should be considered command
+#  separators, redirections, history references, etc.  The default is to
+#  quote the standard set of shell separators, excluding those that
+#  overlap with the extended globbing characters, but including '<' and
+#  '>' and the first character of $histchars.
+#
+# url-globbers
+#  This style is looked up in the context :url-quote-magic.  The values
+#  form a list of command names that are expected to do their own globbing
+#  on the URL string.  This implies that they are aliased to use the
+#  "noglob" modifier.  When the first word on the line matches one of the
+#  values AND the URL refers to a local file (see url-local-schema), only
+#  the url-seps characters are quoted; the url-metas are left alone,
+#  allowing them to affect command-line parsing, completion, etc.  The
+#  default values are a literal "noglob" plus (when the zsh/parameter
+#  module is available) any commands aliased to the helper function
+#  "urlglobber" or its alias "globurl".
+#
+# url-local-schema
+#  This style is always looked up in the context :urlglobber, even though
+#  it is used by both url-quote-magic and urlglobber.  The values form
+#  a list of URI schema that should be treated as referring to local files
+#  by their real local path names, as opposed to files which are specified
+#  relative to a web-server-defined document root.  The defaults are "ftp"
+#  and "file".
+#
+# url-other-schema
+#  Like url-local-schema, but lists all other URI schema upon which
+#  urlglobber and url-quote-magic should act.  If the URI on the
+#  command line does not have a scheme appearing either in this list or in
+#  url-local-schema, it is not magically quoted.  The default values are
+#  "http", "https", and "ftp".  When a scheme appears both here and in
+#  url-local-schema, it is quoted differently depending on whether the
+#  command name appears in url-globbers.
+
+# TODO:
+#	Add a style for "document root" for globbing local URLs.
+#	Turn this on at colon, and off again at space or accept.
+#       Use compsys for nested quoting analysis and command parsing.
+
+# Establish default values for styles, but only if not already set
+
+zstyle -m ':url-quote-magic:\*' url-metas '*' ||
+    zstyle ':url-quote-magic:*' url-metas '*?[]^(|)~#{}='
+
+zstyle -m ':url-quote-magic:\*' url-seps '*' ||
+    zstyle -e ':url-quote-magic:*' url-seps 'reply=(";&<>${histchars[1]}")'
+
+zstyle -m :url-quote-magic url-globbers '*' ||
+    zstyle -e :url-quote-magic url-globbers \
+	'zmodload -i zsh/parameter;
+	 reply=( noglob
+		 ${(k)galiases[(R)(* |)(noglob|urlglobber|globurl) *]:-}
+		 ${(k)aliases[(R)(* |)(noglob|urlglobber|globurl) *]:-} )'
+
+zstyle -m ':urlglobber' url-local-schema '*' ||
+    zstyle ':urlglobber' url-local-schema ftp file
+
+zstyle -m ':urlglobber' url-other-schema '*' ||
+    zstyle ':urlglobber' url-other-schema http https ftp
+
+# Define the "urlglobber" helper function and shorthand "globurl" alias
+
+function urlglobber {
+    local -a args globbed localschema otherschema
+    local arg command="$1"
+    shift
+    zstyle -s :urlglobber url-local-schema localschema '|'
+    zstyle -s :urlglobber url-other-schema otherschema '|'
+    for arg
+    do
+	case "${arg}" in
+	((${~localschema}):/(|/localhost)/*)
+	    globbed=( ${~${arg##ftp://(localhost|)}} )
+	    args[$#args+1]=( "${(M)arg##(${~localchema})://(localhost|)}${(@)^globbed}" )
+	    ;;
+	((${~otherschema}):*) args[${#args}+1]="$arg";;
+	(*) args[${#args}+1]=( ${~arg} );;
+	esac
+    done
+    "$command" "${(@)args}"
+}
+alias globurl='noglob urlglobber '
+
+# Finally, define (and execute if necessary) the function we really want
+
+function url-quote-magic {
+    setopt localoptions noksharrays extendedglob
+    local qkey="${(q)KEYS}"
+    if [[ "$KEYS" != "$qkey" ]]
+    then
+	local lbuf="$LBUFFER$qkey"
+	if [[ "${(Q)LBUFFER}$KEYS" == "${(Q)lbuf}" ]]
+	then
+	    local -a words
+	    words=("${(@Q)${(z)lbuf}}")
+	    local urlseps urlmetas urlglobbers localschema otherschema
+	    if [[ "$words[-1]" == (#b)([^:]##):* ]]
+	    then
+		zstyle -s ":url-quote-magic:$match[1]" url-seps urlseps ''
+		zstyle -s ":url-quote-magic:$match[1]" url-metas urlmetas ''
+	    fi
+	    zstyle -s :url-quote-magic url-globbers urlglobbers '|'
+	    zstyle -s :urlglobber url-other-schema otherschema '|'
+	    if [[ "$words[1]" == ${~urlglobbers} ]]
+	    then
+		zstyle -s :urlglobber url-local-schema localschema '|'
+	    else
+		localschema=' '
+	    fi
+	    case "$words[-1]" in
+	    (*[\'\"]*) ;;
+	    ((${~localschema}):/(|/localhost)/*)
+		[[ "$urlseps" == *"$KEYS"* ]] &&
+		    LBUFFER="$LBUFFER\\" ;;
+	    ((${~otherschema}):*)
+		[[ "$urlseps$urlmetas" == *"$KEYS"* ]] &&
+		    LBUFFER="$LBUFFER\\" ;;
+	    esac
+	fi
+    fi
+    zle .self-insert
+}
+
+# Handle zsh autoloading conventions
+
+[[ -o kshautoload ]] || url-quote-magic "$@"