diff options
| author | Mike Vink <59492084+ivi-vink@users.noreply.github.com> | 2025-01-16 22:22:34 +0100 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2025-01-16 22:22:34 +0100 |
| commit | 8e7bd91f353caacc0bc4105f573eb3e17f09e03a (patch) | |
| tree | c5059edcbebd9644290cad7c653c49a36d593021 /modules/system | |
| parent | 6bd39d420578aacf7c0bab7de3e7027b952115ae (diff) | |
| parent | bd921223ba7cdac346477d7ea5204d6f4736fcc6 (diff) | |
Diffstat (limited to 'modules/system')
34 files changed, 963 insertions, 294 deletions
diff --git a/modules/system/activation-scripts.nix b/modules/system/activation-scripts.nix index 68e01b5..5f8916c 100644 --- a/modules/system/activation-scripts.nix +++ b/modules/system/activation-scripts.nix @@ -22,7 +22,7 @@ in internal = true; type = types.attrsOf (types.submodule script); default = {}; - description = lib.mdDoc '' + description = '' A set of shell script fragments that are executed when a NixOS system configuration is activated. Examples are updating /etc, creating accounts, and so on. Since these are executed @@ -67,6 +67,7 @@ in ${cfg.activationScripts.nix-daemon.text} ${cfg.activationScripts.time.text} ${cfg.activationScripts.networking.text} + ${cfg.activationScripts.power.text} ${cfg.activationScripts.keyboard.text} ${cfg.activationScripts.fonts.text} ${cfg.activationScripts.nvram.text} @@ -85,6 +86,7 @@ in exit $_status ''; + # FIXME: activationScripts.checks should be system level system.activationScripts.userScript.text = '' #! ${stdenv.shell} set -e @@ -101,6 +103,8 @@ in ${cfg.activationScripts.preUserActivation.text} + # This should be running at the system level, but as user activation runs first + # we run it here with sudo ${cfg.activationScripts.createRun.text} ${cfg.activationScripts.checks.text} ${cfg.activationScripts.etcChecks.text} diff --git a/modules/system/base.nix b/modules/system/base.nix index 44a8d91..2374855 100644 --- a/modules/system/base.nix +++ b/modules/system/base.nix @@ -2,22 +2,59 @@ { system.activationScripts.createRun.text = '' - if ! test -L /run; then + IFS="." read -r -a macOSVersion <<< "$(sw_vers -productVersion)" + + if [[ ''${macOSVersion[0]} -gt 10 || ( ''${macOSVersion[0]} -eq 10 && ''${macOSVersion[1]} -ge 15 ) ]]; then + if [[ $(stat -c '%a' /etc/synthetic.conf) != "644" ]]; then + echo "fixing permissions on /etc/synthetic.conf..." + sudo chmod 644 /etc/synthetic.conf + fi + + if [[ $(grep -c '^run\b' /etc/synthetic.conf) -gt 1 ]]; then + echo "found duplicate run entries in /etc/synthetic.conf, removing..." + sudo sed -i "" -e '/^run\tprivate\/var\/run$/d' /etc/synthetic.conf + fi + if ! grep -q '^run\b' /etc/synthetic.conf 2>/dev/null; then - echo "setting up /run via /etc/synthetic.conf..." - echo -e "run\tprivate/var/run" | sudo tee -a /etc/synthetic.conf >/dev/null - sudo /System/Library/Filesystems/apfs.fs/Contents/Resources/apfs.util -B &>/dev/null || true - sudo /System/Library/Filesystems/apfs.fs/Contents/Resources/apfs.util -t &>/dev/null || true - if ! test -L /run; then - echo "warning: apfs.util failed to symlink /run" - fi + echo "setting up /run via /etc/synthetic.conf..." + printf 'run\tprivate/var/run\n' | sudo tee -a /etc/synthetic.conf >/dev/null fi - if ! test -L /run; then - echo "setting up /run..." - sudo ln -sfn private/var/run /run + + if [[ ''${macOSVersion[0]} -gt 10 ]]; then + sudo /System/Library/Filesystems/apfs.fs/Contents/Resources/apfs.util -t || true + else + sudo /System/Library/Filesystems/apfs.fs/Contents/Resources/apfs.util -B || true fi - if ! test -L /run; then - echo "warning: failed to symlink /run" + + if [[ ! -L /run ]]; then + printf >&2 '[1;31merror: apfs.util failed to symlink /run, aborting activation[0m\n' + printf >&2 'To create a symlink from /run to /var/run, please run:\n' + printf >&2 '\n' + printf >&2 "$ printf 'run\tprivate/var/run\n' | sudo tee -a /etc/synthetic.conf" + + if [[ ''${macOSVersion[0]} -gt 10 ]]; then + printf >&2 '$ sudo /System/Library/Filesystems/apfs.fs/Contents/Resources/apfs.util -t\n' + else + printf >&2 '$ sudo /System/Library/Filesystems/apfs.fs/Contents/Resources/apfs.util -B\n' + fi + + printf >&2 '\n' + printf >&2 'The current contents of /etc/synthetic.conf is:\n' + printf >&2 '\n' + sudo sed 's/^/ /' /etc/synthetic.conf >&2 + printf >&2 '\n' + exit 1 + fi + else + echo "setting up /run..." + sudo ln -sfn private/var/run /run + + if [[ ! -L /run ]]; then + printf >&2 '[1;31merror: failed to symlink /run, aborting activation[0m\n' + printf >&2 'To create a symlink from /run to /var/run, please run:\n' + printf >&2 '\n' + printf >&2 '$ sudo ln -sfn private/var/link /run\n' + exit 1 fi fi ''; diff --git a/modules/system/checks.nix b/modules/system/checks.nix index 5989dc4..a5fd44a 100644 --- a/modules/system/checks.nix +++ b/modules/system/checks.nix @@ -3,6 +3,9 @@ with lib; let + # Similar to lib.escapeShellArg but escapes "s instead of 's, to allow for parameter expansion in shells + escapeDoubleQuote = arg: ''"${replaceStrings ["\""] ["\"\\\"\""] (toString arg)}"''; + cfg = config.system.checks; darwinChanges = '' @@ -22,42 +25,74 @@ let ''; runLink = '' - if ! test -e /run; then - echo "[1;31merror: Directory /run does not exist, aborting activation[0m" >&2 - echo "Create a symlink to /var/run with:" >&2 - if test -e /etc/synthetic.conf; then - echo >&2 - echo "$ printf 'run\tprivate/var/run\n' | sudo tee -a /etc/synthetic.conf" >&2 - echo "$ sudo /System/Library/Filesystems/apfs.fs/Contents/Resources/apfs.util -B # For Catalina" >&2 - echo "$ sudo /System/Library/Filesystems/apfs.fs/Contents/Resources/apfs.util -t # For Big Sur and later" >&2 - echo >&2 - echo "The current contents of /etc/synthetic.conf is:" >&2 - echo >&2 - sed 's/^/ /' /etc/synthetic.conf >&2 - echo >&2 - else - echo >&2 - echo "$ sudo ln -s private/var/run /run" >&2 - echo >&2 - fi - exit 2 + if [[ ! -e /run ]]; then + printf >&2 '[1;31merror: directory /run does not exist, aborting activation[0m\n' + exit 1 fi ''; + oldBuildUsers = '' if dscl . -list /Users | grep -q '^nixbld'; then - echo "[1;31mwarning: Detected old style nixbld users[0m" >&2 + echo "[1;31merror: Detected old style nixbld users, aborting activation[0m" >&2 echo "These can cause migration problems when upgrading to certain macOS versions" >&2 echo "You can enable the following option to migrate to new style nixbld users" >&2 echo >&2 echo " nix.configureBuildUsers = true;" >&2 echo >&2 + echo "or disable this check with" >&2 + echo >&2 + echo " system.checks.verifyBuildUsers = false;" >&2 + echo >&2 + exit 2 + fi + ''; + + preSequoiaBuildUsers = '' + ${lib.optionalString config.nix.configureBuildUsers '' + # Don’t complain when we’re about to migrate old‐style build users… + if ! dscl . -list /Users | grep -q '^nixbld'; then + ''} + firstBuildUserID=$(dscl . -read /Users/_nixbld1 UniqueID | awk '{print $2}') + if [[ $firstBuildUserID != ${toString (config.ids.uids.nixbld + 1)} ]]; then + printf >&2 '\e[1;31merror: Build users have unexpected UIDs, aborting activation\e[0m\n' + printf >&2 'The default Nix build user ID range has been adjusted for\n' + printf >&2 'compatibility with macOS Sequoia 15. Your _nixbld1 user currently has\n' + printf >&2 'UID %d rather than the new default of 351.\n' "$firstBuildUserID" + printf >&2 '\n' + printf >&2 'You can automatically migrate the users with the following command:\n' + printf >&2 '\n' + if [[ -e /nix/receipt.json ]]; then + if + ${pkgs.jq}/bin/jq --exit-status \ + 'try(.planner.settings | has("enable_flakes"))' \ + /nix/receipt.json \ + >/dev/null + then + installerUrl="https://install.lix.systems/lix" + else + installerUrl="https://install.determinate.systems/nix" + fi + printf >&2 " curl --proto '=https' --tlsv1.2 -sSf -L %s | sh -s -- repair sequoia --move-existing-users\n" \ + "$installerUrl" + else + printf >&2 " curl --proto '=https' --tlsv1.2 -sSf -L https://github.com/NixOS/nix/raw/master/scripts/sequoia-nixbld-user-migration.sh | bash -\n" + fi + printf >&2 '\n' + printf >&2 'If you have no intention of upgrading to macOS Sequoia 15, or already\n' + printf >&2 'have a custom UID range that you know is compatible with Sequoia, you\n' + printf >&2 'can disable this check by setting:\n' + printf >&2 '\n' + printf >&2 ' ids.uids.nixbld = %d;\n' "$((firstBuildUserID - 1))" + printf >&2 '\n' + exit 2 fi + ${lib.optionalString config.nix.configureBuildUsers "fi"} ''; buildUsers = '' buildUser=$(dscl . -read /Groups/nixbld GroupMembership 2>&1 | awk '/^GroupMembership: / {print $2}') || true - if [ -z $buildUser ]; then + if [[ -z "$buildUser" ]]; then echo "[1;31merror: Using the nix-daemon requires build users, aborting activation[0m" >&2 echo "Create the build users or disable the daemon:" >&2 echo "$ darwin-install" >&2 @@ -70,21 +105,56 @@ let fi ''; - singleUser = '' - if grep -q 'build-users-group =' /etc/nix/nix.conf; then - echo "[1;31merror: The daemon is not enabled but this is a multi-user install, aborting activation[0m" >&2 - echo "Enable the nix-daemon service:" >&2 - echo >&2 - echo " services.nix-daemon.enable = true;" >&2 - echo >&2 - echo "or set" >&2 - echo >&2 - echo " nix.useDaemon = true;" >&2 - echo >&2 + buildGroupID = '' + buildGroupID=$(dscl . -read /Groups/nixbld PrimaryGroupID | awk '{print $2}') + expectedBuildGroupID=${toString config.ids.gids.nixbld} + if [[ $buildGroupID != "$expectedBuildGroupID" ]]; then + printf >&2 '\e[1;31merror: Build user group has mismatching GID, aborting activation\e[0m\n' + printf >&2 'The default Nix build user group ID was changed from 30000 to 350.\n' + printf >&2 'You are currently managing Nix build users with nix-darwin, but your\n' + printf >&2 'nixbld group has GID %d, whereas we expected %d.\n' \ + "$buildGroupID" "$expectedBuildGroupID" + printf >&2 '\n' + printf >&2 'Possible causes include setting up a new Nix installation with an\n' + printf >&2 'existing nix-darwin configuration, setting up a new nix-darwin\n' + printf >&2 'installation with an existing Nix installation, or manually increasing\n' + # shellcheck disable=SC2016 + printf >&2 'your `system.stateVersion` setting.\n' + printf >&2 '\n' + printf >&2 'You can set the configured group ID to match the actual value:\n' + printf >&2 '\n' + printf >&2 ' ids.gids.nixbld = %d;\n' "$buildGroupID" + printf >&2 '\n' + printf >&2 'We do not recommend trying to change the group ID with macOS user\n' + printf >&2 'management tools without a complete uninstallation and reinstallation\n' + printf >&2 'of Nix.\n' exit 2 fi ''; + nixDaemon = if config.nix.useDaemon then '' + if ! dscl . -read /Groups/nixbld PrimaryGroupID &> /dev/null; then + printf >&2 '[1;31merror: The daemon should not be enabled for single-user installs, aborting activation[0m\n' + printf >&2 'Disable the nix-daemon service:\n' + printf >&2 '\n' + printf >&2 ' services.nix-daemon.enable = false;\n' + printf >&2 '\n' + # shellcheck disable=SC2016 + printf >&2 'and remove `nix.useDaemon` from your configuration if it is present.\n' + printf >&2 '\n' + exit 2 + fi + '' else '' + if dscl . -read /Groups/nixbld PrimaryGroupID &> /dev/null; then + printf >&2 '[1;31merror: The daemon should be enabled for multi-user installs, aborting activation[0m\n' + printf >&2 'Enable the nix-daemon service:\n' + printf >&2 '\n' + printf >&2 ' services.nix-daemon.enable = true;\n' + printf >&2 '\n' + exit 2 + fi + ''; + nixChannels = '' channelsLink=$(readlink "$HOME/.nix-defexpr/channels") || true case "$channelsLink" in @@ -121,7 +191,7 @@ let ''; nixPath = '' - nixPath=${concatStringsSep ":" config.nix.nixPath}:$HOME/.nix-defexpr/channels + nixPath=${concatMapStringsSep ":" escapeDoubleQuote config.nix.nixPath}:$HOME/.nix-defexpr/channels darwinConfig=$(NIX_PATH=$nixPath nix-instantiate --find-file darwin-config) || true if ! test -e "$darwinConfig"; then @@ -141,8 +211,8 @@ let if ! test -e "$darwinPath"; then echo "[1;31merror: Changed <darwin> but target does not exist, aborting activation[0m" >&2 echo "Add the darwin repo as a channel or set nix.nixPath:" >&2 - echo "$ nix-channel --add https://github.com/LnL7/nix-darwin/archive/master.tar.gz darwin" >&2 - echo "$ nix-channel --update" >&2 + echo "$ sudo nix-channel --add https://github.com/LnL7/nix-darwin/archive/master.tar.gz darwin" >&2 + echo "$ sudo nix-channel --update" >&2 echo >&2 echo "or set" >&2 echo >&2 @@ -155,8 +225,8 @@ let if ! test -e "$nixpkgsPath"; then echo "[1;31merror: Changed <nixpkgs> but target does not exist, aborting activation[0m" >&2 echo "Add a nixpkgs channel or set nix.nixPath:" >&2 - echo "$ nix-channel --add http://nixos.org/channels/nixpkgs-unstable nixpkgs" >&2 - echo "$ nix-channel --update" >&2 + echo "$ sudo nix-channel --add http://nixos.org/channels/nixpkgs-unstable nixpkgs" >&2 + echo "$ sudo nix-channel --update" >&2 echo >&2 echo "or set" >&2 echo >&2 @@ -197,11 +267,56 @@ let echo "[1;31merror: A single-user install can't run optimiser as root, aborting activation[0m" >&2 echo "Configure the optimiser to run as the current user:" >&2 echo >&2 - echo " nix.optimiser.user = \"$USER\";" >&2 + echo " nix.optimise.user = \"$USER\";" >&2 + echo >&2 + exit 2 + fi + ''; + + # TODO: Remove this a couple years down the line when we can assume + # that anyone who cares about security has upgraded. + oldSshAuthorizedKeysDirectory = '' + if [[ -d /etc/ssh/authorized_keys.d ]]; then + printf >&2 '\e[1;31merror: /etc/ssh/authorized_keys.d exists, aborting activation\e[0m\n' + printf >&2 'SECURITY NOTICE: The previous implementation of the\n' + # shellcheck disable=SC2016 + printf >&2 '`users.users.<name>.openssh.authorizedKeys.*` options would not delete\n' + printf >&2 'authorized keys files when the setting for a given user was removed.\n' + printf >&2 '\n' + printf >&2 "This means that if you previously stopped managing a user's authorized\n" + printf >&2 'SSH keys with nix-darwin, or intended to revoke their access by\n' + printf >&2 'removing the option, the previous set of keys could still be used to\n' + printf >&2 'log in as that user.\n' + printf >&2 '\n' + printf >&2 'You can check the /etc/ssh/authorized_keys.d directory to see which\n' + printf >&2 'keys were permitted; afterwards, please remove the directory and\n' + printf >&2 're-run activation. The options continue to be supported and will now\n' + printf >&2 'correctly permit only the keys in your current system configuration.\n' + exit 2 + fi + ''; + + homebrewInstalled = '' + if [[ ! -f ${escapeShellArg config.homebrew.brewPrefix}/brew && -z "''${INSTALLING_HOMEBREW:-}" ]]; then + echo "[1;31merror: Using the homebrew module requires homebrew installed, aborting activation[0m" >&2 + echo "Homebrew doesn't seem to be installed. Please install homebrew separately." >&2 + echo "You can install homebrew using the following command:" >&2 + echo >&2 + # shellcheck disable=SC2016 + echo ' /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"' >&2 echo >&2 exit 2 fi ''; + + # some mac devices, notably notebook do not support restartAfterPowerFailure option + restartAfterPowerFailureIsSupported = '' + if sudo /usr/sbin/systemsetup -getRestartPowerFailure | grep -q "Not supported"; then + printf >&2 "\e[1;31merror: restarting after power failure is not supported on your machine\e[0m\n" >&2 + printf >&2 "Please ensure that \`power.restartAfterPowerFailure\` is not set.\n" >&2 + exit 2 + fi + ''; in { @@ -209,19 +324,21 @@ in system.checks.verifyNixPath = mkOption { type = types.bool; default = true; - description = lib.mdDoc "Whether to run the NIX_PATH validation checks."; + description = "Whether to run the NIX_PATH validation checks."; }; system.checks.verifyNixChannels = mkOption { type = types.bool; - default = true; - description = lib.mdDoc "Whether to run the nix-channels validation checks."; + default = config.nix.channel.enable; + description = "Whether to run the nix-channels validation checks."; }; system.checks.verifyBuildUsers = mkOption { type = types.bool; - default = true; - description = lib.mdDoc "Whether to run the Nix build users validation checks."; + default = + (config.nix.useDaemon && !(config.nix.settings.auto-allocate-uids or false)) + || config.nix.configureBuildUsers; + description = "Whether to run the Nix build users validation checks."; }; system.checks.text = mkOption { @@ -236,21 +353,26 @@ in system.checks.text = mkMerge [ darwinChanges runLink - oldBuildUsers - (mkIf (config.nix.useDaemon && cfg.verifyBuildUsers) buildUsers) - (mkIf (!config.nix.useDaemon) singleUser) + (mkIf (cfg.verifyBuildUsers && !config.nix.configureBuildUsers) oldBuildUsers) + (mkIf cfg.verifyBuildUsers buildUsers) + (mkIf cfg.verifyBuildUsers preSequoiaBuildUsers) + (mkIf config.nix.configureBuildUsers buildGroupID) + nixDaemon nixStore (mkIf (config.nix.gc.automatic && config.nix.gc.user == null) nixGarbageCollector) (mkIf (config.nix.optimise.automatic && config.nix.optimise.user == null) nixStoreOptimiser) (mkIf cfg.verifyNixChannels nixChannels) nixInstaller (mkIf cfg.verifyNixPath nixPath) + oldSshAuthorizedKeysDirectory + (mkIf config.homebrew.enable homebrewInstalled) + (mkIf (config.power.restartAfterPowerFailure != null) restartAfterPowerFailureIsSupported) ]; system.activationScripts.checks.text = '' ${cfg.text} - if test ''${checkActivation:-0} -eq 1; then + if [[ "''${checkActivation:-0}" -eq 1 ]]; then echo "ok" >&2 exit 0 fi diff --git a/modules/system/default.nix b/modules/system/default.nix index fbe169e..a1862fa 100644 --- a/modules/system/default.nix +++ b/modules/system/default.nix @@ -22,7 +22,7 @@ in internal = true; type = types.attrsOf types.unspecified; default = {}; - description = lib.mdDoc '' + description = '' Attribute set of derivation used to setup the system. ''; }; @@ -30,7 +30,7 @@ in system.path = mkOption { internal = true; type = types.package; - description = lib.mdDoc '' + description = '' The packages you want in the system environment. ''; }; @@ -38,7 +38,7 @@ in system.profile = mkOption { type = types.path; default = "/nix/var/nix/profiles/system"; - description = lib.mdDoc '' + description = '' Profile to use for the system. ''; }; @@ -56,7 +56,7 @@ in internal = true; type = types.attrsOf types.unspecified; default = {}; - description = lib.mdDoc '' + description = '' `lib.mkDerivation` attributes that will be passed to the top level system builder. ''; }; @@ -66,7 +66,7 @@ in internal = true; default = []; example = [ { assertion = false; message = "you can't enable this for that reason"; } ]; - description = lib.mdDoc '' + description = '' This option allows modules to express conditions that must hold for the evaluation of the system configuration to succeed, along with associated error messages for the user. @@ -78,7 +78,7 @@ in default = []; type = types.listOf types.str; example = [ "The `foo' service is deprecated and will go away soon!" ]; - description = lib.mdDoc '' + description = '' This option allows modules to show warnings to users during the evaluation of the system configuration. ''; @@ -92,6 +92,8 @@ in name = "darwin-system-${cfg.darwinLabel}"; preferLocalBuild = true; + nativeBuildInputs = [ pkgs.shellcheck ]; + activationScript = cfg.activationScripts.script.text; activationUserScript = cfg.activationScripts.userScript.text; inherit (cfg) darwinLabel; @@ -133,6 +135,8 @@ in chmod u+x $out/activate-user unset activationUserScript + shellcheck $out/activate $out/activate-user + echo -n "$systemConfig" > $out/systemConfig echo -n "$darwinLabel" > $out/darwin-version diff --git a/modules/system/defaults-write.nix b/modules/system/defaults-write.nix index 7e1fc44..2265721 100644 --- a/modules/system/defaults-write.nix +++ b/modules/system/defaults-write.nix @@ -9,20 +9,24 @@ let "defaults write ${domain} '${key}' $'${strings.escape [ "'" ] (generators.toPlist { } value)}'"; defaultsToList = domain: attrs: mapAttrsToList (writeDefault domain) (filterAttrs (n: v: v != null) attrs); + # Filter out options to not pass through + # dock has alias options that we need to ignore + dockFiltered = (builtins.removeAttrs cfg.dock ["expose-group-by-app"]); # defaults alf = defaultsToList "/Library/Preferences/com.apple.alf" cfg.alf; loginwindow = defaultsToList "/Library/Preferences/com.apple.loginwindow" cfg.loginwindow; smb = defaultsToList "/Library/Preferences/SystemConfiguration/com.apple.smb.server" cfg.smb; - SoftwareUpdate = defaultsToList "/Library/Preferences/SystemConfiguration/com.apple.SoftwareUpdate" cfg.SoftwareUpdate; + SoftwareUpdate = defaultsToList "/Library/Preferences/com.apple.SoftwareUpdate" cfg.SoftwareUpdate; # userDefaults GlobalPreferences = defaultsToList ".GlobalPreferences" cfg.".GlobalPreferences"; LaunchServices = defaultsToList "com.apple.LaunchServices" cfg.LaunchServices; NSGlobalDomain = defaultsToList "-g" cfg.NSGlobalDomain; menuExtraClock = defaultsToList "com.apple.menuextra.clock" cfg.menuExtraClock; - dock = defaultsToList "com.apple.dock" cfg.dock; + dock = defaultsToList "com.apple.dock" dockFiltered; finder = defaultsToList "com.apple.finder" cfg.finder; + hitoolbox = defaultsToList "com.apple.HIToolbox" cfg.hitoolbox; magicmouse = defaultsToList "com.apple.AppleMultitouchMouse" cfg.magicmouse; magicmouseBluetooth = defaultsToList "com.apple.driver.AppleMultitouchMouse.mouse" cfg.magicmouse; screencapture = defaultsToList "com.apple.screencapture" cfg.screencapture; @@ -32,9 +36,12 @@ let trackpadBluetooth = defaultsToList "com.apple.driver.AppleBluetoothMultitouch.trackpad" cfg.trackpad; universalaccess = defaultsToList "com.apple.universalaccess" cfg.universalaccess; ActivityMonitor = defaultsToList "com.apple.ActivityMonitor" cfg.ActivityMonitor; + WindowManager = defaultsToList "com.apple.WindowManager" cfg.WindowManager; + controlcenter = defaultsToList "~/Library/Preferences/ByHost/com.apple.controlcenter" cfg.controlcenter; CustomUserPreferences = flatten (mapAttrsToList (name: value: defaultsToList name value) cfg.CustomUserPreferences); CustomSystemPreferences = flatten (mapAttrsToList (name: value: defaultsToList name value) cfg.CustomSystemPreferences); + mkIfAttrs = list: mkIf (any (attrs: attrs != { }) list); in @@ -75,6 +82,7 @@ in menuExtraClock dock finder + hitoolbox magicmouse magicmouseBluetooth screencapture @@ -85,6 +93,8 @@ in universalaccess ActivityMonitor CustomUserPreferences + WindowManager + controlcenter ] '' # Set defaults @@ -97,6 +107,7 @@ in ${concatStringsSep "\n" menuExtraClock} ${concatStringsSep "\n" dock} ${concatStringsSep "\n" finder} + ${concatStringsSep "\n" hitoolbox} ${concatStringsSep "\n" magicmouse} ${concatStringsSep "\n" magicmouseBluetooth} ${concatStringsSep "\n" screencapture} @@ -107,6 +118,16 @@ in ${concatStringsSep "\n" universalaccess} ${concatStringsSep "\n" ActivityMonitor} ${concatStringsSep "\n" CustomUserPreferences} + ${concatStringsSep "\n" WindowManager} + ${concatStringsSep "\n" controlcenter} + + ${optionalString (length dock > 0) '' + # Only restart Dock if current user is logged in + if pgrep -xu $UID Dock >/dev/null; then + echo >&2 "restarting Dock..." + killall Dock || true + fi + ''} ''; }; diff --git a/modules/system/defaults/ActivityMonitor.nix b/modules/system/defaults/ActivityMonitor.nix index 9f4617c..8786375 100644 --- a/modules/system/defaults/ActivityMonitor.nix +++ b/modules/system/defaults/ActivityMonitor.nix @@ -8,7 +8,7 @@ with lib; system.defaults.ActivityMonitor.ShowCategory = mkOption { type = types.nullOr (types.enum [100 101 102 103 104 105 106 107]); default = null; - description = lib.mdDoc '' + description = '' Change which processes to show. * 100: All Processes * 101: All Processes, Hierarchally @@ -25,7 +25,7 @@ with lib; system.defaults.ActivityMonitor.IconType = mkOption { type = types.nullOr types.int; default = null; - description = lib.mdDoc '' + description = '' Change the icon in the dock when running. * 0: Application Icon * 2: Network Usage @@ -39,7 +39,7 @@ with lib; system.defaults.ActivityMonitor.SortColumn = mkOption { type = types.nullOr types.str; default = null; - description = lib.mdDoc '' + description = '' Which column to sort the main activity page (such as "CPUUsage"). Default is null. ''; }; @@ -47,7 +47,7 @@ with lib; system.defaults.ActivityMonitor.SortDirection = mkOption { type = types.nullOr types.int; default = null; - description = lib.mdDoc '' + description = '' The sort direction of the sort column (0 is decending). Default is null. ''; }; @@ -55,7 +55,7 @@ with lib; system.defaults.ActivityMonitor.OpenMainWindow = mkOption { type = types.nullOr types.bool; default = null; - description = lib.mdDoc '' + description = '' Open the main window when opening Activity Monitor. Default is true. ''; }; diff --git a/modules/system/defaults/CustomPreferences.nix b/modules/system/defaults/CustomPreferences.nix index 134c8d0..1b4b99b 100644 --- a/modules/system/defaults/CustomPreferences.nix +++ b/modules/system/defaults/CustomPreferences.nix @@ -14,7 +14,7 @@ with lib; true; }; }; - description = lib.mdDoc '' + description = '' Sets custom user preferences ''; }; @@ -29,7 +29,7 @@ with lib; true; }; }; - description = lib.mdDoc '' + description = '' Sets custom system preferences ''; }; diff --git a/modules/system/defaults/GlobalPreferences.nix b/modules/system/defaults/GlobalPreferences.nix index a975802..9709711 100644 --- a/modules/system/defaults/GlobalPreferences.nix +++ b/modules/system/defaults/GlobalPreferences.nix @@ -11,7 +11,7 @@ in { mkOption { type = types.nullOr (types.path); default = null; - description = lib.mdDoc '' + description = '' Sets the system-wide alert sound. Found under "Sound Effects" in the "Sound" section of "System Preferences". Look in "/System/Library/Sounds" for possible candidates. @@ -23,7 +23,7 @@ in { type = types.nullOr floatWithDeprecationError; default = null; example = -1.0; - description = lib.mdDoc '' + description = '' Sets the mouse tracking speed. Found in the "Mouse" section of "System Preferences". Set to -1.0 to disable mouse acceleration. ''; diff --git a/modules/system/defaults/LaunchServices.nix b/modules/system/defaults/LaunchServices.nix index b76231f..d9ffcda 100644 --- a/modules/system/defaults/LaunchServices.nix +++ b/modules/system/defaults/LaunchServices.nix @@ -8,7 +8,7 @@ with lib; system.defaults.LaunchServices.LSQuarantine = mkOption { type = types.nullOr types.bool; default = null; - description = lib.mdDoc '' + description = '' Whether to enable quarantine for downloaded applications. The default is true. ''; }; diff --git a/modules/system/defaults/NSGlobalDomain.nix b/modules/system/defaults/NSGlobalDomain.nix index 03a7da2..01e7a45 100644 --- a/modules/system/defaults/NSGlobalDomain.nix +++ b/modules/system/defaults/NSGlobalDomain.nix @@ -7,11 +7,10 @@ let inherit (config.lib.defaults.types) floatWithDeprecationError; in { options = { - system.defaults.NSGlobalDomain.AppleShowAllFiles = mkOption { type = types.nullOr types.bool; default = null; - description = lib.mdDoc '' + description = '' Whether to always show hidden files. The default is false. ''; }; @@ -19,7 +18,7 @@ in { system.defaults.NSGlobalDomain.AppleEnableMouseSwipeNavigateWithScrolls = mkOption { type = types.nullOr types.bool; default = null; - description = lib.mdDoc '' + description = '' Enables swiping left or right with two fingers to navigate backward or forward. The default is true. ''; }; @@ -27,7 +26,7 @@ in { system.defaults.NSGlobalDomain.AppleEnableSwipeNavigateWithScrolls = mkOption { type = types.nullOr types.bool; default = null; - description = lib.mdDoc '' + description = '' Enables swiping left or right with two fingers to navigate backward or forward. The default is true. ''; }; @@ -35,7 +34,7 @@ in { system.defaults.NSGlobalDomain.AppleFontSmoothing = mkOption { type = types.nullOr (types.enum [ 0 1 2 ]); default = null; - description = lib.mdDoc '' + description = '' Sets the level of font smoothing (sub-pixel font rendering). ''; }; @@ -43,7 +42,7 @@ in { system.defaults.NSGlobalDomain.AppleInterfaceStyle = mkOption { type = types.nullOr (types.enum [ "Dark" ]); default = null; - description = lib.mdDoc '' + description = '' Set to 'Dark' to enable dark mode, or leave unset for normal mode. ''; }; @@ -51,7 +50,7 @@ in { system.defaults.NSGlobalDomain.AppleInterfaceStyleSwitchesAutomatically = mkOption { type = types.nullOr types.bool; default = null; - description = lib.mdDoc '' + description = '' Whether to automatically switch between light and dark mode. The default is false. ''; }; @@ -59,7 +58,7 @@ in { system.defaults.NSGlobalDomain.AppleKeyboardUIMode = mkOption { type = types.nullOr (types.enum [ 3 ]); default = null; - description = lib.mdDoc '' + description = '' Configures the keyboard control behavior. Mode 3 enables full keyboard control. ''; }; @@ -67,7 +66,7 @@ in { system.defaults.NSGlobalDomain.ApplePressAndHoldEnabled = mkOption { type = types.nullOr types.bool; default = null; - description = lib.mdDoc '' + description = '' Whether to enable the press-and-hold feature. The default is true. ''; }; @@ -75,7 +74,7 @@ in { system.defaults.NSGlobalDomain.AppleShowAllExtensions = mkOption { type = types.nullOr types.bool; default = null; - description = lib.mdDoc '' + description = '' Whether to show all file extensions in Finder. The default is false. ''; }; @@ -83,7 +82,7 @@ in { system.defaults.NSGlobalDomain.AppleShowScrollBars = mkOption { type = types.nullOr (types.enum [ "WhenScrolling" "Automatic" "Always" ]); default = null; - description = lib.mdDoc '' + description = '' When to show the scrollbars. Options are 'WhenScrolling', 'Automatic' and 'Always'. ''; }; @@ -91,23 +90,39 @@ in { system.defaults.NSGlobalDomain.AppleScrollerPagingBehavior = mkOption { type = types.nullOr types.bool; default = null; - description = lib.mdDoc '' + description = '' Jump to the spot that's clicked on the scroll bar. The default is false. ''; }; + system.defaults.NSGlobalDomain.AppleSpacesSwitchOnActivate = mkOption { + type = types.nullOr types.bool; + default = null; + description = '' + Whether or not to switch to a workspace that has a window of the application open, that is switched to. The default is true. + ''; + }; + system.defaults.NSGlobalDomain.NSAutomaticCapitalizationEnabled = mkOption { type = types.nullOr types.bool; default = null; - description = lib.mdDoc '' + description = '' Whether to enable automatic capitalization. The default is true. ''; }; + system.defaults.NSGlobalDomain.NSAutomaticInlinePredictionEnabled = mkOption { + type = types.nullOr types.bool; + default = null; + description = '' + Whether to enable inline predictive text. The default is true. + ''; + }; + system.defaults.NSGlobalDomain.NSAutomaticDashSubstitutionEnabled = mkOption { type = types.nullOr types.bool; default = null; - description = lib.mdDoc '' + description = '' Whether to enable smart dash substitution. The default is true. ''; }; @@ -115,7 +130,7 @@ in { system.defaults.NSGlobalDomain.NSAutomaticPeriodSubstitutionEnabled = mkOption { type = types.nullOr types.bool; default = null; - description = lib.mdDoc '' + description = '' Whether to enable smart period substitution. The default is true. ''; }; @@ -123,7 +138,7 @@ in { system.defaults.NSGlobalDomain.NSAutomaticQuoteSubstitutionEnabled = mkOption { type = types.nullOr types.bool; default = null; - description = lib.mdDoc '' + description = '' Whether to enable smart quote substitution. The default is true. ''; }; @@ -131,7 +146,7 @@ in { system.defaults.NSGlobalDomain.NSAutomaticSpellingCorrectionEnabled = mkOption { type = types.nullOr types.bool; default = null; - description = lib.mdDoc '' + description = '' Whether to enable automatic spelling correction. The default is true. ''; }; @@ -139,7 +154,7 @@ in { system.defaults.NSGlobalDomain.NSAutomaticWindowAnimationsEnabled = mkOption { type = types.nullOr types.bool; default = null; - description = lib.mdDoc '' + description = '' Whether to animate opening and closing of windows and popovers. The default is true. ''; }; @@ -147,7 +162,7 @@ in { system.defaults.NSGlobalDomain.NSDisableAutomaticTermination = mkOption { type = types.nullOr types.bool; default = null; - description = lib.mdDoc '' + description = '' Whether to disable the automatic termination of inactive apps. ''; }; @@ -155,7 +170,7 @@ in { system.defaults.NSGlobalDomain.NSDocumentSaveNewDocumentsToCloud = mkOption { type = types.nullOr types.bool; default = null; - description = lib.mdDoc '' + description = '' Whether to save new documents to iCloud by default. The default is true. ''; }; @@ -163,7 +178,7 @@ in { system.defaults.NSGlobalDomain.AppleWindowTabbingMode = mkOption { type = types.nullOr (types.enum [ "manual" "always" "fullscreen" ]); default = null; - description = lib.mdDoc '' + description = '' Sets the window tabbing when opening a new document: 'manual', 'always', or 'fullscreen'. The default is 'fullscreen'. ''; }; @@ -171,7 +186,7 @@ in { system.defaults.NSGlobalDomain.NSNavPanelExpandedStateForSaveMode = mkOption { type = types.nullOr types.bool; default = null; - description = lib.mdDoc '' + description = '' Whether to use expanded save panel by default. The default is false. ''; }; @@ -179,7 +194,7 @@ in { system.defaults.NSGlobalDomain.NSNavPanelExpandedStateForSaveMode2 = mkOption { type = types.nullOr types.bool; default = null; - description = lib.mdDoc '' + description = '' Whether to use expanded save panel by default. The default is false. ''; }; @@ -187,7 +202,7 @@ in { system.defaults.NSGlobalDomain.NSTableViewDefaultSizeMode = mkOption { type = types.nullOr (types.enum [ 1 2 3 ]); default = null; - description = lib.mdDoc '' + description = '' Sets the size of the finder sidebar icons: 1 (small), 2 (medium) or 3 (large). The default is 3. ''; }; @@ -195,7 +210,7 @@ in { system.defaults.NSGlobalDomain.NSTextShowsControlCharacters = mkOption { type = types.nullOr types.bool; default = null; - description = lib.mdDoc '' + description = '' Whether to display ASCII control characters using caret notation in standard text views. The default is false. ''; }; @@ -203,7 +218,7 @@ in { system.defaults.NSGlobalDomain.NSUseAnimatedFocusRing = mkOption { type = types.nullOr types.bool; default = null; - description = lib.mdDoc '' + description = '' Whether to enable the focus ring animation. The default is true. ''; }; @@ -211,7 +226,7 @@ in { system.defaults.NSGlobalDomain.NSScrollAnimationEnabled = mkOption { type = types.nullOr types.bool; default = null; - description = lib.mdDoc '' + description = '' Whether to enable smooth scrolling. The default is true. ''; }; @@ -220,7 +235,7 @@ in { type = types.nullOr floatWithDeprecationError; default = null; example = 0.20; - description = lib.mdDoc '' + description = '' Sets the speed speed of window resizing. The default is given in the example. ''; }; @@ -228,7 +243,7 @@ in { system.defaults.NSGlobalDomain.NSWindowShouldDragOnGesture = mkOption { type = types.nullOr types.bool; default = null; - description = lib.mdDoc '' + description = '' Whether to enable moving window by holding anywhere on it like on Linux. The default is false. ''; }; @@ -236,7 +251,7 @@ in { system.defaults.NSGlobalDomain.InitialKeyRepeat = mkOption { type = types.nullOr types.int; default = null; - description = lib.mdDoc '' + description = '' Apple menu > System Preferences > Keyboard If you press and hold certain keyboard keys when in a text area, the key’s character begins to repeat. @@ -249,7 +264,7 @@ in { system.defaults.NSGlobalDomain.KeyRepeat = mkOption { type = types.nullOr types.int; default = null; - description = lib.mdDoc '' + description = '' Apple menu > System Preferences > Keyboard If you press and hold certain keyboard keys when in a text area, the key’s character begins to repeat. @@ -262,7 +277,7 @@ in { system.defaults.NSGlobalDomain.PMPrintingExpandedStateForPrint = mkOption { type = types.nullOr types.bool; default = null; - description = lib.mdDoc '' + description = '' Whether to use the expanded print panel by default. The default is false. ''; }; @@ -270,7 +285,7 @@ in { system.defaults.NSGlobalDomain.PMPrintingExpandedStateForPrint2 = mkOption { type = types.nullOr types.bool; default = null; - description = lib.mdDoc '' + description = '' Whether to use the expanded print panel by default. The default is false. ''; }; @@ -278,7 +293,7 @@ in { system.defaults.NSGlobalDomain."com.apple.keyboard.fnState" = mkOption { type = types.nullOr types.bool; default = null; - description = lib.mdDoc '' + description = '' Use F1, F2, etc. keys as standard function keys. ''; }; @@ -286,7 +301,7 @@ in { system.defaults.NSGlobalDomain."com.apple.mouse.tapBehavior" = mkOption { type = types.nullOr (types.enum [ 1 ]); default = null; - description = lib.mdDoc '' + description = '' Configures the trackpad tap behavior. Mode 1 enables tap to click. ''; }; @@ -294,7 +309,7 @@ in { system.defaults.NSGlobalDomain."com.apple.sound.beep.volume" = mkOption { type = types.nullOr floatWithDeprecationError; default = null; - description = lib.mdDoc '' + description = '' Apple menu > System Preferences > Sound Sets the beep/alert volume level from 0.000 (muted) to 1.000 (100% volume). @@ -310,7 +325,7 @@ in { system.defaults.NSGlobalDomain."com.apple.sound.beep.feedback" = mkOption { type = types.nullOr types.int; default = null; - description = lib.mdDoc '' + description = '' Apple menu > System Preferences > Sound Make a feedback sound when the system volume changed. This setting accepts @@ -321,7 +336,7 @@ in { system.defaults.NSGlobalDomain."com.apple.trackpad.enableSecondaryClick" = mkOption { type = types.nullOr types.bool; default = null; - description = lib.mdDoc '' + description = '' Whether to enable trackpad secondary click. The default is true. ''; }; @@ -329,7 +344,7 @@ in { system.defaults.NSGlobalDomain."com.apple.trackpad.trackpadCornerClickBehavior" = mkOption { type = types.nullOr (types.enum [ 1 ]); default = null; - description = lib.mdDoc '' + description = '' Configures the trackpad corner click behavior. Mode 1 enables right click. ''; }; @@ -337,15 +352,23 @@ in { system.defaults.NSGlobalDomain."com.apple.trackpad.scaling" = mkOption { type = types.nullOr floatWithDeprecationError; default = null; - description = lib.mdDoc '' + description = '' Configures the trackpad tracking speed (0 to 3). The default is "1". ''; }; + system.defaults.NSGlobalDomain."com.apple.trackpad.forceClick" = mkOption { + type = types.nullOr types.bool; + default = null; + description = '' + Whether to enable trackpad force click. + ''; + }; + system.defaults.NSGlobalDomain."com.apple.springing.enabled" = mkOption { type = types.nullOr types.bool; default = null; - description = lib.mdDoc '' + description = '' Whether to enable spring loading (expose) for directories. ''; }; @@ -354,7 +377,7 @@ in { type = types.nullOr floatWithDeprecationError; default = null; example = 1.0; - description = lib.mdDoc '' + description = '' Set the spring loading delay for directories. The default is given in the example. ''; }; @@ -362,7 +385,7 @@ in { system.defaults.NSGlobalDomain."com.apple.swipescrolldirection" = mkOption { type = types.nullOr types.bool; default = null; - description = lib.mdDoc '' + description = '' Whether to enable "Natural" scrolling direction. The default is true. ''; }; @@ -370,7 +393,7 @@ in { system.defaults.NSGlobalDomain.AppleMeasurementUnits = mkOption { type = types.nullOr (types.enum [ "Centimeters" "Inches" ]); default = null; - description = lib.mdDoc '' + description = '' Whether to use centimeters (metric) or inches (US, UK) as the measurement unit. The default is based on region settings. ''; }; @@ -378,7 +401,7 @@ in { system.defaults.NSGlobalDomain.AppleMetricUnits = mkOption { type = types.nullOr (types.enum [ 0 1 ]); default = null; - description = lib.mdDoc '' + description = '' Whether to use the metric system. The default is based on region settings. ''; }; @@ -386,7 +409,7 @@ in { system.defaults.NSGlobalDomain.AppleTemperatureUnit = mkOption { type = types.nullOr (types.enum [ "Celsius" "Fahrenheit" ]); default = null; - description = lib.mdDoc '' + description = '' Whether to use Celsius or Fahrenheit. The default is based on region settings. ''; }; @@ -394,7 +417,7 @@ in { system.defaults.NSGlobalDomain.AppleICUForce24HourTime = mkOption { type = types.nullOr types.bool; default = null; - description = lib.mdDoc '' + description = '' Whether to use 24-hour or 12-hour time. The default is based on region settings. ''; }; @@ -402,7 +425,7 @@ in { system.defaults.NSGlobalDomain._HIHideMenuBar = mkOption { type = types.nullOr types.bool; default = null; - description = lib.mdDoc '' + description = '' Whether to autohide the menu bar. The default is false. ''; }; diff --git a/modules/system/defaults/SoftwareUpdate.nix b/modules/system/defaults/SoftwareUpdate.nix index 2882e8c..ec89bce 100644 --- a/modules/system/defaults/SoftwareUpdate.nix +++ b/modules/system/defaults/SoftwareUpdate.nix @@ -7,7 +7,7 @@ with lib; system.defaults.SoftwareUpdate.AutomaticallyInstallMacOSUpdates = mkOption { type = types.nullOr types.bool; default = null; - description = lib.mdDoc '' + description = '' Automatically install Mac OS software updates. Defaults to false. ''; }; diff --git a/modules/system/defaults/WindowManager.nix b/modules/system/defaults/WindowManager.nix new file mode 100644 index 0000000..6a62ebc --- /dev/null +++ b/modules/system/defaults/WindowManager.nix @@ -0,0 +1,83 @@ +{ config, lib, ... }: + +with lib; +{ + options = { + system.defaults.WindowManager.GloballyEnabled = mkOption { + type = types.nullOr types.bool; + default = null; + description = '' + Enable Stage Manager + Stage Manager arranges your recent windows into a single strip for reduced clutter and quick access. Default is false. + ''; + }; + + system.defaults.WindowManager.EnableStandardClickToShowDesktop = mkOption { + type = types.nullOr types.bool; + default = null; + description = '' + Click wallpaper to reveal desktop + Clicking your wallpaper will move all windows out of the way to allow access to your desktop items and widgets. Default is true. + false means "Only in Stage Manager" + true means "Always" + ''; + }; + + system.defaults.WindowManager.AutoHide = mkOption { + type = types.nullOr types.bool; + default = null; + description = '' + Auto hide stage strip showing recent apps. Default is false. + ''; + }; + + system.defaults.WindowManager.AppWindowGroupingBehavior = mkOption { + type = types.nullOr types.bool; + default = null; + description = '' + Grouping strategy when showing windows from an application. + false means "One at a time" + true means "All at once" + ''; + }; + + system.defaults.WindowManager.StandardHideDesktopIcons = mkOption { + type = types.nullOr types.bool; + default = null; + description = '' + Hide items on desktop. + ''; + }; + + system.defaults.WindowManager.HideDesktop = mkOption { + type = types.nullOr types.bool; + default = null; + description = '' + Hide items in Stage Manager. + ''; + }; + system.defaults.WindowManager.EnableTiledWindowMargins = mkOption { + type = types.nullOr types.bool; + default = null; + description = '' + Enable Window Margins. The default is true. + ''; + }; + + system.defaults.WindowManager.StandardHideWidgets = mkOption { + type = types.nullOr types.bool; + default = null; + description = '' + Hide widgets on desktop. + ''; + }; + + system.defaults.WindowManager.StageManagerHideWidgets = mkOption { + type = types.nullOr types.bool; + default = null; + description = '' + Hide widgets in Stage Manager. + ''; + }; + }; +} diff --git a/modules/system/defaults/alf.nix b/modules/system/defaults/alf.nix index 6b82eca..96a9806 100644 --- a/modules/system/defaults/alf.nix +++ b/modules/system/defaults/alf.nix @@ -7,7 +7,7 @@ with lib; system.defaults.alf.globalstate = mkOption { type = types.nullOr types.int; default = null; - description = lib.mdDoc '' + description = '' Apple menu > System Preferences > Security and Privacy > Firewall Enable the internal firewall to prevent unauthorised applications, programs @@ -22,7 +22,7 @@ with lib; system.defaults.alf.allowsignedenabled = mkOption { type = types.nullOr types.int; default = null; - description = lib.mdDoc '' + description = '' Apple menu > System Preferences > Security and Privacy > Firewall Allows any signed Application to accept incoming requests. Default is true. @@ -35,7 +35,7 @@ with lib; system.defaults.alf.allowdownloadsignedenabled = mkOption { type = types.nullOr types.int; default = null; - description = lib.mdDoc '' + description = '' Apple menu > System Preferences > Security and Privacy > Firewall Allows any downloaded Application that has been signed to accept incoming requests. Default is 0. @@ -48,7 +48,7 @@ with lib; system.defaults.alf.loggingenabled = mkOption { type = types.nullOr types.int; default = null; - description = lib.mdDoc '' + description = '' Apple menu > System Preferences > Security and Privacy > Firewall Enable logging of requests made to the firewall. Default is 0. @@ -61,7 +61,7 @@ with lib; system.defaults.alf.stealthenabled = mkOption { type = types.nullOr types.int; default = null; - description = lib.mdDoc '' + description = '' Apple menu > System Preferences > Security and firewall Drops incoming requests via ICMP such as ping requests. Default is 0. diff --git a/modules/system/defaults/clock.nix b/modules/system/defaults/clock.nix index cd5c0e8..50eb517 100644 --- a/modules/system/defaults/clock.nix +++ b/modules/system/defaults/clock.nix @@ -5,10 +5,18 @@ with lib; { options = { + system.defaults.menuExtraClock.FlashDateSeparators = mkOption { + type = types.nullOr types.bool; + default = null; + description = '' + When enabled, the clock indicator (which by default is the colon) will flash on and off each second. Default is null. + ''; + }; + system.defaults.menuExtraClock.IsAnalog = mkOption { type = types.nullOr types.bool; default = null; - description = lib.mdDoc '' + description = '' Show an analog clock instead of a digital one. Default is null. ''; }; @@ -16,7 +24,7 @@ with lib; system.defaults.menuExtraClock.Show24Hour = mkOption { type = types.nullOr types.bool; default = null; - description = lib.mdDoc '' + description = '' Show a 24-hour clock, instead of a 12-hour clock. Default is null. ''; }; @@ -24,7 +32,7 @@ with lib; system.defaults.menuExtraClock.ShowAMPM = mkOption { type = types.nullOr types.bool; default = null; - description = lib.mdDoc '' + description = '' Show the AM/PM label. Useful if Show24Hour is false. Default is null. ''; }; @@ -32,7 +40,7 @@ with lib; system.defaults.menuExtraClock.ShowDayOfMonth = mkOption { type = types.nullOr types.bool; default = null; - description = lib.mdDoc '' + description = '' Show the day of the month. Default is null. ''; }; @@ -40,7 +48,7 @@ with lib; system.defaults.menuExtraClock.ShowDayOfWeek = mkOption { type = types.nullOr types.bool; default = null; - description = lib.mdDoc '' + description = '' Show the day of the week. Default is null. ''; }; @@ -48,21 +56,19 @@ with lib; system.defaults.menuExtraClock.ShowDate = mkOption { type = types.nullOr (types.enum [ 0 1 2 ]); default = null; - description = lib.mdDoc '' + description = '' Show the full date. Default is null. - 0 = Show the date - 1 = Don't show - 2 = Don't show - - TODO: I don't know what the difference is between 1 and 2. + 0 = When space allows + 1 = Always + 2 = Never ''; }; system.defaults.menuExtraClock.ShowSeconds = mkOption { type = types.nullOr types.bool; default = null; - description = lib.mdDoc '' + description = '' Show the clock with second precision, instead of minutes. Default is null. ''; }; diff --git a/modules/system/defaults/controlcenter.nix b/modules/system/defaults/controlcenter.nix new file mode 100644 index 0000000..91532fa --- /dev/null +++ b/modules/system/defaults/controlcenter.nix @@ -0,0 +1,100 @@ +{ config, lib, ... }: + +{ + options = { + + system.defaults.controlcenter.BatteryShowPercentage = lib.mkOption { + type = lib.types.nullOr lib.types.bool; + default = null; + description = '' + Apple menu > System Preferences > Control Center > Battery + + Show a battery percentage in menu bar. Default is null. + ''; + }; + + system.defaults.controlcenter.Sound = lib.mkOption { + type = lib.types.nullOr lib.types.bool; + apply = v: if v == null then null else if v == true then 18 else 24; + default = null; + description = '' + Apple menu > System Preferences > Control Center > Sound + + Show a sound control in menu bar . Default is null. + + 18 = Display icon in menu bar + 24 = Hide icon in menu bar + ''; + }; + + system.defaults.controlcenter.Bluetooth = lib.mkOption { + type = lib.types.nullOr lib.types.bool; + apply = v: if v == null then null else if v == true then 18 else 24; + default = null; + description = '' + Apple menu > System Preferences > Control Center > Bluetooth + + Show a bluetooth control in menu bar. Default is null. + + 18 = Display icon in menu bar + 24 = Hide icon in menu bar + ''; + }; + + system.defaults.controlcenter.AirDrop = lib.mkOption { + type = lib.types.nullOr lib.types.bool; + apply = v: if v == null then null else if v == true then 18 else 24; + default = null; + description = '' + Apple menu > System Preferences > Control Center > AirDrop + + Show a AirDrop control in menu bar. Default is null. + + 18 = Display icon in menu bar + 24 = Hide icon in menu bar + ''; + }; + + system.defaults.controlcenter.Display = lib.mkOption { + type = lib.types.nullOr lib.types.bool; + apply = v: if v == null then null else if v == true then 18 else 24; + default = null; + description = '' + Apple menu > System Preferences > Control Center > Display + + Show a Screen Brightness control in menu bar. Default is null. + + 18 = Display icon in menu bar + 24 = Hide icon in menu bar + ''; + }; + + system.defaults.controlcenter.FocusModes = lib.mkOption { + type = lib.types.nullOr lib.types.bool; + apply = v: if v == null then null else if v == true then 18 else 24; + default = null; + description = '' + Apple menu > System Preferences > Control Center > Focus + + Show a Focus control in menu bar. Default is null. + + 18 = Display icon in menu bar + 24 = Hide icon in menu bar + ''; + }; + + system.defaults.controlcenter.NowPlaying = lib.mkOption { + type = lib.types.nullOr lib.types.bool; + apply = v: if v == null then null else if v == true then 18 else 24; + default = null; + description = '' + Apple menu > System Preferences > Control Center > Now Playing + + Show a Now Playing control in menu bar. Default is null. + + 18 = Display icon in menu bar + 24 = Hide icon in menu bar + ''; + }; + }; +} diff --git a/modules/system/defaults/dock.nix b/modules/system/defaults/dock.nix index 9d54f75..bba0afb 100644 --- a/modules/system/defaults/dock.nix +++ b/modules/system/defaults/dock.nix @@ -6,12 +6,16 @@ let # Should only be used with options that previously used floats defined as strings. inherit (config.lib.defaults.types) floatWithDeprecationError; in { + imports = [ + (mkRenamedOptionModule [ "system" "defaults" "dock" "expose-group-by-app" ] [ "system" "defaults" "dock" "expose-group-apps" ]) + ]; + options = { system.defaults.dock.appswitcher-all-displays = mkOption { type = types.nullOr types.bool; default = null; - description = lib.mdDoc '' + description = '' Whether to display the appswitcher on all displays or only the main one. The default is false. ''; }; @@ -19,8 +23,8 @@ in { system.defaults.dock.autohide = mkOption { type = types.nullOr types.bool; default = null; - description = lib.mdDoc '' - Whether to automatically hide and show the dock. The default is false. + description = '' + Whether to automatically hide and show the dock. The default is false. ''; }; @@ -28,7 +32,7 @@ in { type = types.nullOr floatWithDeprecationError; default = null; example = 0.24; - description = lib.mdDoc '' + description = '' Sets the speed of the autohide delay. The default is given in the example. ''; }; @@ -37,7 +41,7 @@ in { type = types.nullOr floatWithDeprecationError; default = null; example = 1.0; - description = lib.mdDoc '' + description = '' Sets the speed of the animation when hiding/showing the Dock. The default is given in the example. ''; }; @@ -45,7 +49,7 @@ in { system.defaults.dock.dashboard-in-overlay = mkOption { type = types.nullOr types.bool; default = null; - description = lib.mdDoc '' + description = '' Whether to hide Dashboard as a Space. The default is false. ''; }; @@ -53,7 +57,7 @@ in { system.defaults.dock.enable-spring-load-actions-on-all-items = mkOption { type = types.nullOr types.bool; default = null; - description = lib.mdDoc '' + description = '' Enable spring loading for all Dock items. The default is false. ''; }; @@ -62,23 +66,23 @@ in { type = types.nullOr floatWithDeprecationError; default = null; example = 1.0; - description = lib.mdDoc '' + description = '' Sets the speed of the Mission Control animations. The default is given in the example. ''; }; - system.defaults.dock.expose-group-by-app = mkOption { + system.defaults.dock.expose-group-apps = mkOption { type = types.nullOr types.bool; default = null; - description = lib.mdDoc '' - Whether to group windows by application in Mission Control's Exposé. The default is true. + description = '' + Whether to group windows by application in Mission Control's Exposé. The default is false. ''; }; system.defaults.dock.launchanim = mkOption { type = types.nullOr types.bool; default = null; - description = lib.mdDoc '' + description = '' Animate opening applications from the Dock. The default is true. ''; }; @@ -86,7 +90,7 @@ in { system.defaults.dock.mineffect = mkOption { type = types.nullOr (types.enum [ "genie" "suck" "scale" ]); default = null; - description = lib.mdDoc '' + description = '' Set the minimize/maximize window effect. The default is genie. ''; }; @@ -94,7 +98,7 @@ in { system.defaults.dock.minimize-to-application = mkOption { type = types.nullOr types.bool; default = null; - description = lib.mdDoc '' + description = '' Whether to minimize windows into their application icon. The default is false. ''; }; @@ -102,7 +106,7 @@ in { system.defaults.dock.mouse-over-hilite-stack = mkOption { type = types.nullOr types.bool; default = null; - description = lib.mdDoc '' + description = '' Enable highlight hover effect for the grid view of a stack in the Dock. ''; }; @@ -110,7 +114,7 @@ in { system.defaults.dock.mru-spaces = mkOption { type = types.nullOr types.bool; default = null; - description = lib.mdDoc '' + description = '' Whether to automatically rearrange spaces based on most recent use. The default is true. ''; }; @@ -118,7 +122,7 @@ in { system.defaults.dock.orientation = mkOption { type = types.nullOr (types.enum [ "bottom" "left" "right" ]); default = null; - description = lib.mdDoc '' + description = '' Position of the dock on screen. The default is "bottom". ''; }; @@ -127,7 +131,7 @@ in { type = types.nullOr (types.listOf (types.either types.path types.str)); default = null; example = [ "/Applications/Safari.app" "/System/Applications/Utilities/Terminal.app" ]; - description = lib.mdDoc '' + description = '' Persistent applications in the dock. ''; apply = value: @@ -136,10 +140,31 @@ in { else map (app: { tile-data = { file-data = { _CFURLString = app; _CFURLStringType = 0; }; }; }) value; }; + system.defaults.dock.persistent-others = mkOption { + type = types.nullOr (types.listOf (types.either types.path types.str)); + default = null; + example = [ "~/Documents" "~/Downloads" ]; + description = '' + Persistent folders in the dock. + ''; + apply = value: + if !(isList value) + then value + else map (folder: { tile-data = { file-data = { _CFURLString = "file://" + folder; _CFURLStringType = 15; }; }; tile-type = if strings.hasInfix "." (last (splitString "/" folder)) then "file-tile" else "directory-tile"; }) value; + }; + + system.defaults.dock.scroll-to-open = mkOption { + type = types.nullOr types.bool; + default = null; + description = '' + Scroll up on a Dock icon to show all Space's opened windows for an app, or open stack. The default is false. + ''; + }; + system.defaults.dock.show-process-indicators = mkOption { type = types.nullOr types.bool; default = null; - description = lib.mdDoc '' + description = '' Show indicator lights for open applications in the Dock. The default is true. ''; }; @@ -147,7 +172,7 @@ in { system.defaults.dock.showhidden = mkOption { type = types.nullOr types.bool; default = null; - description = lib.mdDoc '' + description = '' Whether to make icons of hidden applications tranclucent. The default is false. ''; }; @@ -155,15 +180,23 @@ in { system.defaults.dock.show-recents = mkOption { type = types.nullOr types.bool; default = null; - description = lib.mdDoc '' + description = '' Show recent applications in the dock. The default is true. ''; }; + system.defaults.dock.slow-motion-allowed = mkOption { + type = types.nullOr types.bool; + default = null; + description = '' + Allow for slow-motion minimize effect while holding Shift key. The default is false. + ''; + }; + system.defaults.dock.static-only = mkOption { type = types.nullOr types.bool; default = null; - description = lib.mdDoc '' + description = '' Show only open applications in the Dock. The default is false. ''; }; @@ -171,7 +204,7 @@ in { system.defaults.dock.tilesize = mkOption { type = types.nullOr types.int; default = null; - description = lib.mdDoc '' + description = '' Size of the icons in the dock. The default is 64. ''; }; @@ -179,7 +212,7 @@ in { system.defaults.dock.magnification = mkOption { type = types.nullOr types.bool; default = null; - description = lib.mdDoc '' + description = '' Magnify icon on hover. The default is false. ''; }; @@ -187,16 +220,15 @@ in { system.defaults.dock.largesize = mkOption { type = types.nullOr (types.ints.between 16 128); default = null; - description = lib.mdDoc '' + description = '' Magnified icon size on hover. The default is 16. ''; }; - system.defaults.dock.wvous-tl-corner = mkOption { type = types.nullOr types.ints.positive; default = null; - description = lib.mdDoc '' + description = '' Hot corner action for top left corner. Valid values include: * `1`: Disabled @@ -217,7 +249,7 @@ in { system.defaults.dock.wvous-bl-corner = mkOption { type = types.nullOr types.ints.positive; default = null; - description = lib.mdDoc '' + description = '' Hot corner action for bottom left corner. Valid values include: * `1`: Disabled @@ -238,7 +270,7 @@ in { system.defaults.dock.wvous-tr-corner = mkOption { type = types.nullOr types.ints.positive; default = null; - description = lib.mdDoc '' + description = '' Hot corner action for top right corner. Valid values include: * `1`: Disabled @@ -259,7 +291,7 @@ in { system.defaults.dock.wvous-br-corner = mkOption { type = types.nullOr types.ints.positive; default = null; - description = lib.mdDoc '' + description = '' Hot corner action for bottom right corner. Valid values include: * `1`: Disabled diff --git a/modules/system/defaults/finder.nix b/modules/system/defaults/finder.nix index 1137e6c..5004b2c 100644 --- a/modules/system/defaults/finder.nix +++ b/modules/system/defaults/finder.nix @@ -1,14 +1,17 @@ { config, lib, ... }: -with lib; +let + inherit (lib) mkOption types; + cfg = config.system.defaults.finder; +in { options = { system.defaults.finder.AppleShowAllFiles = mkOption { type = types.nullOr types.bool; default = null; - description = lib.mdDoc '' + description = '' Whether to always show hidden files. The default is false. ''; }; @@ -16,7 +19,7 @@ with lib; system.defaults.finder.ShowStatusBar = mkOption { type = types.nullOr types.bool; default = null; - description = lib.mdDoc '' + description = '' Show status bar at bottom of finder windows with item/disk space stats. The default is false. ''; }; @@ -24,7 +27,7 @@ with lib; system.defaults.finder.ShowPathbar = mkOption { type = types.nullOr types.bool; default = null; - description = lib.mdDoc '' + description = '' Show path breadcrumbs in finder windows. The default is false. ''; }; @@ -32,16 +35,25 @@ with lib; system.defaults.finder.FXDefaultSearchScope = mkOption { type = types.nullOr types.str; default = null; - description = lib.mdDoc '' + description = '' Change the default search scope. Use "SCcf" to default to current folder. The default is unset ("This Mac"). ''; }; + system.defaults.finder.FXRemoveOldTrashItems = mkOption { + type = types.nullOr types.bool; + default = null; + description = '' + Remove items in the trash after 30 days. + The default is false. + ''; + }; + system.defaults.finder.FXPreferredViewStyle = mkOption { type = types.nullOr types.str; default = null; - description = lib.mdDoc '' + description = '' Change the default finder view. "icnv" = Icon view, "Nlsv" = List view, "clmv" = Column View, "Flwv" = Gallery View The default is icnv. @@ -51,15 +63,15 @@ with lib; system.defaults.finder.AppleShowAllExtensions = mkOption { type = types.nullOr types.bool; default = null; - description = lib.mdDoc '' - Whether to always show file extensions. The default is false. + description = '' + Whether to always show file extensions. The default is false. ''; }; system.defaults.finder.CreateDesktop = mkOption { type = types.nullOr types.bool; default = null; - description = lib.mdDoc '' + description = '' Whether to show icons on the desktop or not. The default is true. ''; }; @@ -67,26 +79,123 @@ with lib; system.defaults.finder.QuitMenuItem = mkOption { type = types.nullOr types.bool; default = null; - description = lib.mdDoc '' - Whether to allow quitting of the Finder. The default is false. + description = '' + Whether to allow quitting of the Finder. The default is false. + ''; + }; + + system.defaults.finder.ShowExternalHardDrivesOnDesktop = mkOption { + type = types.nullOr types.bool; + default = null; + description = '' + Whether to show external disks on desktop. The default is true. + ''; + }; + + system.defaults.finder.ShowHardDrivesOnDesktop = mkOption { + type = types.nullOr types.bool; + default = null; + description = '' + Whether to show hard disks on desktop. The default is false. + ''; + }; + + system.defaults.finder.ShowMountedServersOnDesktop = mkOption { + type = types.nullOr types.bool; + default = null; + description = '' + Whether to show connected servers on desktop. The default is false. + ''; + }; + + system.defaults.finder.ShowRemovableMediaOnDesktop = mkOption { + type = types.nullOr types.bool; + default = null; + description = '' + Whether to show removable media (CDs, DVDs and iPods) on desktop. The default is true. ''; }; system.defaults.finder._FXShowPosixPathInTitle = mkOption { type = types.nullOr types.bool; default = null; - description = lib.mdDoc '' - Whether to show the full POSIX filepath in the window title. The default is false. + description = '' + Whether to show the full POSIX filepath in the window title. The default is false. + ''; + }; + + system.defaults.finder._FXSortFoldersFirst = mkOption { + type = types.nullOr types.bool; + default = null; + description = '' + Keep folders on top when sorting by name. The default is false. + ''; + }; + + system.defaults.finder._FXSortFoldersFirstOnDesktop = mkOption { + type = types.nullOr types.bool; + default = null; + description = '' + Keep folders on top when sorting by name on the desktop. The default is false. ''; }; system.defaults.finder.FXEnableExtensionChangeWarning = mkOption { type = types.nullOr types.bool; default = null; - description = lib.mdDoc '' - Whether to show warnings when change the file extension of files. The default is true. + description = '' + Whether to show warnings when change the file extension of files. The default is true. + ''; + }; + + system.defaults.finder.NewWindowTarget = mkOption { + type = types.nullOr (types.enum [ + "Computer" + "OS volume" + "Home" + "Desktop" + "Documents" + "Recents" + "iCloud Drive" + "Other" + ]); + apply = key: if key == null then null else { + "Computer" = "PfCm"; + "OS volume" = "PfVo"; + "Home" = "PfHm"; + "Desktop" = "PfDe"; + "Documents" = "PfDo"; + "Recents" = "PfAF"; + "iCloud Drive" = "PfID"; + "Other" = "PfLo"; + }.${key}; + default = null; + description = '' + Change the default folder shown in Finder windows. "Other" corresponds to the value of + NewWindowTargetPath. The default is unset ("Recents"). ''; }; + system.defaults.finder.NewWindowTargetPath = mkOption { + type = types.nullOr types.str; + default = null; + description = '' + Sets the URI to open when NewWindowTarget is "Other". Spaces and similar characters must be + escaped. If the value is invalid, Finder will open your home directory. + Example: "file:///Users/foo/long%20cat%20pics". + The default is unset. + ''; + }; + }; + + config = { + assertions = [{ + assertion = cfg.NewWindowTargetPath != null -> cfg.NewWindowTarget == "PfLo"; + message = "`system.defaults.finder.NewWindowTarget` should be set to `Other` when `NewWindowTargetPath` is non-null."; + } + { + assertion = cfg.NewWindowTarget == "PfLo" -> cfg.NewWindowTargetPath != null; + message = "`system.defaults.finder.NewWindowTargetPath` should be non-null when `NewWindowTarget` is set to `Other`."; + }]; }; } diff --git a/modules/system/defaults/hitoolbox.nix b/modules/system/defaults/hitoolbox.nix new file mode 100644 index 0000000..c2e336b --- /dev/null +++ b/modules/system/defaults/hitoolbox.nix @@ -0,0 +1,29 @@ +{ lib, ... }: + +{ + options = { + + system.defaults.hitoolbox.AppleFnUsageType = lib.mkOption { + type = lib.types.nullOr (lib.types.enum [ + "Do Nothing" + "Change Input Source" + "Show Emoji & Symbols" + "Start Dictation" + ]); + apply = key: if key == null then null else { + "Do Nothing" = 0; + "Change Input Source" = 1; + "Show Emoji & Symbols" = 2; + "Start Dictation" = 3; + }.${key}; + default = null; + description = '' + Chooses what happens when you press the Fn key on the keyboard. A restart is required for + this setting to take effect. + + The default is unset ("Show Emoji & Symbols"). + ''; + }; + + }; +} diff --git a/modules/system/defaults/loginwindow.nix b/modules/system/defaults/loginwindow.nix index 81f7dfa..a8a06eb 100644 --- a/modules/system/defaults/loginwindow.nix +++ b/modules/system/defaults/loginwindow.nix @@ -7,7 +7,7 @@ with lib; system.defaults.loginwindow.SHOWFULLNAME = mkOption { type = types.nullOr types.bool; default = null; - description = lib.mdDoc '' + description = '' Apple menu > System Preferences > Users and Groups > Login Options Displays login window as a name and password field instead of a list of users. @@ -18,7 +18,7 @@ with lib; system.defaults.loginwindow.autoLoginUser = mkOption { type = types.nullOr types.str; default = null; - description = lib.mdDoc '' + description = '' Apple menu > System Preferences > Users and Groups > Login Options Auto login the supplied user on boot. Default is Off. @@ -28,7 +28,7 @@ with lib; system.defaults.loginwindow.GuestEnabled = mkOption { type = types.nullOr types.bool; default = null; - description = lib.mdDoc '' + description = '' Apple menu > System Preferences > Users and Groups > Login Options Allow users to login to the machine as guests using the Guest account. Default is true. @@ -38,7 +38,7 @@ with lib; system.defaults.loginwindow.LoginwindowText = mkOption { type = types.nullOr types.str; default = null; - description = lib.mdDoc '' + description = '' Text to be shown on the login window. Default is "\\\\U03bb". ''; }; @@ -46,7 +46,7 @@ with lib; system.defaults.loginwindow.ShutDownDisabled = mkOption { type = types.nullOr types.bool; default = null; - description = lib.mdDoc '' + description = '' Apple menu > System Preferences > Users and Groups > Login Options Hides the Shut Down button on the login screen. Default is false. @@ -56,7 +56,7 @@ with lib; system.defaults.loginwindow.SleepDisabled = mkOption { type = types.nullOr types.bool; default = null; - description = lib.mdDoc '' + description = '' Apple menu > System Preferences > Users and Groups > Login Options Hides the Sleep button on the login screen. Default is false. @@ -66,7 +66,7 @@ with lib; system.defaults.loginwindow.RestartDisabled = mkOption { type = types.nullOr types.bool; default = null; - description = lib.mdDoc '' + description = '' Apple menu > System Preferences > Users and Groups > Login Options Hides the Restart button on the login screen. Default is false. @@ -76,7 +76,7 @@ with lib; system.defaults.loginwindow.ShutDownDisabledWhileLoggedIn = mkOption { type = types.nullOr types.bool; default = null; - description = lib.mdDoc '' + description = '' Apple menu > System Preferences > Users and Groups > Login Options Disables the "Shutdown" option when users are logged in. Default is false. @@ -86,7 +86,7 @@ with lib; system.defaults.loginwindow.PowerOffDisabledWhileLoggedIn = mkOption { type = types.nullOr types.bool; default = null; - description = lib.mdDoc '' + description = '' Apple menu > System Preferences > Users and Groups > Login Options If set to true, the Power Off menu item will be disabled when the user is logged in. Default is false. @@ -96,7 +96,7 @@ with lib; system.defaults.loginwindow.RestartDisabledWhileLoggedIn = mkOption { type = types.nullOr types.bool; default = null; - description = lib.mdDoc '' + description = '' Apple menu > System Preferences > Users and Groups > Login Options Disables the “Restart” option when users are logged in. Default is false. @@ -106,7 +106,7 @@ with lib; system.defaults.loginwindow.DisableConsoleAccess = mkOption { type = types.nullOr types.bool; default = null; - description = lib.mdDoc '' + description = '' Disables the ability for a user to access the console by typing “>console” for a username at the login window. Default is false. ''; diff --git a/modules/system/defaults/magicmouse.nix b/modules/system/defaults/magicmouse.nix index 56d7f71..9344ffe 100644 --- a/modules/system/defaults/magicmouse.nix +++ b/modules/system/defaults/magicmouse.nix @@ -11,7 +11,7 @@ with lib; "TwoButton" ]); default = null; - description = lib.mdDoc '' + description = '' "OneButton": any tap is a left click. "TwoButton": allow left- and right-clicking. ''; diff --git a/modules/system/defaults/screencapture.nix b/modules/system/defaults/screencapture.nix index 4483fd6..351ca5f 100644 --- a/modules/system/defaults/screencapture.nix +++ b/modules/system/defaults/screencapture.nix @@ -1,4 +1,4 @@ -{ config, lib, ... }: +{ lib, ... }: with lib; @@ -8,7 +8,7 @@ with lib; system.defaults.screencapture.location = mkOption { type = types.nullOr types.str; default = null; - description = lib.mdDoc '' + description = '' The filesystem path to which screencaptures should be written. ''; }; @@ -16,7 +16,7 @@ with lib; system.defaults.screencapture.type = mkOption { type = types.nullOr types.str; default = null; - description = lib.mdDoc '' + description = '' The image format to use, such as "jpg". ''; }; @@ -24,9 +24,44 @@ with lib; system.defaults.screencapture.disable-shadow = mkOption { type = types.nullOr types.bool; default = null; - description = lib.mdDoc '' + description = '' Disable drop shadow border around screencaptures. The default is false. ''; }; + + system.defaults.screencapture.include-date = mkOption { + type = types.nullOr types.bool; + default = null; + description = '' + Include date and time in screenshot filenames. The default is true. + Screenshot 2024-01-09 at 13.27.20.png would be an example for true. + + Screenshot.png + Screenshot 1.png would be an example for false. + ''; + }; + + system.defaults.screencapture.show-thumbnail = mkOption { + type = types.nullOr types.bool; + default = null; + description = '' + Show thumbnail after screencapture before writing to file. The default is true. + ''; + }; + + system.defaults.screencapture.target = mkOption { + type = types.nullOr (types.enum [ "file" "clipboard" "preview" "mail" "messages" ]); + default = null; + description = '' + Target to which screencapture should save screenshot to. The default is "file". + Valid values include: + + * `file`: Saves as a file in location specified by `system.defaults.screencapture.location` + * `clipboard`: Saves screenshot to clipboard + * `preview`: Opens screenshot in Preview app + * `mail` + * `messages` + ''; + }; }; } diff --git a/modules/system/defaults/screensaver.nix b/modules/system/defaults/screensaver.nix index 68bd1e0..3e5032b 100644 --- a/modules/system/defaults/screensaver.nix +++ b/modules/system/defaults/screensaver.nix @@ -8,7 +8,7 @@ with lib; system.defaults.screensaver.askForPassword = mkOption { type = types.nullOr types.bool; default = null; - description = lib.mdDoc '' + description = '' If true, the user is prompted for a password when the screen saver is unlocked or stopped. The default is false. ''; }; @@ -16,7 +16,7 @@ with lib; system.defaults.screensaver.askForPasswordDelay = mkOption { type = types.nullOr types.int; default = null; - description = lib.mdDoc '' + description = '' The number of seconds to delay before the password will be required to unlock or stop the screen saver (the grace period). ''; }; diff --git a/modules/system/defaults/smb.nix b/modules/system/defaults/smb.nix index b694059..0bc8be5 100644 --- a/modules/system/defaults/smb.nix +++ b/modules/system/defaults/smb.nix @@ -7,13 +7,13 @@ with lib; system.defaults.smb.NetBIOSName = mkOption { type = types.nullOr types.str; default = null; - description = lib.mdDoc "Hostname to use for NetBIOS."; + description = "Hostname to use for NetBIOS."; }; system.defaults.smb.ServerDescription = mkOption { type = types.nullOr types.str; default = null; - description = lib.mdDoc "Hostname to use for sharing services."; + description = "Hostname to use for sharing services."; }; }; } diff --git a/modules/system/defaults/spaces.nix b/modules/system/defaults/spaces.nix index 4b535d1..ac2355b 100644 --- a/modules/system/defaults/spaces.nix +++ b/modules/system/defaults/spaces.nix @@ -7,7 +7,7 @@ with lib; system.defaults.spaces.spans-displays = mkOption { type = types.nullOr types.bool; default = null; - description = lib.mdDoc '' + description = '' Apple menu > System Preferences > Mission Control Displays have separate Spaces (note a logout is required before diff --git a/modules/system/defaults/trackpad.nix b/modules/system/defaults/trackpad.nix index ff5e2bb..354cfc6 100644 --- a/modules/system/defaults/trackpad.nix +++ b/modules/system/defaults/trackpad.nix @@ -8,7 +8,7 @@ with lib; system.defaults.trackpad.Clicking = mkOption { type = types.nullOr types.bool; default = null; - description = lib.mdDoc '' + description = '' Whether to enable trackpad tap to click. The default is false. ''; }; @@ -16,7 +16,7 @@ with lib; system.defaults.trackpad.Dragging = mkOption { type = types.nullOr types.bool; default = null; - description = lib.mdDoc '' + description = '' Whether to enable tap-to-drag. The default is false. ''; }; @@ -24,7 +24,7 @@ with lib; system.defaults.trackpad.TrackpadRightClick = mkOption { type = types.nullOr types.bool; default = null; - description = lib.mdDoc '' + description = '' Whether to enable trackpad right click. The default is false. ''; }; @@ -32,7 +32,7 @@ with lib; system.defaults.trackpad.TrackpadThreeFingerDrag = mkOption { type = types.nullOr types.bool; default = null; - description = lib.mdDoc '' + description = '' Whether to enable three finger drag. The default is false. ''; }; @@ -40,7 +40,7 @@ with lib; system.defaults.trackpad.ActuationStrength = mkOption { type = types.nullOr (types.enum [ 0 1 ]); default = null; - description = lib.mdDoc '' + description = '' 0 to enable Silent Clicking, 1 to disable. The default is 1. ''; }; @@ -48,7 +48,7 @@ with lib; system.defaults.trackpad.FirstClickThreshold = mkOption { type = types.nullOr (types.enum [ 0 1 2 ]); default = null; - description = lib.mdDoc '' + description = '' For normal click: 0 for light clicking, 1 for medium, 2 for firm. The default is 1. ''; @@ -57,11 +57,20 @@ with lib; system.defaults.trackpad.SecondClickThreshold = mkOption { type = types.nullOr (types.enum [ 0 1 2 ]); default = null; - description = lib.mdDoc '' + description = '' For force touch: 0 for light clicking, 1 for medium, 2 for firm. The default is 1. ''; }; + system.defaults.trackpad.TrackpadThreeFingerTapGesture = mkOption { + type = types.nullOr (types.enum [ 0 2 ]); + default = null; + description = '' + 0 to disable three finger tap, 2 to trigger Look up & data detectors. + The default is 2. + ''; + }; + }; } diff --git a/modules/system/defaults/universalaccess.nix b/modules/system/defaults/universalaccess.nix index 8d012e6..8a2de90 100644 --- a/modules/system/defaults/universalaccess.nix +++ b/modules/system/defaults/universalaccess.nix @@ -9,7 +9,7 @@ with lib; type = types.nullOr types.float; default = null; example = 1.5; - description = lib.mdDoc '' + description = '' Set the size of cursor. 1 for normal, 4 for maximum. The default is 1. ''; @@ -18,7 +18,7 @@ with lib; system.defaults.universalaccess.reduceMotion = mkOption { type = types.nullOr types.bool; default = null; - description = lib.mdDoc '' + description = '' Disable animation when switching screens or opening apps ''; }; @@ -26,7 +26,7 @@ with lib; system.defaults.universalaccess.reduceTransparency = mkOption { type = types.nullOr types.bool; default = null; - description = lib.mdDoc '' + description = '' Disable transparency in the menu bar and elsewhere. Requires macOS Yosemite or later. The default is false. @@ -36,7 +36,7 @@ with lib; system.defaults.universalaccess.closeViewScrollWheelToggle = mkOption { type = types.nullOr types.bool; default = null; - description = lib.mdDoc '' + description = '' Use scroll gesture with the Ctrl (^) modifier key to zoom. The default is false. ''; @@ -45,7 +45,7 @@ with lib; system.defaults.universalaccess.closeViewZoomFollowsFocus = mkOption { type = types.nullOr types.bool; default = null; - description = lib.mdDoc '' + description = '' Follow the keyboard focus while zoomed in. Without setting `closeViewScrollWheelToggle` this has no effect. The default is false. diff --git a/modules/system/etc.nix b/modules/system/etc.nix index 1c41526..bc60bef 100644 --- a/modules/system/etc.nix +++ b/modules/system/etc.nix @@ -10,7 +10,6 @@ let }; etc = filter (f: f.enable) (attrValues config.environment.etc); - etcCopy = filter (f: f.copy) (attrValues config.environment.etc); in @@ -20,7 +19,7 @@ in environment.etc = mkOption { type = types.attrsOf (types.submodule text); default = { }; - description = lib.mdDoc '' + description = '' Set of files that have to be linked in {file}`/etc`. ''; }; @@ -34,9 +33,10 @@ in '' mkdir -p $out/etc cd $out/etc - ${concatMapStringsSep "\n" (attr: "mkdir -p $(dirname '${attr.target}')") etc} - ${concatMapStringsSep "\n" (attr: "ln -s '${attr.source}' '${attr.target}'") etc} - ${concatMapStringsSep "\n" (attr: "touch '${attr.target}'.copy") etcCopy} + ${concatMapStringsSep "\n" (attr: '' + mkdir -p "$(dirname ${escapeShellArg attr.target})" + ln -s ${escapeShellArgs [ attr.source attr.target ]} + '') etc} ''; system.activationScripts.etcChecks.text = '' @@ -55,10 +55,6 @@ in etcStaticFile=/etc/static/$subPath etcFile=/etc/$subPath - if [[ -e $configFile.copy ]]; then - continue - fi - # We need to check files that exist and aren't already links to # $etcStaticFile for known hashes. if [[ @@ -109,11 +105,6 @@ in mkdir -p "$etcDir" fi - if [[ -e $etcStaticFile.copy ]]; then - cp "$etcStaticFile" "$etcFile" - continue - fi - if [[ -e $etcFile ]]; then if [[ $(readlink -- "$etcFile") == "$etcStaticFile" ]]; then continue @@ -130,7 +121,7 @@ in # Delete stale links into /etc/static. if [[ - $(readlink "$etcFile") == "$etcStaticFile" + $(readlink -- "$etcFile") == "$etcStaticFile" && ! -e $etcStaticFile ]]; then rm "$etcFile" diff --git a/modules/system/keyboard.nix b/modules/system/keyboard.nix index 6e4275e..f4f6406 100644 --- a/modules/system/keyboard.nix +++ b/modules/system/keyboard.nix @@ -11,38 +11,44 @@ in system.keyboard.enableKeyMapping = mkOption { type = types.bool; default = false; - description = lib.mdDoc "Whether to enable keyboard mappings."; + description = "Whether to enable keyboard mappings."; }; system.keyboard.remapCapsLockToControl = mkOption { type = types.bool; default = false; - description = lib.mdDoc "Whether to remap the Caps Lock key to Control."; + description = "Whether to remap the Caps Lock key to Control."; }; system.keyboard.remapCapsLockToEscape = mkOption { type = types.bool; default = false; - description = lib.mdDoc "Whether to remap the Caps Lock key to Escape."; + description = "Whether to remap the Caps Lock key to Escape."; }; system.keyboard.nonUS.remapTilde = mkOption { type = types.bool; default = false; - description = lib.mdDoc "Whether to remap the Tilde key on non-us keyboards."; + description = "Whether to remap the Tilde key on non-us keyboards."; }; system.keyboard.swapLeftCommandAndLeftAlt = mkOption { type = types.bool; default = false; - description = lib.mdDoc "Whether to swap the left Command key and left Alt key."; + description = "Whether to swap the left Command key and left Alt key."; + }; + + system.keyboard.swapLeftCtrlAndFn = mkOption { + type = types.bool; + default = false; + description = "Whether to swap the left Control key and Fn (Globe) key."; }; system.keyboard.userKeyMapping = mkOption { internal = true; type = types.listOf (types.attrsOf types.int); default = []; - description = lib.mdDoc '' + description = '' List of keyboard mappings to apply, for more information see <https://developer.apple.com/library/content/technotes/tn2450/_index.html>. ''; @@ -66,6 +72,14 @@ in HIDKeyboardModifierMappingSrc = 30064771298; HIDKeyboardModifierMappingDst = 30064771299; }) + (mkIf cfg.swapLeftCtrlAndFn { + HIDKeyboardModifierMappingSrc = 30064771296; + HIDKeyboardModifierMappingDst = 1095216660483; + }) + (mkIf cfg.swapLeftCtrlAndFn { + HIDKeyboardModifierMappingSrc = 1095216660483; + HIDKeyboardModifierMappingDst = 30064771296; + }) ]; system.activationScripts.keyboard.text = optionalString cfg.enableKeyMapping '' diff --git a/modules/system/launchd.nix b/modules/system/launchd.nix index 7f6b485..c578dec 100644 --- a/modules/system/launchd.nix +++ b/modules/system/launchd.nix @@ -59,7 +59,7 @@ in environment.launchAgents = mkOption { type = types.attrsOf (types.submodule text); default = { }; - description = lib.mdDoc '' + description = '' Set of files that have to be linked in {file}`/Library/LaunchAgents`. ''; }; @@ -67,7 +67,7 @@ in environment.launchDaemons = mkOption { type = types.attrsOf (types.submodule text); default = { }; - description = lib.mdDoc '' + description = '' Set of files that have to be linked in {file}`/Library/LaunchDaemons`. ''; }; @@ -75,7 +75,7 @@ in environment.userLaunchAgents = mkOption { type = types.attrsOf (types.submodule text); default = { }; - description = lib.mdDoc '' + description = '' Set of files that have to be linked in {file}`~/Library/LaunchAgents`. ''; }; @@ -105,19 +105,29 @@ in ${concatMapStringsSep "\n" (attr: launchdActivation "LaunchAgents" attr.target) launchAgents} ${concatMapStringsSep "\n" (attr: launchdActivation "LaunchDaemons" attr.target) launchDaemons} - for f in $(ls /run/current-system/Library/LaunchAgents 2> /dev/null); do - if test ! -e "${cfg.build.launchd}/Library/LaunchAgents/$f"; then - echo "removing service $(basename $f .plist)" >&2 + for f in /run/current-system/Library/LaunchAgents/*; do + [[ -e "$f" ]] || break # handle when directory is empty + f=''${f#/run/current-system/Library/LaunchAgents/} + + if [[ ! -e "${cfg.build.launchd}/Library/LaunchAgents/$f" ]]; then + echo "removing service $(basename "$f" .plist)" >&2 launchctl unload "/Library/LaunchAgents/$f" || true - if test -e "/Library/LaunchAgents/$f"; then rm -f "/Library/LaunchAgents/$f"; fi + if [[ -e "/Library/LaunchAgents/$f" ]]; then + rm -f "/Library/LaunchAgents/$f" + fi fi done - for f in $(ls /run/current-system/Library/LaunchDaemons 2> /dev/null); do - if test ! -e "${cfg.build.launchd}/Library/LaunchDaemons/$f"; then - echo "removing service $(basename $f .plist)" >&2 + for f in /run/current-system/Library/LaunchDaemons/*; do + [[ -e "$f" ]] || break # handle when directory is empty + f=''${f#/run/current-system/Library/LaunchDaemons/} + + if [[ ! -e "${cfg.build.launchd}/Library/LaunchDaemons/$f" ]]; then + echo "removing service $(basename "$f" .plist)" >&2 launchctl unload "/Library/LaunchDaemons/$f" || true - if test -e "/Library/LaunchDaemons/$f"; then rm -f "/Library/LaunchDaemons/$f"; fi + if [[ -e "/Library/LaunchDaemons/$f" ]]; then + rm -f "/Library/LaunchDaemons/$f" + fi fi done ''; @@ -133,11 +143,16 @@ in ''} ${concatMapStringsSep "\n" (attr: userLaunchdActivation attr.target) userLaunchAgents} - for f in $(ls /run/current-system/user/Library/LaunchAgents 2> /dev/null); do - if test ! -e "${cfg.build.launchd}/user/Library/LaunchAgents/$f"; then - echo "removing user service $(basename $f .plist)" >&2 - launchctl unload ~/Library/LaunchAgents/$f || true - if test -e ~/Library/LaunchAgents/$f; then rm -f ~/Library/LaunchAgents/$f; fi + for f in /run/current-system/user/Library/LaunchAgents/*; do + [[ -e "$f" ]] || break # handle when directory is empty + f=''${f#/run/current-system/user/Library/LaunchAgents/} + + if [[ ! -e "${cfg.build.launchd}/user/Library/LaunchAgents/$f" ]]; then + echo "removing user service $(basename "$f" .plist)" >&2 + launchctl unload ~/Library/LaunchAgents/"$f" || true + if [[ -e ~/Library/LaunchAgents/"$f" ]]; then + rm -f ~/Library/LaunchAgents/"$f" + fi fi done ''; diff --git a/modules/system/nvram.nix b/modules/system/nvram.nix index efc9c99..48e75fb 100644 --- a/modules/system/nvram.nix +++ b/modules/system/nvram.nix @@ -22,7 +22,7 @@ in example = { "StartupMute" = "%01"; }; - description = lib.mdDoc '' + description = '' Non-volatile RAM variables to set. Removing a key-value pair from this list will **not** return the variable to its previous value, but will no longer set its value on system configuration activations. diff --git a/modules/system/patches.nix b/modules/system/patches.nix index 9ac15ec..7b19255 100644 --- a/modules/system/patches.nix +++ b/modules/system/patches.nix @@ -26,13 +26,13 @@ in '''') ] ''; - description = lib.mdDoc '' + description = '' Set of patches to apply to {file}`/`. ::: {.warning} - + This can modify everything so use with caution. - + ::: Useful for safely changing system files. Unlike the etc module this @@ -56,10 +56,13 @@ in # Applying patches to /. echo "applying patches..." >&2 - for f in $(ls /run/current-system/patches 2> /dev/null); do - if test ! -e "${config.system.build.patches}/patches/$f"; then - patch --force --reverse --backup -d / -p1 < "/run/current-system/patches/$f" || true - fi + for f in /run/current-system/patches/*; do + [[ -e "$f" ]] || break # handle when directory is empty + f=''${f#/run/current-system/patches/} + + if [[ ! -e "${config.system.build.patches}/patches/$f" ]]; then + patch --force --reverse --backup -d / -p1 < "/run/current-system/patches/$f" || true + fi done ${concatMapStringsSep "\n" (f: '' diff --git a/modules/system/shells.nix b/modules/system/shells.nix index 9399327..025936d 100644 --- a/modules/system/shells.nix +++ b/modules/system/shells.nix @@ -12,11 +12,17 @@ in type = types.listOf (types.either types.shellPackage types.path); default = []; example = literalExpression "[ pkgs.bashInteractive pkgs.zsh ]"; - description = lib.mdDoc '' + description = '' A list of permissible login shells for user accounts. - No need to mention `/bin/sh` - and other shells that are available by default on - macOS. + + The default macOS shells will be automatically included: + - /bin/bash + - /bin/csh + - /bin/dash + - /bin/ksh + - /bin/sh + - /bin/tcsh + - /bin/zsh ''; apply = map (v: if types.shellPackage.check v then "/run/current-system/sw${v.shellPath}" else v); }; diff --git a/modules/system/startup.nix b/modules/system/startup.nix index ecbef46..ae7f2ef 100644 --- a/modules/system/startup.nix +++ b/modules/system/startup.nix @@ -14,7 +14,7 @@ in type = with lib.types; nullOr bool; default = null; example = false; - description = lib.mdDoc '' + description = '' Whether to enable the startup chime. By default, this option does not affect your system configuration in any way. diff --git a/modules/system/version.nix b/modules/system/version.nix index 3effb50..54829d1 100644 --- a/modules/system/version.nix +++ b/modules/system/version.nix @@ -5,8 +5,6 @@ with lib; let cfg = config.system; - defaultStateVersion = options.system.stateVersion.default; - # Based on `lib.trivial.revisionWithDefault` from nixpkgs. gitRevision = path: if pathIsGitRepo "${path}/.git" @@ -34,9 +32,10 @@ in { options = { system.stateVersion = mkOption { - type = types.int; - default = 4; - description = lib.mdDoc '' + type = types.ints.between 1 config.system.maxStateVersion; + # TODO: Remove this default and the assertion below. + default = config.system.maxStateVersion; + description = '' Every once in a while, a new NixOS release may change configuration defaults in a way incompatible with stateful data. For instance, if the default version of PostgreSQL @@ -49,16 +48,29 @@ in ''; }; + system.maxStateVersion = mkOption { + internal = true; + type = types.int; + default = 5; + }; + system.darwinLabel = mkOption { type = types.str; - description = lib.mdDoc "Label to be used in the names of generated outputs."; + description = "Label to be used in the names of generated outputs."; + }; + + system.darwinRelease = mkOption { + readOnly = true; + type = types.str; + default = (lib.importJSON ../../version.json).release; + description = "The nix-darwin release (e.g. `24.11`)."; }; system.darwinVersion = mkOption { internal = true; type = types.str; - default = "darwin${toString cfg.stateVersion}${cfg.darwinVersionSuffix}"; - description = lib.mdDoc "The full darwin version (e.g. `darwin4.2abdb5a`)."; + default = cfg.darwinRelease + cfg.darwinVersionSuffix; + description = "The full nix-darwin version (e.g. `24.11.2abdb5a`)."; }; system.darwinVersionSuffix = mkOption { @@ -67,28 +79,29 @@ in default = if cfg.darwinRevision != null then ".${substring 0 7 cfg.darwinRevision}" else ""; - description = lib.mdDoc "The short darwin version suffix (e.g. `.2abdb5a`)."; + description = "The short nix-darwin version suffix (e.g. `.2abdb5a`)."; }; system.darwinRevision = mkOption { internal = true; type = types.nullOr types.str; default = gitRevision (toString ../..); - description = lib.mdDoc "The darwin git revision from which this configuration was built."; + description = "The darwin git revision from which this configuration was built."; }; system.nixpkgsRelease = mkOption { readOnly = true; type = types.str; default = lib.trivial.release; - description = lib.mdDoc "The nixpkgs release (e.g. `16.03`)."; + description = "The nixpkgs release (e.g. `24.11`)."; }; + # TODO: Shouldn’t mismatch the Darwin release, rethink all this… system.nixpkgsVersion = mkOption { internal = true; type = types.str; default = cfg.nixpkgsRelease + cfg.nixpkgsVersionSuffix; - description = lib.mdDoc "The full nixpkgs version (e.g. `16.03.1160.f2d4ee1`)."; + description = "The full nixpkgs version (e.g. `24.11.1160.f2d4ee1`)."; }; system.nixpkgsVersionSuffix = mkOption { @@ -97,7 +110,7 @@ in default = if useSourceRevision then ".${lib.substring 0 8 (nixpkgsSrc.lastModifiedDate or nixpkgsSrc.lastModified or "19700101")}.${nixpkgsSrc.shortRev or "dirty"}" else lib.trivial.versionSuffix; - description = lib.mdDoc "The short nixpkgs version suffix (e.g. `.1160.f2d4ee1`)."; + description = "The short nixpkgs version suffix (e.g. `.1160.f2d4ee1`)."; }; system.nixpkgsRevision = mkOption { @@ -106,24 +119,37 @@ in default = if useSourceRevision && nixpkgsSrc ? rev then nixpkgsSrc.rev else lib.trivial.revisionWithDefault null; - description = lib.mdDoc "The nixpkgs git revision from which this configuration was built."; + description = "The nixpkgs git revision from which this configuration was built."; }; system.configurationRevision = mkOption { type = types.nullOr types.str; default = null; - description = lib.mdDoc "The Git revision of the top-level flake from which this configuration was built."; + description = "The Git revision of the top-level flake from which this configuration was built."; }; }; config = { # This default is set here rather than up there so that the options # documentation is not reprocessed on every commit - system.darwinLabel = mkDefault "${cfg.nixpkgsVersion}+${cfg.darwinVersion}"; - - assertions = [ { - assertion = cfg.stateVersion <= defaultStateVersion; - message = "system.stateVersion = ${toString cfg.stateVersion}; is not a valid value"; - } ]; + system.darwinLabel = mkDefault cfg.darwinVersion; + + assertions = [ + { + assertion = options.system.stateVersion.highestPrio != (lib.mkOptionDefault { }).priority; + message = '' + The `system.stateVersion` option is not defined in your + nix-darwin configuration. The value is used to conditionalize + backwards‐incompatible changes in default settings. You should + usually set this once when installing nix-darwin on a new system + and then never change it (at least without reading all the relevant + entries in the changelog using `darwin-rebuild changelog`). + + You can use the current value for new installations as follows: + + system.stateVersion = ${toString config.system.maxStateVersion}; + ''; + } + ]; }; } |
