use crate::config;
pub fn resolve_db_path(config: &config::Config) -> std::path::PathBuf {
if let Some(p) = &config.db_path {
return p.clone();
}
let home = std::env::var("HOME")
.map(std::path::PathBuf::from)
.unwrap_or_else(|_| std::path::PathBuf::from("."));
home.join(".local/share/docterm/library.db")
}
pub fn sanitize_for_terminal(s: &str) -> String {
s.chars()
.map(|c| match c {
'\t' | '\n' => c,
c if c.is_control() => '\u{FFFD}',
c => c,
})
.collect()
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn sanitize_passes_printable_ascii() {
assert_eq!(sanitize_for_terminal("Rust 1.94"), "Rust 1.94");
}
#[test]
fn sanitize_passes_unicode_letters_and_punctuation() {
assert_eq!(sanitize_for_terminal("café — β"), "café — β");
}
#[test]
fn sanitize_keeps_tab_and_newline() {
assert_eq!(sanitize_for_terminal("a\tb\nc"), "a\tb\nc");
}
#[test]
fn sanitize_replaces_ansi_csi_intro() {
let dirty = "\x1b[31mred\x1b[0m";
let clean = sanitize_for_terminal(dirty);
assert!(!clean.contains('\x1b'));
assert!(clean.contains('\u{FFFD}'));
}
#[test]
fn sanitize_replaces_bel_and_backspace() {
assert!(!sanitize_for_terminal("a\x07b").contains('\x07'));
assert!(!sanitize_for_terminal("a\x08b").contains('\x08'));
}
#[test]
fn sanitize_replaces_delete_char() {
assert!(!sanitize_for_terminal("a\x7fb").contains('\x7f'));
}
}