diff --git a/modules/hooks.nix b/modules/hooks.nix index bb8ce86a..98afee10 100644 --- a/modules/hooks.nix +++ b/modules/hooks.nix @@ -2,7 +2,7 @@ let inherit (config) hooks tools settings; cfg = config; - inherit (lib) flatten mapAttrs mapAttrsToList mkDefault mkOption mkRenamedOptionModule types; + inherit (lib) flatten mapAttrs mapAttrsToList mkDefault mkOption mkRemovedOptionModule mkRenamedOptionModule types; cargoManifestPathArg = lib.optionalString @@ -27,16 +27,27 @@ in imports = # Rename `settings..package` to `hooks..package` map (name: mkRenamedOptionModule [ "settings" name "package" ] [ "hooks" name "package" ]) [ "alejandra" "eclint" "flynt" "mdl" "treefmt" ] - # Manually rename options that had a package option + # These options were renamed in 20fbe2c9731810b1020572a2cb6cbf64e3dd3873 to avoid shadowing + ++ map (name: mkRenamedOptionModule [ "settings" name "config" ] [ "hooks" name "settings" "configuration" ]) [ "lua-ls" "markdownlint" "typos" "vale" ] + ++ [ + (mkRemovedOptionModule [ "settings" "yamllint" "relaxed" ] '' + This option has been removed. Use `hooks.yamllint.settings.preset = "relaxed"`. + '') + ] + # Manually rename options that had a package or a config option ++ flatten (mapAttrsToList (name: map (o: mkRenamedOptionModule [ "settings" name o ] [ "hooks" name "settings" o ])) { "alejandra" = [ "check" "exclude" "threads" "verbosity" ]; "eclint" = [ "fix" "summary" "color" "exclude" "verbosity" ]; "flynt" = [ "aggressive" "binPath" "dry-run" "exclude" "fail-on-change" "line-length" "no-multiline" "quiet" "string" "transform-concats" "verbose" ]; "mdl" = [ "configPath" "git-recurse" "ignore-front-matter" "json" "rules" "rulesets" "show-aliases" "warnings" "skip-default-ruleset" "style" "tags" "verbose" ]; + "lua-ls" = [ "checklevel" ]; + "typos" = [ "binary" "color" "configPath" "diff" "exclude" "format" "hidden" "ignored-words" "locale" "no-check-filenames" "no-check-files" "no-unicode" "quiet" "verbose" "write" ]; + "vale" = [ "configPath" "flags" ]; + "yamllint" = [ "configPath" ]; }) # Rename the remaining `settings.` to `hooks..settings` ++ map (name: mkRenamedOptionModule [ "settings" name ] [ "hooks" name "settings" ]) - [ "ansible-lint" "autoflake" "clippy" "cmake-format" "credo" "deadnix" "denofmt" "denolint" "dune-fmt" "eslint" "flake8" "headache" "hlint" "hpack" "isort" "latexindent" "lua-ls" "lychee" "markdownlint" "mkdocs-linkcheck" "mypy" "nixfmt" "ormolu" "php-cs-fixer" "phpcbf" "phpcs" "phpstan" "prettier" "psalm" "pylint" "pyright" "pyupgrade" "revive" "rome" "statix" "typos" "vale" "yamllint" ]; + [ "ansible-lint" "autoflake" "clippy" "cmake-format" "credo" "deadnix" "denofmt" "denolint" "dune-fmt" "eslint" "flake8" "headache" "hlint" "hpack" "isort" "latexindent" "lychee" "mkdocs-linkcheck" "mypy" "nixfmt" "ormolu" "php-cs-fixer" "phpcbf" "phpcs" "phpstan" "prettier" "psalm" "pylint" "pyright" "pyupgrade" "revive" "rome" "statix" ]; options.hookModule = lib.mkOption { type = types.deferredModule; @@ -594,7 +605,7 @@ in "The diagnostic check level"; default = "Warning"; }; - config = mkOption { + configuration = mkOption { type = types.attrs; description = lib.mdDoc "See https://github.com/LuaLS/lua-language-server/wiki/Configuration-File#luarcjson"; @@ -628,7 +639,7 @@ in type = types.submodule { imports = [ hookModule ]; options.settings = { - config = + configuration = mkOption { type = types.attrs; description = lib.mdDoc @@ -1416,7 +1427,7 @@ in description = lib.mdDoc "When to use generate output."; default = "auto"; }; - config = + configuration = mkOption { type = types.str; description = lib.mdDoc "Multiline-string configuration passed as config file. If set, config set in `typos.settings.configPath` gets ignored."; @@ -1537,7 +1548,7 @@ in type = types.submodule { imports = [ hookModule ]; options.settings = { - config = + configuration = mkOption { type = types.str; description = lib.mdDoc "Multiline-string configuration passed as config file."; @@ -1568,19 +1579,53 @@ in type = types.submodule { imports = [ hookModule ]; options.settings = { - relaxed = mkOption { - type = types.bool; - description = lib.mdDoc "Whether to use the relaxed configuration."; - default = false; - }; + # `list-files` is not useful for a pre-commit hook as it always exits with exit code 0 + # `no-warnings` is not useful for a pre-commit hook as it exits with exit code 2 and the hook + # therefore fails when warnings level problems are detected but there is no output + configuration = mkOption { + type = types.str; + description = lib.mdDoc "Multiline-string configuration passed as config file. If set, configuration file set in `yamllint.settings.configPath` gets ignored."; + default = ""; + example = '' + --- + + extends: relaxed + rules: + indentation: enable + ''; + }; + configData = mkOption { + type = types.str; + description = lib.mdDoc "Serialized YAML object describing the configuration."; + default = ""; + example = "{extends: relaxed, rules: {line-length: {max: 120}}}"; + }; configPath = mkOption { type = types.str; - description = lib.mdDoc "Path to the YAML configuration file."; - # an empty string translates to use default configuration of the - # underlying yamllint binary + description = lib.mdDoc "Path to a custom configuration file."; + # An empty string translates to yamllint looking for a configuration file in the + # following locations (by order of preference): + # a file named .yamllint, .yamllint.yaml or .yamllint.yml in the current working directory + # a filename referenced by $YAMLLINT_CONFIG_FILE, if set + # a file named $XDG_CONFIG_HOME/yamllint/config or ~/.config/yamllint/config, if present default = ""; }; + format = mkOption { + type = types.enum [ "parsable" "standard" "colored" "github" "auto" ]; + description = lib.mdDoc "Format for parsing output."; + default = "auto"; + }; + preset = mkOption { + type = types.enum [ "default" "relaxed" ]; + description = lib.mdDoc "The configuration preset to use."; + default = "default"; + }; + strict = mkOption { + type = types.bool; + description = lib.mdDoc "Return non-zero exit code on warnings as well as errors."; + default = true; + }; }; }; }; @@ -2483,7 +2528,7 @@ lib.escapeShellArgs (lib.concatMap (ext: [ "--ghc-opt" "-X${ext}" ]) hooks.ormol let # .luarc.json has to be in a directory, # or lua-language-server will hang forever. - luarc = pkgs.writeText ".luarc.json" (builtins.toJSON hooks.lua-ls.settings.config); + luarc = pkgs.writeText ".luarc.json" (builtins.toJSON hooks.lua-ls.settings.configuration); luarc-dir = pkgs.stdenv.mkDerivation { name = "luarc"; unpackPhase = "true"; @@ -2547,7 +2592,7 @@ lib.escapeShellArgs (lib.concatMap (ext: [ "--ghc-opt" "-X${ext}" ]) hooks.ormol name = "markdownlint"; description = "Style checker and linter for markdown files."; package = tools.markdownlint-cli; - entry = "${hooks.markdownlint.package}/bin/markdownlint -c ${pkgs.writeText "markdownlint.json" (builtins.toJSON hooks.markdownlint.settings.config)}"; + entry = "${hooks.markdownlint.package}/bin/markdownlint -c ${pkgs.writeText "markdownlint.json" (builtins.toJSON hooks.markdownlint.settings.configuration)}"; files = "\\.md$"; }; mdl = @@ -3262,15 +3307,15 @@ lib.escapeShellArgs (lib.concatMap (ext: [ "--ghc-opt" "-X${ext}" ]) hooks.ormol entry = let # Concatenate config in config file with section for ignoring words generated from list of words to ignore - config = "${hooks.typos.settings.config}" + lib.strings.optionalString (hooks.typos.settings.ignored-words != [ ]) "\n\[default.extend-words\]" + lib.strings.concatMapStrings (x: "\n${x} = \"${x}\"") hooks.typos.settings.ignored-words; - configFile = builtins.toFile "typos-config.toml" config; + configuration = "${hooks.typos.settings.configuration}" + lib.strings.optionalString (hooks.typos.settings.ignored-words != [ ]) "\n\[default.extend-words\]" + lib.strings.concatMapStrings (x: "\n${x} = \"${x}\"") hooks.typos.settings.ignored-words; + configFile = builtins.toFile "typos-config.toml" configuration; cmdArgs = mkCmdArgs (with hooks.typos.settings; [ [ binary "--binary" ] [ (color != "auto") "--color ${color}" ] - [ (config != "") "--config ${configFile}" ] - [ (configPath != "" && config == "") "--config ${configPath}" ] + [ (configuration != "") "--config ${configFile}" ] + [ (configPath != "" && configuration == "") "--config ${configPath}" ] [ diff "--diff" ] [ (exclude != "") "--exclude ${exclude} --force-exclude" ] [ (format != "long") "--format ${format}" ] @@ -3306,7 +3351,7 @@ lib.escapeShellArgs (lib.concatMap (ext: [ "--ghc-opt" "-X${ext}" ]) hooks.ormol mkCmdArgs (with hooks.vale.settings; [ [ (configPath != "") " --config ${configPath}" ] - [ (config != "" && configPath == "") " --config ${configFile}" ] + [ (configuration != "" && configPath == "") " --config ${configFile}" ] ]); in "${hooks.vale.package}/bin/vale${cmdArgs} ${hooks.vale.settings.flags}"; @@ -3315,16 +3360,23 @@ lib.escapeShellArgs (lib.concatMap (ext: [ "--ghc-opt" "-X${ext}" ]) hooks.ormol yamllint = { name = "yamllint"; - description = "Yaml linter."; + description = "Linter for YAML files."; types = [ "file" "yaml" ]; package = tools.yamllint; entry = let + configFile = builtins.toFile "yamllint.yaml" "${hooks.yamllint.settings.configuration}"; cmdArgs = - mkCmdArgs [ - [ (hooks.yamllint.settings.relaxed) "-d relaxed" ] - [ (hooks.yamllint.settings.configPath != "") "-c ${hooks.yamllint.settings.configPath}" ] - ]; + mkCmdArgs + (with hooks.yamllint.settings; [ + # Priorize multiline configuration over serialized configuration and configuration file + [ (configuration != "") "--config-file ${configFile}" ] + [ (configData != "" && configuration == "") "--config-data \"${configData}\"" ] + [ (configPath != "" && configData == "" && configuration == "" && preset == "default") "--config-file ${configPath}" ] + [ (format != "auto") "--format ${format}" ] + [ (preset != "default" && configuration == "") "--config-data ${preset}" ] + [ strict "--strict" ] + ]); in "${hooks.yamllint.package}/bin/yamllint ${cmdArgs}"; };