use std::io::Write;
use anyhow::Result;
mod data;
mod detection;
pub use data::{LANGUAGES, Language};
pub use detection::{detect_language_info, scoring};
use crate::display::formatting::pluralize;
pub fn print_all_languages(writer: &mut dyn Write, terminal_width: usize) -> Result<()> {
let lang_count = u64::try_from(LANGUAGES.len()).unwrap_or(u64::MAX);
writeln!(
writer,
"Total number of supported programming {}: {}",
pluralize(lang_count, "language", "languages"),
LANGUAGES.len()
)?;
let mut lines: Vec<String> = Vec::new();
let mut current_line = String::new();
let mut current_width = 0usize;
for (i, lang) in LANGUAGES.iter().enumerate() {
let is_last = i == LANGUAGES.len() - 1;
let separator = if is_last { "." } else { ", " };
let item = format!("{}{}", lang.name, separator);
let item_width = item.chars().count();
let would_exceed = !current_line.is_empty() && current_width + item_width > terminal_width;
if would_exceed {
lines.push(current_line);
current_line = item;
current_width = item_width;
} else {
current_line.push_str(&item);
current_width += item_width;
}
}
if !current_line.is_empty() {
lines.push(current_line);
}
for line in lines {
writeln!(writer, "{line}")?;
}
Ok(())
}
#[cfg(test)]
mod tests {
use super::detection::patterns::get_candidates;
#[test]
fn get_candidates_uses_literal_map() {
let candidates = get_candidates("Makefile");
assert_eq!(candidates.len(), 1);
assert_eq!(candidates[0].name, "Makefile");
}
#[test]
fn get_candidates_handles_case_insensitive_literals() {
let candidates = get_candidates("MAKEFILE");
assert_eq!(candidates.len(), 1);
assert_eq!(candidates[0].name, "Makefile");
}
#[test]
fn get_candidates_supports_wildcards() {
let candidates = get_candidates("lib.rs");
assert!(candidates.iter().any(|lang| lang.name == "Rust"));
}
}