5.8 KiB
title: "Open URLs based on regular expressions" slug: "regex-based-url-opener" description: null date: 2022-04-18T17:16:08+02:00 type: posts draft: true tags: - WWW - Zsh toc: true ---
One of the shell scripts that bring me the most joy is my URL opener. I have it set as my default browser, so whenever I click a hyperlink somewhere it gets called and decides if the URL should be opened with Firefox or with another program. mpv for video files and YouTube URLs, a download-and-launch-viewer function for pictures and so on.
The script
I have abbreviated the script here a bit for better readability, the full version is available in my dotfiles repo.
#!/usr/bin/env zsh
# Open URLs based on perl compatible regular expressions. Several commands can
# be specified with ; as separator. If the URL doesn't match anything or the
# commands are not found, use ${default_cmd}.
setopt ERR_RETURN NO_UNSET PIPE_FAIL
if [[ ! -v 1 ]]; then
print -u 2 "usage: ${0} <URL> …"
return 1
fi
local -a urls=(${@})
autoload -U readwwwlog openwwwimg
zmodload zsh/pcre
local default_cmd="firefox"
First, we set some essential options. ERR_RETURN
stops execution when a
command has a non-zero exit status, NO_UNSET
treats non-existing variables as
an error and PIPE_FAIL
sets ${?}
to non-zero if any command in a pipeline
fails. You can read more about them in the zshoptions man-page or in the
online documentation.
Next we check if ${1}
is set (we have at least 1 URL) and assign all arguments
to the array ${urls}
. Then we autoload some function we
later use, load the PCRE module and set the default browser.
local mpv="mpv --force-window=yes"
local -A assignments=(
'\.(mp4|m4v|mkv|avi|webm|flv|xvid|ogv|theora|mov|wmv)$' "${mpv};vlc"
'\.(ogg|flac|opus|m4a|wav|mp3|mid|aac|wma)$' "${mpv};vlc"
'^https://media\.ccc\.de/v/[^/]*$' "${mpv}"
'^https?://(www\.)?youtu(\.be|be\.com)/' "${mpv}"
'^(gemini|gopher)://' "kristall"
'\.(log|txt)$' "readwwwlog"
'^https?://(www\.)?(dpaste|pastebin|irccloud)\.com/' "readwwwlog"
'\.(webm|png|jpe?g|gif|svg|bmp|xcf)$' "openwwwimg"
)
Now we define the associative array ${assignments}
with the regular expression
on the left and the command(s) to run on the right. The first command that
exists will be run.
local selected_cmd=${default_cmd}
for regex cmds in ${(kv)assignments}; do
if [[ ${urls[1]} -pcre-match ${regex} ]]; then
for cmd in ${(s/;/)cmds}; do
if type ${cmd%% *} >& -; then
selected_cmd=${cmd}
break
fi
done
break
fi
done
${(@s/ /)selected_cmd} ${urls}
This loops through all regular expressions and compares it against the first URL (we naively assume that all supplied URLs are of the same type 😊). If it matches, the first command that exists is run with the URL. If nothing matches, the default browser we set earlier is used.
Note
|
Because commands can contain options, we split the command-strings at spaces in the existence check and when we run the command. This has the side-effect that commands can not contain spaces. |
Helper functions
The functions readwwwlog
and openwwwimage
are available in the
Zsh functions directory of my dotfiles repo. Put them
anywhere in your ${fpath}
. Learn more from the zshmisc man-page or the
online documentation. Or you could just put them inside
the script, like this for example:
function openwwwimg() {
local file="$(mktemp --suffix='.openwwwimg')"
curl --silent --location --output ${file} ${url}
if [[ ${?} -eq 0 ]]; then
viewnior ${file}
else
firefox ${url}
fi
rm -f ${file}
}
Don’t forget to remove the autoloads if you put them directly in the script.
Setting the script as default browser
To set the default browser in Linux, you need to have a .desktop
file
(specification).
[Desktop Entry]
Type=Application
Version=1.0
Name=urlhandler
Comment=Open URLs with different commands
TryExec=urlhandler
Exec=urlhandler %u
Terminal=false
Save this in ~/.local/share/applications/urlhandler.desktop
and run
xdg-settings set default-web-browser urlhandler.desktop
. Congratulations, you
are ready to go! 🥳