207 lines
6.5 KiB
Bash
Executable file
207 lines
6.5 KiB
Bash
Executable file
#!/bin/sh
|
|
|
|
require() {
|
|
for cmd in "$@"; do
|
|
command -v "$cmd" >/dev/null 2>&1 || {
|
|
echo "ctl: missing dependency: $cmd" >&2
|
|
exit 1
|
|
}
|
|
done
|
|
}
|
|
|
|
case "$1" in
|
|
screenshot)
|
|
dir="$HOME/img/ss"
|
|
mkdir -p "$dir"
|
|
file="$dir/$(openssl rand -hex 10)-$(date +'%Y-%m-%d_%H-%M-%S').png"
|
|
if [ "${XDG_SESSION_TYPE:-}" = "wayland" ]; then
|
|
require grim slurp wl-copy
|
|
grim -g "$(slurp)" "$file" && wl-copy < "$file"
|
|
else
|
|
require maim xclip
|
|
maim -s "$file" && xclip -selection clipboard -t image/png -i "$file" &
|
|
fi
|
|
;;
|
|
ocr)
|
|
require tesseract
|
|
dir="$HOME/img/ss"
|
|
mkdir -p "$dir"
|
|
file="$dir/$(openssl rand -hex 10)-$(date +'%Y-%m-%d_%H-%M-%S').png"
|
|
if [ "${XDG_SESSION_TYPE:-}" = "wayland" ]; then
|
|
require grim slurp wl-copy
|
|
(
|
|
region="$(slurp)"
|
|
[ -n "$region" ] || exit 0
|
|
grim -g "$region" "$file" &&
|
|
tesseract -l eng "$file" - 2>/dev/null | wl-copy
|
|
) </dev/null >/dev/null 2>&1 &
|
|
else
|
|
require maim xclip
|
|
(
|
|
maim -s "$file" &&
|
|
tesseract -l eng "$file" - 2>/dev/null | xclip -selection clipboard -in
|
|
) </dev/null >/dev/null 2>&1 &
|
|
fi
|
|
;;
|
|
keyboard)
|
|
case "$2" in
|
|
next)
|
|
if [ "${XDG_SESSION_TYPE:-}" = "wayland" ]; then
|
|
if [ "$XDG_CURRENT_DESKTOP" = "Hyprland" ]; then
|
|
hyprctl switchxkblayout current next
|
|
elif [ "$XDG_CURRENT_DESKTOP" = "sway" ]; then
|
|
swaymsg input type:keyboard xkb_switch_layout next
|
|
fi
|
|
else
|
|
current="$(setxkbmap -query | awk '/variant/{print $2}')"
|
|
case "$current" in
|
|
"") setxkbmap -layout us -variant dvorak ;;
|
|
dvorak) setxkbmap -layout us -variant colemak ;;
|
|
*) setxkbmap -layout us ;;
|
|
esac
|
|
fi
|
|
;;
|
|
pick)
|
|
require fuzzel
|
|
choice=$(printf 'QWERTY\nDvorak\nColemak' | fuzzel --dmenu --prompt="keyboard: " --lines=3 --no-icons)
|
|
[ -z "$choice" ] && exit 0
|
|
case "$choice" in
|
|
QWERTY) variant="" ;;
|
|
Dvorak) variant="dvorak" ;;
|
|
Colemak) variant="colemak" ;;
|
|
esac
|
|
if [ "$XDG_CURRENT_DESKTOP" = "Hyprland" ]; then
|
|
hyprctl keyword input:kb_layout "us,us,us"
|
|
hyprctl keyword input:kb_variant ",$variant"
|
|
hyprctl switchxkblayout current 1
|
|
fi
|
|
;;
|
|
*)
|
|
echo "Usage: ctl keyboard {next|pick}" >&2
|
|
exit 1
|
|
;;
|
|
esac
|
|
;;
|
|
audio)
|
|
require wpctl pw-dump jq
|
|
case "$2" in
|
|
out)
|
|
sinks="$(pw-dump | jq -r '.[] | select(.info.props."media.class" == "Audio/Sink") | "\(.id)\t\(.info.props."node.description" // .info.props."node.name" // "unknown")"')"
|
|
[ -z "$sinks" ] && exit 0
|
|
if [ "$XDG_SESSION_TYPE" = x11 ]; then
|
|
choice="$(printf "%s\n" "$sinks" | awk -F'\t' '{print $1": "$2}' | dmenu -i -p "select sink:" | cut -d: -f1)"
|
|
else
|
|
count=$(printf "%s\n" "$sinks" | wc -l)
|
|
choice="$(printf "%s\n" "$sinks" | awk -F'\t' '{print $1": "$2}' | fuzzel --dmenu --prompt="sink: " --lines="$count" | cut -d: -f1)"
|
|
fi
|
|
[ "$choice" ] && wpctl set-default "$choice"
|
|
;;
|
|
in)
|
|
sources="$(pw-dump | jq -r '.[] | select(.info.props."media.class" == "Audio/Source") | "\(.id)\t\(.info.props."node.description" // .info.props."node.name" // "unknown")"')"
|
|
[ -z "$sources" ] && exit 0
|
|
if [ "$XDG_SESSION_TYPE" = x11 ]; then
|
|
choice="$(printf "%s\n" "$sources" | awk -F'\t' '{print $1": "$2}' | dmenu -i -p "select source:" | cut -d: -f1)"
|
|
else
|
|
count=$(printf "%s\n" "$sources" | wc -l)
|
|
choice="$(printf "%s\n" "$sources" | awk -F'\t' '{print $1": "$2}' | fuzzel --dmenu --prompt="source: " --lines="$count" | cut -d: -f1)"
|
|
fi
|
|
[ "$choice" ] && wpctl set-default "$choice"
|
|
;;
|
|
*)
|
|
echo "Usage: ctl audio {in|out}" >&2
|
|
exit 1
|
|
;;
|
|
esac
|
|
;;
|
|
brightness)
|
|
require brightnessctl notify-send
|
|
BRIGHT_STEP=5
|
|
case "$2" in
|
|
up) brightnessctl set "$BRIGHT_STEP"%+ ;;
|
|
down) brightnessctl set "$BRIGHT_STEP"%- ;;
|
|
*) echo "Usage: ctl brightness {up|down}" >&2; exit 1 ;;
|
|
esac
|
|
pct=$(awk -v cur="$(brightnessctl get)" -v max="$(brightnessctl max)" 'BEGIN { printf "%d", cur * 100 / max }')
|
|
filled=$((pct / 5))
|
|
empty=$((20 - filled))
|
|
bar=""
|
|
i=0; while [ "$i" -lt "$filled" ]; do bar="${bar}━"; i=$((i + 1)); done
|
|
i=0; while [ "$i" -lt "$empty" ]; do bar="${bar}─"; i=$((i + 1)); done
|
|
notify-send -a ctl -t 2500 -r 5555 " $bar"
|
|
;;
|
|
volume)
|
|
require wpctl notify-send
|
|
SINK="@DEFAULT_AUDIO_SINK@"
|
|
VOL_STEP=5
|
|
get_vol() { wpctl get-volume "$SINK" | awk '{printf "%d", $2 * 100}'; }
|
|
case "$2" in
|
|
up) wpctl set-volume "$SINK" "${VOL_STEP}%+" --limit 1.0 ;;
|
|
down) wpctl set-volume "$SINK" "${VOL_STEP}%-" ;;
|
|
toggle) wpctl set-mute "$SINK" toggle ;;
|
|
*) echo "Usage: ctl volume {up|down|toggle}" >&2; exit 1 ;;
|
|
esac
|
|
vol=$(get_vol)
|
|
filled=$((vol / 5))
|
|
empty=$((20 - filled))
|
|
bar=""
|
|
i=0; while [ "$i" -lt "$filled" ]; do bar="${bar}━"; i=$((i + 1)); done
|
|
i=0; while [ "$i" -lt "$empty" ]; do bar="${bar}─"; i=$((i + 1)); done
|
|
if wpctl get-volume "$SINK" | grep -q MUTED; then
|
|
icon=""
|
|
elif [ "$vol" -le 33 ]; then
|
|
icon=""
|
|
elif [ "$vol" -le 66 ]; then
|
|
icon=""
|
|
else
|
|
icon=""
|
|
fi
|
|
notify-send -a ctl -t 2500 -r 5556 "$icon $bar"
|
|
;;
|
|
wifi)
|
|
case "$2" in
|
|
pick)
|
|
require fuzzel
|
|
station=$(iwctl device list 2>/dev/null | sed 's/\x1b\[[0-9;]*[a-zA-Z]//g' | awk '/station/{print $1}')
|
|
[ -z "$station" ] && { echo "ctl: no wifi device found" >&2; exit 1; }
|
|
iwctl station "$station" scan 2>/dev/null
|
|
sleep 1
|
|
networks=$(iwctl station "$station" get-networks 2>/dev/null | \
|
|
sed 's/\x1b\[[0-9;]*[a-zA-Z]//g' | \
|
|
awk 'NR>4 && /\S/' | \
|
|
sed 's/^[[:space:]>]*//' | \
|
|
sed 's/[[:space:]]\{3,\}.*//' | \
|
|
sed 's/[[:space:]]*$//' | \
|
|
grep -v '^-')
|
|
[ -z "$networks" ] && exit 0
|
|
count=$(printf '%s\n' "$networks" | wc -l)
|
|
ssid=$(printf '%s\n' "$networks" | fuzzel --dmenu --prompt="wifi: " --no-icons --lines="$count")
|
|
[ -z "$ssid" ] && exit 0
|
|
iwctl station "$station" connect "$ssid"
|
|
;;
|
|
*)
|
|
echo "Usage: ctl wifi {pick}" >&2
|
|
exit 1
|
|
;;
|
|
esac
|
|
;;
|
|
power)
|
|
require fuzzel
|
|
lock=" Lock"
|
|
suspend=" Suspend"
|
|
logout=" Logout"
|
|
reboot=" Reboot"
|
|
shutdown=" Shutdown"
|
|
chosen="$(printf '%s\n' "$lock" "$suspend" "$logout" "$reboot" "$shutdown" | fuzzel --dmenu --hide-prompt --lines=5 --width=20 --no-icons)"
|
|
case "$chosen" in
|
|
"$lock") hyprlock ;;
|
|
"$suspend") systemctl suspend ;;
|
|
"$logout") hyprctl dispatch exit ;;
|
|
"$reboot") systemctl reboot ;;
|
|
"$shutdown") systemctl poweroff ;;
|
|
esac
|
|
;;
|
|
*)
|
|
echo "Usage: ctl {screenshot|ocr|keyboard|audio|wifi|brightness|volume|power}" >&2
|
|
exit 1
|
|
;;
|
|
esac
|