From 111329b475f7db892fef44059109108cbb45ab9c Mon Sep 17 00:00:00 2001 From: Austin Horstman Date: Thu, 16 Oct 2025 21:10:33 -0500 Subject: [PATCH] difftastic: new module Signed-off-by: Austin Horstman --- modules/programs/difftastic.nix | 146 ++++++++++++++++++ modules/programs/git.nix | 87 +---------- tests/modules/programs/git/default.nix | 1 - .../programs/git/git-difftastic-expected.conf | 12 -- tests/modules/programs/git/git-difftastic.nix | 23 --- 5 files changed, 147 insertions(+), 122 deletions(-) create mode 100644 modules/programs/difftastic.nix delete mode 100644 tests/modules/programs/git/git-difftastic-expected.conf delete mode 100644 tests/modules/programs/git/git-difftastic.nix diff --git a/modules/programs/difftastic.nix b/modules/programs/difftastic.nix new file mode 100644 index 000000000..640d61581 --- /dev/null +++ b/modules/programs/difftastic.nix @@ -0,0 +1,146 @@ +{ + config, + options, + lib, + pkgs, + ... +}: +let + cfg = config.programs.difftastic; + + inherit (lib) + mkEnableOption + mkIf + mkMerge + mkOption + mkPackageOption + types + ; +in +{ + meta.maintainers = with lib.maintainers; [ khaneliman ]; + + imports = [ + (lib.mkRenamedOptionModule + [ "programs" "git" "difftastic" "enable" ] + [ "programs" "difftastic" "enable" ] + ) + (lib.mkRenamedOptionModule + [ "programs" "git" "difftastic" "package" ] + [ "programs" "difftastic" "package" ] + ) + (lib.mkRenamedOptionModule + [ "programs" "git" "difftastic" "enableAsDifftool" ] + [ "programs" "difftastic" "git" "diffToolMode" ] + ) + (lib.mkRenamedOptionModule + [ "programs" "git" "difftastic" "options" ] + [ "programs" "difftastic" "options" ] + ) + ] + ++ ( + let + mkRenamed = + opt: + lib.mkRenamedOptionModule + [ "programs" "git" "difftastic" opt ] + [ "programs" "git" "difftastic" "options" opt ]; + in + map mkRenamed [ + "background" + "color" + "context" + "display" + ] + ) + ++ [ + (lib.mkRemovedOptionModule [ "programs" "git" "difftastic" "extraArgs" ] '' + 'programs.git.difftastic.extraArgs' has been replaced by 'programs.git.difftastic.options' + '') + ]; + + options.programs.difftastic = { + enable = mkEnableOption "difftastic, a structural diff tool"; + + package = mkPackageOption pkgs "difftastic" { }; + + options = mkOption { + type = + with types; + attrsOf (oneOf [ + str + int + bool + ]); + default = { }; + example = { + color = "dark"; + sort-path = true; + tab-width = 8; + }; + description = "Configuration options for {command}`difftastic`. See {command}`difft --help`"; + }; + + git = { + enable = mkOption { + type = types.bool; + default = false; + description = '' + Whether to enable git integration for difftastic. + + When enabled, difftastic will be configured as git's external diff tool or difftool + depending on the value of {option}`programs.difftastic.git.diffToolMode`. + ''; + }; + + diffToolMode = mkOption { + type = types.bool; + default = false; + description = '' + Whether to additionally configure difftastic as a git difftool. + + When `false`, only `diff.external` is set (used for `git diff`). + When `true`, both `diff.external` and difftool config are set (supporting both `git diff` and `git difftool`). + ''; + }; + }; + }; + + config = + let + oldOption = lib.attrByPath [ "programs" "git" "difftastic" "enable" ] null options; + oldOptionEnabled = + oldOption != null && oldOption.isDefined && (builtins.length oldOption.files) > 0; + in + mkMerge [ + (mkIf cfg.enable { + home.packages = [ cfg.package ]; + + # Auto-enable git integration if programs.git.difftastic.enable was set to true + programs.difftastic.git.enable = lib.mkIf oldOptionEnabled (lib.mkOverride 1490 true); + + warnings = + lib.optional (cfg.git.enable && options.programs.difftastic.git.enable.highestPrio == 1490) + "`programs.difftastic.git.enable` automatic enablement is deprecated. Please explicitly set `programs.difftastic.git.enable = true`."; + }) + + (mkIf (cfg.enable && cfg.git.enable) { + programs.git = { + enable = lib.mkDefault true; + iniContent = + let + difftCommand = "${lib.getExe cfg.package} ${lib.cli.toGNUCommandLineShell { } cfg.options}"; + in + mkMerge [ + { + diff.external = difftCommand; + } + (mkIf cfg.git.diffToolMode { + diff.tool = lib.mkDefault "difftastic"; + difftool.difftastic.cmd = "${difftCommand} $LOCAL $REMOTE"; + }) + ]; + }; + }) + ]; +} diff --git a/modules/programs/git.nix b/modules/programs/git.nix index 44fbc89cb..d170df2be 100644 --- a/modules/programs/git.nix +++ b/modules/programs/git.nix @@ -90,7 +90,6 @@ let ); } ); - in { meta.maintainers = with lib.maintainers; [ @@ -292,41 +291,6 @@ in }; }; - difftastic = { - enable = mkEnableOption "" // { - description = '' - Enable the {command}`difftastic` syntax highlighter. - See . - ''; - }; - - package = mkPackageOption pkgs "difftastic" { }; - - enableAsDifftool = mkEnableOption "" // { - description = '' - Enable the {command}`difftastic` syntax highlighter as a git difftool. - See . - ''; - }; - - options = mkOption { - type = - with lib.types; - attrsOf (oneOf [ - str - number - bool - ]); - default = { }; - example = { - color = "dark"; - sort-path = true; - tab-width = 8; - }; - description = "Configuration options for {command}`difftastic`. See {command}`difft --help`"; - }; - }; - riff = { enable = mkEnableOption "" // { description = '' @@ -373,26 +337,6 @@ in "signer" ] ) - ] - ++ ( - let - mkRenamed = - opt: - lib.mkRenamedOptionModule - [ "programs" "git" "difftastic" opt ] - [ "programs" "git" "difftastic" "options" opt ]; - in - map mkRenamed [ - "background" - "color" - "context" - "display" - ] - ) - ++ [ - (lib.mkRemovedOptionModule [ "programs" "git" "difftastic" "extraArgs" ] '' - 'programs.git.difftastic.extraArgs' has been replaced by 'programs.git.difftastic.options' - '') ]; config = mkIf cfg.enable ( @@ -408,7 +352,7 @@ in (config.programs.delta.enable && config.programs.delta.enableGitIntegration) (config.programs.diff-highlight.enable && config.programs.diff-highlight.enableGitIntegration) (config.programs.diff-so-fancy.enable && config.programs.diff-so-fancy.enableGitIntegration) - cfg.difftastic.enable + (config.programs.difftastic.enable && config.programs.difftastic.git.enable) cfg.riff.enable cfg.patdiff.enable ]; @@ -688,35 +632,6 @@ in }; }) - ( - let - difftCommand = "${lib.getExe cfg.difftastic.package} ${ - lib.cli.toGNUCommandLineShell { } cfg.difftastic.options - }"; - in - (lib.mkMerge [ - (mkIf cfg.difftastic.enable { - home.packages = [ cfg.difftastic.package ]; - programs.git.iniContent = { - diff.external = difftCommand; - }; - }) - (mkIf cfg.difftastic.enableAsDifftool { - home.packages = [ cfg.difftastic.package ]; - programs.git.iniContent = { - diff = { - tool = lib.mkDefault "difftastic"; - }; - difftool = { - difftastic = { - cmd = "${difftCommand} $LOCAL $REMOTE"; - }; - }; - }; - }) - ]) - ) - ( let riffExe = baseNameOf (lib.getExe cfg.riff.package); diff --git a/tests/modules/programs/git/default.nix b/tests/modules/programs/git/default.nix index ad37969c7..5f2330dd4 100644 --- a/tests/modules/programs/git/default.nix +++ b/tests/modules/programs/git/default.nix @@ -10,5 +10,4 @@ git-with-hooks = ./git-with-hooks.nix; git-with-maintenance = ./git-with-maintenance.nix; git-patdiff = ./git-patdiff.nix; - git-difftastic = ./git-difftastic.nix; } diff --git a/tests/modules/programs/git/git-difftastic-expected.conf b/tests/modules/programs/git/git-difftastic-expected.conf deleted file mode 100644 index f9a18eb10..000000000 --- a/tests/modules/programs/git/git-difftastic-expected.conf +++ /dev/null @@ -1,12 +0,0 @@ -[diff] - external = "@difftastic@/bin/difft --background dark --color always --context 5 --display inline --sort-paths --tab-width 8" - tool = "difftastic" - -[difftool "difftastic"] - cmd = "@difftastic@/bin/difft --background dark --color always --context 5 --display inline --sort-paths --tab-width 8 $LOCAL $REMOTE" - -[gpg] - format = "openpgp" - -[gpg "openpgp"] - program = "path-to-gpg" diff --git a/tests/modules/programs/git/git-difftastic.nix b/tests/modules/programs/git/git-difftastic.nix deleted file mode 100644 index 8a8085811..000000000 --- a/tests/modules/programs/git/git-difftastic.nix +++ /dev/null @@ -1,23 +0,0 @@ -{ - programs.git = { - enable = true; - signing.signer = "path-to-gpg"; - difftastic = { - enable = true; - enableAsDifftool = true; - options = { - background = "dark"; - color = "always"; - context = 5; - display = "inline"; - tab-width = 8; - sort-paths = true; - }; - }; - }; - - nmt.script = '' - assertFileExists home-files/.config/git/config - assertFileContent home-files/.config/git/config ${./git-difftastic-expected.conf} - ''; -}