willbe/command/
crate_doc.rs

1// module/move/willbe/src/command/crate_doc.rs
2mod private
3{
4  #[ allow( clippy::wildcard_imports ) ]
5  use crate::*;
6
7  use std::path::PathBuf;
8  use wca::VerifiedCommand;
9  use error::untyped::Error; // Use untyped::Error for the command return
10  use entity::{ Workspace, WorkspaceInitError, PathError }; // Import Workspace, WorkspaceInitError, PathError
11  use path::{ AbsolutePath, CurrentPath }; // Import AbsolutePath and CurrentPath from pth
12
13  ///
14  /// Generate documentation for a crate in a single Markdown file.
15  ///
16  /// # Errors
17  /// Returns an error if the command arguments are invalid, the workspace cannot be loaded,
18  /// or if the documentation generation action fails.
19  #[allow(clippy::needless_pass_by_value)]
20  pub fn crate_doc( o : VerifiedCommand ) -> error::untyped::Result< () >
21  {
22    let path_arg : PathBuf = o.args.get_owned( 0 ).unwrap_or_else( || "./".into() );
23
24    // qqq : xxx : refactor this block
25    //       Use the requested `pth::absolute::join` function (see qqq in pth/src/lib.rs)
26    //       to simplify this path resolution. The call should look something like:
27    //       `let absolute_path = pth::absolute::join( ( CurrentPath, path_arg.clone() ) )?`
28    //       This assumes `join_absolute` takes a tuple and handles the logic internally.
29    // Determine the absolute path explicitly
30    let absolute_path = if path_arg.is_relative()
31    {
32      // If relative, resolve it against the current directory
33      let current_dir = AbsolutePath::try_from( CurrentPath )
34        .map_err( | e | Error::new( e ).context( "Failed to get current directory" ) )?;
35      current_dir.join( path_arg.clone() ) // Clone path_arg as join consumes it
36    }
37    else
38    {
39      // If already absolute, try to create AbsolutePath directly
40      AbsolutePath::try_from( path_arg.clone() )
41        .map_err( | e | Error::new( e ).context( format!( "Invalid absolute path provided: {}", path_arg.display() ) ) )?
42    };
43    // Note: AbsolutePath::try_from also performs canonicalization implicitly via path::canonicalize
44
45    // Create CrateDir from the verified AbsolutePath
46    let crate_dir = CrateDir::try_from( absolute_path ) // This should now work as AbsolutePath is canonical
47      .map_err( | e : PathError | Error::new( e ).context( "Failed to identify crate directory (does Cargo.toml exist?)" ) )?;
48
49    // Load the workspace based on the crate directory
50    let workspace = Workspace::try_from( crate_dir.clone() )
51      .map_err( | e : WorkspaceInitError | Error::new( e ).context( "Failed to load workspace information" ) )?;
52
53    // Parse output property
54    let output_path_req : Option< PathBuf > = o.props.get_owned( "output" );
55
56    // Call the action, passing the workspace reference
57    match action::crate_doc::doc( &workspace, &crate_dir, output_path_req )
58    {
59      Ok( report ) =>
60      {
61        println!( "{report}" ); // Print the success report
62        Ok( () )
63      }
64      Err( ( report, e ) ) =>
65      {
66        eprintln!( "{report}" ); // Print the report even on failure
67        // Convert the specific CrateDocError into a general untyped::Error for the command return
68        Err( Error::new( e ).context( "Documentation generation failed" ) )
69      }
70    }
71  }
72}
73
74crate::mod_interface!
75{
76  /// Generate documentation for a crate.
77  orphan use crate_doc;
78}