mod extract;
mod outline;
pub use extract::extract;
pub use outline::{SymbolOutline, WIRE_VERSION};
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum Lang {
Rust,
Python,
TypeScript,
Tsx,
JavaScript,
Go,
}
#[must_use]
pub fn detect(path: &str) -> Option<Lang> {
let basename = path.rsplit(['/', '\\']).next().unwrap_or(path);
let ext = basename.rsplit_once('.').map(|(_, e)| e)?;
match ext.to_ascii_lowercase().as_str() {
"rs" => Some(Lang::Rust),
"py" | "pyi" => Some(Lang::Python),
"ts" | "mts" | "cts" => Some(Lang::TypeScript),
"tsx" => Some(Lang::Tsx),
"js" | "mjs" | "cjs" | "jsx" => Some(Lang::JavaScript),
"go" => Some(Lang::Go),
_ => None,
}
}
pub const OUTLINE_CONTENT_TYPE: &str = "application/waggle-outline+json";
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn detection_is_extension_driven_and_total() {
assert_eq!(detect("crates/waggle-core/src/mint.rs"), Some(Lang::Rust));
assert_eq!(detect("a/b/app.test.TSX"), Some(Lang::Tsx));
assert_eq!(detect("script.mjs"), Some(Lang::JavaScript));
assert_eq!(detect("cmd/main.go"), Some(Lang::Go));
assert_eq!(detect("README.md"), None, "no grammar is not an error");
assert_eq!(detect("Makefile"), None, "extension-less: text loop only");
assert_eq!(detect(".hidden"), None);
}
}