diff --git a/crates/prek/src/cli/list_builtins.rs b/crates/prek/src/cli/list_builtins.rs index c07ad849f..7d416ed6a 100644 --- a/crates/prek/src/cli/list_builtins.rs +++ b/crates/prek/src/cli/list_builtins.rs @@ -24,28 +24,35 @@ pub(crate) fn list_builtins( ) -> anyhow::Result { let hooks = BuiltinHooks::iter().map(|variant| { let id = variant.as_ref(); - BuiltinHook::from_id(id).expect("All BuiltinHooks variants should be valid") + let hook = BuiltinHook::from_id(id).expect("All BuiltinHooks variants should be valid"); + (variant, hook) }); match output_format { ListOutputFormat::Text => { if verbose { - for hook in hooks { + for (variant, hook) in hooks { writeln!(printer.stdout_important(), "{}", hook.id.bold())?; if let Some(description) = &hook.options.description { writeln!(printer.stdout_important(), " {description}")?; } + if let Some(flags_help) = variant.flags_help() { + writeln!(printer.stdout_important(), " flags:")?; + for line in flags_help.lines() { + writeln!(printer.stdout_important(), " {line}")?; + } + } writeln!(printer.stdout_important())?; } } else { - for hook in hooks { + for (_, hook) in hooks { writeln!(printer.stdout_important(), "{}", hook.id)?; } } } ListOutputFormat::Json => { let serializable: Vec<_> = hooks - .map(|h| SerializableBuiltinHook { + .map(|(_, h)| SerializableBuiltinHook { id: h.id, name: h.name, description: h.options.description, diff --git a/crates/prek/src/hooks/builtin_hooks/mod.rs b/crates/prek/src/hooks/builtin_hooks/mod.rs index 7b5871ed2..13a968974 100644 --- a/crates/prek/src/hooks/builtin_hooks/mod.rs +++ b/crates/prek/src/hooks/builtin_hooks/mod.rs @@ -2,6 +2,7 @@ use std::path::Path; use std::str::FromStr; use anyhow::Result; +use clap::{Command, CommandFactory}; use prek_identify::tags; use crate::cli::run::HookRunReporter; @@ -60,6 +61,30 @@ pub(crate) enum BuiltinHooks { } impl BuiltinHooks { + fn flags_command(self) -> Option { + Some(match self { + Self::CheckAddedLargeFiles => { + pre_commit_hooks::check_added_large_files::Args::command() + } + Self::CheckMergeConflict => pre_commit_hooks::check_merge_conflict::Args::command(), + Self::CheckVcsPermalinks => pre_commit_hooks::check_vcs_permalinks::Args::command(), + Self::CheckYaml => pre_commit_hooks::check_yaml::Args::command(), + Self::DenyPattern | Self::RequirePattern => pattern::Args::command(), + Self::FileContentsSorter => pre_commit_hooks::file_contents_sorter::Args::command(), + Self::MixedLineEnding => pre_commit_hooks::mixed_line_ending::Args::command(), + Self::NoCommitToBranch => pre_commit_hooks::no_commit_to_branch::Args::command(), + Self::PrettyFormatJson => pre_commit_hooks::pretty_format_json::Args::command(), + Self::TrailingWhitespace => pre_commit_hooks::fix_trailing_whitespace::Args::command(), + _ => return None, + }) + } + + pub(crate) fn flags_help(self) -> Option { + let mut command = self.flags_command()?.help_template("{options}"); + let help = command.render_help().to_string(); + if help.is_empty() { None } else { Some(help) } + } + pub(crate) fn may_modify_files(self) -> bool { match self { Self::EndOfFileFixer @@ -175,7 +200,7 @@ impl BuiltinHook { priority: None, groups: None, options: HookOptions { - description: Some("prevents giant files from being committed.".to_string()), + description: Some("Prevents giant files from being committed.".to_string()), stages: Some([Stage::PreCommit, Stage::PrePush, Stage::Manual].into()), ..Default::default() }, @@ -188,7 +213,7 @@ impl BuiltinHook { groups: None, options: HookOptions { description: Some( - "checks for files that would conflict in case-insensitive filesystems" + "Checks for files that would conflict in case-insensitive filesystems." .to_string(), ), ..Default::default() @@ -202,7 +227,7 @@ impl BuiltinHook { groups: None, options: HookOptions { description: Some( - "ensures that (non-binary) executables have a shebang.".to_string(), + "Ensures that (non-binary) executables have a shebang.".to_string(), ), types: Some(tags::TAG_SET_EXECUTABLE_TEXT), stages: Some([Stage::PreCommit, Stage::PrePush, Stage::Manual].into()), @@ -217,7 +242,7 @@ impl BuiltinHook { groups: None, options: HookOptions { description: Some( - "checks for filenames which cannot be created on Windows.".to_string(), + "Checks for filenames which cannot be created on Windows.".to_string(), ), files: Some( FilePattern::regex( @@ -235,7 +260,7 @@ impl BuiltinHook { priority: None, groups: None, options: HookOptions { - description: Some("checks json files for parseable syntax.".to_string()), + description: Some("Checks JSON files for parseable syntax.".to_string()), types: Some(tags::TAG_SET_JSON), ..Default::default() }, @@ -247,7 +272,7 @@ impl BuiltinHook { priority: None, groups: None, options: HookOptions { - description: Some("checks json5 files for parseable syntax.".to_string()), + description: Some("Checks JSON5 files for parseable syntax.".to_string()), types: Some(tags::TAG_SET_JSON5), ..Default::default() }, @@ -260,7 +285,7 @@ impl BuiltinHook { groups: None, options: HookOptions { description: Some( - "checks for files that contain merge conflict strings.".to_string(), + "Checks for files that contain merge conflict strings.".to_string(), ), types: Some(tags::TAG_SET_TEXT), ..Default::default() @@ -274,7 +299,7 @@ impl BuiltinHook { groups: None, options: HookOptions { description: Some( - "ensures that (non-binary) files with a shebang are executable." + "Ensures that (non-binary) files with a shebang are executable." .to_string(), ), types: Some(tags::TAG_SET_TEXT), @@ -290,7 +315,7 @@ impl BuiltinHook { groups: None, options: HookOptions { description: Some( - "checks for symlinks which do not point to anything.".to_string(), + "Checks for symlinks which do not point to anything.".to_string(), ), types: Some(tags::TAG_SET_SYMLINK), ..Default::default() @@ -303,7 +328,7 @@ impl BuiltinHook { priority: None, groups: None, options: HookOptions { - description: Some("checks toml files for parseable syntax.".to_string()), + description: Some("Checks TOML files for parseable syntax.".to_string()), types: Some(tags::TAG_SET_TOML), ..Default::default() }, @@ -316,7 +341,7 @@ impl BuiltinHook { groups: None, options: HookOptions { description: Some( - "ensures that links to vcs websites are permalinks.".to_string(), + "Ensures that links to VCS websites are permalinks.".to_string(), ), types: Some(tags::TAG_SET_TEXT), ..Default::default() @@ -329,7 +354,7 @@ impl BuiltinHook { priority: None, groups: None, options: HookOptions { - description: Some("checks xml files for parseable syntax.".to_string()), + description: Some("Checks XML files for parseable syntax.".to_string()), types: Some(tags::TAG_SET_XML), ..Default::default() }, @@ -341,7 +366,7 @@ impl BuiltinHook { priority: None, groups: None, options: HookOptions { - description: Some("checks yaml files for parseable syntax.".to_string()), + description: Some("Checks YAML files for parseable syntax.".to_string()), types: Some(tags::TAG_SET_YAML), ..Default::default() }, @@ -354,7 +379,7 @@ impl BuiltinHook { groups: None, options: HookOptions { description: Some( - "fails if any file contains a matching regular expression.".to_string(), + "Fails if any file contains a matching regular expression.".to_string(), ), types: Some(tags::TAG_SET_TEXT), ..Default::default() @@ -368,7 +393,7 @@ impl BuiltinHook { groups: None, options: HookOptions { description: Some( - "detects symlinks that were replaced with regular files whose contents are the original symlink target path.".to_string(), + "Detects symlinks that were replaced with regular files whose contents are the original symlink target path.".to_string(), ), types: Some(tags::TAG_SET_FILE), stages: Some([Stage::PreCommit, Stage::PrePush, Stage::Manual].into()), @@ -382,7 +407,7 @@ impl BuiltinHook { priority: None, groups: None, options: HookOptions { - description: Some("detects the presence of private keys.".to_string()), + description: Some("Detects the presence of private keys.".to_string()), types: Some(tags::TAG_SET_TEXT), ..Default::default() }, @@ -395,7 +420,7 @@ impl BuiltinHook { groups: None, options: HookOptions { description: Some( - "ensures that a file is either empty, or ends with one newline." + "Ensures that a file is either empty, or ends with one newline." .to_string(), ), types: Some(tags::TAG_SET_TEXT), @@ -411,7 +436,7 @@ impl BuiltinHook { groups: None, options: HookOptions { description: Some( - "sorts the lines in specified files (defaults to alphabetical)." + "Sorts the lines in specified files (defaults to alphabetical)." .to_string(), ), files: Some(FilePattern::Never), @@ -425,7 +450,7 @@ impl BuiltinHook { priority: None, groups: None, options: HookOptions { - description: Some("removes utf-8 byte order marker.".to_string()), + description: Some("Removes UTF-8 byte order marker.".to_string()), types: Some(tags::TAG_SET_TEXT), ..Default::default() }, @@ -437,7 +462,7 @@ impl BuiltinHook { priority: None, groups: None, options: HookOptions { - description: Some("Prevent addition of new git submodules.".to_string()), + description: Some("Prevents the addition of new Git submodules.".to_string()), types: Some(tags::TAG_SET_DIRECTORY), ..Default::default() }, @@ -449,7 +474,7 @@ impl BuiltinHook { priority: None, groups: None, options: HookOptions { - description: Some("replaces or checks mixed line ending.".to_string()), + description: Some("Replaces or checks mixed line endings.".to_string()), types: Some(tags::TAG_SET_TEXT), ..Default::default() }, @@ -462,7 +487,7 @@ impl BuiltinHook { groups: None, options: HookOptions { description: Some( - "protects specific branches from direct commits.".to_string(), + "Protects specific branches from direct commits.".to_string(), ), pass_filenames: Some(PassFilenames::None), always_run: Some(true), @@ -476,7 +501,7 @@ impl BuiltinHook { priority: None, groups: None, options: HookOptions { - description: Some("checks that JSON files are pretty-formatted.".to_string()), + description: Some("Checks that JSON files are pretty-formatted.".to_string()), types: Some(tags::TAG_SET_JSON), stages: Some([Stage::PreCommit, Stage::PrePush, Stage::Manual].into()), ..Default::default() @@ -490,7 +515,7 @@ impl BuiltinHook { groups: None, options: HookOptions { description: Some( - "fails if any file does not contain a matching regular expression." + "Fails if any file does not contain a matching regular expression." .to_string(), ), types: Some(tags::TAG_SET_TEXT), @@ -504,7 +529,7 @@ impl BuiltinHook { priority: None, groups: None, options: HookOptions { - description: Some("sorts entries in requirements.txt.".to_string()), + description: Some("Sorts entries in requirements.txt.".to_string()), files: Some( FilePattern::regex(r"(requirements|constraints).*\.txt$") .expect("builtin files regex must be valid"), @@ -519,7 +544,7 @@ impl BuiltinHook { priority: None, groups: None, options: HookOptions { - description: Some("trims trailing whitespace.".to_string()), + description: Some("Trims trailing whitespace.".to_string()), types: Some(tags::TAG_SET_TEXT), stages: Some([Stage::PreCommit, Stage::PrePush, Stage::Manual].into()), ..Default::default() diff --git a/crates/prek/src/hooks/builtin_hooks/pattern.rs b/crates/prek/src/hooks/builtin_hooks/pattern.rs index 810c8dc3d..a796cecde 100644 --- a/crates/prek/src/hooks/builtin_hooks/pattern.rs +++ b/crates/prek/src/hooks/builtin_hooks/pattern.rs @@ -15,9 +15,11 @@ use crate::run::INTERNAL_CONCURRENCY; #[command(disable_help_subcommand = true)] #[command(disable_version_flag = true)] #[command(disable_help_flag = true)] -struct Args { +pub(crate) struct Args { + /// Match patterns case-insensitively. #[arg(short = 'i', long)] ignore_case: bool, + /// Search each file as a whole. #[arg(short = 'm', long)] multiline: bool, #[arg(required = true, value_name = "PATTERN")] diff --git a/crates/prek/src/hooks/pre_commit_hooks/check_added_large_files.rs b/crates/prek/src/hooks/pre_commit_hooks/check_added_large_files.rs index ced1d3071..c9e2e2483 100644 --- a/crates/prek/src/hooks/pre_commit_hooks/check_added_large_files.rs +++ b/crates/prek/src/hooks/pre_commit_hooks/check_added_large_files.rs @@ -13,9 +13,11 @@ use crate::run::INTERNAL_CONCURRENCY; #[command(disable_help_subcommand = true)] #[command(disable_version_flag = true)] #[command(disable_help_flag = true)] -struct Args { +pub(crate) struct Args { + /// Check all files, not just those staged for addition. #[arg(long)] enforce_all: bool, + /// Maximum allowed file size in KiB. #[arg(long = "maxkb", default_value = "500")] max_kb: u64, #[arg(value_name = "FILENAMES")] diff --git a/crates/prek/src/hooks/pre_commit_hooks/check_merge_conflict.rs b/crates/prek/src/hooks/pre_commit_hooks/check_merge_conflict.rs index e4c119106..ebb919968 100644 --- a/crates/prek/src/hooks/pre_commit_hooks/check_merge_conflict.rs +++ b/crates/prek/src/hooks/pre_commit_hooks/check_merge_conflict.rs @@ -20,7 +20,8 @@ const SEPARATOR_PATTERNS: &[&[u8]] = &[b"======= ", b"=======\r\n", b"=======\n" #[command(disable_help_subcommand = true)] #[command(disable_version_flag = true)] #[command(disable_help_flag = true)] -struct Args { +pub(crate) struct Args { + /// Run even when no merge or rebase is detected. #[arg(long)] assume_in_merge: bool, #[arg(value_name = "FILENAMES")] diff --git a/crates/prek/src/hooks/pre_commit_hooks/check_vcs_permalinks.rs b/crates/prek/src/hooks/pre_commit_hooks/check_vcs_permalinks.rs index 94184ad63..bfeeaa4ec 100644 --- a/crates/prek/src/hooks/pre_commit_hooks/check_vcs_permalinks.rs +++ b/crates/prek/src/hooks/pre_commit_hooks/check_vcs_permalinks.rs @@ -17,8 +17,9 @@ use crate::run::INTERNAL_CONCURRENCY; #[command(disable_help_subcommand = true)] #[command(disable_version_flag = true)] #[command(disable_help_flag = true)] -struct Args { - #[arg(long = "additional-github-domain")] +pub(crate) struct Args { + /// Additional GitHub-style domain to check (repeatable). + #[arg(long = "additional-github-domain", value_name = "DOMAIN")] additional_github_domains: Vec, #[arg(value_name = "FILENAMES")] filenames: Vec, diff --git a/crates/prek/src/hooks/pre_commit_hooks/check_yaml.rs b/crates/prek/src/hooks/pre_commit_hooks/check_yaml.rs index cb6760a5d..30c5417a7 100644 --- a/crates/prek/src/hooks/pre_commit_hooks/check_yaml.rs +++ b/crates/prek/src/hooks/pre_commit_hooks/check_yaml.rs @@ -13,8 +13,9 @@ use crate::run::INTERNAL_CONCURRENCY; #[command(disable_help_subcommand = true)] #[command(disable_version_flag = true)] #[command(disable_help_flag = true)] -struct Args { - #[arg(long, short = 'm', alias = "multi")] +pub(crate) struct Args { + /// Allow multiple YAML documents. + #[arg(long, short = 'm', visible_alias = "multi")] allow_multiple_documents: bool, #[arg(value_name = "FILENAMES")] filenames: Vec, diff --git a/crates/prek/src/hooks/pre_commit_hooks/file_contents_sorter.rs b/crates/prek/src/hooks/pre_commit_hooks/file_contents_sorter.rs index c974852c5..8799e3d5a 100644 --- a/crates/prek/src/hooks/pre_commit_hooks/file_contents_sorter.rs +++ b/crates/prek/src/hooks/pre_commit_hooks/file_contents_sorter.rs @@ -12,9 +12,11 @@ use crate::run::INTERNAL_CONCURRENCY; #[command(disable_help_subcommand = true)] #[command(disable_version_flag = true)] #[command(disable_help_flag = true)] -struct Args { +pub(crate) struct Args { + /// Sort lines case-insensitively. #[arg(long, conflicts_with = "unique")] ignore_case: bool, + /// Remove duplicate lines. #[arg(long, conflicts_with = "ignore_case")] unique: bool, #[arg(value_name = "FILENAMES")] diff --git a/crates/prek/src/hooks/pre_commit_hooks/fix_trailing_whitespace.rs b/crates/prek/src/hooks/pre_commit_hooks/fix_trailing_whitespace.rs index 7357cb4ca..3f6fa23b5 100644 --- a/crates/prek/src/hooks/pre_commit_hooks/fix_trailing_whitespace.rs +++ b/crates/prek/src/hooks/pre_commit_hooks/fix_trailing_whitespace.rs @@ -26,11 +26,13 @@ impl FromStr for Chars { #[command(disable_help_subcommand = true)] #[command(disable_version_flag = true)] #[command(disable_help_flag = true)] -struct Args { - #[arg(long)] +pub(crate) struct Args { + /// Preserve Markdown hard line breaks for EXT (repeatable). + #[arg(long, value_name = "EXT")] markdown_linebreak_ext: Vec, // `clap` cannot parse `--chars= \t` into vec correctly. // so, we use Chars to achieve it. + /// Trim only these characters. #[arg(long)] chars: Option, #[arg(value_name = "FILENAMES")] diff --git a/crates/prek/src/hooks/pre_commit_hooks/mixed_line_ending.rs b/crates/prek/src/hooks/pre_commit_hooks/mixed_line_ending.rs index 6b2959d70..598876c87 100644 --- a/crates/prek/src/hooks/pre_commit_hooks/mixed_line_ending.rs +++ b/crates/prek/src/hooks/pre_commit_hooks/mixed_line_ending.rs @@ -17,7 +17,7 @@ const CR: &[u8] = b"\r"; #[command(disable_help_subcommand = true)] #[command(disable_version_flag = true)] #[command(disable_help_flag = true)] -struct Args { +pub(crate) struct Args { /// Fix mixed line endings by converting to the most common line ending /// or a specified line ending. #[clap(long, short, value_enum, default_value_t = FixMode::Auto)] diff --git a/crates/prek/src/hooks/pre_commit_hooks/mod.rs b/crates/prek/src/hooks/pre_commit_hooks/mod.rs index d23f85f22..758de9fe3 100644 --- a/crates/prek/src/hooks/pre_commit_hooks/mod.rs +++ b/crates/prek/src/hooks/pre_commit_hooks/mod.rs @@ -10,27 +10,27 @@ use crate::hooks::run_concurrent_file_checks; use super::HookFuture; -mod check_added_large_files; +pub(super) mod check_added_large_files; mod check_case_conflict; mod check_executables_have_shebangs; pub(crate) mod check_json; -mod check_merge_conflict; +pub(super) mod check_merge_conflict; mod check_shebang_scripts_are_executable; mod check_symlinks; mod check_toml; -mod check_vcs_permalinks; +pub(super) mod check_vcs_permalinks; mod check_xml; -mod check_yaml; +pub(super) mod check_yaml; mod destroyed_symlinks; mod detect_private_key; -mod file_contents_sorter; +pub(super) mod file_contents_sorter; mod fix_byte_order_marker; mod fix_end_of_file; -mod fix_trailing_whitespace; +pub(super) mod fix_trailing_whitespace; mod forbid_new_submodules; -mod mixed_line_ending; -mod no_commit_to_branch; -mod pretty_format_json; +pub(super) mod mixed_line_ending; +pub(super) mod no_commit_to_branch; +pub(super) mod pretty_format_json; mod requirements_txt_fixer; mod shebangs; diff --git a/crates/prek/src/hooks/pre_commit_hooks/no_commit_to_branch.rs b/crates/prek/src/hooks/pre_commit_hooks/no_commit_to_branch.rs index 5a93a7e6e..9cc0629a4 100644 --- a/crates/prek/src/hooks/pre_commit_hooks/no_commit_to_branch.rs +++ b/crates/prek/src/hooks/pre_commit_hooks/no_commit_to_branch.rs @@ -9,10 +9,17 @@ use anyhow::{Context, Result}; #[command(disable_help_subcommand = true)] #[command(disable_version_flag = true)] #[command(disable_help_flag = true)] -struct Args { - #[arg(short, long = "branch", default_values = &["main", "master"])] +pub(crate) struct Args { + /// Branch to protect (repeatable). + #[arg( + short, + long = "branch", + value_name = "BRANCH", + default_values = &["main", "master"] + )] branches: Vec, - #[arg(short, long = "pattern")] + /// Regular expression matching branches to protect (repeatable). + #[arg(short, long = "pattern", value_name = "REGEX")] patterns: Vec, } diff --git a/crates/prek/src/hooks/pre_commit_hooks/pretty_format_json.rs b/crates/prek/src/hooks/pre_commit_hooks/pretty_format_json.rs index 642723c39..601efd731 100644 --- a/crates/prek/src/hooks/pre_commit_hooks/pretty_format_json.rs +++ b/crates/prek/src/hooks/pre_commit_hooks/pretty_format_json.rs @@ -17,20 +17,25 @@ use crate::run::INTERNAL_CONCURRENCY; #[command(disable_help_subcommand = true)] #[command(disable_version_flag = true)] #[command(disable_help_flag = true)] -struct Args { +pub(crate) struct Args { + /// Rewrite files in place. #[arg(long = "autofix")] auto_fix: bool, + /// Indentation width or string. #[arg(long, default_value = "2")] indent: String, + /// Keep non-ASCII characters as UTF-8. #[arg(long)] no_ensure_ascii: bool, + /// Preserve object key order. #[arg(long)] no_sort_keys: bool, - #[arg(long, value_delimiter = ',')] + /// Object keys to move to the front, comma-separated. + #[arg(long, value_name = "KEYS", value_delimiter = ',')] top_keys: Vec, #[arg(value_name = "FILENAMES")] filenames: Vec, diff --git a/crates/prek/tests/list_builtins.rs b/crates/prek/tests/list_builtins.rs index f6d9568fa..0d8c3fc03 100644 --- a/crates/prek/tests/list_builtins.rs +++ b/crates/prek/tests/list_builtins.rs @@ -50,82 +50,115 @@ fn list_builtins_verbose() { exit_code: 0 ----- stdout ----- check-added-large-files - prevents giant files from being committed. + Prevents giant files from being committed. + flags: + --enforce-all Check all files, not just those staged for addition + --maxkb Maximum allowed file size in KiB [default: 500] check-case-conflict - checks for files that would conflict in case-insensitive filesystems + Checks for files that would conflict in case-insensitive filesystems. check-executables-have-shebangs - ensures that (non-binary) executables have a shebang. + Ensures that (non-binary) executables have a shebang. check-illegal-windows-names - checks for filenames which cannot be created on Windows. + Checks for filenames which cannot be created on Windows. check-json - checks json files for parseable syntax. + Checks JSON files for parseable syntax. check-json5 - checks json5 files for parseable syntax. + Checks JSON5 files for parseable syntax. check-merge-conflict - checks for files that contain merge conflict strings. + Checks for files that contain merge conflict strings. + flags: + --assume-in-merge Run even when no merge or rebase is detected check-shebang-scripts-are-executable - ensures that (non-binary) files with a shebang are executable. + Ensures that (non-binary) files with a shebang are executable. check-symlinks - checks for symlinks which do not point to anything. + Checks for symlinks which do not point to anything. check-toml - checks toml files for parseable syntax. + Checks TOML files for parseable syntax. check-vcs-permalinks - ensures that links to vcs websites are permalinks. + Ensures that links to VCS websites are permalinks. + flags: + --additional-github-domain Additional GitHub-style domain to check (repeatable) check-xml - checks xml files for parseable syntax. + Checks XML files for parseable syntax. check-yaml - checks yaml files for parseable syntax. + Checks YAML files for parseable syntax. + flags: + -m, --allow-multiple-documents Allow multiple YAML documents [alias: --multi] deny-pattern - fails if any file contains a matching regular expression. + Fails if any file contains a matching regular expression. + flags: + -i, --ignore-case Match patterns case-insensitively + -m, --multiline Search each file as a whole destroyed-symlinks - detects symlinks that were replaced with regular files whose contents are the original symlink target path. + Detects symlinks that were replaced with regular files whose contents are the original symlink target path. detect-private-key - detects the presence of private keys. + Detects the presence of private keys. end-of-file-fixer - ensures that a file is either empty, or ends with one newline. + Ensures that a file is either empty, or ends with one newline. file-contents-sorter - sorts the lines in specified files (defaults to alphabetical). + Sorts the lines in specified files (defaults to alphabetical). + flags: + --ignore-case Sort lines case-insensitively + --unique Remove duplicate lines fix-byte-order-marker - removes utf-8 byte order marker. + Removes UTF-8 byte order marker. forbid-new-submodules - Prevent addition of new git submodules. + Prevents the addition of new Git submodules. mixed-line-ending - replaces or checks mixed line ending. + Replaces or checks mixed line endings. + flags: + -f, --fix Fix mixed line endings by converting to the most common line ending or a + specified line ending [default: auto] [possible values: auto, no, lf, crlf, cr] no-commit-to-branch - protects specific branches from direct commits. + Protects specific branches from direct commits. + flags: + -b, --branch Branch to protect (repeatable) [default: main master] + -p, --pattern Regular expression matching branches to protect (repeatable) pretty-format-json - checks that JSON files are pretty-formatted. + Checks that JSON files are pretty-formatted. + flags: + --autofix Rewrite files in place + --indent Indentation width or string [default: 2] + --no-ensure-ascii Keep non-ASCII characters as UTF-8 + --no-sort-keys Preserve object key order + --top-keys Object keys to move to the front, comma-separated require-pattern - fails if any file does not contain a matching regular expression. + Fails if any file does not contain a matching regular expression. + flags: + -i, --ignore-case Match patterns case-insensitively + -m, --multiline Search each file as a whole requirements-txt-fixer - sorts entries in requirements.txt. + Sorts entries in requirements.txt. trailing-whitespace - trims trailing whitespace. + Trims trailing whitespace. + flags: + --markdown-linebreak-ext Preserve Markdown hard line breaks for EXT (repeatable) + --chars Trim only these characters ----- stderr ----- @@ -144,132 +177,132 @@ fn list_builtins_json() { { "id": "check-added-large-files", "name": "check for added large files", - "description": "prevents giant files from being committed." + "description": "Prevents giant files from being committed." }, { "id": "check-case-conflict", "name": "check for case conflicts", - "description": "checks for files that would conflict in case-insensitive filesystems" + "description": "Checks for files that would conflict in case-insensitive filesystems." }, { "id": "check-executables-have-shebangs", "name": "check that executables have shebangs", - "description": "ensures that (non-binary) executables have a shebang." + "description": "Ensures that (non-binary) executables have a shebang." }, { "id": "check-illegal-windows-names", "name": "check illegal windows names", - "description": "checks for filenames which cannot be created on Windows." + "description": "Checks for filenames which cannot be created on Windows." }, { "id": "check-json", "name": "check json", - "description": "checks json files for parseable syntax." + "description": "Checks JSON files for parseable syntax." }, { "id": "check-json5", "name": "check json5", - "description": "checks json5 files for parseable syntax." + "description": "Checks JSON5 files for parseable syntax." }, { "id": "check-merge-conflict", "name": "check for merge conflicts", - "description": "checks for files that contain merge conflict strings." + "description": "Checks for files that contain merge conflict strings." }, { "id": "check-shebang-scripts-are-executable", "name": "check that scripts with shebangs are executable", - "description": "ensures that (non-binary) files with a shebang are executable." + "description": "Ensures that (non-binary) files with a shebang are executable." }, { "id": "check-symlinks", "name": "check for broken symlinks", - "description": "checks for symlinks which do not point to anything." + "description": "Checks for symlinks which do not point to anything." }, { "id": "check-toml", "name": "check toml", - "description": "checks toml files for parseable syntax." + "description": "Checks TOML files for parseable syntax." }, { "id": "check-vcs-permalinks", "name": "check vcs permalinks", - "description": "ensures that links to vcs websites are permalinks." + "description": "Ensures that links to VCS websites are permalinks." }, { "id": "check-xml", "name": "check xml", - "description": "checks xml files for parseable syntax." + "description": "Checks XML files for parseable syntax." }, { "id": "check-yaml", "name": "check yaml", - "description": "checks yaml files for parseable syntax." + "description": "Checks YAML files for parseable syntax." }, { "id": "deny-pattern", "name": "deny patterns", - "description": "fails if any file contains a matching regular expression." + "description": "Fails if any file contains a matching regular expression." }, { "id": "destroyed-symlinks", "name": "detect destroyed symlinks", - "description": "detects symlinks that were replaced with regular files whose contents are the original symlink target path." + "description": "Detects symlinks that were replaced with regular files whose contents are the original symlink target path." }, { "id": "detect-private-key", "name": "detect private key", - "description": "detects the presence of private keys." + "description": "Detects the presence of private keys." }, { "id": "end-of-file-fixer", "name": "fix end of files", - "description": "ensures that a file is either empty, or ends with one newline." + "description": "Ensures that a file is either empty, or ends with one newline." }, { "id": "file-contents-sorter", "name": "file contents sorter", - "description": "sorts the lines in specified files (defaults to alphabetical)." + "description": "Sorts the lines in specified files (defaults to alphabetical)." }, { "id": "fix-byte-order-marker", "name": "fix utf-8 byte order marker", - "description": "removes utf-8 byte order marker." + "description": "Removes UTF-8 byte order marker." }, { "id": "forbid-new-submodules", "name": "forbid new submodules", - "description": "Prevent addition of new git submodules." + "description": "Prevents the addition of new Git submodules." }, { "id": "mixed-line-ending", "name": "mixed line ending", - "description": "replaces or checks mixed line ending." + "description": "Replaces or checks mixed line endings." }, { "id": "no-commit-to-branch", "name": "don't commit to branch", - "description": "protects specific branches from direct commits." + "description": "Protects specific branches from direct commits." }, { "id": "pretty-format-json", "name": "pretty format json", - "description": "checks that JSON files are pretty-formatted." + "description": "Checks that JSON files are pretty-formatted." }, { "id": "require-pattern", "name": "require patterns", - "description": "fails if any file does not contain a matching regular expression." + "description": "Fails if any file does not contain a matching regular expression." }, { "id": "requirements-txt-fixer", "name": "fix requirements.txt", - "description": "sorts entries in requirements.txt." + "description": "Sorts entries in requirements.txt." }, { "id": "trailing-whitespace", "name": "trim trailing whitespace", - "description": "trims trailing whitespace." + "description": "Trims trailing whitespace." } ]