use std::path::Path;
pub fn complete_path(input: &str) -> Option<String> {
if input.is_empty() {
return None;
}
let path = Path::new(input);
let (base_dir, prefix) = if input.ends_with('/') || input.ends_with('\\') {
(path, "")
} else {
(path.parent().unwrap_or(Path::new(".")),
path.file_name().and_then(|n| n.to_str()).unwrap_or(""))
};
let entries = match std::fs::read_dir(base_dir) {
Ok(entries) => entries,
Err(_) => return None,
};
let mut matches: Vec<String> = Vec::new();
for entry in entries.flatten() {
if let Some(name) = entry.file_name().to_str() {
if name.starts_with(prefix) {
let full_path = if base_dir == Path::new(".") {
name.to_string()
} else {
base_dir.join(name).to_string_lossy().to_string()
};
let metadata = entry.metadata().ok();
if metadata.map(|m| m.is_dir()).unwrap_or(false) {
matches.push(format!("{}/", full_path));
} else {
matches.push(full_path);
}
}
}
}
if matches.is_empty() {
None
} else if matches.len() == 1 {
Some(matches[0].clone())
} else {
let common_prefix = find_common_prefix(&matches);
if common_prefix.len() > input.len() {
Some(common_prefix)
} else {
None
}
}
}
pub fn find_common_prefix(strings: &[String]) -> String {
if strings.is_empty() {
return String::new();
}
let first = &strings[0];
let mut prefix_len = first.len();
for s in strings.iter().skip(1) {
prefix_len = first
.chars()
.zip(s.chars())
.take_while(|(a, b)| a == b)
.count()
.min(prefix_len);
}
first.chars().take(prefix_len).collect()
}