mirror of
https://github.com/astral-sh/ruff
synced 2026-01-21 13:30:49 -05:00
100 lines
2.8 KiB
Rust
100 lines
2.8 KiB
Rust
//! Generate a Markdown-compatible listing of configuration options.
|
|
|
|
use anyhow::Result;
|
|
use clap::Args;
|
|
use itertools::Itertools;
|
|
use ruff::settings::options::Options;
|
|
use ruff::settings::options_base::{ConfigurationOptions, OptionEntry, OptionField};
|
|
|
|
use crate::utils::replace_readme_section;
|
|
|
|
const BEGIN_PRAGMA: &str = "<!-- Begin auto-generated options sections. -->";
|
|
const END_PRAGMA: &str = "<!-- End auto-generated options sections. -->";
|
|
|
|
#[derive(Args)]
|
|
pub struct Cli {
|
|
/// Write the generated table to stdout (rather than to `README.md`).
|
|
#[arg(long)]
|
|
pub(crate) dry_run: bool,
|
|
}
|
|
|
|
fn emit_field(output: &mut String, field: &OptionField, group_name: Option<&str>) {
|
|
output.push_str(&format!("#### [`{0}`](#{0})\n", field.name));
|
|
output.push('\n');
|
|
output.push_str(field.doc);
|
|
output.push_str("\n\n");
|
|
output.push_str(&format!("**Default value**: `{}`\n", field.default));
|
|
output.push('\n');
|
|
output.push_str(&format!("**Type**: `{}`\n", field.value_type));
|
|
output.push('\n');
|
|
output.push_str(&format!(
|
|
"**Example usage**:\n\n```toml\n[tool.ruff{}]\n{}\n```\n",
|
|
if group_name.is_some() {
|
|
format!(".{}", group_name.unwrap())
|
|
} else {
|
|
String::new()
|
|
},
|
|
field.example
|
|
));
|
|
output.push('\n');
|
|
}
|
|
|
|
pub fn main(cli: &Cli) -> Result<()> {
|
|
let mut output = String::new();
|
|
|
|
// Generate all the top-level fields.
|
|
for field in Options::get_available_options()
|
|
.into_iter()
|
|
.filter_map(|entry| {
|
|
if let OptionEntry::Field(field) = entry {
|
|
Some(field)
|
|
} else {
|
|
None
|
|
}
|
|
})
|
|
.sorted_by_key(|field| field.name)
|
|
{
|
|
emit_field(&mut output, &field, None);
|
|
output.push_str("---\n\n");
|
|
}
|
|
|
|
// Generate all the sub-groups.
|
|
for group in Options::get_available_options()
|
|
.into_iter()
|
|
.filter_map(|entry| {
|
|
if let OptionEntry::Group(group) = entry {
|
|
Some(group)
|
|
} else {
|
|
None
|
|
}
|
|
})
|
|
.sorted_by_key(|group| group.name)
|
|
{
|
|
output.push_str(&format!("### `{}`\n", group.name));
|
|
output.push('\n');
|
|
for field in group
|
|
.fields
|
|
.iter()
|
|
.filter_map(|entry| {
|
|
if let OptionEntry::Field(field) = entry {
|
|
Some(field)
|
|
} else {
|
|
None
|
|
}
|
|
})
|
|
.sorted_by_key(|field| field.name)
|
|
{
|
|
emit_field(&mut output, field, Some(group.name));
|
|
output.push_str("---\n\n");
|
|
}
|
|
}
|
|
|
|
if cli.dry_run {
|
|
print!("{output}");
|
|
} else {
|
|
replace_readme_section(&output, BEGIN_PRAGMA, END_PRAGMA)?;
|
|
}
|
|
|
|
Ok(())
|
|
}
|