From fad8e3033e95d0a4595080e1efc8927b16ac18ed Mon Sep 17 00:00:00 2001 From: Tim Keller <36288711+tjkeller-xyz@users.noreply.github.com> Date: Tue, 16 Sep 2025 22:31:54 -0500 Subject: [PATCH] fontconfig: add fonts.fontconfig.extraConfigFiles option (#7754) Co-authored-by: Tim Keller Co-authored-by: Benedikt M. Rips --- modules/misc/fontconfig.nix | 136 +++++++++++++++--- tests/modules/misc/fontconfig/default.nix | 1 + .../misc/fontconfig/extra-config-files.nix | 33 +++++ .../misc/fontconfig/sample-extra-config.conf | 14 ++ 4 files changed, 161 insertions(+), 23 deletions(-) create mode 100644 tests/modules/misc/fontconfig/extra-config-files.nix create mode 100644 tests/modules/misc/fontconfig/sample-extra-config.conf diff --git a/modules/misc/fontconfig.nix b/modules/misc/fontconfig.nix index 0485e81f4..a2bb39879 100644 --- a/modules/misc/fontconfig.nix +++ b/modules/misc/fontconfig.nix @@ -15,6 +15,39 @@ let profileDirectory = config.home.profileDirectory; + fontConfigFileType = lib.types.submodule ( + { name, ... }: + { + options = { + enable = lib.mkEnableOption "Whether this font config file should be generated."; + text = lib.mkOption { + type = lib.types.nullOr lib.types.lines; + default = null; + description = "Verbatim contents of the config file. If this option is null then the 'source' option must be set."; + }; + source = lib.mkOption { + type = lib.types.nullOr lib.types.path; + default = null; + description = "Config file to source. Alternatively, use the 'text' option instead."; + }; + label = lib.mkOption { + type = lib.types.str; + default = name; + defaultText = ""; + description = "Label to use for the name of the config file."; + }; + priority = lib.mkOption { + type = lib.types.ints.between 0 99; + default = 90; + description = '' + Determines the order in which configs are loaded. + Must be a value within the range of 0-99, where priority 0 is the highest priority and 99 is the lowest. + ''; + }; + }; + } + ); + in { meta.maintainers = with lib.maintainers; [ @@ -125,6 +158,44 @@ in example = "rgb"; }; + configFile = lib.mkOption { + type = lib.types.attrsOf fontConfigFileType; + default = { }; + description = '' + Extra font config files that will be added to `~/.config/fontconfig/conf.d/`. + Files are named like `fontconfig/conf.d/{priority}-{label}.conf`. + ''; + example = { + tamzen = { + enable = true; + label = "tamzen-disable-antialiasing"; + text = '' + + + + + Disable anti-aliasing for Tamzen since it is a bitmap font + + + Tamzen + + + false + + + + ''; + priority = 90; + }; # => conf.d/90-tamzen-disable-antialiasing.conf + commit-mono-options = { + enable = true; + source = "./resources/fontconfig/commit-mono.conf"; + priority = 80; + }; # => conf.d/80-commit-mono-options.conf + }; + + }; + }; }; @@ -164,7 +235,7 @@ in fi ''; - xdg.configFile = + fonts.fontconfig.configFile = let mkFontconfigConf = conf: '' @@ -178,21 +249,25 @@ in ''; in { - "fontconfig/conf.d/10-hm-fonts.conf".text = mkFontconfigConf '' - Add fonts in the Nix user profile + fonts = { + enable = true; + priority = 10; + source = null; # Set the source as null explicitly so that it cannot be overwritten by mistake by a user + text = mkFontconfigConf '' + Add fonts in the Nix user profile - ${config.home.path}/etc/fonts/conf.d - ${config.home.path}/etc/fonts/fonts.conf + ${config.home.path}/etc/fonts/conf.d + ${config.home.path}/etc/fonts/fonts.conf - ${config.home.path}/lib/X11/fonts - ${config.home.path}/share/fonts - ${profileDirectory}/lib/X11/fonts - ${profileDirectory}/share/fonts + ${config.home.path}/lib/X11/fonts + ${config.home.path}/share/fonts + ${profileDirectory}/lib/X11/fonts + ${profileDirectory}/share/fonts - ${config.home.path}/lib/fontconfig/cache - ''; - - "fontconfig/conf.d/10-hm-rendering.conf" = + ${config.home.path}/lib/fontconfig/cache + ''; + }; + rendering = let set = name: value: @@ -222,13 +297,15 @@ in set "rgba" (builtins.replaceStrings [ "ertical-" ] [ "" ] cfg.subpixelRendering) ); in - lib.mkIf (builtins.length content > 0) { + { + enable = builtins.length content > 0; + priority = 10; + source = null; text = mkFontconfigConf ( lib.concatStrings ([ "Set the rendering mode\n" ] ++ content) ); }; - - "fontconfig/conf.d/52-hm-default-fonts.conf".text = + default-fonts = let genDefault = fonts: name: @@ -245,13 +322,26 @@ in ''; in - mkFontconfigConf '' - - ${genDefault cfg.defaultFonts.sansSerif "sans-serif"} - ${genDefault cfg.defaultFonts.serif "serif"} - ${genDefault cfg.defaultFonts.monospace "monospace"} - ${genDefault cfg.defaultFonts.emoji "emoji"} - ''; + { + enable = true; + priority = 52; + source = null; + text = mkFontconfigConf '' + + ${genDefault cfg.defaultFonts.sansSerif "sans-serif"} + ${genDefault cfg.defaultFonts.serif "serif"} + ${genDefault cfg.defaultFonts.monospace "monospace"} + ${genDefault cfg.defaultFonts.emoji "emoji"} + ''; + }; }; + + xdg.configFile = lib.mapAttrs' ( + name: config: + lib.nameValuePair "fontconfig/conf.d/${builtins.toString config.priority}-hm-${config.label}.conf" { + inherit (config) enable text; + source = lib.mkIf (config.source != null) config.source; + } + ) cfg.configFile; }; } diff --git a/tests/modules/misc/fontconfig/default.nix b/tests/modules/misc/fontconfig/default.nix index 7509af66a..50ab6acba 100644 --- a/tests/modules/misc/fontconfig/default.nix +++ b/tests/modules/misc/fontconfig/default.nix @@ -22,4 +22,5 @@ fontconfig-default-rendering = ./default-rendering.nix; fontconfig-custom-rendering = ./custom-rendering.nix; + fontconfig-extra-config-files = ./extra-config-files.nix; } diff --git a/tests/modules/misc/fontconfig/extra-config-files.nix b/tests/modules/misc/fontconfig/extra-config-files.nix new file mode 100644 index 000000000..647b99b98 --- /dev/null +++ b/tests/modules/misc/fontconfig/extra-config-files.nix @@ -0,0 +1,33 @@ +let + sampleTextContent = "hello world"; + fcConfD = "home-files/.config/fontconfig/conf.d"; +in +{ + fonts.fontconfig = { + enable = true; + configFile = { + text-label-test = { + enable = true; + label = "sample-text-config"; + text = sampleTextContent; + priority = 55; + }; + source-nolabel-test = { + enable = true; + source = ./sample-extra-config.conf; + }; + }; + }; + + nmt.script = '' + assertDirectoryExists ${fcConfD} + + assertFileExists ${fcConfD}/55-hm-sample-text-config.conf + assertFileContent ${fcConfD}/55-hm-sample-text-config.conf \ + ${builtins.toFile "sample-text-config" sampleTextContent} + + assertFileExists ${fcConfD}/90-hm-source-nolabel-test.conf + assertFileContent ${fcConfD}/90-hm-source-nolabel-test.conf \ + ${./sample-extra-config.conf} + ''; +} diff --git a/tests/modules/misc/fontconfig/sample-extra-config.conf b/tests/modules/misc/fontconfig/sample-extra-config.conf new file mode 100644 index 000000000..5bf94d760 --- /dev/null +++ b/tests/modules/misc/fontconfig/sample-extra-config.conf @@ -0,0 +1,14 @@ + + + + + Disable anti-aliasing for Tamzen since it is a bitmap font + + + Tamzen + + + false + + +