241 lines
10 KiB
Bash
Executable file
241 lines
10 KiB
Bash
Executable file
#!/bin/sh
|
|
# fontctrl
|
|
# Minimal font manager for GNU/Linux.
|
|
# https://git.speedie.site/speedie/fontctrl
|
|
#
|
|
# Copyright (C) 2022-2023 speedie
|
|
#
|
|
# This program is free software: you can redistribute it and/or modify
|
|
# it under the terms of the GNU 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 General Public License for more details.
|
|
#
|
|
# You should have received a copy of the GNU General Public License
|
|
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
|
|
# hardcoded base directories, can however be overriden by exporting these
|
|
FONTCTRL_BASEDIR_USER="${FONTCTRL_BASEDIR_USER:-$HOME/.config/fontctrl}"
|
|
FONTCTRL_BASEDIR_GLOBAL="${FONTCTRL_BASEDIR_GLOBAL:-/etc/fontctrl}"
|
|
FONTCTRL_VER="${FONTCTRL_VER:-1.3}"
|
|
GLOBALFONTDIR="${GLOBALFONTDIR:-/usr/share/fonts/fonts}"
|
|
USERFONTDIR="${USERFONTDIR:-$HOME/.local/share/fonts}"
|
|
|
|
# wrapper functions to clean up codebase
|
|
die() { stderr "$@"; exit 1; }
|
|
msg() { [ -n "$*" ] && printf "%s\n" "$@"; }
|
|
msg_n() { [ -n "$*" ] && printf "%s" "$@"; }
|
|
stderr() { msg "$@" >&2; }
|
|
is_narg() { echo "$carg" | grep -qE "$copt|--global|--user" && return 1 || return 0; }
|
|
|
|
# help argument
|
|
ls_args() {
|
|
msg "fontctrl - minimal font manager for POSIX compliant shells."
|
|
msg "usage: [stdin] fontctrl [install FONT] [remove FONT] [list] [enable FONT] [disable FONT] [license] [help] [version] [arg]"
|
|
msg "--global perform the action as a superuser."
|
|
msg "--user perform the action as the current user."
|
|
}
|
|
|
|
# create base for fontctrl
|
|
mk() {
|
|
# create base directories where font symlinks and configurations for fonts will be placed.
|
|
[ "$(id -u)" = "0" ] && \
|
|
mkdir -p $FONTCTRL_BASEDIR_GLOBAL/fonts && isroot=true; \
|
|
mkdir -p "$FONTCTRL_BASEDIR_USER/fonts"
|
|
|
|
echo "$arg" | grep -q "global" && isglobal=true
|
|
|
|
FAIL_NOROOT() {
|
|
[ -z "$isroot" ] || return
|
|
die "This action must be used as root."
|
|
}
|
|
|
|
echo "$arg" | grep -q "global" && FAIL_NOROOT
|
|
}
|
|
|
|
# function to parse arguments and install fonts
|
|
install_font() {
|
|
exitcode=0 # exit code
|
|
[ -z "$2" ] && die "You must specify a font to install."
|
|
|
|
# loop through arguments
|
|
for i in $(seq "$argc"); do
|
|
carg="$(printf "%s\n" "$@" | sed -n "${i}","${i}"p)"
|
|
copt=install
|
|
is_narg || continue
|
|
[ ! -e "$carg" ] && exitcode=1 && stderr "Font '$carg' does not exist." && continue || arg2="$carg"
|
|
[ ! -e "$carg" ] && die "Failed to install '$carg': Not a valid font, exiting." || msg "Installing font '$carg'."
|
|
|
|
# install the font
|
|
[ "$isroot" != "true" ] && cp -f "$arg2" "$FONTCTRL_BASEDIR_USER/fonts/" && msg "Font '$arg2' installed successfully for $(whoami)." && hi=true && continue
|
|
[ "$isroot" = "true" ] && cp -f "$arg2" "$FONTCTRL_BASEDIR_GLOBAL/fonts/" && msg "Font '$arg2' installed globally successfully." && hi=true && continue
|
|
done
|
|
|
|
[ "$hi" != "true" ] && die "Font does not exist."
|
|
|
|
if [ "$isroot" != "true" ]; then
|
|
msg "Run fontctrl list --user followed by fontctrl enable <font> --user to enable the font."
|
|
else
|
|
msg "Run fontctrl list --global followed by fontctrl enable <font> --global to enable the font."
|
|
fi
|
|
|
|
return $exitcode # return the exit code
|
|
}
|
|
|
|
# function to parse arguments and remove fonts
|
|
rm_font() {
|
|
exitcode=0 # exit code
|
|
[ -z "$2" ] && die "You must specify a font to remove."
|
|
|
|
for i in $(seq "$argc"); do
|
|
carg="$(printf "%s\n" "$@" | sed -n "${i}","${i}"p)"
|
|
copt=remove
|
|
is_narg || continue
|
|
[ -z "$arg2" ] && msg "You must specify a font to remove." && exit 1
|
|
|
|
# remove globally
|
|
if [ "$isglobal" = "true" ]; then
|
|
selfont="$(find "$FONTCTRL_BASEDIR_GLOBAL"/fonts/*"$carg"* -type f 2>/dev/null | head -n 1)" # Head in case there are multiple matches
|
|
[ ! -e "$selfont" ] && exitcode=1 && stderr "No fonts matching '$carg' found." && continue
|
|
msg "Removing font '$selfont' globally."
|
|
hi=true
|
|
rm -f "$FONTCTRL_BASEDIR_GLOBAL/fonts/$selfont" && msg "Font '$selfont' removed successfully. Run fontctrl list to see available fonts."
|
|
else # for the user
|
|
selfont="$(find "$FONTCTRL_BASEDIR_USER"/fonts/*"$carg"* -type f 2>/dev/null | head -n 1)" # Head in case there are multiple matches
|
|
[ ! -e "$selfont" ] && exitcode=1 && stderr "No fonts matching '$carg' found." && continue
|
|
msg "Removing font '$selfont' for $(whoami)"
|
|
hi=true
|
|
rm -f "$selfont" && msg "Font '$selfont' removed successfully. Run fontctrl list to see available fonts."
|
|
fi
|
|
done
|
|
|
|
[ "$hi" != "true" ] && die "Font does not exist."
|
|
return $exitcode # return the exit code
|
|
}
|
|
|
|
# function to parse arguments and enable fonts
|
|
enable_font() {
|
|
exitcode=0 # exit code
|
|
[ -z "$2" ] && die "You must specify a font to enable."
|
|
|
|
for i in $(seq "$argc"); do
|
|
carg="$(printf "%s\n" "$@" | sed -n "${i}","${i}"p)"
|
|
copt=enable
|
|
is_narg || continue
|
|
|
|
if [ "$isglobal" != "true" ]; then # user
|
|
selfont="$(find "$FONTCTRL_BASEDIR_USER"/fonts/*"$carg"* -type f 2>/dev/null | head -n 1)" # Head in case there are multiple matches
|
|
b_selfont="$(basename "$selfont")"
|
|
[ ! -e "$selfont" ] && exitcode=1 && stderr "No fonts matching '$carg' found." && continue
|
|
msg "Enabling font '$b_selfont' for $(whoami)"
|
|
mkdir -p "$USERFONTDIR/fontctrl-fonts"
|
|
rm -f "$USERFONTDIR/fontctrl-fonts/$b_selfont"
|
|
hi=true
|
|
[ -e "$FONTCTRL_BASEDIR_USER/fonts/$b_selfont" ] && ln -s "$FONTCTRL_BASEDIR_USER/fonts/$b_selfont" "$USERFONTDIR/fontctrl-fonts/$b_selfont" && msg "Font '$b_selfont' enabled successfully." && continue
|
|
exit 1
|
|
else # global
|
|
selfont="$(find "$FONTCTRL_BASEDIR_GLOBAL"/fonts/*"$carg"* -type f 2>/dev/null | head -n 1)" # Head in case there are multiple matches
|
|
b_selfont="$(basename "$selfont")"
|
|
[ ! -e "$selfont" ] && stderr "No fonts matching '$carg' found." && exitcode=1 && continue
|
|
msg "Enabling font '$b_selfont' globally."
|
|
mkdir -p "$GLOBALFONTDIR/fontctrl-fonts"
|
|
rm -f "$GLOBALFONTDIR/fontctrl-fonts/$b_selfont"
|
|
hi=true
|
|
[ -e "$FONTCTRL_BASEDIR_GLOBAL/fonts/$selfont" ] && ln -s "$FONTCTRL_BASEDIR_GLOBAL/fonts/$selfont" "$GLOBALFONTDIR/fontctrl-fonts/$b_selfont" && msg "Font '$selfont' enabled successfully." && continue
|
|
exit 1
|
|
fi
|
|
done
|
|
|
|
[ "$hi" != "true" ] && die "Font does not exist."
|
|
return $exitcode # return the exit code
|
|
}
|
|
|
|
# function to parse arguments and disable fonts
|
|
disable_font() {
|
|
exitcode=0 # exit code
|
|
[ -z "$2" ] && die "You must specify a font to disable."
|
|
|
|
for i in $(seq "$argc"); do
|
|
carg="$(printf "%s\n" "$@" | sed -n "${i}","${i}"p)"
|
|
copt=disable
|
|
is_narg || continue
|
|
|
|
if [ "$isglobal" != "true" ]; then # user
|
|
selfont="$(find "$FONTCTRL_BASEDIR_USER"/fonts/*"$carg"* -type f 2>/dev/null | head -n 1)" # Head in case there are multiple matches
|
|
b_selfont="$(basename "$selfont")"
|
|
[ ! -e "$selfont" ] && exitcode=1 && stderr "No fonts matching '$carg' found." && continue
|
|
msg "Disabling font '$b_selfont' for $(whoami)"
|
|
hi=true
|
|
rm -f "$USERFONTDIR/fontctrl-fonts/$b_selfont" && msg "Font '$selfont' disabled successfully." && continue
|
|
exit 1
|
|
else # global
|
|
selfont="$(find "$FONTCTRL_BASEDIR_GLOBAL"/fonts/*"$carg"* -type f 2>/dev/null | head -n 1)" # Head in case there are multiple matches
|
|
b_selfont="$(basename "$selfont")"
|
|
[ ! -e "$selfont" ] && exitcode=1 && stderr "No fonts matching '$carg' found." && continue
|
|
msg "Disabling font '$b_selfont' globally."
|
|
hi=true
|
|
rm -f "$GLOBALFONTDIR/fontctrl-fonts/$b_selfont" && msg "Font '$b_selfont' disabled successfully." && continue
|
|
exit 1
|
|
fi
|
|
done
|
|
|
|
[ "$hi" != "true" ] && die "Font does not exist."
|
|
return $exitcode # return the exit code
|
|
}
|
|
|
|
# list fonts
|
|
ls_font() {
|
|
msg "List of all installed fonts:"
|
|
[ "$isglobal" = "true" ] && basename "$(find "$FONTCTRL_BASEDIR_GLOBAL/fonts/" -type f)" || find "$FONTCTRL_BASEDIR_USER/fonts/" -type f -printf '\033[0;35m%f\033[0m\n'
|
|
msg "Use fontctrl enable/disable to enable/disable a font. See fontctrl help for more information." && return || exit 1
|
|
}
|
|
|
|
# print version information
|
|
print_ver() {
|
|
[ -z "$arg3" ] || die "This option does not take a third argument."
|
|
[ -n "$arg2" ] && die "Invalid argument: '$arg2'"
|
|
msg "$FONTCTRL_VER"
|
|
}
|
|
|
|
# print license information
|
|
print_license() {
|
|
[ -z "$arg2" ] && msg "fontctrl is free software, licensed under the GNU General Public License version 3.0. See https://git.speedie.site/speedie/fontctrl for more information." || die "This option does not take an argument."
|
|
}
|
|
|
|
# set everything up
|
|
main() {
|
|
# convenient variables
|
|
arg="$*"
|
|
arg1="$1"
|
|
arg2="$2"
|
|
arg3="$3"
|
|
|
|
mk "$@"
|
|
|
|
# arg count, this is used many times so why not set it here
|
|
argc="$(printf "%s\n" "$@" | grep -c '')"
|
|
|
|
case "$arg1" in
|
|
"install") arg=recognized && install_font "$@" && exit 0 || exit 1 ;;
|
|
"remove") arg=recognized && rm_font "$@" && exit 0 || exit 1 ;;
|
|
"enable") arg=recognized && enable_font "$@" && exit 0 || exit 1 ;;
|
|
"disable") arg=recognized && disable_font "$@" && exit 0 || exit 1 ;;
|
|
"list") arg=recognized && ls_font "$@" && exit 0 || exit 1 ;;
|
|
"help") arg=recognized && ls_args "$@" && exit 0 || exit 1 ;;
|
|
"version") arg=recognized && print_ver "$@" && exit 0 || exit 1 ;;
|
|
"license") arg=recognized && print_license "$@" && exit 0 || exit 1 ;;
|
|
"") arg=recognized && ls_args "$@" && exit 0 || exit 1 ;;
|
|
esac
|
|
|
|
[ "$arg" != "recognized" ] && msg "Invalid argument: '$arg1'" && die "Run fontctrl help or with no arguments for help."
|
|
}
|
|
|
|
# take stdin
|
|
[ -p /proc/self/fd/0 ] && read stdin && set -- "$@" $stdin
|
|
|
|
main "$@"
|