Vendor the command set the menu and shell depend on
This commit is contained in:
Executable
+236
@@ -0,0 +1,236 @@
|
||||
#!/bin/bash
|
||||
|
||||
# blob:summary=Scale text everywhere — blob shell, GTK apps, and terminals
|
||||
# blob:args=[size|reset]
|
||||
# blob:examples=blob display text size | blob display text size 16 | blob display text size reset
|
||||
|
||||
# One knob for apparent text size across the desktop. It drives three settings
|
||||
# in lockstep, all anchored to the shell default of 12px:
|
||||
# • the blob shell's font base-size (~/.config/blob/shell.toml [font])
|
||||
# • GNOME/GTK's text-scaling-factor (12px -> 1.0, quantized so the GTK
|
||||
# interface font lands on a whole point size, so 16 -> 15pt/11pt = 1.3636)
|
||||
# • the terminal font point size (12px -> 9pt, so terminal_pt = px * 9/12)
|
||||
# The shell override layers on top of the active theme (so the size survives
|
||||
# theme switches) and the shell watches the file, so shell text re-flows live.
|
||||
# Accepts an integer from 9 to 20 (px).
|
||||
|
||||
MIN=9
|
||||
MAX=20
|
||||
GKEY_SCHEMA="org.gnome.desktop.interface"
|
||||
GKEY_NAME="text-scaling-factor"
|
||||
|
||||
# Anchors: 12px shell base == factor 1.0 == 9pt terminal font.
|
||||
TERM_DEFAULT_PT=9
|
||||
SHELL_DEFAULT_PX=12
|
||||
|
||||
shell_config="$HOME/.config/blob/shell.toml"
|
||||
|
||||
usage() {
|
||||
echo "Usage: blob-display-size [size|reset]"
|
||||
echo " (no args) print the current text size, GTK factor, and terminal size"
|
||||
echo " <size> set text size in px ($MIN–$MAX); shell + GTK + terminals together"
|
||||
echo " reset return all three to their defaults (12px / 1.0 / 9pt)"
|
||||
}
|
||||
|
||||
# ---- shell base-size: the rem root every shell type size derives from ----
|
||||
|
||||
# Print the base-size currently set under [font], or nothing if unset.
|
||||
current_base_size() {
|
||||
[[ -f $shell_config ]] || return 0
|
||||
awk '
|
||||
/^[[:space:]]*\[/ { in_font = ($0 ~ /^[[:space:]]*\[font\]([[:space:]]|$)/); next }
|
||||
in_font && /^[[:space:]]*base-size[[:space:]]*=/ {
|
||||
v = $0
|
||||
sub(/^[^=]*=[[:space:]]*/, "", v)
|
||||
sub(/[[:space:]]*(#.*)?$/, "", v)
|
||||
print v
|
||||
exit
|
||||
}
|
||||
' "$shell_config"
|
||||
}
|
||||
|
||||
# Upsert base-size under [font]: replace it in place if present, insert it into
|
||||
# an existing [font] section, or append a fresh [font] section otherwise. Other
|
||||
# sections and keys in the user override are left untouched.
|
||||
set_base_size() {
|
||||
local size="$1"
|
||||
mkdir -p "$(dirname "$shell_config")"
|
||||
|
||||
if [[ ! -f $shell_config ]]; then
|
||||
printf '[font]\nbase-size = %s\n' "$size" >"$shell_config"
|
||||
return
|
||||
fi
|
||||
|
||||
local tmp
|
||||
tmp="$(mktemp)"
|
||||
awk -v val="$size" '
|
||||
function emit_base() { print "base-size = " val; done = 1 }
|
||||
/^[[:space:]]*\[/ {
|
||||
if (in_font && !done) emit_base()
|
||||
in_font = ($0 ~ /^[[:space:]]*\[font\]([[:space:]]|$)/)
|
||||
print
|
||||
next
|
||||
}
|
||||
in_font && /^[[:space:]]*base-size[[:space:]]*=/ {
|
||||
if (!done) emit_base()
|
||||
next
|
||||
}
|
||||
{ print }
|
||||
END {
|
||||
if (in_font && !done) emit_base()
|
||||
if (!done) {
|
||||
if (NR > 0) print ""
|
||||
print "[font]"
|
||||
emit_base()
|
||||
}
|
||||
}
|
||||
' "$shell_config" >"$tmp"
|
||||
mv "$tmp" "$shell_config"
|
||||
}
|
||||
|
||||
# Drop the base-size line, returning the shell to the theme/default size.
|
||||
reset_base_size() {
|
||||
[[ -f $shell_config ]] || return 0
|
||||
local tmp
|
||||
tmp="$(mktemp)"
|
||||
awk '
|
||||
/^[[:space:]]*\[/ { in_font = ($0 ~ /^[[:space:]]*\[font\]([[:space:]]|$)/) }
|
||||
in_font && /^[[:space:]]*base-size[[:space:]]*=/ { next }
|
||||
{ print }
|
||||
' "$shell_config" >"$tmp"
|
||||
mv "$tmp" "$shell_config"
|
||||
}
|
||||
|
||||
# ---- GTK text-scaling-factor ----
|
||||
|
||||
# Point size of the GTK interface font (font-name), used to quantize the
|
||||
# scaling factor. Falls back to the GNOME default when unreadable.
|
||||
gtk_font_pt() {
|
||||
local name pt
|
||||
name="$(gsettings get "$GKEY_SCHEMA" font-name 2>/dev/null)"
|
||||
pt="${name%\'}"
|
||||
pt="${pt##* }"
|
||||
if [[ $pt =~ ^[0-9]+(\.[0-9]+)?$ ]]; then
|
||||
echo "$pt"
|
||||
else
|
||||
echo 11
|
||||
fi
|
||||
}
|
||||
|
||||
set_factor() {
|
||||
gsettings set "$GKEY_SCHEMA" "$GKEY_NAME" "$1" 2>/dev/null || true
|
||||
}
|
||||
|
||||
# ---- terminal font point size ----
|
||||
|
||||
# px base-size -> terminal point size, rounded to the nearest integer.
|
||||
term_pt_for() {
|
||||
awk -v s="$1" -v p="$TERM_DEFAULT_PT" -v b="$SHELL_DEFAULT_PX" \
|
||||
'BEGIN { printf "%d", int(s * p / b + 0.5) }'
|
||||
}
|
||||
|
||||
# Set the font point size in terminal configs, creating Kitty overrides when
|
||||
# it inherits its size from the system config. Family is left
|
||||
# untouched — that is blob-font-set's job. Live-reload signals mirror
|
||||
# blob-font-set; foot has no reload signal, so running instances are nudged.
|
||||
set_terminal_size() {
|
||||
local pt="$1"
|
||||
|
||||
if [[ -f ~/.config/alacritty/alacritty.toml ]]; then
|
||||
sed -i -E "s/^size[[:space:]]*=.*/size = $pt/" ~/.config/alacritty/alacritty.toml
|
||||
fi
|
||||
|
||||
if [[ -f ~/.config/kitty/kitty.conf ]] || blob-cmd-present kitty; then
|
||||
mkdir -p ~/.config/kitty
|
||||
if grep -qE '^[[:space:]]*font_size[[:space:]]+' ~/.config/kitty/kitty.conf 2>/dev/null; then
|
||||
sed --follow-symlinks -i -E "s/^[[:space:]]*font_size[[:space:]]+.*/font_size $pt.0/" ~/.config/kitty/kitty.conf
|
||||
else
|
||||
printf '\nfont_size %s.0\n' "$pt" >>~/.config/kitty/kitty.conf
|
||||
fi
|
||||
pkill -USR1 kitty 2>/dev/null || true
|
||||
fi
|
||||
|
||||
if [[ -f ~/.config/ghostty/config ]]; then
|
||||
sed -i -E "s/^font-size = .*/font-size = $pt/" ~/.config/ghostty/config
|
||||
pkill -SIGUSR2 ghostty 2>/dev/null || true
|
||||
fi
|
||||
|
||||
if [[ -f ~/.config/foot/foot.ini ]]; then
|
||||
sed -i -E "s/(:size=)[0-9.]+/\1$pt/" ~/.config/foot/foot.ini
|
||||
# Foot has no config-reload signal, so a running instance keeps its startup
|
||||
# size until relaunched (new windows pick up the change). Nudge the user —
|
||||
# but reuse the same notification id (freedesktop replaces_id) so dragging
|
||||
# through several sizes refreshes one toast instead of stacking a pile.
|
||||
if pgrep -x foot >/dev/null 2>&1; then
|
||||
local id_file="${XDG_RUNTIME_DIR:-/tmp}/blob-display-size.foot-notif-id"
|
||||
local prev_id=""
|
||||
[[ -f $id_file ]] && read -r prev_id <"$id_file" 2>/dev/null
|
||||
local replace=()
|
||||
[[ $prev_id =~ ^[0-9]+$ ]] && replace=(-r "$prev_id")
|
||||
local new_id
|
||||
new_id="$(blob-notify-send \
|
||||
"Restart Foot to apply the new terminal font size" \
|
||||
"${replace[@]}" -p 2>/dev/null)" || true
|
||||
[[ $new_id =~ ^[0-9]+$ ]] && printf '%s\n' "$new_id" >"$id_file"
|
||||
fi
|
||||
fi
|
||||
}
|
||||
|
||||
# Report the current terminal point size from whichever config we find first.
|
||||
term_current_pt() {
|
||||
if [[ -f ~/.config/ghostty/config ]]; then
|
||||
grep -oP '^font-size = \K[0-9.]+' ~/.config/ghostty/config | head -1
|
||||
elif [[ -f ~/.config/alacritty/alacritty.toml ]]; then
|
||||
grep -oP '^size[[:space:]]*=[[:space:]]*\K[0-9.]+' ~/.config/alacritty/alacritty.toml | head -1
|
||||
elif [[ -f ~/.config/kitty/kitty.conf ]]; then
|
||||
local pt
|
||||
pt=$(grep -oP '^[[:space:]]*font_size[[:space:]]+\K[0-9.]+' ~/.config/kitty/kitty.conf | tail -1)
|
||||
echo "${pt:-$TERM_DEFAULT_PT}"
|
||||
elif [[ -f ~/.config/foot/foot.ini ]]; then
|
||||
grep -oP ':size=\K[0-9.]+' ~/.config/foot/foot.ini | head -1
|
||||
elif blob-cmd-present kitty; then
|
||||
echo "$TERM_DEFAULT_PT"
|
||||
fi
|
||||
}
|
||||
|
||||
case "${1:-}" in
|
||||
-h | --help)
|
||||
usage
|
||||
exit 0
|
||||
;;
|
||||
"")
|
||||
cur="$(current_base_size)"
|
||||
size="${cur:-12 (default)}"
|
||||
factor="$(gsettings get "$GKEY_SCHEMA" "$GKEY_NAME" 2>/dev/null)"
|
||||
term="$(term_current_pt)"
|
||||
printf 'text size: %s px\ngtk text-scaling-factor: %s\nterminal font: %s pt\n' \
|
||||
"$size" "$factor" "${term:-n/a}"
|
||||
exit 0
|
||||
;;
|
||||
reset | default)
|
||||
reset_base_size
|
||||
gsettings reset "$GKEY_SCHEMA" "$GKEY_NAME" 2>/dev/null || true
|
||||
set_terminal_size "$TERM_DEFAULT_PT"
|
||||
exit 0
|
||||
;;
|
||||
esac
|
||||
|
||||
size="$1"
|
||||
if [[ ! $size =~ ^[0-9]+$ ]] || ((size < MIN || size > MAX)); then
|
||||
echo "Size must be an integer between $MIN and $MAX (px)." >&2
|
||||
usage >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Shell side: base-size in px (the blob shell's rem root).
|
||||
set_base_size "$size"
|
||||
|
||||
# GTK side: multiplier anchored so 12px == 1.0, quantized so the interface
|
||||
# font renders at a whole point size. Raw ratios yield fractional point sizes,
|
||||
# which GTK4 menus clip at the ascenders on scale-1 monitors.
|
||||
factor="$(awk -v s="$size" -v b="$SHELL_DEFAULT_PX" -v f="$(gtk_font_pt)" \
|
||||
'BEGIN { printf "%.4f", int(f * s / b + 0.5) / f }')"
|
||||
set_factor "$factor"
|
||||
|
||||
# Terminal side: point size anchored so 12px == 9pt.
|
||||
set_terminal_size "$(term_pt_for "$size")"
|
||||
Reference in New Issue
Block a user