darwin: add support for 'defaults -currentHost' options

Closes #2615
This commit is contained in:
midchildan 2022-04-24 16:19:56 +09:00 committed by Robert Helgesson
parent 1d3380afba
commit 572f348a10
No known key found for this signature in database
GPG key ID: 36BDAA14C2797E89
7 changed files with 183 additions and 76 deletions

View file

@ -605,6 +605,17 @@ in
A new module is available: 'programs.librewolf'.
'';
}
{
time = "2022-07-24T13:17:01+00:00";
condition = hostPlatform.isDarwin;
message = ''
A new option is available: 'targets.darwin.currentHostDefaults'.
This exposes macOS preferences that are available through the
'defaults -currentHost' command.
'';
}
];
};
}

View file

@ -1,76 +1,13 @@
{ config, lib, pkgs, ... }:
{ lib, ... }:
with lib;
{
meta.maintainers = with lib.maintainers; [ midchildan ];
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 {
meta.maintainers = [ maintainers.midchildan ];
imports = [ ./fonts.nix ./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 != [ ]) {
assertions = [
(hm.assertions.assertPlatform "targets.darwin.defaults" pkgs
platforms.darwin)
];
warnings = let
batteryPercentage =
attrByPath [ "com.apple.menuextra.battery" "ShowPercent" ] null
cfg.defaults;
webkitDevExtras = attrByPath [
"com.apple.Safari"
"com.apple.Safari.ContentPageGroupIdentifier.WebKit2DeveloperExtrasEnabled"
] null cfg.defaults;
in optional (batteryPercentage != null) ''
The option 'com.apple.menuextra.battery.ShowPercent' no longer works on
macOS 11 and later. Instead, open System Preferences, go to "Dock &amp;
Menu Bar", select "Battery", and toggle the checkbox labeled "Show
Percentage."
'' ++ optional (webkitDevExtras != null) ''
The option 'com.apple.Safari.com.apple.Safari.ContentPageGroupIdentifier.WebKit2DeveloperExtrasEnabled'
is no longer present in recent versions of Safari.
'';
home.activation.setDarwinDefaults = hm.dag.entryAfter [ "writeBoundary" ] ''
$VERBOSE_ECHO "Configuring macOS user defaults"
${concatStringsSep "\n" activationCmds}
'';
};
imports = [
./user-defaults
./fonts.nix
./keybindings.nix
./linkapps.nix
./search.nix
];
}

View file

@ -0,0 +1,112 @@
{ config, lib, pkgs, ... }:
with lib;
let
cfg = config.targets.darwin;
mkActivationCmds = isLocal: settings:
let
toDefaultsFile = domain: attrs:
pkgs.writeText "${domain}.plist" (lib.generators.toPlist { } attrs);
cliFlags = lib.optionalString isLocal "-currentHost";
toActivationCmd = domain: attrs:
"$DRY_RUN_CMD defaults ${cliFlags} import ${escapeShellArg domain} ${
toDefaultsFile domain attrs
}";
nonNullDefaults =
mapAttrs (domain: attrs: (filterAttrs (n: v: v != null) attrs))
settings;
writableDefaults =
filterAttrs (domain: attrs: attrs != { }) nonNullDefaults;
in mapAttrsToList toActivationCmd writableDefaults;
defaultsCmds = mkActivationCmds false cfg.defaults;
currentHostDefaultsCmds = mkActivationCmds true cfg.currentHostDefaults;
activationCmds = defaultsCmds ++ currentHostDefaultsCmds;
in {
meta.maintainers = [ maintainers.midchildan ];
options.targets.darwin.defaults = mkOption {
type = types.submodule ./opts-allhosts.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>
<warning>
<para>
Some settings are only read from
<option>targets.darwin.currentHostDefaults</option>.
</para>
</warning>
'';
};
options.targets.darwin.currentHostDefaults = mkOption {
type = types.submodule ./opts-currenthost.nix;
default = { };
example = {
"com.apple.controlcenter" = { BatteryShowPercentage = true; };
};
description = ''
Set macOS user defaults. Unlike <option>targets.darwin.defaults</option>,
the preferences will only be applied to the currently logged-in host. This
distinction is important for networked accounts.
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 != [ ]) {
assertions = [
(hm.assertions.assertPlatform "targets.darwin.defaults" pkgs
platforms.darwin)
];
warnings = let
batteryOptionName = ''
targets.darwin.currentHostDefaults."com.apple.controlcenter".BatteryShowPercentage'';
batteryPercentage =
attrByPath [ "com.apple.menuextra.battery" "ShowPercent" ] null
cfg.defaults;
webkitDevExtras = attrByPath [
"com.apple.Safari"
"com.apple.Safari.ContentPageGroupIdentifier.WebKit2DeveloperExtrasEnabled"
] null cfg.defaults;
in optional (batteryPercentage != null) ''
The option 'com.apple.menuextra.battery.ShowPercent' no longer works on
macOS 11 and later. Instead, use '${batteryOptionName}'.
'' ++ optional (webkitDevExtras != null) ''
The option 'com.apple.Safari.com.apple.Safari.ContentPageGroupIdentifier.WebKit2DeveloperExtrasEnabled'
is no longer present in recent versions of Safari.
'';
home.activation.setDarwinDefaults = hm.dag.entryAfter [ "writeBoundary" ] ''
$VERBOSE_ECHO "Configuring macOS user defaults"
${concatStringsSep "\n" activationCmds}
'';
};
}

View file

@ -99,9 +99,8 @@ in {
type = types.enum [ "YES" "NO" ];
example = "NO";
description = ''
This option no longer works on macOS 11 and later. Instead, open System
Preferences, go to "Dock &amp; Menu Bar", select "Battery", and toggle
the checkbox labeled "Show Percentage."
This option no longer works on macOS 11 and later. Instead, use
<option>targets.darwin.currentHostDefaults.\"com.apple.controlcenter\".BatteryShowPercentage</option>.
Whether to show battery percentage in the menu bar.
'';

View file

@ -0,0 +1,29 @@
{ config, lib, ... }:
let
mkNullableOption = args:
lib.mkOption (args // {
type = lib.types.nullOr args.type;
default = null;
});
mkNullableEnableOption = name:
lib.mkOption {
type = with lib.types; nullOr bool;
default = null;
example = true;
description = "Whether to enable ${name}.";
};
in {
freeformType = with lib.types; attrsOf (attrsOf anything);
options = {
"com.apple.controlcenter".BatteryShowPercentage = mkNullableOption {
type = lib.types.bool;
example = true;
description = ''
Whether to show battery percentage in the menu bar.
'';
};
};
}

View file

@ -2,4 +2,5 @@
# Disabled for now due to conflicting behavior with nix-darwin. See
# https://github.com/nix-community/home-manager/issues/1341#issuecomment-687286866
#targets-darwin = ./darwin.nix;
user-defaults = ./user-defaults.nix;
}

View file

@ -0,0 +1,18 @@
{ lib, ... }:
{
config = {
targets.darwin = {
defaults."com.apple.desktopservices".DSDontWriteNetworkStores = true;
currentHostDefaults."com.apple.controlcenter".BatteryShowPercentage =
true;
};
nmt.script = ''
assertFileRegex activate \
"defaults import 'com.apple.desktopservices' /nix/store/[a-z0-9]\\{32\\}-com\\.apple\\.desktopservices\\.plist"
assertFileRegex activate \
"defaults -currentHost import 'com.apple.controlcenter' /nix/store/[a-z0-9]\\{32\\}-com\\.apple\\.controlcenter\\.plist"
'';
};
}