# 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 -Uz 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 local -a reply match mbegin mend 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 reply 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}" local -a reply 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 "$@"