mirror of
https://github.com/astral-sh/uv.git
synced 2025-08-04 19:08:04 +00:00
Generate environment variables doc from code (#8493)
## Summary Resolves #8417 I've just begun learning procedural macros, so this PR is more of a proof of concept. It's still a work in progress, and I welcome any assistance or feedback.
This commit is contained in:
parent
545a55f58f
commit
3dfedf1fef
13 changed files with 491 additions and 135 deletions
|
@ -2,7 +2,10 @@
|
|||
|
||||
use anyhow::Result;
|
||||
|
||||
use crate::{generate_cli_reference, generate_json_schema, generate_options_reference};
|
||||
use crate::{
|
||||
generate_cli_reference, generate_env_vars_reference, generate_json_schema,
|
||||
generate_options_reference,
|
||||
};
|
||||
|
||||
#[derive(clap::Args)]
|
||||
pub(crate) struct Args {
|
||||
|
@ -27,5 +30,6 @@ pub(crate) fn main(args: &Args) -> Result<()> {
|
|||
generate_json_schema::main(&generate_json_schema::Args { mode: args.mode })?;
|
||||
generate_options_reference::main(&generate_options_reference::Args { mode: args.mode })?;
|
||||
generate_cli_reference::main(&generate_cli_reference::Args { mode: args.mode })?;
|
||||
generate_env_vars_reference::main(&generate_env_vars_reference::Args { mode: args.mode })?;
|
||||
Ok(())
|
||||
}
|
||||
|
|
|
@ -31,7 +31,6 @@ const SHOW_HIDDEN_COMMANDS: &[&str] = &["generate-shell-completion"];
|
|||
|
||||
#[derive(clap::Args)]
|
||||
pub(crate) struct Args {
|
||||
/// Write the generated output to stdout (rather than to `settings.md`).
|
||||
#[arg(long, default_value_t, value_enum)]
|
||||
pub(crate) mode: Mode,
|
||||
}
|
||||
|
|
98
crates/uv-dev/src/generate_env_vars_reference.rs
Normal file
98
crates/uv-dev/src/generate_env_vars_reference.rs
Normal file
|
@ -0,0 +1,98 @@
|
|||
//! Generate the environment variables reference from `uv_static::EnvVars`.
|
||||
|
||||
use anyhow::bail;
|
||||
use pretty_assertions::StrComparison;
|
||||
use std::path::PathBuf;
|
||||
|
||||
use uv_static::EnvVars;
|
||||
|
||||
use crate::generate_all::Mode;
|
||||
use crate::ROOT_DIR;
|
||||
|
||||
#[derive(clap::Args)]
|
||||
pub(crate) struct Args {
|
||||
#[arg(long, default_value_t, value_enum)]
|
||||
pub(crate) mode: Mode,
|
||||
}
|
||||
|
||||
pub(crate) fn main(args: &Args) -> anyhow::Result<()> {
|
||||
let reference_string = generate();
|
||||
let filename = "environment.md";
|
||||
let reference_path = PathBuf::from(ROOT_DIR)
|
||||
.join("docs")
|
||||
.join("configuration")
|
||||
.join(filename);
|
||||
|
||||
match args.mode {
|
||||
Mode::DryRun => {
|
||||
anstream::println!("{reference_string}");
|
||||
}
|
||||
Mode::Check => match fs_err::read_to_string(reference_path) {
|
||||
Ok(current) => {
|
||||
if current == reference_string {
|
||||
anstream::println!("Up-to-date: {filename}");
|
||||
} else {
|
||||
let comparison = StrComparison::new(¤t, &reference_string);
|
||||
bail!("{filename} changed, please run `cargo dev generate-env-vars-reference`:\n{comparison}");
|
||||
}
|
||||
}
|
||||
Err(err) if err.kind() == std::io::ErrorKind::NotFound => {
|
||||
bail!("{filename} not found, please run `cargo dev generate-env-vars-reference`");
|
||||
}
|
||||
Err(err) => {
|
||||
bail!(
|
||||
"{filename} changed, please run `cargo dev generate-env-vars-reference`:\n{err}"
|
||||
);
|
||||
}
|
||||
},
|
||||
Mode::Write => match fs_err::read_to_string(&reference_path) {
|
||||
Ok(current) => {
|
||||
if current == reference_string {
|
||||
anstream::println!("Up-to-date: {filename}");
|
||||
} else {
|
||||
anstream::println!("Updating: {filename}");
|
||||
fs_err::write(reference_path, reference_string.as_bytes())?;
|
||||
}
|
||||
}
|
||||
Err(err) if err.kind() == std::io::ErrorKind::NotFound => {
|
||||
anstream::println!("Updating: {filename}");
|
||||
fs_err::write(reference_path, reference_string.as_bytes())?;
|
||||
}
|
||||
Err(err) => {
|
||||
bail!("{filename} changed, please run `cargo dev generate-env-vars-reference`:\n{err}");
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn generate() -> String {
|
||||
let mut output = String::new();
|
||||
|
||||
output.push_str("# Environment variables\n\n");
|
||||
output.push_str("uv respects the following environment variables:\n\n");
|
||||
|
||||
for (var, doc) in EnvVars::metadata() {
|
||||
// Remove empty lines and ddd two spaces to the beginning from the second line.
|
||||
let doc = doc
|
||||
.lines()
|
||||
.enumerate()
|
||||
.filter(|(_, line)| !line.trim().is_empty())
|
||||
.map(|(i, line)| {
|
||||
if i == 0 {
|
||||
line.to_string()
|
||||
} else {
|
||||
format!(" {line}")
|
||||
}
|
||||
})
|
||||
.collect::<Vec<_>>()
|
||||
.join("\n");
|
||||
output.push_str(&format!("- `{var}`: {doc}\n"));
|
||||
}
|
||||
|
||||
output
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests;
|
19
crates/uv-dev/src/generate_env_vars_reference/tests.rs
Normal file
19
crates/uv-dev/src/generate_env_vars_reference/tests.rs
Normal file
|
@ -0,0 +1,19 @@
|
|||
use std::env;
|
||||
|
||||
use anyhow::Result;
|
||||
|
||||
use uv_static::EnvVars;
|
||||
|
||||
use crate::generate_all::Mode;
|
||||
|
||||
use super::{main, Args};
|
||||
|
||||
#[test]
|
||||
fn test_generate_env_vars_reference() -> Result<()> {
|
||||
let mode = if env::var(EnvVars::UV_UPDATE_SCHEMA).as_deref() == Ok("1") {
|
||||
Mode::Write
|
||||
} else {
|
||||
Mode::Check
|
||||
};
|
||||
main(&Args { mode })
|
||||
}
|
|
@ -27,7 +27,6 @@ struct CombinedOptions {
|
|||
|
||||
#[derive(clap::Args)]
|
||||
pub(crate) struct Args {
|
||||
/// Write the generated output to stdout (rather than to `uv.schema.json`).
|
||||
#[arg(long, default_value_t, value_enum)]
|
||||
pub(crate) mode: Mode,
|
||||
}
|
||||
|
|
|
@ -34,7 +34,6 @@ struct CombinedOptions {
|
|||
|
||||
#[derive(clap::Args)]
|
||||
pub(crate) struct Args {
|
||||
/// Write the generated output to stdout (rather than to `settings.md`).
|
||||
#[arg(long, default_value_t, value_enum)]
|
||||
pub(crate) mode: Mode,
|
||||
}
|
||||
|
|
|
@ -20,6 +20,7 @@ use crate::clear_compile::ClearCompileArgs;
|
|||
use crate::compile::CompileArgs;
|
||||
use crate::generate_all::Args as GenerateAllArgs;
|
||||
use crate::generate_cli_reference::Args as GenerateCliReferenceArgs;
|
||||
use crate::generate_env_vars_reference::Args as GenerateEnvVarsReferenceArgs;
|
||||
use crate::generate_json_schema::Args as GenerateJsonSchemaArgs;
|
||||
use crate::generate_options_reference::Args as GenerateOptionsReferenceArgs;
|
||||
#[cfg(feature = "render")]
|
||||
|
@ -31,6 +32,7 @@ mod clear_compile;
|
|||
mod compile;
|
||||
mod generate_all;
|
||||
mod generate_cli_reference;
|
||||
mod generate_env_vars_reference;
|
||||
mod generate_json_schema;
|
||||
mod generate_options_reference;
|
||||
mod render_benchmarks;
|
||||
|
@ -54,6 +56,8 @@ enum Cli {
|
|||
GenerateOptionsReference(GenerateOptionsReferenceArgs),
|
||||
/// Generate the CLI reference for the documentation.
|
||||
GenerateCliReference(GenerateCliReferenceArgs),
|
||||
/// Generate the environment variables reference for the documentation.
|
||||
GenerateEnvVarsReference(GenerateEnvVarsReferenceArgs),
|
||||
#[cfg(feature = "render")]
|
||||
/// Render the benchmarks.
|
||||
RenderBenchmarks(RenderBenchmarksArgs),
|
||||
|
@ -70,6 +74,7 @@ async fn run() -> Result<()> {
|
|||
Cli::GenerateJSONSchema(args) => generate_json_schema::main(&args)?,
|
||||
Cli::GenerateOptionsReference(args) => generate_options_reference::main(&args)?,
|
||||
Cli::GenerateCliReference(args) => generate_cli_reference::main(&args)?,
|
||||
Cli::GenerateEnvVarsReference(args) => generate_env_vars_reference::main(&args)?,
|
||||
#[cfg(feature = "render")]
|
||||
Cli::RenderBenchmarks(args) => render_benchmarks::render_benchmarks(&args)?,
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue