use anyhow::Result;
use std::fs;
use std::path::Path;
pub fn handle() -> Result<()> {
println!("📋 Registered Routes");
println!("{:-<60}", "");
let routes_dir = Path::new("routes");
if routes_dir.is_dir() {
let mut found = false;
let mut entries: Vec<_> = fs::read_dir(routes_dir)?
.filter_map(|e| e.ok())
.filter(|e| e.path().extension().is_some_and(|ext| ext == "rs"))
.collect();
entries.sort_by_key(|e| e.file_name());
for entry in &entries {
let path = entry.path();
let name = path.file_stem().unwrap().to_str().unwrap_or("unknown");
let content = fs::read_to_string(&path)?;
let file_routes = parse_routes(&content);
if !file_routes.is_empty() {
found = true;
println!(" 📄 routes/{}.rs", name);
for (method, route_path) in &file_routes {
println!(" {} {}", method, route_path);
}
}
}
if !found {
println!(" (no route definitions found in routes/)");
}
} else {
println!(" (no routes/ directory found — run `ravel new` first)");
}
println!();
println!("💡 Tip: Use Route::new().get(\"/\", handler) to define routes.");
Ok(())
}
fn parse_routes(source: &str) -> Vec<(String, String)> {
let mut routes = Vec::new();
let methods = ["get", "post", "put", "delete", "patch"];
for line in source.lines() {
let trimmed = line.trim();
for method in &methods {
if trimmed.starts_with(&format!(".{}(\"", method))
&& let Some(path) = extract_path(trimmed, method)
{
routes.push((method.to_uppercase(), path));
}
}
}
routes
}
fn extract_path(line: &str, method: &str) -> Option<String> {
let prefix = format!(".{}(\"", method);
let start = line.find(&prefix)? + prefix.len();
let rest = &line[start..];
let end = rest.find('"')?;
Some(rest[..end].to_string())
}