Compare commits
12 Commits
4b51c0e3f8
...
man
| Author | SHA1 | Date | |
|---|---|---|---|
|
02831fd304
|
|||
| 447f9a1d39 | |||
|
ada7c6976f
|
|||
|
da348f82f2
|
|||
|
265a1b9b95
|
|||
|
494d9ad140
|
|||
|
b636494fd7
|
|||
| 00bd98df9a | |||
| e4501794f2 | |||
| 78e2bcf9ca | |||
| 5ca13548d7 | |||
| ad64911c7f |
75
README.md
75
README.md
@@ -1,5 +1,3 @@
|
|||||||
# xdg-sanity
|
|
||||||
|
|
||||||
The `xdg-sanity` script is built to replace your default web browser in your
|
The `xdg-sanity` script is built to replace your default web browser in your
|
||||||
desktop/XDG settings. It intercepts http/s URIs sent to the default browser by
|
desktop/XDG settings. It intercepts http/s URIs sent to the default browser by
|
||||||
`xdg-open` and sends it to the appropriate application. For example, it will
|
`xdg-open` and sends it to the appropriate application. For example, it will
|
||||||
@@ -16,43 +14,20 @@ AUR](https://aur.archlinux.org/packages/xdg-sanity).
|
|||||||
|
|
||||||
Dependencies:
|
Dependencies:
|
||||||
- `curl(1)`
|
- `curl(1)`
|
||||||
- `xdg-utils(1)` or `handlr(1)`
|
- `handlr(1)`
|
||||||
- `tomcat(1)`
|
- [`tomcat(1)`](https://git.tebibyte.media/emma/tomcat) (optional; enables
|
||||||
|
[extensions](#extensions))
|
||||||
You can get `tomcat` [here](https://git.tebibyte.media/emma/tomcat)
|
|
||||||
|
|
||||||
Instructions:
|
Instructions:
|
||||||
Clone this repository and move the `xdg-sanity` binary wherever your operating
|
Clone this repository and move the `xdg-sanity` binary wherever your operating
|
||||||
system stores locally-installed binaries. This is usually `/usr/local/bin` or
|
system stores locally-installed binaries. This is usually `/usr/local/bin/` or
|
||||||
`$HOME/.local/bin` for your user. Make sure the installation location is in your
|
`"$HOME/.local/bin/"` for your user. Make sure the installation location is in
|
||||||
`$PATH`.
|
your `$PATH`.
|
||||||
|
|
||||||
Create an `xdg-sanity.desktop` file either manually or with `gendesk(1)`,
|
Create an `xdg-sanity.desktop` file, placing it where your OS stores
|
||||||
placing it where your OS stores locally-installed `.desktop` files, which is
|
locally-installed `.desktop` files, which is usually
|
||||||
usually `/usr/local/share/applications` or `$XDG_DATA_HOME/applications` for
|
`/usr/local/share/applications` or `$XDG_DATA_HOME/applications` for your user.
|
||||||
your user. Set your default web browser to that `.desktop` file with
|
Set your default web browser to that `.desktop` file using `handlr set`.
|
||||||
`xdg-settings(1)` or an equivalent.
|
|
||||||
|
|
||||||
### Configuration
|
|
||||||
|
|
||||||
This program uses [TOML](https://toml.io/en/v1.0.0) for its configuration. The
|
|
||||||
configuration file is set up like this:
|
|
||||||
```
|
|
||||||
$ cat $XDG_CONFIG_HOME/xdg-sanity.toml
|
|
||||||
[tools]
|
|
||||||
browser = "firefox"
|
|
||||||
xdg = "handlr launch"
|
|
||||||
```
|
|
||||||
|
|
||||||
The options available for `xdg` are `handlr launch` if you use `handlr(1)` and
|
|
||||||
`xdg-open` if you use `xdg-utils(1)`.
|
|
||||||
|
|
||||||
### Usage
|
|
||||||
|
|
||||||
`xdg-sanity [RESOURCE]`
|
|
||||||
|
|
||||||
Open links from applications outside your web browser as normal. Alternatively,
|
|
||||||
you can call `xdg-sanity` directly with the only argument accepted being a URI.
|
|
||||||
|
|
||||||
#### Extensions
|
#### Extensions
|
||||||
|
|
||||||
@@ -61,28 +36,42 @@ Extensions are written using TOML and are stored in either
|
|||||||
`/usr/local/share/xdg-sanity` when installed locally, or
|
`/usr/local/share/xdg-sanity` when installed locally, or
|
||||||
`$XDG_DATA_HOME/xdg-sanity` for your user.
|
`$XDG_DATA_HOME/xdg-sanity` for your user.
|
||||||
|
|
||||||
There are two types of extensions: MIME and replace. MIME extensions are parsed
|
Extension support requires the installation of the `tomcat(1)` tool, which
|
||||||
first and replace the MIME type of the content being fetched. Replace extensions
|
parses TOML for the command line.
|
||||||
change the URI passed to the command to another.
|
|
||||||
|
There are three kinds of extensions: MIME, replace, and scheme. MIME extensions
|
||||||
|
are parsed first and replace the MIME type of the content being fetched. Replace
|
||||||
|
extensions change the URI passed to the command to another. Scheme extensions
|
||||||
|
replace the protocol by which the URI hostname is being accessed.
|
||||||
|
|
||||||
The type of the extension depends on the file name. MIME extensions should have
|
The type of the extension depends on the file name. MIME extensions should have
|
||||||
a name ending in `-mime.toml` and replace extensions should have
|
a name ending in `.mime.toml`, replace extensions should have
|
||||||
`-replace.toml`.
|
`.replace.toml`, and scheme extensions should end with `.scheme.toml`.
|
||||||
|
|
||||||
Here's what a MIME extension looks like:
|
Here's what a MIME extension looks like:
|
||||||
```
|
```
|
||||||
cat $XDG_DATA_HOME/xdg-sanity/youtube-mime.toml
|
$ cat $XDG_DATA_HOME/xdg-sanity/youtube.mime.toml
|
||||||
[replace]
|
[replace]
|
||||||
urls = [ "youtube.com", "youtu.be" ]
|
urls = [ "youtube.com", "youtu.be" ]
|
||||||
|
|
||||||
[with]
|
[with]
|
||||||
mime = "video/vnd.youtube.yt"
|
mime = "video/vnd.youtube.yt"
|
||||||
```
|
```
|
||||||
and here's what a replace extension looks like:
|
what a replace extension looks like:
|
||||||
```
|
```
|
||||||
cat $XDG_DATA_HOME/xdg-sanity/youtube-replace.toml
|
$ cat $XDG_DATA_HOME/xdg-sanity/youtube.replace.toml
|
||||||
[replace]
|
[replace]
|
||||||
urls = [ "youtube.com", "youtu.be" ]
|
urls = [ "youtube.com", "youtu.be" ]
|
||||||
|
|
||||||
[with]
|
[with]
|
||||||
url = "https://piped.mint.lgbt/"
|
url = "https://piped.mint.lgbt/"
|
||||||
|
```
|
||||||
|
and what a scheme extension looks like:
|
||||||
|
```
|
||||||
|
$ cat $XDG_DATA_HOME/xdg-sanity/spotify.scheme.toml
|
||||||
|
[replace]
|
||||||
|
urls = [ "spotify.com" ]
|
||||||
|
|
||||||
|
[with]
|
||||||
|
scheme = "spotify://"
|
||||||
|
```
|
||||||
|
|||||||
@@ -1,7 +0,0 @@
|
|||||||
# xdg-sanity mime extension
|
|
||||||
|
|
||||||
[replace] # replaces these urls
|
|
||||||
urls = [ "youtube.com", "youtu.be" ]
|
|
||||||
|
|
||||||
[with] # replaces the mime type of the above
|
|
||||||
mime = "video/vnd.youtube.yt"
|
|
||||||
201
xdg-sanity
201
xdg-sanity
@@ -1,118 +1,133 @@
|
|||||||
#!/bin/sh
|
#!/bin/sh
|
||||||
|
|
||||||
|
# Copyright (c) 2022–2023 Emma Tebibyte <emma@tebibyte.media>
|
||||||
|
# SPDX-License-Identifier: AGPL-3.0-or-later
|
||||||
|
#
|
||||||
|
# This program is free software: you can redistribute it and/or modify it under
|
||||||
|
# the terms of the GNU Affero General Public License as published by the Free
|
||||||
|
# Software Foundation, either version 3 of the License, or (at your option) any
|
||||||
|
# later version.
|
||||||
|
#
|
||||||
|
# This program is distributed in the hope that it will be useful, but WITHOUT
|
||||||
|
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||||
|
# FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
|
||||||
|
# details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU Affero General Public License along
|
||||||
|
# with this program. If not, see https://www.gnu.org/licenses/.
|
||||||
|
|
||||||
set -e
|
set -e
|
||||||
|
|
||||||
argv0="$0"
|
argv0="$0"
|
||||||
|
|
||||||
# grabs configuration files
|
get_urls() {
|
||||||
CONFIG="$XDG_CONFIG_HOME"/xdg-sanity.toml
|
i="0"
|
||||||
if ! test -e "$CONFIG"; then
|
until ! tomcat replace.urls["$i"] "$file" >/dev/null 2>&1
|
||||||
touch "$CONFIG"
|
do
|
||||||
CONFIG=/etc/xdg-sanity.toml
|
URLS="$(printf "%s\n%s" \
|
||||||
if ! test -e "$CONFIG"; then
|
"$URLS" \
|
||||||
exit 66 # sysexits(3) EX_NOINPUT
|
"$(tomcat replace.urls["$i"] "$file")"
|
||||||
fi
|
)"
|
||||||
fi
|
|
||||||
|
|
||||||
|
i="$(printf "%s+1\n" "$i" | bc)"
|
||||||
|
done
|
||||||
|
}
|
||||||
|
|
||||||
# check if usage is valid
|
# check if usage is valid
|
||||||
if ! test -n "$1"; then
|
if test -z "$1"; then
|
||||||
printf "Usage: %s [resource...]\n" "$argv0" 1>&2
|
printf "Usage: %s [resource...]\n" "$argv0" 1>&2
|
||||||
exit 64 # sysexits(3) EX_USAGE
|
exit 64 # sysexits(3) EX_USAGE
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# check if we have curl(1)
|
for dep in \
|
||||||
if ! command -v curl >/dev/null 2>&1; then
|
curl \
|
||||||
printf "%s: Missing dependency: curl(1)\n" "$argv0" 1>&2
|
handlr
|
||||||
exit 71 # sysexits(3) EX_OSERR
|
do
|
||||||
fi
|
if ! command -v "$dep" >/dev/null 2>&1; then
|
||||||
|
printf "%s: Missing dependency: %s(1)\n" "$argv0" "$dep" 1>&2
|
||||||
# check if we have tomcat(1)
|
exit 69 # sysexits(3) EX_UNAVAILABLE
|
||||||
if ! command -v tomcat >/dev/null 2>&1; then
|
fi
|
||||||
printf "%s: Missing dependency: stoml(1)\n" "$argv0" 1>&2
|
done
|
||||||
exit 71 # sysexits(3) EX_OSERR
|
|
||||||
fi
|
|
||||||
|
|
||||||
# set the XDG_COMMAND
|
|
||||||
test -n "$XDG_COMMAND" || XDG_COMMAND="$(tomcat tools.xdg $CONFIG)"
|
|
||||||
! command -v handlr >/dev/null 2>&1 && ! command -v xdg-open >/dev/null 2>&1 \
|
|
||||||
&& XDG_COMMAND=false \
|
|
||||||
|| true
|
|
||||||
|
|
||||||
|
|
||||||
# check if we have a BROWSER
|
# check if we have a BROWSER
|
||||||
test -n "$BROWSER" || BROWSER="$(tomcat tools.browser $CONFIG)"
|
if test -z "$BROWSER"; then
|
||||||
if ! test -n "$BROWSER"; then
|
printf "%s: \$BROWSER not filled.\n" "$argv0" 1>&2
|
||||||
printf "\
|
exit 71 # sysexits(3) EX_OSERR
|
||||||
%s: \$BROWSER not filled.
|
|
||||||
Please place the path to your preferred browser's executable in
|
|
||||||
$XDG_CONFIG_HOME/xdg-sanity.conf or /etc/xdg-sanity.conf
|
|
||||||
" "$argv0" 1>&2
|
|
||||||
exit 71 # sysexits(3) EX_OSERR
|
|
||||||
fi
|
fi
|
||||||
|
|
||||||
while test -n "$1"; do
|
while test -n "$1"; do
|
||||||
URL="$1"
|
URL="$1"
|
||||||
|
|
||||||
# use curl(1) to write out the request header's content_type,
|
# use curl(1) to write out the request header's content_type, strip everything
|
||||||
# strip everything after the first semicolon,
|
# after the first semicolon, chop off any weird whitespace remnants
|
||||||
# chop off any weird whitespace remnants
|
MIME="$(curl -Ls -o /dev/null -w '%{content_type}' "$1" | sed 's/\;.*//' \
|
||||||
MIME="$(curl -Ls -o /dev/null -w '%{content_type}' "$1" | sed 's/\;.*//' |\
|
| xargs echo)"
|
||||||
xargs echo)"
|
|
||||||
|
|
||||||
# get the pattern for the extensions to MATCH
|
# get the URL with no scheme
|
||||||
MATCH=$(printf "%s\n" "$URL" | sed -ne 's/^h.\+\/\///p' |\
|
NO_SCHEME="$(printf "%s\n" "$URL" | sed -n 's/^h.\+\/\///p')"
|
||||||
sed -e 's/\/.*\+//g')
|
|
||||||
|
|
||||||
# run through MIME extensions
|
# get the pattern for the extensions to MATCH
|
||||||
for file in \
|
MATCH="$(printf "%s\n" "$NO_SCHEME" | sed 's/\/.*\+//g')"
|
||||||
"$XDG_DATA_HOME"/xdg-sanity/*-mime.toml \
|
|
||||||
/usr/share/xdg-sanity/*-mime.toml \
|
|
||||||
/usr/local/share/xdg-sanity/*-mime.toml \
|
|
||||||
/dev/null
|
|
||||||
do
|
|
||||||
i=$(tomcat replace.urls "$file" | sed 's/ /\n/g' | xargs wc -l)
|
|
||||||
while ! [ "$i" = 0 ]; do
|
|
||||||
if [ "$MATCH" = "$(tomcat replace.urls[$i] $file)" ]; then
|
|
||||||
MIME=$(tomcat with.mime "$file")
|
|
||||||
fi
|
|
||||||
i=$(dc -e "$i 1 - p")
|
|
||||||
done
|
|
||||||
done
|
|
||||||
|
|
||||||
# and the replace extensions
|
# get the non-domain of the URI for tacking onto the end of replaced URIs
|
||||||
for file in \
|
URI="$(printf "%s\n" "$NO_SCHEME" | sed -n 's/^[^/]*\///p')"
|
||||||
"$XDG_DATA_HOME"/xdg-sanity/*-replace.toml \
|
|
||||||
/usr/share/xdg-sanity/*-replace.toml \
|
# only check for extensions if tomcat(1) is installed
|
||||||
/usr/local/share/xdg-sanity/*-replace.toml \
|
if command -v tomcat >/dev/null 2>&1; then
|
||||||
/dev/null
|
# run through MIME extensions
|
||||||
do
|
for file in \
|
||||||
i=$(tomcat replace.urls "$file" | sed 's/ /\n/g' | xargs wc -l)
|
"$XDG_DATA_HOME"/xdg-sanity/*.mime.toml \
|
||||||
while ! [ "$i" = 0 ]; do
|
/usr/share/xdg-sanity/*.mime.toml \
|
||||||
if [ "$MATCH" = "$(tomcat replace.urls[$i] $file)" ]; then
|
/usr/local/share/xdg-sanity/*.mime.toml
|
||||||
URL=$(tomcat with.url "$file")
|
do
|
||||||
fi
|
if test -e "$file"; then
|
||||||
i=$(dc -e "$i 1 - p")
|
get_urls
|
||||||
done
|
for url in $URLS; do
|
||||||
done
|
if [ "$MATCH" = "$url" ]; then
|
||||||
|
MIME="$(tomcat with.mime "$file")"
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
# then replace extensions
|
||||||
|
for file in \
|
||||||
|
"$XDG_DATA_HOME"/xdg-sanity/*.replace.toml \
|
||||||
|
/usr/share/xdg-sanity/*.replace.toml \
|
||||||
|
/usr/local/share/xdg-sanity/*.replace.toml
|
||||||
|
do
|
||||||
|
if test -e "$file"; then
|
||||||
|
get_urls
|
||||||
|
for url in $URLS; do
|
||||||
|
if [ "$MATCH" = "$url" ]; then
|
||||||
|
URL="$(tomcat with.url "$file")$URI"
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
# and the scheme extensions
|
||||||
|
for file in \
|
||||||
|
"$XDG_DATA_HOME"/xdg-sanity/*.scheme.toml \
|
||||||
|
/usr/share/xdg-sanity/*.scheme.toml \
|
||||||
|
/usr/local/share/xdg-sanity/*.scheme.toml
|
||||||
|
do
|
||||||
|
get_urls
|
||||||
|
for url in $URLS; do
|
||||||
|
if [ "$URL" = "$url" ]; then
|
||||||
|
URL="$(tomcat with.scheme "$file")$MATCH"
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
done
|
||||||
|
fi
|
||||||
|
|
||||||
# these commands may fail; this is intentional
|
# these commands may fail; this is intentional
|
||||||
if [ "$MIME" = "text/html" ]; then
|
if [ "$MIME" = "text/html" ]; then
|
||||||
"$BROWSER" "$URL"
|
"$BROWSER" "$URL"
|
||||||
else
|
else
|
||||||
case "$(command -v $XDG_COMMAND)" in
|
handlr launch "$MIME" -- "$URL"
|
||||||
*/handlr )
|
fi
|
||||||
"XDG_COMMAND" "$MIME" -- "$URL"
|
shift
|
||||||
;;
|
|
||||||
*/xdg-open )
|
|
||||||
"$(xdg-mime query default $MIME)" "$URL"
|
|
||||||
;;
|
|
||||||
false )
|
|
||||||
exit 69 # sysexits(3) EX_UNAVAILABLE
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
fi
|
|
||||||
shift
|
|
||||||
done
|
done
|
||||||
|
|
||||||
exit 0
|
exit 0
|
||||||
|
|||||||
29
xdg-sanity.1
Normal file
29
xdg-sanity.1
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
.TH XDG-SANITY 1
|
||||||
|
.SH NAME
|
||||||
|
.B xdg-sanity
|
||||||
|
\(en sanely handle HTTP/S URIs.
|
||||||
|
.SH SYNOPSIS
|
||||||
|
.B xdg-sanity [URI...]
|
||||||
|
.SH DESCRIPTION
|
||||||
|
The xdg-sanity tool stands in as the user’s web browser, handling links as they
|
||||||
|
are passed to it.
|
||||||
|
.SH EXAMPLES
|
||||||
|
Given a remote PNG file, the following command will open that file using the
|
||||||
|
user’s configured handler for that MIME type:
|
||||||
|
|
||||||
|
xdg-sanity https://example.com/image.png
|
||||||
|
.SH AUTHOR
|
||||||
|
Written by Emma Tebibyte.
|
||||||
|
.SH REPORTING BUGS
|
||||||
|
Any bugs may be reported on the bug tracker at
|
||||||
|
<https://git.tebibyte.media/emma/xdg-sanity>.
|
||||||
|
.SH COPYRIGHT
|
||||||
|
Copyright © 2023 Emma Tebibyte. License AGPLv3+: GNU AGPL version 3 or later
|
||||||
|
<https://gnu.org/licenses/gpl.html>.
|
||||||
|
|
||||||
|
This is free software: you are free to change and redistribute it. There is NO
|
||||||
|
WARRANTY, to the extent permitted by law.
|
||||||
|
.SH SEE ALSO
|
||||||
|
.BR xdg-open(1)\
|
||||||
|
,
|
||||||
|
.BR xdg-mime(1)
|
||||||
@@ -1,66 +0,0 @@
|
|||||||
#!/bin/sh
|
|
||||||
|
|
||||||
INPUT=$(echo $1)
|
|
||||||
echo "Loading configuration..."
|
|
||||||
CONFIG=$(cat /etc/xdg-sanity/xdg-sanity.conf)
|
|
||||||
BROWSER=$(echo $CONFIG | sed -ne 's/^browser *= *//p')
|
|
||||||
|
|
||||||
if [ "$BROWSER" = "" ]
|
|
||||||
then
|
|
||||||
echo "Please place the path to your default browser's executable in /etc/xdg-sanity/xdg-sanity.conf"
|
|
||||||
exit
|
|
||||||
else
|
|
||||||
echo "Found default browser $BROWSER"
|
|
||||||
fi
|
|
||||||
|
|
||||||
echo "Loading extensions..."
|
|
||||||
for EXT in /etc/xdg-sanity/extensions/*.sh
|
|
||||||
do
|
|
||||||
|
|
||||||
if [ "$EXT" = "/etc/xdg-sanity/extensions/*.sh" ]
|
|
||||||
then
|
|
||||||
echo "No extensions to load"
|
|
||||||
else
|
|
||||||
|
|
||||||
for EXT in /etc/xdg-sanity/extensions/*.sh
|
|
||||||
do
|
|
||||||
TYPE=$(cat $EXT | sed -ne 's/^# EXT-TYPE=//p' | tr -d '\n')
|
|
||||||
echo "Found $TYPE extension $EXT"
|
|
||||||
|
|
||||||
if [ "$TYPE" = "replace" ]
|
|
||||||
then
|
|
||||||
echo "Modifying $INPUT..."
|
|
||||||
INPUT=$($EXT "$INPUT")
|
|
||||||
echo "Got $INPUT"
|
|
||||||
|
|
||||||
else
|
|
||||||
if [ "$TYPE" = "mime" ]
|
|
||||||
then
|
|
||||||
echo "Modifying MIME type..."
|
|
||||||
MIME=$($EXT "$INPUT")
|
|
||||||
echo "Got $MIME"
|
|
||||||
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
|
|
||||||
done
|
|
||||||
fi
|
|
||||||
|
|
||||||
done
|
|
||||||
|
|
||||||
if [ "$MIME" = "" ] || [ "$MIME" = "$1" ] || [ "$MIME" = "$INPUT" ]
|
|
||||||
then
|
|
||||||
echo "Determining MIME type of $INPUT:"
|
|
||||||
# Determines HTTP code, might use for something else?
|
|
||||||
# CODE=$(curl -fLIs "$INPUT" | sed -ne 's/ [[:space:]]*$//p' | sed -ne 's|^HTTP/.\+ ||p')
|
|
||||||
MIME=$(curl -fLIs "$INPUT" | sed -ne 's/^[cC]ontent-[tT]ype: //p' | sed -e 's/;.\+//p' | tail -n1 | tr -d '\r')
|
|
||||||
echo $MIME
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [ "$MIME" = "text/html" ]
|
|
||||||
then
|
|
||||||
$BROWSER $INPUT
|
|
||||||
|
|
||||||
else
|
|
||||||
handlr launch "$MIME" -- "$INPUT"
|
|
||||||
fi
|
|
||||||
Reference in New Issue
Block a user