sxmo_files now respect user desktop configurations
We use our own implementation of xdg-open that replace the hardcoded script used in sxmo_files. We add and will maintain some desktop entries to offer a suckless experience by default. Signed-off-by: Reed Wade <reedwade@misterbanal.net> Signed-off-by: Anjandev Momi <anjan@momi.ca>
This commit is contained in:
parent
a90f565c12
commit
08b95c6182
5 changed files with 344 additions and 14 deletions
6
configs/applications/sxmo-mpv-music.desktop
Normal file
6
configs/applications/sxmo-mpv-music.desktop
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
[Desktop Entry]
|
||||||
|
Name=mpv Music Player
|
||||||
|
Exec=mpv -ao=alsa --vid=no -v
|
||||||
|
Terminal=true
|
||||||
|
Type=Application
|
||||||
|
MimeType=audio/wav;audio/opus;audio/m4a;audio/flac;audio/mp3
|
6
configs/applications/sxmo-sxiv.desktop
Normal file
6
configs/applications/sxmo-sxiv.desktop
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
[Desktop Entry]
|
||||||
|
Name=sxiv Image Viewer
|
||||||
|
Exec=sxiv
|
||||||
|
Terminal=false
|
||||||
|
Type=Application
|
||||||
|
MimeType=image/jpeg;image/png;image/gif
|
6
configs/applications/sxmo-zathura.desktop
Normal file
6
configs/applications/sxmo-zathura.desktop
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
[Desktop Entry]
|
||||||
|
Name=Zathura
|
||||||
|
Exec=zathura
|
||||||
|
Terminal=false
|
||||||
|
Type=Application
|
||||||
|
MimeType=application/pdf;application/x-rar;application/epub+zip
|
|
@ -3,18 +3,6 @@ DIR="$1"
|
||||||
[ -z "$DIR" ] && DIR="/home/$USER/"
|
[ -z "$DIR" ] && DIR="/home/$USER/"
|
||||||
cd "$DIR" || exit 1
|
cd "$DIR" || exit 1
|
||||||
|
|
||||||
handlefiles() {
|
|
||||||
if echo "$1" | grep -iE ".(webm|ogg|mp4|mov|avi|mkv)$"; then
|
|
||||||
st -e mpv -ao=alsa "$@"
|
|
||||||
elif echo "$1" | grep -iE ".(wav|opus|m4a|flac|mp3)$"; then
|
|
||||||
st -e mpv -ao=alsa --vid=no -v "$@"
|
|
||||||
elif echo "$1" | grep -iE ".(jpg|png|gif)$"; then
|
|
||||||
st -e sxiv "$@"
|
|
||||||
else
|
|
||||||
st -e sh -ic "$EDITOR $*"
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
|
|
||||||
while true; do
|
while true; do
|
||||||
CHOICES="$(printf %b 'Close Menu\n../\n*\n'"$(ls -1p)")"
|
CHOICES="$(printf %b 'Close Menu\n../\n*\n'"$(ls -1p)")"
|
||||||
DIR="$(basename "$(pwd)")"
|
DIR="$(basename "$(pwd)")"
|
||||||
|
@ -31,6 +19,6 @@ while true; do
|
||||||
|
|
||||||
echo "$PICKED" | grep "Close Menu" && exit 0
|
echo "$PICKED" | grep "Close Menu" && exit 0
|
||||||
[ -d "$PICKED" ] && cd "$PICKED" && continue
|
[ -d "$PICKED" ] && cd "$PICKED" && continue
|
||||||
echo "$PICKED" | grep -E '^[*]$' && handlefiles ./*
|
echo "$PICKED" | grep -E '^[*]$' && sxmo_open.sh -a ./*
|
||||||
[ -f "$PICKED" ] && handlefiles "$PICKED"
|
[ -f "$PICKED" ] && sxmo_open.sh -a "$PICKED"
|
||||||
done
|
done
|
||||||
|
|
324
scripts/core/sxmo_open.sh
Executable file
324
scripts/core/sxmo_open.sh
Executable file
|
@ -0,0 +1,324 @@
|
||||||
|
#!/usr/bin/env sh
|
||||||
|
|
||||||
|
MIMEAPPS="${XDG_CONFIG_HOME:-$HOME/.config}/mimeapps.list"
|
||||||
|
DESKTOPS_CACHED_MIMEAPPS="${XDG_CONFIG_HOME:-$HOME/.config}/desktops.mimeapps.list"
|
||||||
|
DESKTOP_DIRS="/usr/share/sxmo/applications/|/usr/share/applications/|/usr/local/share/applications/|${XDG_DATA_HOME:-$HOME/.local/share}/applications/"
|
||||||
|
attached=
|
||||||
|
debug=
|
||||||
|
TERMCMD="${TERMCMD:-st -e}"
|
||||||
|
|
||||||
|
# This will convert a mimeapps.list to a parsable mapping
|
||||||
|
# Lines with multiple mimetype will be splitted
|
||||||
|
# The mapping format is something as
|
||||||
|
# added;image/jpeg;bar.desktop
|
||||||
|
# added;image/jpeg;baz.desktop
|
||||||
|
# added;video/H264;bar.desktop
|
||||||
|
# default;image/jpeg;foo.desktop
|
||||||
|
# removed;video/H264;baz.desktop
|
||||||
|
mimeapps_to_desktop_mapping() {
|
||||||
|
[ ! -f "$1" ] && return
|
||||||
|
awk '
|
||||||
|
/^\[Default Applications\]$/ { kind = "default" }
|
||||||
|
/^\[Added Associations\]$/ { kind = "added" }
|
||||||
|
/^\[Removed Associations\]$/ { kind = "removed" }
|
||||||
|
/=/ {
|
||||||
|
split($0, mime_desktops, "=")
|
||||||
|
split(mime_desktops[2], desktops, ";")
|
||||||
|
|
||||||
|
for ( key in desktops ) {
|
||||||
|
print kind ";" mime_desktops[1] ";" desktops[key]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
' "$1"
|
||||||
|
}
|
||||||
|
|
||||||
|
# This will generate the added mapping from all destkop entries in a dir
|
||||||
|
get_mimeapps_entries_from_desktop_dir() {
|
||||||
|
for desktop_path in "$1"/*.desktop; do
|
||||||
|
grep --include "*.desktop" '^MimeType=' "$desktop_path" \
|
||||||
|
| tr ';' '\n' \
|
||||||
|
| cut -d= -f2 \
|
||||||
|
| xargs -i{} printf "%s=%s\n" "{}" "$(basename "$desktop_path")"
|
||||||
|
done
|
||||||
|
}
|
||||||
|
|
||||||
|
# Build and save the desktop mimeapps mapping if necessary
|
||||||
|
prepare_desktop_mimeapps_mapping_cache() {
|
||||||
|
last_desktop_modif_date="$(printf %s "$DESKTOP_DIRS" | tr '|' '\n' | while read -r desktop_dir; do
|
||||||
|
for desktop_file in "$desktop_dir"/*.desktop; do
|
||||||
|
stat -c %Y "$desktop_file"
|
||||||
|
done
|
||||||
|
done | sort -r | head -n1)"
|
||||||
|
|
||||||
|
if [ -r "$DESKTOPS_CACHED_MIMEAPPS" ]; then
|
||||||
|
desktop_cache_modif_date="$(stat -c %Y "$DESKTOPS_CACHED_MIMEAPPS")"
|
||||||
|
if [ "$last_desktop_modif_date" -gt "$desktop_cache_modif_date" ]; then
|
||||||
|
rm "$DESKTOPS_CACHED_MIMEAPPS"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ ! -r "$DESKTOPS_CACHED_MIMEAPPS" ]; then
|
||||||
|
IFS='|'
|
||||||
|
echo "[Added Associations]" > "$DESKTOPS_CACHED_MIMEAPPS"
|
||||||
|
for desktop_dir in $DESKTOP_DIRS; do
|
||||||
|
get_mimeapps_entries_from_desktop_dir "$desktop_dir"
|
||||||
|
done >> "$DESKTOPS_CACHED_MIMEAPPS"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
find_desktop_path() {
|
||||||
|
desktop_name="$1"
|
||||||
|
|
||||||
|
IFS='|'
|
||||||
|
for desktop_dir in $DESKTOP_DIRS; do
|
||||||
|
if [ -r "$desktop_dir/$desktop_name" ]; then
|
||||||
|
realpath "$desktop_dir/$desktop_name"
|
||||||
|
return
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
}
|
||||||
|
|
||||||
|
# This will take the full maping and simplify it which means
|
||||||
|
# * strip added entries with removed ones
|
||||||
|
# * put default entries first
|
||||||
|
# * remove duplicates lines
|
||||||
|
# following this format
|
||||||
|
# image/jpeg;foo.desktop
|
||||||
|
# image/jpeg;bar.desktop
|
||||||
|
# image/jpeg;baz.desktop
|
||||||
|
simplify_mapping() {
|
||||||
|
awk '
|
||||||
|
function contains(array, value) {
|
||||||
|
for (key in array) {
|
||||||
|
if (array[key] == value)
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
/^$/ {next}
|
||||||
|
|
||||||
|
/^default;/ { kind = "default" }
|
||||||
|
/^added;/ { kind = "added" }
|
||||||
|
/^removed;/ { kind = "removed" }
|
||||||
|
|
||||||
|
{ gsub(kind ";", "", $0) }
|
||||||
|
|
||||||
|
kind == "default" { default_entries[NR]=$0 }
|
||||||
|
kind == "added" { added_entries[NR]=$0 }
|
||||||
|
kind == "removed" { removed_entries[NR]=$0 }
|
||||||
|
|
||||||
|
END {
|
||||||
|
for (key in default_entries) {
|
||||||
|
print default_entries[key]
|
||||||
|
}
|
||||||
|
for (key in added_entries) {
|
||||||
|
entry = added_entries[key]
|
||||||
|
if (contains(removed_entries, entry)) { continue }
|
||||||
|
if (contains(default_entries, entry)) { continue }
|
||||||
|
print entry
|
||||||
|
}
|
||||||
|
}
|
||||||
|
' /dev/stdin
|
||||||
|
}
|
||||||
|
|
||||||
|
get_mimeapps_mapping() {
|
||||||
|
prepare_desktop_mimeapps_mapping_cache
|
||||||
|
|
||||||
|
printf '%s\n%s' \
|
||||||
|
"$(mimeapps_to_desktop_mapping "$MIMEAPPS")" \
|
||||||
|
"$(mimeapps_to_desktop_mapping "$DESKTOPS_CACHED_MIMEAPPS")" \
|
||||||
|
| simplify_mapping
|
||||||
|
}
|
||||||
|
|
||||||
|
filter_matching_desktops() {
|
||||||
|
mime_type="$1"
|
||||||
|
|
||||||
|
grep "^$mime_type;" /dev/stdin \
|
||||||
|
| cut -d";" -f2
|
||||||
|
}
|
||||||
|
|
||||||
|
curl_mime_type() {
|
||||||
|
curl --head -fsw '%{content_type}' "$1" | tail -n1 | sed 's|;.*||'
|
||||||
|
}
|
||||||
|
|
||||||
|
extension_mime_type() {
|
||||||
|
[ ! -r "/etc/mime.types" ] && return # require mailcap
|
||||||
|
|
||||||
|
ext="${1##*.}"
|
||||||
|
grep "\t.*$ext" /etc/mime.types | awk '{print $1}'
|
||||||
|
}
|
||||||
|
|
||||||
|
get_mime_type() {
|
||||||
|
# Seems like an x-scheme
|
||||||
|
if echo "$1" | grep -q '^.\+:'; then
|
||||||
|
if echo "$1" | grep -q '^https\?:'; then
|
||||||
|
mime_type="$(curl_mime_type "$1")"
|
||||||
|
fi
|
||||||
|
|
||||||
|
[ -z "$mime_type" ] && mime_type="x-scheme-handler/$(echo "$1" | grep -o '^\w\+')"
|
||||||
|
else
|
||||||
|
# is readable
|
||||||
|
if [ -r "$1" ]; then
|
||||||
|
mime_type="$(file -b --mime-type "$1")"
|
||||||
|
else
|
||||||
|
echo "This file does not exists?" > /dev/stderr
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
# we try to be more precise then
|
||||||
|
if [ "application/octet-stream" = "$mime_type" ]; then
|
||||||
|
new_mime_type="$(extension_mime_type "$1")"
|
||||||
|
[ -n "$new_mime_type" ] && mime_type="$new_mime_type"
|
||||||
|
elif [ "inode/symlink" = "$mime_type" ]; then
|
||||||
|
real_path="$(realpath "$1")"
|
||||||
|
mime_type="$(get_mime_type "$real_path")"
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "$mime_type"
|
||||||
|
}
|
||||||
|
|
||||||
|
execute() {
|
||||||
|
if [ -n "$debug" ]; then
|
||||||
|
echo "The final command to execute is:" > /dev/stderr
|
||||||
|
echo "$@" > /dev/stderr
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
eval "$@"
|
||||||
|
}
|
||||||
|
|
||||||
|
fetch_file() {
|
||||||
|
if [ -n "$debug" ]; then
|
||||||
|
echo "The file would be downloaded with '$*'" > /dev/stderr
|
||||||
|
return
|
||||||
|
fi
|
||||||
|
|
||||||
|
eval "$@"
|
||||||
|
}
|
||||||
|
|
||||||
|
build_command() {
|
||||||
|
exec="$1"
|
||||||
|
shift
|
||||||
|
|
||||||
|
IFS="
|
||||||
|
"
|
||||||
|
file_paths="$*"
|
||||||
|
unset IFS
|
||||||
|
|
||||||
|
if echo "$exec" | grep -q '%f\|%F'; then # We must retrieve distant files
|
||||||
|
file_paths="$(
|
||||||
|
echo "$file_paths" | while read -r file_path; do
|
||||||
|
local_file_path="$(mktemp --suffix=".$(basename "$file_path")")"
|
||||||
|
if echo "$file_path" | grep -q '^https\?://'; then
|
||||||
|
fetch_file curl -so "$local_file_path" "$file_path"
|
||||||
|
else
|
||||||
|
echo "$file_path"
|
||||||
|
continue
|
||||||
|
fi
|
||||||
|
echo "$local_file_path"
|
||||||
|
done
|
||||||
|
)"
|
||||||
|
exec="$(echo "$exec" | sed -e 's|%f|%u|' -e 's|%F|%U|')"
|
||||||
|
fi
|
||||||
|
|
||||||
|
file_paths="$(echo "$file_paths" | awk '{print "\"" $0 "\""}')"
|
||||||
|
|
||||||
|
command=
|
||||||
|
if echo "$exec" | grep -q '%u'; then # handle url file one by one
|
||||||
|
exec="$(echo "$exec" | sed 's|%u|"%s"|')"
|
||||||
|
if [ "true" = "$terminal" ]; then
|
||||||
|
command="$(echo "$file_paths" | xargs printf "$TERMCMD $exec & " | sed 's| $||')"
|
||||||
|
else
|
||||||
|
command="$(echo "$file_paths" | xargs printf "$exec & " | sed -e 's|^ ||' -e 's| $||')"
|
||||||
|
fi
|
||||||
|
elif echo "$exec" | grep -q '%U'; then # handle url file grouped
|
||||||
|
exec_before="$(echo "$exec" | awk -F' %U' '{print $1}')"
|
||||||
|
exec_after="$(echo "$exec" | awk -F'%U ' '{$1=""; print $0}')"
|
||||||
|
command="$exec_before $(echo "$file_paths" | xargs printf '"%s" ')${exec_after:+ $exec_after }&"
|
||||||
|
if [ "true" = "$terminal" ]; then
|
||||||
|
command="$TERMCMD $command"
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
command="$exec $(echo "$file_paths" | xargs printf '"%s" ')&"
|
||||||
|
if [ "true" = "$terminal" ]; then
|
||||||
|
command="$TERMCMD $command"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "$command"
|
||||||
|
}
|
||||||
|
|
||||||
|
run_desktop() {
|
||||||
|
desktop="$1"
|
||||||
|
shift
|
||||||
|
|
||||||
|
desktop_path="$(find_desktop_path "$desktop")"
|
||||||
|
if [ -z "$desktop_path" ]; then
|
||||||
|
echo "We can't find the desktop file \"$desktop\"" > /dev/stderr
|
||||||
|
return
|
||||||
|
fi
|
||||||
|
|
||||||
|
desktop_content="$(cat "$desktop_path")"
|
||||||
|
exec="$(echo "$desktop_content" | grep '^Exec=' | sed 's|^Exec=||' | head -n1)"
|
||||||
|
terminal="$(echo "$desktop_content" | grep '^Terminal=' | cut -d= -f2)"
|
||||||
|
[ -z "$terminal" ] && terminal="false"
|
||||||
|
|
||||||
|
command="$(build_command "$exec" "$@")"
|
||||||
|
|
||||||
|
if [ -n "$attached" ]; then
|
||||||
|
command="$(echo "$command" | sed 's| &|;|g')"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ -n "$debug" ]; then
|
||||||
|
echo "Exec is \"$exec\"" > /dev/stderr
|
||||||
|
echo "Terminal is \"$terminal\"" > /dev/stderr
|
||||||
|
echo "Command is \"$command\"" > /dev/stderr
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
eval "$command"
|
||||||
|
|
||||||
|
exit 0
|
||||||
|
}
|
||||||
|
|
||||||
|
run() {
|
||||||
|
mime_type="$(get_mime_type "$1")"
|
||||||
|
|
||||||
|
if [ -z "$mime_type" ]; then
|
||||||
|
echo "We failed to find the mime_type for \"$1\"" > /dev/stderr
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
desktops="$(get_mimeapps_mapping | filter_matching_desktops "$mime_type")"
|
||||||
|
|
||||||
|
if [ -n "$debug" ]; then
|
||||||
|
echo "The mime type is \"$mime_type\"" > /dev/stderr
|
||||||
|
echo "The matching desktops are:" > /dev/stderr
|
||||||
|
echo "$desktops" > /dev/stderr
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ -z "$desktops" ]; then
|
||||||
|
echo "There is no matching desktop to open \"$mime_type\"" > /dev/stderr
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "$desktops" | while read -r desktop; do
|
||||||
|
run_desktop "$desktop" "$@"
|
||||||
|
done
|
||||||
|
}
|
||||||
|
|
||||||
|
if [ "-d" = "$1" ]; then
|
||||||
|
debug="1"
|
||||||
|
shift
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ "-a" = "$1" ]; then
|
||||||
|
attached="1"
|
||||||
|
shift
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ $# -gt 0 ]; then
|
||||||
|
run "$@"
|
||||||
|
fi
|
Loading…
Add table
Add a link
Reference in a new issue