diff --git a/bin/omarchy-setup-keyboard b/bin/omarchy-setup-keyboard index 671051dfc8c..323a1cce1bf 100755 --- a/bin/omarchy-setup-keyboard +++ b/bin/omarchy-setup-keyboard @@ -1,41 +1,50 @@ #!/bin/bash + # omarchy:summary=Configure the keyboard layout # Setup keyboard layout for Omarchy -# Provides interactive keyboard layout configuration using the first-run script +# Re-runs the provisioning layout picker on a running system and persists the +# choice through localectl: the console keymap and XKB layout land in +# /etc/vconsole.conf, which default/hypr/input.lua reads for kb_layout. set -euo pipefail -OMARCHY_PATH="${HOME}/.local/share/omarchy" -KEYBOARD_SCRIPT="${OMARCHY_PATH}/install/first-run/keyboard-layout.sh" - -# Check if the keyboard layout script exists -if [[ ! -f "$KEYBOARD_SCRIPT" ]]; then - echo "Error: Keyboard layout setup script not found at:" - echo " $KEYBOARD_SCRIPT" - exit 1 -fi +OMARCHY_PATH="${OMARCHY_PATH:-/usr/share/omarchy}" -# Check if gum is installed if ! omarchy-cmd-present gum; then echo "Error: gum is not installed. Please install it first:" echo " sudo pacman -S gum" exit 1 fi -# Display current keyboard layout +# The picker and layout table are shared with first-boot provisioning so this +# command can never offer a layout that setup could not have applied. +source "$OMARCHY_PATH/install/provisioning/setup-form.sh" + echo "Current keyboard layout configuration:" echo "" localectl status | grep -E "X11 Layout|VC Keymap" || echo " Layout: (unset or default)" echo "" -echo "Starting keyboard layout configuration..." -echo "" -# Run the keyboard layout configuration script -# This always prompts so Menu > Setup > Keyboard Layout can change layouts later -bash "$KEYBOARD_SCRIPT" --force +# Esc and Ctrl+C both leave the current layout in place. +omarchy_prompt_keyboard || exit 0 + +# Apply the console keymap to the live VT when the command runs on one. +[[ $(tty 2>/dev/null) == /dev/tty* ]] && loadkeys "$keyboard" 2>/dev/null || true + +if localectl --no-pager list-keymaps 2>/dev/null | grep -qix "$keyboard"; then + localectl set-keymap "$keyboard" +else + echo "Warning: keymap '$keyboard' is unknown to localectl; keeping the current console keymap" +fi + +# --no-convert keeps the console keymap set above instead of deriving one from +# the XKB layout. +localectl --no-convert set-x11-keymap "$keyboard_xkb_layout" "" "$keyboard_xkb_variant" + +# input.lua re-reads vconsole.conf on every config evaluation, so a reload +# applies the new layout without relaunching the session. +hyprctl reload >/dev/null 2>&1 || true echo "" -echo "✓ Keyboard layout setup complete" -echo "" -echo "Note: The new layout will apply immediately to new applications." -echo "For Hyprland keybindings, you may need to restart Hyprland (Super+Shift+E > Relaunch)" +echo "✓ Keyboard layout set to $keyboard_label" +echo " Console keymap: $keyboard XKB: $keyboard_xkb_layout${keyboard_xkb_variant:+/$keyboard_xkb_variant}" diff --git a/tests/test-setup-keyboard.sh b/tests/test-setup-keyboard.sh new file mode 100755 index 00000000000..647dd1ffa91 --- /dev/null +++ b/tests/test-setup-keyboard.sh @@ -0,0 +1,102 @@ +#!/bin/bash +set -uo pipefail + +ROOT="$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")/.." && pwd)" +WORK=$(mktemp -d) +trap 'rm -rf "$WORK"' EXIT +pass=0 +failures=0 + +check() { + local label="$1" + shift + if "$@"; then + echo "✓ $label" + ((++pass)) + else + echo "✗ $label" + ((++failures)) + fi +} + +# Stub the interactive and system-touching commands; gum drains stdin first +# because the prompt pipes the layout list in — exiting early kills cut with +# SIGPIPE and pipefail reads that as a cancelled prompt. +make_stubs() { + local selection="$1" + rm -rf "$WORK/bin" + mkdir -p "$WORK/bin" + : >"$WORK/calls" + + cat >"$WORK/bin/gum" </dev/null +if [[ -n '$selection' ]]; then + printf '%s\n' '$selection' +else + exit 1 +fi +STUB + + cat >"$WORK/bin/localectl" <<'STUB' +#!/bin/bash +local_ifs=$IFS +IFS='|' +printf '%s\n' "$*" >>"$OMARCHY_TEST_CALLS" +IFS=$local_ifs +case "$1" in + status) + echo " VC Keymap: us" + echo " X11 Layout: us" + ;; + --no-pager) + printf 'us\nuk\ndvorak\n' + ;; +esac +STUB + + cat >"$WORK/bin/hyprctl" <<'STUB' +#!/bin/bash +IFS='|' +printf '%s\n' "$*" >>"$OMARCHY_TEST_CALLS" +STUB + chmod +x "$WORK/bin/"* +} + +run_setup() { + OMARCHY_PATH="$ROOT" OMARCHY_TEST_CALLS="$WORK/calls" \ + PATH="$WORK/bin:$ROOT/bin:$PATH" "$ROOT/bin/omarchy-setup-keyboard" +} + +called() { + grep -qF "$1" "$WORK/calls" +} + +not_called() { + ! grep -qF "$1" "$WORK/calls" +} + +make_stubs "English (UK)" +run_setup >/dev/null +check "English (UK) persists the uk console keymap" \ + called "set-keymap|uk" +check "English (UK) persists the gb XKB layout" \ + called "set-x11-keymap|gb" +check "a successful pick reloads Hyprland" \ + called "reload" + +make_stubs "English (US, Dvorak)" +run_setup >/dev/null +check "English (US, Dvorak) passes the dvorak variant through to XKB" \ + called "set-x11-keymap|us||dvorak" + +make_stubs "" +run_setup >/dev/null +check "cancelling the picker changes no keymap" \ + not_called "set-keymap" +check "cancelling the picker changes no XKB layout" \ + not_called "set-x11-keymap" + +echo "" +echo "$pass checks passed, $failures failed" +exit $((failures > 0))