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!(
63 "Extracting API surface for '{}'...",
64 self.target
65 ));
66
67 let lang_str = lang.map(language_to_string);
69
70 let effective_target = if let Some(ref manifest) = self.manifest_path {
73 let is_rust = lang_str.as_deref() == Some("rust");
74 if is_rust {
75 manifest
76 .parent()
77 .map(|p| p.to_string_lossy().into_owned())
78 .unwrap_or_else(|| self.target.clone())
79 } else {
80 self.target.clone()
81 }
82 } else {
83 self.target.clone()
84 };
85
86 let surface = extract_api_surface(
87 &effective_target,
88 lang_str.as_deref(),
89 self.include_private,
90 self.limit,
91 self.lookup.as_deref(),
92 )?;
93
94 if writer.is_text() {
95 writer.write_text(&format_api_surface_text(&surface))?;
96 } else {
97 writer.write(&surface)?;
98 }
99
100 Ok(())
101 }
102}
103
104fn language_to_string(lang: Language) -> String {
106 match lang {
107 Language::Python => "python".to_string(),
108 Language::TypeScript => "typescript".to_string(),
109 Language::JavaScript => "javascript".to_string(),
110 Language::Go => "go".to_string(),
111 Language::Rust => "rust".to_string(),
112 Language::Java => "java".to_string(),
113 Language::C => "c".to_string(),
114 Language::Cpp => "cpp".to_string(),
115 Language::Ruby => "ruby".to_string(),
116 Language::Kotlin => "kotlin".to_string(),
117 Language::Swift => "swift".to_string(),
118 Language::CSharp => "csharp".to_string(),
119 Language::Scala => "scala".to_string(),
120 Language::Php => "php".to_string(),
121 Language::Lua => "lua".to_string(),
122 Language::Luau => "luau".to_string(),
123 Language::Elixir => "elixir".to_string(),
124 Language::Ocaml => "ocaml".to_string(),
125 }
126}
127
128#[cfg(test)]
129mod tests {
130 use super::*;
131 use std::path::PathBuf;
132
133 #[test]
134 fn test_api_surface_args_has_manifest_path_field() {
135 let args = ApiSurfaceArgs {
136 target: "my-crate".to_string(),
137 lookup: None,
138 include_private: false,
139 limit: None,
140 manifest_path: Some(PathBuf::from("./Cargo.toml")),
141 };
142 assert_eq!(
143 args.manifest_path,
144 Some(PathBuf::from("./Cargo.toml"))
145 );
146 }
147
148 #[test]
149 fn test_api_surface_args_manifest_path_defaults_to_none() {
150 let args = ApiSurfaceArgs {
151 target: "json".to_string(),
152 lookup: None,
153 include_private: false,
154 limit: None,
155 manifest_path: None,
156 };
157 assert!(args.manifest_path.is_none());
158 }
159}