diff --git a/README.md b/README.md index c34bc17320..9f598d63b9 100644 --- a/README.md +++ b/README.md @@ -393,6 +393,7 @@ Usage: ruff [OPTIONS] Commands: check Run Ruff on the given files or directories (default) rule Explain a rule + config List or describe the available configuration options linter List all supported upstream linters clean Clear any caches in the current directory and any subdirectories help Print this message or the help of the given subcommand(s) diff --git a/crates/ruff_cli/src/args.rs b/crates/ruff_cli/src/args.rs index 784f0a9236..70110d8ba1 100644 --- a/crates/ruff_cli/src/args.rs +++ b/crates/ruff_cli/src/args.rs @@ -44,6 +44,8 @@ pub enum Command { #[arg(long, value_enum, default_value = "pretty")] format: HelpFormat, }, + /// List or describe the available configuration options + Config { option: Option }, /// List all supported upstream linters Linter { /// Output format diff --git a/crates/ruff_cli/src/commands/config.rs b/crates/ruff_cli/src/commands/config.rs new file mode 100644 index 0000000000..88d58ab8ec --- /dev/null +++ b/crates/ruff_cli/src/commands/config.rs @@ -0,0 +1,48 @@ +use ruff::settings::{ + options::Options, + options_base::{ConfigurationOptions, OptionEntry, OptionField}, +}; + +use crate::ExitStatus; + +#[allow(clippy::print_stdout)] +pub(crate) fn config(option: Option<&str>) -> ExitStatus { + let entries = Options::get_available_options(); + let mut entries = &entries; + + let mut parts_iter = option.iter().flat_map(|s| s.split('.')); + + while let Some(part) = parts_iter.next() { + let Some((_, field)) = entries.iter().find(|(name, _)| *name == part) else { + println!("Unknown option"); + return ExitStatus::Error; + }; + match field { + OptionEntry::Field(OptionField { + doc, + default, + value_type, + example, + }) => { + if parts_iter.next().is_some() { + println!("Unknown option"); + return ExitStatus::Error; + } + + println!("{doc}"); + println!(); + println!("Default value: {default}"); + println!("Type: {value_type}"); + println!("Example usage:\n```toml\n{example}\n```"); + return ExitStatus::Success; + } + OptionEntry::Group(fields) => { + entries = fields; + } + } + } + for (name, _) in entries { + println!("{name}"); + } + ExitStatus::Success +} diff --git a/crates/ruff_cli/src/commands/mod.rs b/crates/ruff_cli/src/commands/mod.rs index a4deee4a14..bc08aa1cd8 100644 --- a/crates/ruff_cli/src/commands/mod.rs +++ b/crates/ruff_cli/src/commands/mod.rs @@ -9,6 +9,7 @@ pub use show_settings::show_settings; mod add_noqa; mod clean; +pub mod config; mod linter; mod rule; mod run; diff --git a/crates/ruff_cli/src/main.rs b/crates/ruff_cli/src/main.rs index 26d6731549..d8ed2bc85e 100644 --- a/crates/ruff_cli/src/main.rs +++ b/crates/ruff_cli/src/main.rs @@ -101,6 +101,7 @@ quoting the executed command, along with the relevant file contents and `pyproje match command { Command::Rule { rule, format } => commands::rule(&rule, format)?, + Command::Config { option } => return Ok(commands::config::config(option.as_deref())), Command::Linter { format } => commands::linter(format)?, Command::Clean => commands::clean(log_level)?, Command::GenerateShellCompletion { shell } => {