Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
60 changes: 60 additions & 0 deletions crates/prek/src/cli/list_builtins.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
use std::fmt::Write;

use owo_colors::OwoColorize;
use serde::Serialize;
use strum::IntoEnumIterator;

use crate::cli::{ExitStatus, ListOutputFormat};
use crate::config::BuiltinHook;
use crate::hooks::BuiltinHooks;
use crate::printer::Printer;

#[derive(Serialize)]
struct SerializableBuiltinHook {
id: String,
name: String,
description: Option<String>,
}

/// List all builtin hooks.
pub(crate) fn list_builtins(
output_format: ListOutputFormat,
verbose: bool,
printer: Printer,
) -> anyhow::Result<ExitStatus> {
let hooks = BuiltinHooks::iter().map(|variant| {
let id = variant.as_ref();
BuiltinHook::from_id(id).expect("All BuiltinHooks variants should be valid")
});

match output_format {
ListOutputFormat::Text => {
if verbose {
for hook in hooks {
writeln!(printer.stdout(), "{}", hook.id.bold())?;
if let Some(description) = &hook.options.description {
writeln!(printer.stdout(), " {description}")?;
}
writeln!(printer.stdout())?;
}
} else {
for hook in hooks {
writeln!(printer.stdout(), "{}", hook.id)?;
}
}
}
ListOutputFormat::Json => {
let serializable: Vec<_> = hooks
.map(|h| SerializableBuiltinHook {
id: h.id,
name: h.name,
description: h.options.description,
})
.collect();
let json_output = serde_json::to_string_pretty(&serializable)?;
writeln!(printer.stdout(), "{json_output}")?;
}
}

Ok(ExitStatus::Success)
}
11 changes: 11 additions & 0 deletions crates/prek/src/cli/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ mod hook_impl;
mod identify;
mod install;
mod list;
mod list_builtins;
pub mod reporter;
pub mod run;
mod sample_config;
Expand All @@ -38,6 +39,7 @@ pub(crate) use hook_impl::hook_impl;
pub(crate) use identify::identify;
pub(crate) use install::{init_template_dir, install, install_hooks, uninstall};
pub(crate) use list::list;
pub(crate) use list_builtins::list_builtins;
pub(crate) use run::run;
pub(crate) use sample_config::sample_config;
#[cfg(feature = "self-update")]
Expand Down Expand Up @@ -518,6 +520,13 @@ pub(crate) enum IdentifyOutputFormat {
Json,
}

#[derive(Debug, Clone, Default, Args)]
pub(crate) struct ListBuiltinsArgs {
/// The output format.
#[arg(long, value_enum, default_value_t = ListOutputFormat::Text)]
pub(crate) output_format: ListOutputFormat,
}

#[derive(Debug, Clone, Default, Args)]
pub(crate) struct ListArgs {
/// Include the specified hooks or projects.
Expand Down Expand Up @@ -722,6 +731,8 @@ pub(crate) struct UtilNamespace {
pub(crate) enum UtilCommand {
/// Show file identification tags.
Identify(IdentifyArgs),
/// List all built-in hooks bundled with prek.
ListBuiltins(ListBuiltinsArgs),
/// Install hook script in a directory intended for use with `git config init.templateDir`.
#[command(alias = "init-templatedir")]
InitTemplateDir(InitTemplateDirArgs),
Expand Down
12 changes: 11 additions & 1 deletion crates/prek/src/hooks/builtin_hooks/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,17 @@ use crate::store::Store;

mod check_json5;

#[derive(Debug, Copy, Clone, PartialEq, Eq, strum::AsRefStr, strum::Display, strum::EnumString)]
#[derive(
Debug,
Copy,
Clone,
PartialEq,
Eq,
strum::AsRefStr,
strum::Display,
strum::EnumIter,
strum::EnumString,
)]
#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
#[cfg_attr(feature = "schemars", schemars(rename_all = "kebab-case"))]
#[strum(serialize_all = "kebab-case")]
Expand Down
5 changes: 5 additions & 0 deletions crates/prek/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -384,6 +384,11 @@ async fn run(cli: Cli) -> Result<ExitStatus> {

cli::identify(&args.paths, args.output_format, printer)
}
UtilCommand::ListBuiltins(args) => {
show_settings!(args);

cli::list_builtins(args.output_format, cli.globals.verbose > 0, printer)
}
UtilCommand::InitTemplateDir(args) => {
show_settings!(args);

Expand Down
187 changes: 187 additions & 0 deletions crates/prek/tests/list_builtins.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,187 @@
use crate::common::{TestContext, cmd_snapshot};

mod common;

#[test]
fn list_builtins_basic() {
let context = TestContext::new();

cmd_snapshot!(context.filters(), context.command().arg("util").arg("list-builtins"), @r"
success: true
exit_code: 0
----- stdout -----
check-added-large-files
check-case-conflict
check-executables-have-shebangs
check-json
check-json5
check-merge-conflict
check-symlinks
check-toml
check-xml
check-yaml
detect-private-key
end-of-file-fixer
fix-byte-order-marker
mixed-line-ending
no-commit-to-branch
trailing-whitespace

----- stderr -----
");
}

#[test]
fn list_builtins_verbose() {
let context = TestContext::new();

cmd_snapshot!(context.filters(), context.command().arg("util").arg("list-builtins").arg("--verbose"), @r"
success: true
exit_code: 0
----- stdout -----
check-added-large-files
prevents giant files from being committed.

check-case-conflict
checks for files that would conflict in case-insensitive filesystems

check-executables-have-shebangs
ensures that (non-binary) executables have a shebang.

check-json
checks json files for parseable syntax.

check-json5
checks json5 files for parseable syntax.

check-merge-conflict
checks for files that contain merge conflict strings.

check-symlinks
checks for symlinks which do not point to anything.

check-toml
checks toml files for parseable syntax.

check-xml
checks xml files for parseable syntax.

check-yaml
checks yaml files for parseable syntax.

detect-private-key
detects the presence of private keys.

end-of-file-fixer
ensures that a file is either empty, or ends with one newline.

fix-byte-order-marker
removes utf-8 byte order marker.

mixed-line-ending
replaces or checks mixed line ending.

no-commit-to-branch

trailing-whitespace
trims trailing whitespace.


----- stderr -----
");
}

#[test]
fn list_builtins_json() {
let context = TestContext::new();

cmd_snapshot!(context.filters(), context.command().arg("util").arg("list-builtins").arg("--output-format=json"), @r#"
success: true
exit_code: 0
----- stdout -----
[
{
"id": "check-added-large-files",
"name": "check for added large files",
"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"
},
{
"id": "check-executables-have-shebangs",
"name": "check that executables have shebangs",
"description": "ensures that (non-binary) executables have a shebang."
},
{
"id": "check-json",
"name": "check json",
"description": "checks json files for parseable syntax."
},
{
"id": "check-json5",
"name": "check json5",
"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."
},
{
"id": "check-symlinks",
"name": "check for broken symlinks",
"description": "checks for symlinks which do not point to anything."
},
{
"id": "check-toml",
"name": "check toml",
"description": "checks toml files for parseable syntax."
},
{
"id": "check-xml",
"name": "check xml",
"description": "checks xml files for parseable syntax."
},
{
"id": "check-yaml",
"name": "check yaml",
"description": "checks yaml files for parseable syntax."
},
{
"id": "detect-private-key",
"name": "detect private key",
"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."
},
{
"id": "fix-byte-order-marker",
"name": "fix utf-8 byte order marker",
"description": "removes utf-8 byte order marker."
},
{
"id": "mixed-line-ending",
"name": "mixed line ending",
"description": "replaces or checks mixed line ending."
},
{
"id": "no-commit-to-branch",
"name": "don't commit to branch",
"description": null
},
{
"id": "trailing-whitespace",
"name": "trim trailing whitespace",
"description": "trims trailing whitespace."
}
]

----- stderr -----
"#);
}
37 changes: 37 additions & 0 deletions docs/cli.md
Original file line number Diff line number Diff line change
Expand Up @@ -810,6 +810,7 @@ prek util [OPTIONS] <COMMAND>
<h3 class="cli-reference">Commands</h3>

<dl class="cli-reference"><dt><a href="#prek-util-identify"><code>prek util identify</code></a></dt><dd><p>Show file identification tags</p></dd>
<dt><a href="#prek-util-list-builtins"><code>prek util list-builtins</code></a></dt><dd><p>List all built-in hooks bundled with prek</p></dd>
<dt><a href="#prek-util-init-template-dir"><code>prek util init-template-dir</code></a></dt><dd><p>Install hook script in a directory intended for use with <code>git config init.templateDir</code></p></dd>
<dt><a href="#prek-util-yaml-to-toml"><code>prek util yaml-to-toml</code></a></dt><dd><p>Convert a YAML configuration file to prek.toml</p></dd>
</dl>
Expand Down Expand Up @@ -855,6 +856,42 @@ prek util identify [OPTIONS] [PATH]...
</dd><dt id="prek-util-identify--version"><a href="#prek-util-identify--version"><code>--version</code></a>, <code>-V</code></dt><dd><p>Display the prek version</p>
</dd></dl>

### prek util list-builtins

List all built-in hooks bundled with prek

<h3 class="cli-reference">Usage</h3>

```
prek util list-builtins [OPTIONS]
```

<h3 class="cli-reference">Options</h3>

<dl class="cli-reference"><dt id="prek-util-list-builtins--cd"><a href="#prek-util-list-builtins--cd"><code>--cd</code></a>, <code>-C</code> <i>dir</i></dt><dd><p>Change to directory before running</p>
</dd><dt id="prek-util-list-builtins--color"><a href="#prek-util-list-builtins--color"><code>--color</code></a> <i>color</i></dt><dd><p>Whether to use color in output</p>
<p>May also be set with the <code>PREK_COLOR</code> environment variable.</p><p>[default: auto]</p><p>Possible values:</p>
<ul>
<li><code>auto</code>: Enables colored output only when the output is going to a terminal or TTY with support</li>
<li><code>always</code>: Enables colored output regardless of the detected environment</li>
<li><code>never</code>: Disables colored output</li>
</ul></dd><dt id="prek-util-list-builtins--config"><a href="#prek-util-list-builtins--config"><code>--config</code></a>, <code>-c</code> <i>config</i></dt><dd><p>Path to alternate config file</p>
</dd><dt id="prek-util-list-builtins--help"><a href="#prek-util-list-builtins--help"><code>--help</code></a>, <code>-h</code></dt><dd><p>Display the concise help for this command</p>
</dd><dt id="prek-util-list-builtins--log-file"><a href="#prek-util-list-builtins--log-file"><code>--log-file</code></a> <i>log-file</i></dt><dd><p>Write trace logs to the specified file. If not specified, trace logs will be written to <code>$PREK_HOME/prek.log</code></p>
</dd><dt id="prek-util-list-builtins--no-progress"><a href="#prek-util-list-builtins--no-progress"><code>--no-progress</code></a></dt><dd><p>Hide all progress outputs.</p>
<p>For example, spinners or progress bars.</p>
</dd><dt id="prek-util-list-builtins--output-format"><a href="#prek-util-list-builtins--output-format"><code>--output-format</code></a> <i>output-format</i></dt><dd><p>The output format</p>
<p>[default: text]</p><p>Possible values:</p>
<ul>
<li><code>text</code></li>
<li><code>json</code></li>
</ul></dd><dt id="prek-util-list-builtins--quiet"><a href="#prek-util-list-builtins--quiet"><code>--quiet</code></a>, <code>-q</code></dt><dd><p>Use quiet output.</p>
<p>Repeating this option, e.g., <code>-qq</code>, will enable a silent mode in which prek will write no output to stdout.</p>
<p>May also be set with the <code>PREK_QUIET</code> environment variable.</p></dd><dt id="prek-util-list-builtins--refresh"><a href="#prek-util-list-builtins--refresh"><code>--refresh</code></a></dt><dd><p>Refresh all cached data</p>
</dd><dt id="prek-util-list-builtins--verbose"><a href="#prek-util-list-builtins--verbose"><code>--verbose</code></a>, <code>-v</code></dt><dd><p>Use verbose output</p>
</dd><dt id="prek-util-list-builtins--version"><a href="#prek-util-list-builtins--version"><code>--version</code></a>, <code>-V</code></dt><dd><p>Display the prek version</p>
</dd></dl>

### prek util init-template-dir

Install hook script in a directory intended for use with `git config init.templateDir`
Expand Down
Loading