From c058a1836d2a4fead06ccfc5616b0a9ba9f4d575 Mon Sep 17 00:00:00 2001 From: Rasmus Wejlgaard Date: Sun, 9 Aug 2026 17:33:22 +0100 Subject: [PATCH 1/3] macos: capture the settings I actually run with The macos set only ever set the keyboard repeat rate. I went through the defaults domains on my MacBook and folded in everything else that differs from stock: text substitutions off, my text replacements, the input-source and Quick Note hotkeys disabled, dark mode, faster trackpad, seconds in the menu bar clock, no Dock recents, Finder in list view opening on ~, and screenshots to the clipboard. macOS's own drag-to-edge tiling is switched off because Rectangle does that job, so the set now installs Rectangle and Maccy via Homebrew Cask and applies their shortcuts too. Both apps rewrite their whole preference domain when they quit, which silently clobbers a defaults write against a running app, so each one is quit first and only relaunched if it was already up. Two things worth knowing for anyone editing this later: - defaults' old-style plist syntax ({ on = 1; }) types every scalar as a string. Text replacements need a real integer in `on` and the symbolic hotkeys a real boolean in `enabled`, so those pass XML plist literals. - pmset needs root, so the display-sleep setting is guarded behind `sudo -n` and prints a hint instead of blocking on a password prompt. Verified by running the whole script against throwaway domains and diffing the parsed plists against the live ones. Everything matches except the two key-repeat values, which are deliberately below the slider's range. --- README.md | 15 ++- config/sets/macos/apply.sh | 228 +++++++++++++++++++++++++++++++++- config/sets/macos/description | 7 +- 3 files changed, 241 insertions(+), 9 deletions(-) diff --git a/README.md b/README.md index fd5cda0..33abf1e 100644 --- a/README.md +++ b/README.md @@ -53,7 +53,7 @@ config/ manifest os # "Linux" — hidden from `make picky` elsewhere apply.sh - macos/ # macOS keyboard repeat settings + macos/ # macOS system settings (`defaults write`) description manifest os # "Darwin" — hidden from `make picky` elsewhere @@ -73,8 +73,17 @@ Config files are grouped into **sets** under `config/sets//`: - **`basic`** — everything this repo has always deployed (Neovim, Fish, Tmux) - **`kde`** — sets the KDE Plasma keyboard repeat rate to 50/s with a 250ms delay (via `kwriteconfig5`/`6` on `kcminputrc`) -- **`macos`** — sets the macOS keyboard repeat rate as fast as possible with - the shortest delay (via `defaults write`) +- **`macos`** — the macOS system settings that differ from stock, applied via + `defaults write`: fastest keyboard repeat rate with the shortest delay, all + automatic text substitution off, text replacements, the input-source and + Quick Note hotkeys disabled, dark mode, a faster trackpad, seconds in the + menu bar clock, no Dock recents, the built-in drag-to-edge window tiling + off (Rectangle handles that), Finder in list view opening on `~` with a + status bar, screenshots to the clipboard, personalised ads off, and — if + passwordless `sudo` is available — a display that never sleeps. It also + installs **Rectangle** and **Maccy** via Homebrew Cask and applies their + shortcuts (Cmd+Shift+arrows for window halves, Cmd+Shift+V for clipboard + history) Each set is independent and additive — enabling `kde` or `macos` doesn't disturb `basic`. `kde` and `macos` each declare an `os` file restricting diff --git a/config/sets/macos/apply.sh b/config/sets/macos/apply.sh index 844e00a..cd4ba55 100755 --- a/config/sets/macos/apply.sh +++ b/config/sets/macos/apply.sh @@ -1,15 +1,233 @@ #!/bin/bash set -euo pipefail -# Sets the macOS keyboard repeat rate as fast as possible and the initial -# repeat delay as short as possible — below the range the System Settings -# slider exposes. Log out/in (or restart affected apps) for it to fully -# take effect everywhere. +# macOS settings that diverge from stock defaults on this machine. +# Each section below is independent and safe to re-run. +# +# Some of these only take effect in apps launched afterwards; the Dock, +# Finder and SystemUIServer are restarted at the end to pick up the rest. if [ "$(uname)" != "Darwin" ] || ! command -v defaults >/dev/null 2>&1; then - echo "Warning: not macOS (or 'defaults' unavailable); skipping keyboard repeat settings." >&2 + echo "Warning: not macOS (or 'defaults' unavailable); skipping macOS settings." >&2 exit 0 fi +# --- Keyboard ------------------------------------------------------------- + +# Keyboard repeat rate as fast as possible and the initial repeat delay as +# short as possible — below the range the System Settings slider exposes. defaults write NSGlobalDomain KeyRepeat -int 1 defaults write NSGlobalDomain InitialKeyRepeat -int 10 + +# Turn off every "helpful" text substitution (System Settings > Keyboard > +# Input Sources > Edit). They fight with writing code and shell commands. +defaults write NSGlobalDomain NSAutomaticCapitalizationEnabled -bool false +defaults write NSGlobalDomain NSAutomaticDashSubstitutionEnabled -bool false +defaults write NSGlobalDomain NSAutomaticInlinePredictionEnabled -bool false +defaults write NSGlobalDomain NSAutomaticPeriodSubstitutionEnabled -bool false +defaults write NSGlobalDomain NSAutomaticQuoteSubstitutionEnabled -bool false +defaults write NSGlobalDomain NSAutomaticSpellingCorrectionEnabled -bool false +defaults write NSGlobalDomain WebAutomaticSpellingCorrectionEnabled -bool false + +# Text replacements (System Settings > Keyboard > Text Replacements). +# Note this replaces the whole list, including macOS's stock "omw" entry — +# which is why it's repeated here. +# +# These use XML plist literals rather than `defaults`' old-style `{ k = v; }` +# syntax, which types every scalar as a string — macOS wants a real integer +# in `on` and a real boolean in the hotkey dicts below. +defaults write NSGlobalDomain NSUserDictionaryReplacementItems ' + on1replaceomwwithOn my way! + on1replace/sternwithಠ_ಠ + on1replace/shrugwith¯\_(ツ)_/¯ +' + +# Free up Ctrl+Space / Ctrl+Opt+Space by disabling the "select previous / +# next input source" shortcuts (System Settings > Keyboard > Keyboard +# Shortcuts > Input Sources), and drop the Quick Note hotkey while we're +# here (Keyboard Shortcuts > Mission Control). +disable_hotkey() { + local id="$1" p1="$2" p2="$3" p3="$4" + defaults write com.apple.symbolichotkeys AppleSymbolicHotKeys -dict-add "$id" \ + " + enabled + value + parameters + $p1$p2$p3 + + typestandard + + " +} +disable_hotkey 60 32 49 262144 # select the previous input source +disable_hotkey 61 32 49 786432 # select the next input source +disable_hotkey 164 65535 65535 0 # show Quick Note + +# --- Appearance ----------------------------------------------------------- + +# Dark mode (System Settings > Appearance). +defaults write NSGlobalDomain AppleInterfaceStyle -string Dark + +# Trackpad tracking speed, faster than the 0.6875 default +# (System Settings > Trackpad > Point & Click). +defaults write NSGlobalDomain com.apple.trackpad.scaling -float 1 + +# Show seconds in the menu bar clock (System Settings > Control Centre > +# Menu Bar Only > Clock Options). +defaults write com.apple.menuextra.clock ShowSeconds -bool true + +# --- Dock ----------------------------------------------------------------- + +# No "Recent Applications" section in the Dock (System Settings > Desktop & +# Dock). +defaults write com.apple.dock show-recents -bool false + +# --- Window tiling -------------------------------------------------------- + +# Disable macOS's own drag-to-edge window tiling and its margins — window +# management is Rectangle's job (System Settings > Desktop & Dock > Windows). +defaults write com.apple.WindowManager EnableTiledWindowMargins -bool false +defaults write com.apple.WindowManager EnableTilingByEdgeDrag -bool false +defaults write com.apple.WindowManager EnableTopTilingByEdgeDrag -bool false +defaults write com.apple.WindowManager EnableTilingOptionAccelerator -bool false + +# --- Finder --------------------------------------------------------------- + +# List view by default, new windows open on ~, and keep the status bar. +defaults write com.apple.finder FXPreferredViewStyle -string Nlsv +defaults write com.apple.finder NewWindowTarget -string PfHm +defaults write com.apple.finder ShowStatusBar -bool true + +# --- Screenshots ---------------------------------------------------------- + +# Screenshots go to the clipboard rather than the Desktop. `target` is the +# older key, `target-screenshot` the one Sonoma and later actually read. +defaults write com.apple.screencapture target -string clipboard +defaults write com.apple.screencapture target-screenshot -string clipboard + +# --- Privacy -------------------------------------------------------------- + +# Opt out of Apple's personalised advertising (System Settings > Privacy & +# Security > Apple Advertising). +defaults write com.apple.AdLib allowApplePersonalizedAdvertising -bool false + +# --- Apps ----------------------------------------------------------------- + +# Rectangle (window management) and Maccy (clipboard history), plus the +# shortcuts and options they're configured with here. +# +# Both apps write their whole preference domain back out when they quit, so +# a `defaults write` against a running app gets silently clobbered. Each one +# is therefore quit first, configured, and only relaunched if it was already +# running. + +install_cask() { + local cask="$1" + if ! command -v brew >/dev/null 2>&1; then + echo "Warning: Homebrew not found; skipping '$cask'." >&2 + return 1 + fi + brew list --cask "$cask" >/dev/null 2>&1 || brew install --cask "$cask" +} + +app_is_running() { + pgrep -qx "$1" 2>/dev/null +} + +quit_app() { + app_is_running "$1" || return 0 + osascript -e "quit app \"$1\"" >/dev/null 2>&1 || killall "$1" >/dev/null 2>&1 || true + # Give the app a moment to flush its preferences before we overwrite them. + for _ in 1 2 3 4 5 6 7 8 9 10; do + app_is_running "$1" || break + sleep 0.5 + done +} + +# Rectangle shortcuts are stored as { keyCode, modifierFlags } dictionaries; +# XML plist literals keep both as real integers. +rectangle_shortcut() { + defaults write com.knollsoft.Rectangle "$1" \ + " + keyCode$2 + modifierFlags$3 + " +} + +if install_cask rectangle; then + rectangle_was_running=false + if app_is_running Rectangle; then + rectangle_was_running=true + fi + quit_app Rectangle + + # 1179648 = Command + Shift, 786432 = Control + Option. + rectangle_shortcut leftHalf 123 1179648 # Cmd+Shift+Left + rectangle_shortcut rightHalf 124 1179648 # Cmd+Shift+Right + rectangle_shortcut maximize 126 1179648 # Cmd+Shift+Up + rectangle_shortcut center 125 1179648 # Cmd+Shift+Down + rectangle_shortcut toggleTodo 11 786432 # Ctrl+Opt+B + rectangle_shortcut reflowTodo 45 786432 # Ctrl+Opt+N + + # Accept shortcuts macOS would otherwise reserve, keep the menu bar + # clear, and don't nag about updates (the cask handles those). + defaults write com.knollsoft.Rectangle allowAnyShortcut -bool true + defaults write com.knollsoft.Rectangle hideMenubarIcon -bool true + defaults write com.knollsoft.Rectangle subsequentExecutionMode -int 0 + defaults write com.knollsoft.Rectangle windowSnapping -int 1 + defaults write com.knollsoft.Rectangle SUEnableAutomaticChecks -bool false + + if [ "$rectangle_was_running" = true ]; then + open -a Rectangle || true + else + echo "Note: Rectangle needs Accessibility permission on first launch" >&2 + echo " (System Settings > Privacy & Security > Accessibility)." >&2 + fi +fi + +if install_cask maccy; then + maccy_was_running=false + if app_is_running Maccy; then + maccy_was_running=true + fi + quit_app Maccy + + # Maccy stores shortcuts as JSON strings of Carbon key/modifier codes. + # 768 = cmdKey + shiftKey, 2048 = optionKey. + defaults write org.p0deje.Maccy KeyboardShortcuts_popup \ + -string '{"carbonKeyCode":9,"carbonModifiers":768}' # Cmd+Shift+V + defaults write org.p0deje.Maccy KeyboardShortcuts_pin \ + -string '{"carbonKeyCode":35,"carbonModifiers":2048}' # Opt+P + defaults write org.p0deje.Maccy KeyboardShortcuts_delete \ + -string '{"carbonKeyCode":51,"carbonModifiers":2048}' # Opt+Delete + + # Open the history under the menu bar item rather than at the pointer. + defaults write org.p0deje.Maccy popupPosition -string statusItem + defaults write org.p0deje.Maccy windowSize -string '[450,800]' + defaults write org.p0deje.Maccy SUEnableAutomaticChecks -bool false + + if [ "$maccy_was_running" = true ]; then + open -a Maccy || true + fi +fi + +# --- Power ---------------------------------------------------------------- + +# Never blank the display when idle, on battery or mains — same choice as +# the kde set makes. Needs root, so it's skipped rather than prompting when +# passwordless sudo isn't available. +if command -v pmset >/dev/null 2>&1 && sudo -n true 2>/dev/null; then + sudo -n pmset -b displaysleep 0 + sudo -n pmset -c displaysleep 0 +else + echo "Note: skipping 'pmset displaysleep 0' (needs sudo). Run manually:" >&2 + echo " sudo pmset -b displaysleep 0 && sudo pmset -c displaysleep 0" >&2 +fi + +# --- Apply ---------------------------------------------------------------- + +# Restart the affected agents so the settings above show up now instead of +# at next login. Finder windows are reopened by Finder itself. +for app in Dock Finder SystemUIServer; do + killall "$app" >/dev/null 2>&1 || true +done diff --git a/config/sets/macos/description b/config/sets/macos/description index ebac978..8e0de4c 100644 --- a/config/sets/macos/description +++ b/config/sets/macos/description @@ -1 +1,6 @@ -macOS: fastest keyboard repeat rate, shortest delay +macOS: fastest keyboard repeat rate + shortest delay, text substitutions +off, text replacements, input-source and Quick Note hotkeys disabled, dark +mode, faster trackpad, seconds in the menu bar clock, no Dock recents, +built-in window tiling off, Finder in list view opening on ~ with a status +bar, screenshots to the clipboard, personalised ads off, display never +sleeps, plus Rectangle and Maccy installed and configured From 7ff2656c26aabfe057540794b7915c059b2814aa Mon Sep 17 00:00:00 2001 From: Rasmus Wejlgaard Date: Sun, 9 Aug 2026 17:33:33 +0100 Subject: [PATCH 2/3] Make the set picker work on macOS's bash 3.2 pick-sets.sh used mapfile, which is a bash 4 builtin. macOS still ships bash 3.2.57, so `make picky` died with "mapfile: command not found" there. It went unnoticed because nothing on my Mac had ever run the interactive path. Swapped both calls for read loops, which is what lib/sets.sh already does. While in there: expanding an empty array trips `set -u` on 3.2, and an empty sets.conf is a legitimate state -- the picker lets you deselect everything. That would have blown up in enabled_sets() and is_enabled() the first time anyone unticked every box, so both now check the length first. Tested on /bin/bash with a stubbed dialog: fresh install, pre-existing selection, deselect-all, a re-run against an empty sets.conf, and cancel. --- install-scripts/lib/sets.sh | 5 +++ install-scripts/pick-sets.sh | 78 ++++++++++++++++++++++++++---------- 2 files changed, 61 insertions(+), 22 deletions(-) diff --git a/install-scripts/lib/sets.sh b/install-scripts/lib/sets.sh index 9a9bfda..04afa27 100644 --- a/install-scripts/lib/sets.sh +++ b/install-scripts/lib/sets.sh @@ -46,6 +46,11 @@ enabled_sets() { sets=("basic") fi + # Expanding an empty array trips `set -u` on bash 3.2 (which is what + # macOS ships), and an empty sets.conf -- every set deselected -- is a + # legitimate state. + [ "${#sets[@]}" -eq 0 ] && return 0 + for set in "${sets[@]}"; do if [ ! -d "$SETS_DIR/$set" ]; then echo "Warning: enabled set '$set' no longer exists in the repo, skipping." >&2 diff --git a/install-scripts/pick-sets.sh b/install-scripts/pick-sets.sh index 7dd3884..67a427d 100755 --- a/install-scripts/pick-sets.sh +++ b/install-scripts/pick-sets.sh @@ -1,19 +1,47 @@ #!/bin/bash set -euo pipefail -# `make picky`: an interactive dialog checklist for choosing which config -# sets (config/sets//) get deployed to this machine. The selection is -# remembered in $SETS_STATE_FILE so future `make refresh` / `make -# full-install` runs keep using it without asking again — re-run `make -# picky` any time to change your mind. +# Chooses which config sets (config/sets//) get deployed to this +# machine, and remembers the choice in $SETS_STATE_FILE so future `make +# refresh` / `make full-install` runs keep using it without asking again. # -# On confirm, the Makefile's `picky` target runs the full install right -# after this script exits successfully. Exiting non-zero (e.g. on cancel) -# stops `make` before that happens. +# With no arguments (a bare `make`, or `make picky`) it shows an interactive +# dialog checklist. With set names as arguments it enables exactly those, +# non-interactively — that's how `make basic` skips the dialog. +# +# Either way the Makefile runs the full install right after this script +# exits successfully. Exiting non-zero (e.g. on cancel) stops `make` before +# that happens. REPO="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)" # shellcheck source=install-scripts/lib/sets.sh source "$REPO/install-scripts/lib/sets.sh" +# Persist the given set names as this machine's selection. +save_sets() { + mkdir -p "$(dirname "$SETS_STATE_FILE")" + printf '%s\n' "$@" | sed '/^$/d' > "$SETS_STATE_FILE" + + if [ -s "$SETS_STATE_FILE" ]; then + echo "Enabled sets: $(paste -sd, "$SETS_STATE_FILE")" + else + echo "Enabled sets: (none)" + fi +} + +# Non-interactive path: enable exactly the named sets and skip the dialog +# (and skip installing `dialog` in the first place). +if [ "$#" -gt 0 ]; then + for set in "$@"; do + if [ ! -d "$SETS_DIR/$set" ]; then + echo "No config set named '$set' under config/sets/." >&2 + echo "Available: $(list_available_sets | paste -sd, -)" >&2 + exit 1 + fi + done + save_sets "$@" + exit 0 +fi + ensure_dialog() { command -v dialog >/dev/null 2>&1 && return @@ -40,19 +68,32 @@ ensure_dialog() { ensure_dialog -mapfile -t available < <(list_pickable_sets) +# Collected with read loops rather than `mapfile -t`: macOS still ships bash +# 3.2, which predates that builtin. +available=() +while IFS= read -r line; do + available+=("$line") +done < <(list_pickable_sets) + if [ "${#available[@]}" -eq 0 ]; then echo "No config sets found under config/sets/ that apply to this OS." >&2 exit 1 fi -mapfile -t currently_enabled < <(enabled_sets) +currently_enabled=() +while IFS= read -r line; do + currently_enabled+=("$line") +done < <(enabled_sets) is_enabled() { - local set="$1" - for enabled in "${currently_enabled[@]}"; do - [ "$set" == "$enabled" ] && return 0 - done + local set="$1" enabled + # Expanding an empty array trips `set -u` on bash 3.2, so check first — + # deselecting every set is a legitimate state. + if [ "${#currently_enabled[@]}" -gt 0 ]; then + for enabled in "${currently_enabled[@]}"; do + [ "$set" == "$enabled" ] && return 0 + done + fi return 1 } @@ -84,11 +125,4 @@ if [ "$status" -ne 0 ]; then exit 1 fi -mkdir -p "$(dirname "$SETS_STATE_FILE")" -printf '%s\n' "$selection" | sed '/^$/d' > "$SETS_STATE_FILE" - -if [ -s "$SETS_STATE_FILE" ]; then - echo "Enabled sets: $(paste -sd, "$SETS_STATE_FILE")" -else - echo "Enabled sets: (none)" -fi +save_sets "$selection" From f18b3458a88c054c6a0aece162405b0e38914525 Mon Sep 17 00:00:00 2001 From: Rasmus Wejlgaard Date: Sun, 9 Aug 2026 17:33:48 +0100 Subject: [PATCH 3/3] Default make to the set picker, add `make basic` A bare `make` now opens the config set checklist instead of silently installing whatever sets.conf happened to say. That's the behaviour I want on a new machine, where the whole point is choosing what to deploy. `make basic` is the non-interactive escape hatch: it enables just the basic set and installs, without the dialog. picky and basic both delegate to full-install via a recursive make rather than repeating the seven install steps -- a prerequisite would have run the install before the picker. pick-sets.sh now takes set names as arguments instead of always prompting, and that branch sits before ensure_dialog so `make basic` doesn't drag in a dialog dependency it never uses. Writing sets.conf is factored into one helper shared by both paths. This breaks CI as-is: all five test jobs ran a bare `make` and would now block on a dialog with no TTY, so they move to `make basic`. That keeps the coverage identical, since with no sets.conf the fallback was already basic. Checked with a full alpine buildx build and an end-to-end `make basic` on ubuntu:24.04. --- .github/workflows/pr-test.yml | 4 ++-- Makefile | 28 ++++++++++++---------- README.md | 45 ++++++++++++++++++++++++----------- tests/Dockerfile-alpine | 4 ++-- tests/Dockerfile-archlinux | 4 ++-- tests/Dockerfile-fedora | 4 ++-- tests/Dockerfile-ubuntu | 4 ++-- 7 files changed, 57 insertions(+), 36 deletions(-) diff --git a/.github/workflows/pr-test.yml b/.github/workflows/pr-test.yml index 0a02d0e..a1a49a7 100644 --- a/.github/workflows/pr-test.yml +++ b/.github/workflows/pr-test.yml @@ -51,9 +51,9 @@ jobs: - uses: actions/checkout@v4 - name: Full install - run: make + run: make basic - # Verify the install actually landed, not just that `make` exited 0. + # Verify the install actually landed, not just that `make basic` exited 0. - name: Verify install run: | test -L ~/.config/nvim/init.lua diff --git a/Makefile b/Makefile index 86f3a0b..bcbae4a 100644 --- a/Makefile +++ b/Makefile @@ -1,3 +1,18 @@ +# A bare `make` asks which config sets this machine should use, then installs +# with that selection. Use `make basic` for the non-interactive equivalent. +.DEFAULT_GOAL := picky + +picky: + @bash ./install-scripts/pick-sets.sh + @$(MAKE) --no-print-directory full-install + +# Enable just the "basic" set and install, skipping the picker. This is what +# CI runs, and the right target for any unattended install. +basic: + @bash ./install-scripts/pick-sets.sh basic + @$(MAKE) --no-print-directory full-install + +# Install using whatever sets are already enabled, without asking. full-install: @bash ./install-scripts/01-install-packages.sh @bash ./install-scripts/02-move-files.sh @@ -12,15 +27,4 @@ refresh: @bash ./install-scripts/02-move-files.sh @exec fish -picky: - @bash ./install-scripts/pick-sets.sh - @bash ./install-scripts/01-install-packages.sh - @bash ./install-scripts/02-move-files.sh - @fish ./install-scripts/03-fisher-install.fish - @fish ./install-scripts/04-fish-plugins.fish - @fish ./install-scripts/05-tmux-plugins.fish - @fish ./install-scripts/06-vim-setup.fish - @bash ./install-scripts/07-last-touches.sh - @exec fish - -.PHONY: full-install refresh picky +.PHONY: picky basic full-install refresh diff --git a/README.md b/README.md index 33abf1e..c3a3243 100644 --- a/README.md +++ b/README.md @@ -8,7 +8,7 @@ A comprehensive dotfiles setup for a modern development environment featuring Ne - **Fish Shell**: Lightweight `simple.fish` prompt, cross-machine history sync, aliases, and productivity functions - **Tmux**: Custom keybindings, mouse support, and a modular status bar with toggleable gadgets - **Cross-platform**: Supports macOS, Linux (Arch, Debian/Ubuntu, Alpine, Fedora/RHEL, Gentoo), and FreeBSD -- **Config Sets**: Pick and choose which groups of config get deployed via an interactive `make picky` dialog +- **Config Sets**: Pick and choose which groups of config get deployed via the interactive checklist a bare `make` opens - **Automated Setup**: One-command installation via Makefile ## Quick Install @@ -17,7 +17,16 @@ A comprehensive dotfiles setup for a modern development environment featuring Ne make ``` -The setup will automatically detect your operating system and install all necessary packages and configurations. +This opens an interactive checklist of the available config sets, then runs +the full install using your selection. The setup automatically detects your +operating system and installs all necessary packages and configurations. + +To install just the `basic` set without being asked anything — the right +choice for an unattended install, and what CI runs: + +```bash +make basic +``` To re-sync just the config file symlinks (without reinstalling packages or plugins): @@ -25,10 +34,11 @@ To re-sync just the config file symlinks (without reinstalling packages or plugi make refresh ``` -To interactively choose which config sets get deployed, then run the full install using that selection: +To re-run the full install using the sets you already picked, without the +checklist: ```bash -make picky +make full-install ``` ## Repository Layout @@ -61,7 +71,7 @@ config/ # further sets live alongside these, following the same layout install-scripts/ # Numbered setup scripts run by the Makefile lib/sets.sh # Shared helpers for discovering/enabling sets - pick-sets.sh # `make picky` — the dialog checklist + pick-sets.sh # the dialog checklist; takes set names to skip it scripts/ # Misc helper scripts (e.g. Gentoo kernel upgrade) tests/ # Dockerfiles used by CI to test installs per distro ``` @@ -92,16 +102,23 @@ them to their platform, so `make picky` only offers `kde` on Linux and wrong OS anyway (e.g. a shared `sets.conf`), it's skipped with a warning at deploy time instead of failing. -Run `make picky` to get an interactive checklist (space to toggle, enter to -confirm) of every set found under `config/sets/`. Confirming saves your -selection to `~/.config/dotfiles/sets.conf` and immediately kicks off the -full install (packages, plugins, config deployment, last touches) using it -— the same steps `make full-install` runs. Cancelling (Esc) leaves your -existing selection untouched and stops there, without installing anything. +A bare `make` (or `make picky`, the same target by name) gives you an +interactive checklist (space to toggle, enter to confirm) of every set found +under `config/sets/`. Confirming saves your selection to +`~/.config/dotfiles/sets.conf` and immediately kicks off the full install +(packages, plugins, config deployment, last touches) using it — the same +steps `make full-install` runs. Cancelling (Esc) leaves your existing +selection untouched and stops there, without installing anything. + +`make basic` is the non-interactive equivalent: it enables just the `basic` +set and installs, skipping the checklist entirely (and skipping the `dialog` +dependency the checklist would otherwise pull in). CI uses it, and so should +any unattended install. + The saved selection is remembered by future `make refresh` / `make -full-install` runs too, so you only need to pick once per machine. If -you've never run `make picky`, everything defaults to just `basic`, -matching this repo's historical behavior. +full-install` runs too, so you only need to pick once per machine. If you've +never picked, everything defaults to just `basic`, matching this repo's +historical behavior. ### Adding a new set diff --git a/tests/Dockerfile-alpine b/tests/Dockerfile-alpine index f9b3960..c62239b 100644 --- a/tests/Dockerfile-alpine +++ b/tests/Dockerfile-alpine @@ -6,9 +6,9 @@ WORKDIR /workspace RUN apk add make shadow bash sudo -RUN make +RUN make basic -# Verify the install actually landed, not just that `make` exited 0. +# Verify the install actually landed, not just that `make basic` exited 0. RUN test -L /root/.config/nvim/init.lua \ && test -L /root/.config/fish/conf.d/aliases.fish \ && fish -c 'functions -q gitissue' \ diff --git a/tests/Dockerfile-archlinux b/tests/Dockerfile-archlinux index d8bff61..252383a 100644 --- a/tests/Dockerfile-archlinux +++ b/tests/Dockerfile-archlinux @@ -7,9 +7,9 @@ WORKDIR /workspace RUN pacman -Syy RUN pacman -S --noconfirm make sudo git -RUN make +RUN make basic -# Verify the install actually landed, not just that `make` exited 0. +# Verify the install actually landed, not just that `make basic` exited 0. RUN test -L /root/.config/nvim/init.lua \ && test -L /root/.config/fish/conf.d/aliases.fish \ && fish -c 'functions -q gitissue' \ diff --git a/tests/Dockerfile-fedora b/tests/Dockerfile-fedora index 03a9574..722fec1 100644 --- a/tests/Dockerfile-fedora +++ b/tests/Dockerfile-fedora @@ -7,9 +7,9 @@ WORKDIR /workspace RUN dnf -y update RUN dnf -y install make sudo -RUN make +RUN make basic -# Verify the install actually landed, not just that `make` exited 0. +# Verify the install actually landed, not just that `make basic` exited 0. RUN test -L /root/.config/nvim/init.lua \ && test -L /root/.config/fish/conf.d/aliases.fish \ && fish -c 'functions -q gitissue' \ diff --git a/tests/Dockerfile-ubuntu b/tests/Dockerfile-ubuntu index 630325a..b9e0d05 100644 --- a/tests/Dockerfile-ubuntu +++ b/tests/Dockerfile-ubuntu @@ -6,9 +6,9 @@ WORKDIR /workspace RUN apt-get update && apt-get install -y make sudo -RUN make +RUN make basic -# Verify the install actually landed, not just that `make` exited 0. +# Verify the install actually landed, not just that `make basic` exited 0. RUN test -L /root/.config/nvim/init.lua \ && test -L /root/.config/fish/conf.d/aliases.fish \ && fish -c 'functions -q gitissue' \