From 388d1056e8adf19453993029b8569c0b00a74a07 Mon Sep 17 00:00:00 2001 From: ncaq Date: Thu, 10 Jul 2025 14:44:29 +0900 Subject: [PATCH 1/3] fix(cabal): cabal-fmt and cabal-gild discover module `cabal-fmt` and `cabal-gild` can discover module and autocomplete. ```cabal -- cabal-gild: discover ./src exposed-modules: ``` The current system, treefmt can't detect change haskell module. I write to depend to haskell module file. --- examples/formatter-cabal-fmt.toml | 19 ++++++++-- examples/formatter-cabal-gild.toml | 17 ++++++++- programs/cabal-fmt.nix | 57 ++++++++++++++++++++++++++++-- programs/cabal-gild.nix | 25 +++++++++++-- 4 files changed, 110 insertions(+), 8 deletions(-) diff --git a/examples/formatter-cabal-fmt.toml b/examples/formatter-cabal-fmt.toml index de69588..9975aa4 100644 --- a/examples/formatter-cabal-fmt.toml +++ b/examples/formatter-cabal-fmt.toml @@ -1,6 +1,19 @@ # Example generated by ../examples.sh [formatter.cabal-fmt] -command = "cabal-fmt" +command = "cabal-fmt-wrapper" excludes = [] -includes = ["*.cabal"] -options = ["--inplace"] +includes = [ + "*.cabal", + "*.chs", + "*.cpphs", + "*.gc", + "*.hs", + "*.hsc", + "*.hsig", + "*.lhs", + "*.lhsig", + "*.ly", + "*.x", + "*.y", +] +options = [] diff --git a/examples/formatter-cabal-gild.toml b/examples/formatter-cabal-gild.toml index 382cdc0..bd6f1a3 100644 --- a/examples/formatter-cabal-gild.toml +++ b/examples/formatter-cabal-gild.toml @@ -2,5 +2,20 @@ [formatter.cabal-gild] command = "cabal-gild-wrapper" excludes = [] -includes = ["*.cabal", "cabal.project", "cabal.project.local"] +includes = [ + "*.cabal", + "cabal.project", + "cabal.project.local", + "*.chs", + "*.cpphs", + "*.gc", + "*.hs", + "*.hsc", + "*.hsig", + "*.lhs", + "*.lhsig", + "*.ly", + "*.x", + "*.y", +] options = [] diff --git a/programs/cabal-fmt.nix b/programs/cabal-fmt.nix index f72895d..c19428c 100644 --- a/programs/cabal-fmt.nix +++ b/programs/cabal-fmt.nix @@ -1,4 +1,13 @@ -{ mkFormatterModule, ... }: +{ + lib, + config, + pkgs, + mkFormatterModule, + ... +}: +let + cfg = config.programs.cabal-fmt; +in { meta.maintainers = [ ]; @@ -10,7 +19,51 @@ "cabal-fmt" ]; args = [ "--inplace" ]; - includes = [ "*.cabal" ]; + includes = [ + "*.cabal" + # Include Haskell source files to detect changes + # for cabal-fmt's module discovery feature + "*.chs" + "*.cpphs" + "*.gc" + "*.hs" + "*.hsc" + "*.hsig" + "*.lhs" + "*.lhsig" + "*.ly" + "*.x" + "*.y" + ]; }) ]; + + config = lib.mkIf cfg.enable { + settings.formatter.cabal-fmt = { + # Override command to filter out non-cabal files + command = pkgs.writeShellApplication { + name = "cabal-fmt-wrapper"; + text = '' + cabal_files=() + for file in "$@"; do + # Only process .cabal files + case "$file" in + *.cabal) + cabal_files+=("$file") + ;; + *) + # Skip non-cabal files (e.g., .hs files) + ;; + esac + done + + if [ ''${#cabal_files[@]} -gt 0 ]; then + ${lib.getExe cfg.package} --inplace "''${cabal_files[@]}" + fi + ''; + }; + # Clear args since we're handling them in the wrapper + options = lib.mkForce [ ]; + }; + }; } diff --git a/programs/cabal-gild.nix b/programs/cabal-gild.nix index 8bf94ac..47b0b8d 100644 --- a/programs/cabal-gild.nix +++ b/programs/cabal-gild.nix @@ -1,8 +1,8 @@ { - mkFormatterModule, lib, config, pkgs, + mkFormatterModule, ... }: @@ -23,6 +23,19 @@ in "*.cabal" "cabal.project" "cabal.project.local" + # Include Haskell source files to detect changes + # for cabal-gild's module discovery feature + "*.chs" + "*.cpphs" + "*.gc" + "*.hs" + "*.hsc" + "*.hsig" + "*.lhs" + "*.lhsig" + "*.ly" + "*.x" + "*.y" ]; }) ]; @@ -35,7 +48,15 @@ in name = "cabal-gild-wrapper"; text = '' for file in "$@"; do - ${lib.getExe cfg.package} --io="$file" + # Only process .cabal files and cabal.project files + case "$file" in + *.cabal|cabal.project|cabal.project.local) + ${lib.getExe cfg.package} --io="$file" + ;; + *) + # Skip non-cabal files (e.g., .hs files) + ;; + esac done ''; }; From dc6e962f92804623a292f5f1444033e2ba780476 Mon Sep 17 00:00:00 2001 From: ncaq Date: Tue, 16 Sep 2025 15:00:50 +0900 Subject: [PATCH 2/3] fix(cabal-fmt): remove `--inplace` argument To use manual script. --- programs/cabal-fmt.nix | 1 - 1 file changed, 1 deletion(-) diff --git a/programs/cabal-fmt.nix b/programs/cabal-fmt.nix index c19428c..c6c5175 100644 --- a/programs/cabal-fmt.nix +++ b/programs/cabal-fmt.nix @@ -18,7 +18,6 @@ in "haskellPackages" "cabal-fmt" ]; - args = [ "--inplace" ]; includes = [ "*.cabal" # Include Haskell source files to detect changes From 52166107b42160b6c29d5472e7d6bc12497b93e4 Mon Sep 17 00:00:00 2001 From: ncaq Date: Tue, 16 Sep 2025 14:57:19 +0900 Subject: [PATCH 3/3] fix(nix): simplify cabal wrappers to execute speculatively - Drop file filtering loops in cabal-fmt.nix and cabal-gild.nix - Use git ls-files -z | xargs to run formatter on all .cabal files - Avoid strict detection of cabal file args to simplify wrapper logic --- programs/cabal-fmt.nix | 23 +++++------------------ programs/cabal-gild.nix | 18 +++++------------- 2 files changed, 10 insertions(+), 31 deletions(-) diff --git a/programs/cabal-fmt.nix b/programs/cabal-fmt.nix index c6c5175..979fc86 100644 --- a/programs/cabal-fmt.nix +++ b/programs/cabal-fmt.nix @@ -42,24 +42,11 @@ in # Override command to filter out non-cabal files command = pkgs.writeShellApplication { name = "cabal-fmt-wrapper"; - text = '' - cabal_files=() - for file in "$@"; do - # Only process .cabal files - case "$file" in - *.cabal) - cabal_files+=("$file") - ;; - *) - # Skip non-cabal files (e.g., .hs files) - ;; - esac - done - - if [ ''${#cabal_files[@]} -gt 0 ]; then - ${lib.getExe cfg.package} --inplace "''${cabal_files[@]}" - fi - ''; + # The cabal file needs to be formatted by a formatter along with other Haskell source code. + # For example, module completion by `cabal-fmt: discover`. + # It is difficult to determine this strictly. + # Since formatting with cabal-fmt doesn't take much time, we execute it speculatively. + text = ''${pkgs.git}/bin/git ls-files -z "*.cabal"|${pkgs.parallel}/bin/parallel --null "${lib.getExe cfg.package} --inplace {}"''; }; # Clear args since we're handling them in the wrapper options = lib.mkForce [ ]; diff --git a/programs/cabal-gild.nix b/programs/cabal-gild.nix index 47b0b8d..81583b6 100644 --- a/programs/cabal-gild.nix +++ b/programs/cabal-gild.nix @@ -46,19 +46,11 @@ in # https://github.com/tfausak/cabal-gild/issues/35 command = pkgs.writeShellApplication { name = "cabal-gild-wrapper"; - text = '' - for file in "$@"; do - # Only process .cabal files and cabal.project files - case "$file" in - *.cabal|cabal.project|cabal.project.local) - ${lib.getExe cfg.package} --io="$file" - ;; - *) - # Skip non-cabal files (e.g., .hs files) - ;; - esac - done - ''; + # The cabal file needs to be formatted by a formatter along with other Haskell source code. + # For example, module completion by `cabal-gild: discover`. + # It is difficult to determine this strictly. + # Since formatting with cabal-gild doesn't take much time, we execute it speculatively. + text = ''${pkgs.git}/bin/git ls-files -z "*.cabal"|${pkgs.parallel}/bin/parallel --null "${lib.getExe cfg.package} --io {}"''; }; }; };