tldr_cli/commands/
api_surface.rs1use std::path::PathBuf;
23
24use anyhow::Result;
25use clap::Args;
26
27use tldr_core::surface::{extract_api_surface, format_api_surface_text};
28use tldr_core::Language;
29
30use crate::output::{OutputFormat, OutputWriter};
31
32#[derive(Debug, Args)]
34pub struct ApiSurfaceArgs {
35 pub target: String,
37
38 #[arg(long)]
40 pub lookup: Option<String>,
41
42 #[arg(long)]
44 pub include_private: bool,
45
46 #[arg(long)]
48 pub limit: Option<usize>,
49
50 #[arg(long)]
52 pub manifest_path: Option<PathBuf>,
53}
54
55impl ApiSurfaceArgs {
56 pub fn run(&self, format: OutputFormat, quiet: bool, lang: Option<Language>) -> Result<()> {
60 let writer = OutputWriter::new(format, quiet);
61
62 writer.progress(&format!("Extracting API surface for '{}'...", self.target));
63
64 let lang_str = lang.map(language_to_string);
66
67 let effective_target = if let Some(ref manifest) = self.manifest_path {
70 let is_rust = lang_str.as_deref() == Some("rust");
71 if is_rust {
72 manifest
73 .parent()
74 .map(|p| p.to_string_lossy().into_owned())
75 .unwrap_or_else(|| self.target.clone())
76 } else {
77 self.target.clone()
78 }
79 } else {
80 self.target.clone()
81 };
82
83 let surface = extract_api_surface(
84 &effective_target,
85 lang_str.as_deref(),
86 self.include_private,
87 self.limit,
88 self.lookup.as_deref(),
89 )?;
90
91 if writer.is_text() {
92 writer.write_text(&format_api_surface_text(&surface))?;
93 } else {
94 writer.write(&surface)?;
95 }
96
97 Ok(())
98 }
99}
100
101fn language_to_string(lang: Language) -> String {
103 match lang {
104 Language::Python => "python".to_string(),
105 Language::TypeScript => "typescript".to_string(),
106 Language::JavaScript => "javascript".to_string(),
107 Language::Go => "go".to_string(),
108 Language::Rust => "rust".to_string(),
109 Language::Java => "java".to_string(),
110 Language::C => "c".to_string(),
111 Language::Cpp => "cpp".to_string(),
112 Language::Ruby => "ruby".to_string(),
113 Language::Kotlin => "kotlin".to_string(),
114 Language::Swift => "swift".to_string(),
115 Language::CSharp => "csharp".to_string(),
116 Language::Scala => "scala".to_string(),
117 Language::Php => "php".to_string(),
118 Language::Lua => "lua".to_string(),
119 Language::Luau => "luau".to_string(),
120 Language::Elixir => "elixir".to_string(),
121 Language::Ocaml => "ocaml".to_string(),
122 }
123}
124
125#[cfg(test)]
126mod tests {
127 use super::*;
128 use std::path::PathBuf;
129
130 #[test]
131 fn test_api_surface_args_has_manifest_path_field() {
132 let args = ApiSurfaceArgs {
133 target: "my-crate".to_string(),
134 lookup: None,
135 include_private: false,
136 limit: None,
137 manifest_path: Some(PathBuf::from("./Cargo.toml")),
138 };
139 assert_eq!(args.manifest_path, Some(PathBuf::from("./Cargo.toml")));
140 }
141
142 #[test]
143 fn test_api_surface_args_manifest_path_defaults_to_none() {
144 let args = ApiSurfaceArgs {
145 target: "json".to_string(),
146 lookup: None,
147 include_private: false,
148 limit: None,
149 manifest_path: None,
150 };
151 assert!(args.manifest_path.is_none());
152 }
153}