Files
dotfiles/.local/bin/monitor-setup
2022-10-09 19:50:56 +02:00

77 lines
2.5 KiB
Bash
Executable File

#!/usr/bin/env bash
################################################################################
#
# Small script using `xrandr` and `fzf` to quickly select connected monitors.
#
# TODO:
# - Add possibility to not only mirror onto all outputs but use the total
# screen space.
################################################################################
command -v xrandr &>/dev/null || exit 1
command -v fzf &>/dev/null || exit 1
xrandr_q="$(xrandr -q)"
# Get outputs currently in use as regex matching either one (e.g. `HDMI-0|DP-0`)
in_use="$( <<<"$xrandr_q" \
tac | # Reverse for non-greedy matches
sed -En '/\*/,/ connected/p' | # lines from selected config to it's name
grep -Po '^.*(?= connected)' | # only the name
tr '\n' '|' # format into regex
)"
in_use="${in_use%|}" # remove trailing `|`
# Get all outputs in a table in the form `<name> <res> [*]`
formatted="$(<<<"$xrandr_q" \
grep -wA1 connected | # output line and highest res
awk '{ print $1 }' | # only name and resolution
grep -ve -- | # remove grep's match separator
paste - - | # join name and res
sed -E "s/($in_use).*/&\t*/" | # append `*` to all in-use
column -t # tabularize
)"
# Select all outputs to-use
selected=( $(<<<"$formatted" \
fzf -m --cycle --header "Select outputs" | # select
cut -d' ' -f1 # only output name
) )
# Abort if nothing was selected
(( ${#selected[@]} )) || exit 1
# Regex to match either one of the selected outputs
selected_regex="$(<<<"${selected[@]}" tr ' ' '|')"
# Gather non-selected outputs
non_selected=( $(<<<"$xrandr_q" \
grep connected | # list lines with output ({,dis}connected)
grep -Ev "$selected_regex" | # filter out selected ones
cut -d' ' -f1 # only output name
) )
# Choose primary
primary="$(<<<"$formatted" \
grep -E "$selected_regex" | # use formatted for more information
fzf --cycle --select-1 --header "Select primary" |
cut -d' ' -f1 # name only
)"
[[ $primary ]] || exit 1
# Build the `xrandr` command
xrandr_cmd=(xrandr)
for out in "${selected[@]}"; do
xrandr_cmd+=(--output "$out" --rotate normal --auto)
[[ $out != $primary ]] || xrandr_cmd+=(--primary)
done
for out in "${non_selected[@]}"; do
xrandr_cmd+=(--output "$out" --off)
done
# Print for debugging purposes and finally execute it
printf "%s\n" "${xrandr_cmd[*]}"
"${xrandr_cmd[@]}"