targets/darwin: add more options for configuring macOS (#1753)

Add new options Darwin options:

- `targets.darwin.defaults`
  This adds options for configuring macOS through the `defaults(1)` system.
  This option can be used to manipulate a vast majority of user settings for macOS
  and its applications.

  This is implemented using freeform modules and includes additional descriptions
  and type information for some useful options.

- `targets.darwin.keybindings`
  This adds options for configuring the default keybindings for macOS text fields.

- `targets.darwin.search`
  This adds options for configuring the default search engine for macOS.
This commit is contained in:
midchildan 2021-02-04 08:46:16 +09:00 committed by GitHub
parent bbb6d30001
commit 9dad146639
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
7 changed files with 339 additions and 1 deletions

View file

@ -1822,6 +1822,29 @@ in
A new module is available: 'services.playerctld'.
'';
}
{
time = "2021-01-28T15:07:34+00:00";
condition = hostPlatform.isDarwin;
message = ''
New options are available for 'targets.darwin':
- targets.darwin.defaults
This adds options for configuring macOS through the defaults(1)
system.
- targets.darwin.keybindings
This adds options for configuring the default keybindings for macOS
text fields.
- targets.darwin.search
This adds options for configuring the default search engine for
macOS.
'';
}
];
};
}

View file

@ -204,7 +204,7 @@ let
(loadModule ./services/xscreensaver.nix { })
(loadModule ./services/xsuspender.nix { condition = hostPlatform.isLinux; })
(loadModule ./systemd.nix { })
(loadModule ./targets/darwin.nix { condition = hostPlatform.isDarwin; })
(loadModule ./targets/darwin { condition = hostPlatform.isDarwin; })
(loadModule ./targets/generic-linux.nix { condition = hostPlatform.isLinux; })
(loadModule ./xcursor.nix { })
(loadModule ./xresources.nix { })

View file

@ -0,0 +1,51 @@
{ config, lib, pkgs, ... }:
with lib;
let
cfg = config.targets.darwin;
toDefaultsFile = domain: attrs:
pkgs.writeText "${domain}.plist" (lib.generators.toPlist { } attrs);
toActivationCmd = domain: attrs:
"$DRY_RUN_CMD defaults import ${escapeShellArg domain} ${
toDefaultsFile domain attrs
}";
nonNullDefaults =
mapAttrs (domain: attrs: (filterAttrs (n: v: v != null) attrs))
cfg.defaults;
writableDefaults = filterAttrs (domain: attrs: attrs != { }) nonNullDefaults;
activationCmds = mapAttrsToList toActivationCmd writableDefaults;
in {
imports = [ ./keybindings.nix ./linkapps.nix ./search.nix ];
options.targets.darwin.defaults = mkOption {
type = types.submodule ./options.nix;
default = { };
example = {
"com.apple.desktopservices" = {
DSDontWriteNetworkStores = true;
DSDontWriteUSBStores = true;
};
};
description = ''
Set macOS user defaults. Values set to <literal>null</literal> are
ignored.
<warning>
<para>
Some settings might require a re-login to take effect.
</para>
</warning>
'';
};
config = mkIf (activationCmds != [ ]) {
home.activation.setDarwinDefaults = hm.dag.entryAfter [ "writeBoundary" ] ''
$VERBOSE_ECHO "Configuring macOS user defaults"
${concatStringsSep "\n" activationCmds}
'';
};
}

View file

@ -0,0 +1,42 @@
{ config, lib, pkgs, ... }:
with lib;
let
cfg = config.targets.darwin;
homeDir = config.home.homeDirectory;
confFile = pkgs.writeText "DefaultKeybinding.dict"
(lib.generators.toPlist { } cfg.keybindings);
in {
options.targets.darwin.keybindings = mkOption {
type = with types; attrsOf anything;
default = { };
example = {
"^u" = "deleteToBeginningOfLine:";
"^w" = "deleteWordBackward:";
};
description = ''
This will configure the default keybindings for text fields in macOS
applications. See
<link xlink:href="https://developer.apple.com/library/archive/documentation/Cocoa/Conceptual/EventOverview/TextDefaultsBindings/TextDefaultsBindings.html">Apple's documentation</link>
for more details.
<warning>
<para>
Existing keybinding configuration will be wiped when using this
option.
</para>
</warning>
'';
};
config = mkIf (cfg.keybindings != { }) {
# NOTE: just copy the files because symlinks won't be recognized by macOS
home.activation.setCocoaKeybindings =
hm.dag.entryAfter [ "writeBoundary" ] ''
$VERBOSE_ECHO "Configuring keybindings for the Cocoa Text System"
$DRY_RUN_CMD install -Dm644 $VERBOSE_ARG \
"${confFile}" "${homeDir}/Library/KeyBindings/DefaultKeyBinding.dict"
'';
};
}

View file

@ -0,0 +1,189 @@
{ config, lib, ... }:
with lib;
let
mkNullableOption = args:
lib.mkOption (args // {
type = types.nullOr args.type;
default = null;
});
mkNullableEnableOption = name:
lib.mkOption {
type = with types; nullOr bool;
default = null;
example = true;
description = "Whether to enable ${name}.";
};
safari = config."com.apple.Safari";
in {
freeformType = with types; attrsOf (attrsOf anything);
options = {
NSGlobalDomain = {
AppleLanguages = mkNullableOption {
type = with types; listOf str;
example = [ "en" ];
description = "Sets the language to use in the preferred order.";
};
AppleLocale = mkNullableOption {
type = types.str;
example = "en_US";
description = "Configures the user locale.";
};
AppleMeasurementUnits = mkNullableOption {
type = types.enum [ "Centimeters" "Inches" ];
example = "Centimeters";
description = "Sets the measurement unit.";
};
AppleTemperatureUnit = mkNullableOption {
type = types.enum [ "Celsius" "Fahrenheit" ];
example = "Celsius";
description = "Sets the temperature unit.";
};
AppleMetricUnits = mkNullableEnableOption "the metric system";
NSAutomaticCapitalizationEnabled =
mkNullableEnableOption "automatic captilization";
NSAutomaticDashSubstitutionEnabled =
mkNullableEnableOption "smart dashes";
NSAutomaticPeriodSubstitutionEnabled =
mkNullableEnableOption "period with double space";
NSAutomaticQuoteSubstitutionEnabled =
mkNullableEnableOption "smart quotes";
NSAutomaticSpellingCorrectionEnabled =
mkNullableEnableOption "spelling correction";
};
"com.apple.desktopservices" = {
DSDontWriteNetworkStores = mkNullableOption {
type = types.bool;
example = false;
description = ''
Disable use of <filename>.DS_Store</filename> files on network shares.
See <link xlink:href="https://support.apple.com/en-us/HT208209">the
official article</link> for more info.
'';
};
DSDontWriteUSBStores = mkNullableOption {
type = types.bool;
example = false;
description = ''
Disable use of <filename>.DS_Store</filename> files on thumb drives.
'';
};
};
"com.apple.dock" = {
tilesize = mkNullableOption {
type = types.int;
example = 64;
description = "Sets the size of the dock.";
};
size-immutable = mkNullableEnableOption "locking of the dock size";
expose-group-apps = mkNullableEnableOption
"grouping of windows by application in Mission Control";
};
"com.apple.menuextra.battery".ShowPercent = mkNullableOption {
type = types.enum [ "YES" "NO" ];
example = "NO";
description = "Whether to show battery percentage in the menu bar.";
};
"com.apple.Safari" = {
AutoOpenSafeDownloads =
mkNullableEnableOption "opening of downloaded files";
AutoFillPasswords =
mkNullableEnableOption "autofill of usernames and passwords";
AutoFillCreditCardData =
mkNullableEnableOption "autofill of credit card numbers";
IncludeDevelopMenu =
mkNullableEnableOption ''"Develop" menu in the menu bar'';
ShowOverlayStatusBar = mkNullableEnableOption "status bar";
WebKitDeveloperExtrasEnabledPreferenceKey = mkNullableOption {
type = types.bool;
description = ''
Configures the web inspector.
<warning>
<para>
Instead of setting this option directly, set
<option>IncludeDevelopMenu</option> instead.
</para>
</warning>
'';
};
"com.apple.Safari.ContentPageGroupIdentifier.WebKit2DeveloperExtrasEnabled" =
mkNullableOption {
type = types.bool;
description = ''
Configures the web inspector.
<warning>
<para>
Instead of setting this option directly, set
<option>IncludeDevelopMenu</option> instead.
</para>
</warning>
'';
};
};
"com.googlecode.iterm2" = {
AddNewTabAtEndOfTabs = mkNullableEnableOption
"placement of new tabs at the end of the tab bar";
AlternateMouseScroll = mkNullableEnableOption
"arrow keys when scrolling in alternate screen mode";
CopySelection =
mkNullableEnableOption "copy to clipboard upon selecting text";
OpenTmuxWindowsIn = mkNullableOption {
type = types.int;
example = 2;
description = ''
Configures how to restore tmux windows when attaching to a session.
<variablelist><title>Possible Values</title>
<varlistentry>
<term><literal>0</literal></term>
<listitem><para>Native windows</para></listitem>
</varlistentry>
<varlistentry>
<term><literal>1</literal></term>
<listitem><para>Native tabs in a new window</para></listitem>
</varlistentry>
<varlistentry>
<term><literal>2</literal></term>
<listitem><para>Tabs in the attaching window</para></listitem>
</varlistentry>
</variablelist>
'';
};
ExperimentalKeyHandling = mkNullableEnableOption
"experimental key handling for AquaSKK compatibility";
};
};
config = {
"com.apple.Safari" = mkIf (safari.IncludeDevelopMenu != null) {
WebKitDeveloperExtrasEnabledPreferenceKey = safari.IncludeDevelopMenu;
"com.apple.Safari.ContentPageGroupIdentifier.WebKit2DeveloperExtrasEnabled" =
safari.IncludeDevelopMenu;
};
};
}

View file

@ -0,0 +1,33 @@
{ config, lib, pkgs, ... }:
with lib;
let
cfg = config.targets.darwin;
searchEngines = {
Bing = "com.bing.www";
DuckDuckGo = "com.duckduckgo";
Ecosia = "org.ecosia.www";
Google = "com.google.www";
Yahoo = "com.yahoo.www";
};
searchId = getAttr cfg.search searchEngines;
in {
options.targets.darwin.search = mkOption {
type = with types; nullOr (enum (attrNames searchEngines));
default = null;
description = "Default search engine.";
};
config = mkIf (cfg.search != null) {
targets.darwin.defaults = {
NSGlobalDomain.NSPreferredWebServices = {
NSWebServicesProviderWebSearch = {
NSDefaultDisplayName = cfg.search;
NSProviderIdentifier = searchId;
};
};
"com.apple.Safari".SearchProviderIdentifier = searchId;
};
};
}