Draft: Open URLs based on regular expressions
This commit is contained in:
parent
f8305131c8
commit
3e785d30bb
161
content/posts/regex-based-url-opener.adoc
Normal file
161
content/posts/regex-based-url-opener.adoc
Normal file
@ -0,0 +1,161 @@
|
|||||||
|
---
|
||||||
|
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
|
||||||
|
---
|
||||||
|
|
||||||
|
:source-highlighter: pygments
|
||||||
|
:idprefix:
|
||||||
|
:experimental: true
|
||||||
|
:toc:
|
||||||
|
:toclevels: 2
|
||||||
|
|
||||||
|
:url-urlhandler: https://schlomp.space/tastytea/dotfiles/src/branch/main/.local/bin/urlhandler
|
||||||
|
:url-functions: https://schlomp.space/tastytea/dotfiles/src/branch/main/.config/zsh/functions
|
||||||
|
:url-zshoptions: https://zsh.sourceforge.io/Doc/Release/Options.html
|
||||||
|
:url-zshfunctions: https://zsh.sourceforge.io/Doc/Release/Functions.html
|
||||||
|
:url-desktop-spec: https://specifications.freedesktop.org/desktop-entry-spec/latest/
|
||||||
|
|
||||||
|
:abbr-pcre: pass:[<abbr title='Perl Compatible Regular Expressions'>PCRE</abbr>]
|
||||||
|
|
||||||
|
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 link:{url-urlhandler}[in my dotfiles repo].
|
||||||
|
|
||||||
|
[source,shell]
|
||||||
|
--------------------------------------------------------------------------------
|
||||||
|
#!/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
|
||||||
|
link:{url-zshoptions}[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 link:#helper_functions[we
|
||||||
|
later use], load the {abbr-pcre} module and set the default browser.
|
||||||
|
|
||||||
|
[source,shell]
|
||||||
|
--------------------------------------------------------------------------------
|
||||||
|
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.
|
||||||
|
|
||||||
|
[source,shell]
|
||||||
|
--------------------------------------------------------------------------------
|
||||||
|
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
|
||||||
|
link:{url-functions}[Zsh functions directory] of my dotfiles repo. Put them
|
||||||
|
anywhere in your `${fpath}`. Learn more from the *zshmisc* man-page or the
|
||||||
|
link:{url-zshfunctions}[online documentation]. Or you could just put them inside
|
||||||
|
the script, like this for example:
|
||||||
|
|
||||||
|
[source,shell]
|
||||||
|
--------------------------------------------------------------------------------
|
||||||
|
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
|
||||||
|
(link:{url-desktop-spec}[specification]).
|
||||||
|
|
||||||
|
[source,toml]
|
||||||
|
--------------------------------------------------------------------------------
|
||||||
|
[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! 🥳
|
Loading…
x
Reference in New Issue
Block a user