Problem
If one uses Bash as one’s shell, and wants to, for example, download a Youtube video using youtube-dl
, a command like this will be sufficient:
youtube-dl https://www.youtube.com/watch?v=C1Ua4UFsmzE
However, if one uses ZSH, the question mark character in the URL may be a problem, because of ZSH’s extended globbing. In this case, one normally has to put quotation marks around URLs like this:
youtube-dl "https://www.youtube.com/watch?v=C1Ua4UFsmzE"
or escape special characters, like this (backslash before question mark):
youtube-dl https://www.youtube.com/watch\?v=C1Ua4UFsmzE
Of course, nobody
types such long and ugly URLs manually, they are usually pasted from the clipboard, so manually adding quotation marks or backslashes afterwards can get a bit tedious.
Solution
Fortunately, there exists an elegant solution in ZSH so that special characters are automagically escaped whenever a URL is pasted.
One merely needs to add the following to one’s .zshrc
:
autoload -U url-quote-magic bracketed-paste-magic
zle -N self-insert url-quote-magic
zle -N bracketed-paste bracketed-paste-magic
Conflict with zsh-autosuggestions
and Solution
This should work well, but if one is using zsh-autosuggestions
there will be a conflict and autosuggestions will be very laggy. That’s relatively easy to fix. This is how the relevant code segment in .zshrc
should look if zsh-autosuggestions
are used:
# First load zsh-autosuggestions
source /usr/share/zsh/plugins/zsh-autosuggestions/zsh-autosuggestions.zsh
ZSH_AUTOSUGGEST_BUFFER_MAX_SIZE=20
# other ZSH_AUTOSUGGEST config goes here
# Then load url-quote-magic and bracketed-paste-magic as above
autoload -U url-quote-magic bracketed-paste-magic
zle -N self-insert url-quote-magic
zle -N bracketed-paste bracketed-paste-magic
# Now the fix, setup these two hooks:
pasteinit() {
OLD_SELF_INSERT=${${(s.:.)widgets[self-insert]}[2,3]}
zle -N self-insert url-quote-magic
}
pastefinish() {
zle -N self-insert $OLD_SELF_INSERT
}
zstyle :bracketed-paste-magic paste-init pasteinit
zstyle :bracketed-paste-magic paste-finish pastefinish
# and finally, make sure zsh-autosuggestions does not interfere with it:
ZSH_AUTOSUGGEST_CLEAR_WIDGETS+=(bracketed-paste)
Result
Now, when the following URL: https://www.youtube.com/watch?v=C1Ua4UFsmzE
is pasted into the terminal emulator, the question mark will be automatically escaped:
youtube-dl https://www.youtube.com/watch\?v=C1Ua4UFsmzE
Isn’t ZSH awesome?
Final Remark: no need to load everything when using the TTY
Finally, I would recommend putting everything (both zsh-autosuggestions
, if used, and paste magic) inside of an if
statement like this, because there is no point in loading any of that when one is using a TTY:
if [ $TERM = "xterm-256color" ]; then
# all of the above code goes here
fi
The exact value of the TERM
variable may depend from terminal emulator to terminal emulator. To find it, just run echo $TERM
while using the terminal emulator.
Well, I hope this is useful…