feat: use actual project data, real usage examples, dry-run/verbose flags, skip-unchanged optimization
- renderer: render_architecture_md accepts Config, uses project name and current date - renderer: generate real Python usage examples from analyzed symbols - writer: skip writing files when content unchanged (optimization) - cli: add --dry-run flag to generate command (lists files without writing) - cli: add verbose logging for file/module/symbol generation progress
This commit is contained in:
@@ -10,7 +10,7 @@ pub fn check_docs_consistency(root: &str, config: &Config) -> Result<()> {
|
||||
let model = analyze_project(root, config)?;
|
||||
|
||||
let renderer = archdoc_core::renderer::Renderer::new();
|
||||
let _generated = renderer.render_architecture_md(&model)?;
|
||||
let _generated = renderer.render_architecture_md(&model, None)?;
|
||||
|
||||
let architecture_md_path = std::path::Path::new(root).join(&config.project.entry_file);
|
||||
if !architecture_md_path.exists() {
|
||||
|
||||
@@ -55,7 +55,46 @@ pub fn analyze_project(root: &str, config: &Config) -> Result<ProjectModel> {
|
||||
Ok(model)
|
||||
}
|
||||
|
||||
pub fn generate_docs(model: &ProjectModel, out: &str, verbose: bool) -> Result<()> {
|
||||
pub fn dry_run_docs(model: &ProjectModel, out: &str, config: &Config) -> Result<()> {
|
||||
println!("{}", "Dry run — no files will be written.".cyan().bold());
|
||||
println!();
|
||||
|
||||
let out_path = std::path::Path::new(out);
|
||||
let arch_path = std::path::Path::new(".").join("ARCHITECTURE.md");
|
||||
|
||||
// ARCHITECTURE.md
|
||||
let exists = arch_path.exists();
|
||||
println!(" {} {}", if exists { "UPDATE" } else { "CREATE" }, arch_path.display());
|
||||
|
||||
// layout.md
|
||||
let layout_path = out_path.join("layout.md");
|
||||
let exists = layout_path.exists();
|
||||
println!(" {} {}", if exists { "UPDATE" } else { "CREATE" }, layout_path.display());
|
||||
|
||||
// Module docs
|
||||
for module_id in model.modules.keys() {
|
||||
let p = out_path.join("modules").join(format!("{}.md", sanitize_filename(module_id)));
|
||||
let exists = p.exists();
|
||||
println!(" {} {}", if exists { "UPDATE" } else { "CREATE" }, p.display());
|
||||
}
|
||||
|
||||
// File docs
|
||||
for file_doc in model.files.values() {
|
||||
let p = out_path.join("files").join(format!("{}.md", sanitize_filename(&file_doc.path)));
|
||||
let exists = p.exists();
|
||||
println!(" {} {}", if exists { "UPDATE" } else { "CREATE" }, p.display());
|
||||
}
|
||||
|
||||
let _ = config; // used for future extensions
|
||||
println!();
|
||||
println!("{} {} file(s) would be generated/updated",
|
||||
"✓".green().bold(),
|
||||
2 + model.modules.len() + model.files.len());
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn generate_docs(model: &ProjectModel, out: &str, verbose: bool, _config: &Config) -> Result<()> {
|
||||
println!("{}", "Generating documentation...".cyan());
|
||||
|
||||
let out_path = std::path::Path::new(out);
|
||||
@@ -74,6 +113,9 @@ pub fn generate_docs(model: &ProjectModel, out: &str, verbose: bool) -> Result<(
|
||||
// Generate module docs
|
||||
for module_id in model.modules.keys() {
|
||||
let module_doc_path = modules_path.join(format!("{}.md", sanitize_filename(module_id)));
|
||||
if verbose {
|
||||
println!(" Generating module doc: {}", module_id);
|
||||
}
|
||||
match renderer.render_module_md(model, module_id) {
|
||||
Ok(module_content) => {
|
||||
std::fs::write(&module_doc_path, module_content)?;
|
||||
@@ -88,6 +130,9 @@ pub fn generate_docs(model: &ProjectModel, out: &str, verbose: bool) -> Result<(
|
||||
|
||||
// Generate file docs
|
||||
for file_doc in model.files.values() {
|
||||
if verbose {
|
||||
println!(" Generating file doc: {}", file_doc.path);
|
||||
}
|
||||
let file_doc_path = files_path.join(format!("{}.md", sanitize_filename(&file_doc.path)));
|
||||
|
||||
let mut file_content = format!("# File: {}\n\n", file_doc.path);
|
||||
|
||||
@@ -34,6 +34,9 @@ enum Commands {
|
||||
out: String,
|
||||
#[arg(short, long, default_value = "archdoc.toml")]
|
||||
config: String,
|
||||
/// Show what would be generated without writing files
|
||||
#[arg(long)]
|
||||
dry_run: bool,
|
||||
},
|
||||
/// Check if documentation is up to date
|
||||
Check {
|
||||
@@ -58,10 +61,14 @@ fn main() -> Result<()> {
|
||||
Commands::Init { root, out } => {
|
||||
commands::init::init_project(root, out)?;
|
||||
}
|
||||
Commands::Generate { root, out, config } => {
|
||||
Commands::Generate { root, out, config, dry_run } => {
|
||||
let config = commands::generate::load_config(config)?;
|
||||
let model = commands::generate::analyze_project(root, &config)?;
|
||||
commands::generate::generate_docs(&model, out, cli.verbose)?;
|
||||
if *dry_run {
|
||||
commands::generate::dry_run_docs(&model, out, &config)?;
|
||||
} else {
|
||||
commands::generate::generate_docs(&model, out, cli.verbose, &config)?;
|
||||
}
|
||||
output::print_generate_summary(&model);
|
||||
}
|
||||
Commands::Check { root, config } => {
|
||||
|
||||
Reference in New Issue
Block a user