Wren Linux

wren-linux / bin / console-font

#!/bin/bash
# console-font [list | NAME | NUMBER]: written by Wren Linux parts/console-tmux.sh
# Changes the text size on a text console (console-only mode) at once, and
# remembers it in ~/.config/wren/console-font for the next login.
# With no argument it shows the list and asks which one.
# Names are a typeface and the height of a character in pixels: dejavu-43,
# terminus-bold-24. A file name from /usr/share/consolefonts also works.
# In a terminal window (foot, in sway) it sets foot's text size instead, in
# points (dejavu-16, dejavu-bold-18): the font= line of ~/.config/foot/foot.ini,
# for every terminal opened after (Ctrl+plus/minus still changes the one you
# are in), remembered in ~/.config/wren/foot-font so that
# parts/foot-config.sh keeps it when it writes foot.ini again.
#   console-font --foot | --console ...   the one or the other, wherever you are
dir=/usr/share/consolefonts
conf="$HOME/.config/wren/console-font"
default=Uni3-Terminus28x14
FOOT_INI=${XDG_CONFIG_HOME:-$HOME/.config}/foot/foot.ini
FOOT_CONF="$HOME/.config/wren/foot-font"
FOOT_DEFAULT="DejaVu Sans Mono:size=14"

# name file size
FONTS=(
    dejavu-30 Uni3-DejaVu30x16 30x16
    dejavu-36 Uni3-DejaVu36x20 36x20
    dejavu-43 Uni3-DejaVu43x24 43x24
    dejavu-51 Uni3-DejaVu51x28 51x28
    dejavu-59 Uni3-DejaVu59x32 59x32
    dejavu-74 Uni3-DejaVu74x40 74x40
    dejavu-89 Uni3-DejaVu89x48 89x48
    dejavu-bold-30 Uni3-DejaVuBold30x16 30x16
    dejavu-bold-36 Uni3-DejaVuBold36x20 36x20
    dejavu-bold-43 Uni3-DejaVuBold43x24 43x24
    dejavu-bold-51 Uni3-DejaVuBold51x28 51x28
    dejavu-bold-59 Uni3-DejaVuBold59x32 59x32
    terminus-12 Uni3-Terminus12x6 12x6
    terminus-16 Uni3-Terminus16 16x8
    terminus-20 Uni3-Terminus20x10 20x10
    terminus-24 Uni3-Terminus24x12 24x12
    terminus-28 Uni3-Terminus28x14 28x14
    terminus-32 Uni3-Terminus32x16 32x16
    terminus-bold-16 Uni3-TerminusBold16 16x8
    terminus-bold-20 Uni3-TerminusBold20x10 20x10
    terminus-bold-24 Uni3-TerminusBold24x12 24x12
    terminus-bold-28 Uni3-TerminusBold28x14 28x14
    terminus-bold-32 Uni3-TerminusBold32x16 32x16
)

current=$(cat "$conf" 2>/dev/null); current=${current:-$default}
names=() files=() sizes=()
for ((i = 0; i < ${#FONTS[@]}; i += 3)); do
    ls "$dir/${FONTS[i+1]}".psf* >/dev/null 2>&1 || continue
    names+=("${FONTS[i]}"); files+=("${FONTS[i+1]}"); sizes+=("${FONTS[i+2]}")
done

show() {
    echo "Console fonts (character size in pixels; bigger is easier to read):"
    for i in "${!names[@]}"; do
        mark=" "; [ "${files[i]}" = "$current" ] && mark="*"
        printf ' %s %2d  %-18s %s\n' "$mark" $((i + 1)) "${names[i]}" "${sizes[i]}"
    done
    echo "(* = in use)  Usage: console-font NAME or NUMBER"
}

apply() {
    local file=$1 tty
    if [ -n "${TMUX:-}" ]; then
        tty=$(tmux display-message -p '#{client_tty}' 2>/dev/null)
    else
        tty=$(tty 2>/dev/null)
    fi
    mkdir -p "${conf%/*}"
    echo "$file" >"$conf"
    case $tty in
        /dev/tty[0-9]*)
            if setfont -C "$tty" "$file" 2>/dev/null; then
                [ -z "${TMUX:-}" ] || tmux refresh-client 2>/dev/null
                echo "Console font is now $file."
            elif [ -n "${TMUX:-}" ] && [ -n "${WREN_LOGIN_LOOP:-}" ]; then
                # the console device is root's, so only the login shell can set the font:
                # leave tmux for a moment and let ~/.profile set it and reattach
                touch "${conf%/*}/console-redraw"
                tmux detach-client
            else
                echo "Could not set the font now; it is saved for your next login." >&2
                return 1
            fi ;;
        *) echo "Saved $file. This is not a text console, so it takes effect at your next console login." ;;
    esac
}

# where: the text console, or a terminal window (foot)
where=console
case ${1:-} in
    --foot) where=foot; shift ;;
    --console) shift ;;
    *)
        if [ -n "${TMUX:-}" ]; then t=$(tmux display-message -p '#{client_tty}' 2>/dev/null); else t=$(tty 2>/dev/null); fi
        case $t in
            /dev/tty[0-9]*) ;;
            *) if [ -n "${WAYLAND_DISPLAY:-}" ] || [[ ${TERM:-} == foot* ]]; then where=foot; fi ;;
        esac ;;
esac

if [ "$where" = foot ]; then
    # name, foot's font= value: DejaVu Sans Mono (fonts-dejavu-mono, the base's)
    names=() files=()
    for s in 11 12 13 14 16 18 20 24 28; do
        names+=("dejavu-$s") files+=("DejaVu Sans Mono:size=$s")
    done
    for s in 14 16 18 20 24; do
        names+=("dejavu-bold-$s") files+=("DejaVu Sans Mono:style=Bold:size=$s")
    done
    current=$(cat "$FOOT_CONF" 2>/dev/null); current=${current:-$FOOT_DEFAULT}
    show() {
        echo "Terminal text sizes (in points; bigger is easier to read):"
        for i in "${!names[@]}"; do
            mark=" "; [ "${files[i]}" = "$current" ] && mark="*"
            printf ' %s %2d  %s\n' "$mark" $((i + 1)) "${names[i]}"
        done
        echo "(* = in use)  Usage: console-font NAME or NUMBER. Ctrl+plus/minus: this window only."
    }
    apply() {
        local font=$1 new
        [ -f "$FOOT_INI" ] || { echo "console-font: there is no $FOOT_INI (wrenctl part foot-config writes it)" >&2; return 1; }
        grep -q '^font=' "$FOOT_INI" || { echo "console-font: $FOOT_INI has no font= line to change" >&2; return 1; }
        new=$(mktemp)
        sed "s|^font=.*|font=$font|" "$FOOT_INI" >"$new"
        if command -v foot >/dev/null && ! foot -C -c "$new" >/dev/null 2>&1; then
            rm -f "$new"
            echo "console-font: foot doesn't take font=$font; nothing changed" >&2
            return 1
        fi
        cat "$new" >"$FOOT_INI"
        rm -f "$new"
        mkdir -p "${FOOT_CONF%/*}"
        echo "$font" >"$FOOT_CONF"
        echo "Terminals you open from now on use $font."
    }
fi

pick=${1:-}
case $pick in
    list) show; exit ;;
    -h | --help) echo "usage: console-font [--foot | --console] [list | NAME | NUMBER]"; exit ;;
    "")
        show
        [ -t 0 ] || exit 0
        read -r -p "Number or name (Enter to leave it): " pick
        [ -n "$pick" ] || exit 0 ;;
esac

file=
if [[ $pick =~ ^[0-9]+$ ]]; then
    n=$((10#$pick - 1))
    [ "$n" -ge 0 ] && [ "$n" -lt "${#names[@]}" ] && file=${files[n]}
else
    for i in "${!names[@]}"; do
        if [ "${names[i]}" = "$pick" ] || [ "${files[i]}" = "$pick" ]; then file=${files[i]}; fi
    done
    [ -n "$file" ] || [ "$where" = foot ] || { ls "$dir/$pick".psf* >/dev/null 2>&1 && file=$pick; }
fi
[ -n "$file" ] || { echo "console-font: no font '$pick'. Try: console-font list" >&2; exit 1; }
apply "$file"