[Tip] Better URL pasting in ZSH

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? :slight_smile:

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…

21 Likes