Add Arch Wayland dotfiles: sway/waybar/kitty/nvim/zsh, idempotent installer
Auto-adapts sway workspace routing to however many monitors are connected (laptop vs. desktop) instead of hardcoding output names.
This commit is contained in:
Executable
+34
@@ -0,0 +1,34 @@
|
||||
#!/usr/bin/env bash
|
||||
set -Eeuo pipefail
|
||||
|
||||
source_ids=()
|
||||
current_index=-1
|
||||
|
||||
while IFS=$'\t' read -r id is_default; do
|
||||
[[ -n "$id" ]] || continue
|
||||
source_ids+=("$id")
|
||||
[[ "$is_default" == true ]] && current_index=$((${#source_ids[@]} - 1))
|
||||
done < <(
|
||||
wpctl status -n | awk '
|
||||
/^Audio$/ {in_audio = 1; next}
|
||||
/^Video$/ {in_audio = 0; in_sources = 0}
|
||||
in_audio && /Sources:/ {in_sources = 1; next}
|
||||
/Filters:/ {in_sources = 0}
|
||||
in_audio && in_sources && match($0, /[0-9]+\./) {
|
||||
id = substr($0, RSTART, RLENGTH - 1)
|
||||
print id "\t" (index($0, "*") ? "true" : "false")
|
||||
}
|
||||
'
|
||||
)
|
||||
|
||||
((${#source_ids[@]} > 0)) || exit 0
|
||||
next_index=$(((current_index + 1) % ${#source_ids[@]}))
|
||||
next_source_id="${source_ids[$next_index]}"
|
||||
wpctl set-default "$next_source_id"
|
||||
|
||||
source_name=$(
|
||||
wpctl inspect "$next_source_id" \
|
||||
| awk -F' = ' '/node.nick/ {gsub(/^"|"$/, "", $2); print $2; exit}'
|
||||
)
|
||||
[[ -n "$source_name" ]] || source_name="Input $next_source_id"
|
||||
notify-send -a Waybar -u low -r 9102 "Audio input changed" "$source_name"
|
||||
Executable
+51
@@ -0,0 +1,51 @@
|
||||
#!/usr/bin/env bash
|
||||
set -Eeuo pipefail
|
||||
|
||||
sink_ids=()
|
||||
current_index=-1
|
||||
|
||||
while IFS=$'\t' read -r id is_default; do
|
||||
[[ -n "$id" ]] || continue
|
||||
sink_ids+=("$id")
|
||||
[[ "$is_default" == true ]] && current_index=$((${#sink_ids[@]} - 1))
|
||||
done < <(
|
||||
wpctl status -n | awk '
|
||||
/^Audio$/ {in_audio = 1; next}
|
||||
/^Video$/ {in_audio = 0; in_sinks = 0}
|
||||
in_audio && /Sinks:/ {in_sinks = 1; next}
|
||||
/Sources:/ {in_sinks = 0}
|
||||
in_audio && in_sinks && match($0, /[0-9]+\./) {
|
||||
id = substr($0, RSTART, RLENGTH - 1)
|
||||
print id "\t" (index($0, "*") ? "true" : "false")
|
||||
}
|
||||
'
|
||||
)
|
||||
|
||||
((${#sink_ids[@]} > 0)) || exit 0
|
||||
next_index=$(((current_index + 1) % ${#sink_ids[@]}))
|
||||
next_sink_id="${sink_ids[$next_index]}"
|
||||
wpctl set-default "$next_sink_id"
|
||||
|
||||
# Move existing playback streams too; set-default alone only affects new ones.
|
||||
while read -r stream_id; do
|
||||
[[ -n "$stream_id" ]] || continue
|
||||
if wpctl inspect "$stream_id" 2>/dev/null | grep -q 'media.class = "Stream/Output/Audio"'; then
|
||||
wpctl set-target "$stream_id" "$next_sink_id" 2>/dev/null || true
|
||||
fi
|
||||
done < <(
|
||||
wpctl status -n | awk '
|
||||
/^Audio$/ {in_audio = 1; next}
|
||||
/^Video$/ {in_audio = 0; in_streams = 0}
|
||||
in_audio && /Streams:/ {in_streams = 1; next}
|
||||
in_audio && in_streams && match($0, /[0-9]+\./) {
|
||||
print substr($0, RSTART, RLENGTH - 1)
|
||||
}
|
||||
'
|
||||
)
|
||||
|
||||
sink_name=$(
|
||||
wpctl inspect "$next_sink_id" \
|
||||
| awk -F' = ' '/node.nick/ {gsub(/^"|"$/, "", $2); print $2; exit}'
|
||||
)
|
||||
[[ -n "$sink_name" ]] || sink_name="Output $next_sink_id"
|
||||
notify-send -a Waybar -u low -r 9102 "Audio output changed" "$sink_name"
|
||||
Executable
+53
@@ -0,0 +1,53 @@
|
||||
#!/usr/bin/env bash
|
||||
set -Eeuo pipefail
|
||||
|
||||
state_file="${XDG_RUNTIME_DIR:-/tmp}/waybar-network-state-${UID}"
|
||||
current_ip_file="${XDG_RUNTIME_DIR:-/tmp}/waybar-network-current-ip-${UID}"
|
||||
|
||||
if [[ "${1:-}" == copy ]]; then
|
||||
if [[ -s "$current_ip_file" ]]; then
|
||||
current_ip=$(<"$current_ip_file")
|
||||
printf '%s' "$current_ip" | wl-copy
|
||||
notify-send -a Waybar -u low -r 9101 "IP address copied" "$current_ip"
|
||||
fi
|
||||
exit 0
|
||||
fi
|
||||
|
||||
if [[ "${1:-}" == next ]]; then
|
||||
state=0
|
||||
[[ -r "$state_file" ]] && read -r state <"$state_file"
|
||||
printf '%s\n' "$((state + 1))" >"$state_file"
|
||||
pkill -RTMIN+8 waybar 2>/dev/null || true
|
||||
exit 0
|
||||
fi
|
||||
|
||||
entries=()
|
||||
while read -r interface addresses; do
|
||||
[[ -n "$interface" && -n "$addresses" ]] || continue
|
||||
entries+=("$interface $addresses")
|
||||
done < <(
|
||||
ip -o -4 addr show scope global \
|
||||
| awk '{sub(/\/.*/, "", $4); addresses[$2] = addresses[$2] (addresses[$2] ? "," : "") $4} END {for (interface in addresses) print interface, addresses[interface]}' \
|
||||
| sort
|
||||
)
|
||||
|
||||
public_ipv4=$(curl -4 -fsS --max-time 3 https://ifconfig.me/ip 2>/dev/null || true)
|
||||
[[ -n "$public_ipv4" ]] && entries+=("public $public_ipv4")
|
||||
|
||||
if ((${#entries[@]} == 0)); then
|
||||
entries+=("network unavailable")
|
||||
fi
|
||||
|
||||
state=0
|
||||
[[ -r "$state_file" ]] && read -r state <"$state_file"
|
||||
index=$((state % ${#entries[@]}))
|
||||
tooltip=$(printf '%s\n' "${entries[@]}")
|
||||
current_ip="${entries[$index]#* }"
|
||||
if [[ "$current_ip" == unavailable ]]; then
|
||||
: >"$current_ip_file"
|
||||
else
|
||||
printf '%s' "$current_ip" >"$current_ip_file"
|
||||
fi
|
||||
|
||||
jq -cn --arg text " ${entries[$index]}" --arg tooltip "$tooltip" \
|
||||
'{text: $text, tooltip: $tooltip}'
|
||||
Executable
+15
@@ -0,0 +1,15 @@
|
||||
#!/usr/bin/env bash
|
||||
set -Eeuo pipefail
|
||||
|
||||
choice=$(
|
||||
printf '%s\n' 'Lock' 'Logout' 'Suspend' 'Reboot' 'Shut down' \
|
||||
| wofi --dmenu --prompt 'Power' --width 320 --height 300
|
||||
) || exit 0
|
||||
|
||||
case "$choice" in
|
||||
Lock) swaylock -f ;;
|
||||
Logout) swaymsg exit ;;
|
||||
Suspend) systemctl suspend ;;
|
||||
Reboot) systemctl reboot ;;
|
||||
'Shut down') systemctl poweroff ;;
|
||||
esac
|
||||
Executable
+33
@@ -0,0 +1,33 @@
|
||||
#!/usr/bin/env bash
|
||||
set -Eeuo pipefail
|
||||
|
||||
workspace=$(swaymsg -t get_workspaces -r | jq -c '.[] | select(.focused)')
|
||||
number=$(jq -r '.num' <<<"$workspace")
|
||||
current_name=$(jq -r '.name' <<<"$workspace")
|
||||
|
||||
if (( number < 1 )); then
|
||||
notify-send -a Waybar -u low "Workspace rename" \
|
||||
"The focused workspace does not have a numeric identity."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
current_label=${current_name#"$number:"}
|
||||
if [[ "$current_label" == "$current_name" ]]; then
|
||||
current_label=
|
||||
else
|
||||
current_label=${current_label# }
|
||||
fi
|
||||
|
||||
label=$(printf '%s\n' "$current_label" | wofi --dmenu \
|
||||
--prompt "Name workspace $number (blank resets)" \
|
||||
--lines 1) || exit 0
|
||||
|
||||
label=${label//$'\n'/ }
|
||||
if [[ -z "${label//[[:space:]]/}" ]]; then
|
||||
new_name=$number
|
||||
else
|
||||
new_name="$number: $label"
|
||||
fi
|
||||
|
||||
quoted_name=$(jq -Rrn --arg name "$new_name" '$name | @json')
|
||||
swaymsg "rename workspace to $quoted_name" >/dev/null
|
||||
Reference in New Issue
Block a user