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