use std::fs;
use std::io;
use std::path::Path;
use crate::diagnostics::{Diagnostic, Location};
pub(crate) const THEMES: [(&str, &str); 4] = [
("monochrome", include_str!("../assets/themes/monochrome.toml")),
("iris", include_str!("../assets/themes/iris.toml")),
("nordic", include_str!("../assets/themes/nordic.toml")),
("amber", include_str!("../assets/themes/amber.toml")),
];
pub(crate) const ICON_SETS: [(&str, &str); 1] = [("default", include_str!("../assets/icons/default.toml"))];
pub(crate) const LOCALES: [(&str, &str); 9] = [
("en", include_str!("../assets/locales/en.toml")),
("tr", include_str!("../assets/locales/tr.toml")),
("de", include_str!("../assets/locales/de.toml")),
("es", include_str!("../assets/locales/es.toml")),
("fr", include_str!("../assets/locales/fr.toml")),
("pt-BR", include_str!("../assets/locales/pt-BR.toml")),
("ru", include_str!("../assets/locales/ru.toml")),
("zh-Hans", include_str!("../assets/locales/zh-Hans.toml")),
("ja", include_str!("../assets/locales/ja.toml")),
];
pub(crate) const KEYMAP: &str = include_str!("../assets/keymaps/default.toml");
pub(crate) struct TomlDir {
pub(crate) files: Vec<(String, String, String)>,
pub(crate) skipped: Vec<Diagnostic>,
}
pub(crate) fn read_toml_dir(dir: &Path) -> io::Result<TomlDir> {
let mut found = TomlDir { files: Vec::new(), skipped: Vec::new() };
for entry in fs::read_dir(dir)? {
let Ok(entry) = entry else { continue };
let path = entry.path();
if !path.is_file() || path.extension().and_then(|e| e.to_str()) != Some("toml") {
continue;
}
let (Some(stem), Some(name)) =
(path.file_stem().and_then(|s| s.to_str()), path.file_name().and_then(|s| s.to_str()))
else {
continue;
};
match fs::read_to_string(&path) {
Ok(text) => found.files.push((stem.to_owned(), name.to_owned(), text)),
Err(error) => found.skipped.push(Diagnostic::error(
Some(Location::from_offset(name, "", 0)),
format!("cannot read the file, it is skipped: {error}"),
)),
}
}
found.files.sort_by(|a, b| a.1.cmp(&b.1));
Ok(found)
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn reads_only_toml_files_in_name_order() {
let dir = std::env::temp_dir().join(format!("quvyta-assets-{}", std::process::id()));
fs::create_dir_all(dir.join("nested.toml")).expect("create dirs");
fs::write(dir.join("b.toml"), "b").expect("write");
fs::write(dir.join("a.toml"), "a").expect("write");
fs::write(dir.join("notes.txt"), "x").expect("write");
let files = read_toml_dir(&dir).expect("readable").files;
fs::remove_dir_all(&dir).expect("clean");
let names: Vec<&str> = files.iter().map(|f| f.1.as_str()).collect();
assert_eq!(names, vec!["a.toml", "b.toml"]);
assert_eq!(files[0].0, "a");
assert_eq!(files[0].2, "a");
}
#[test]
fn a_file_that_is_not_utf8_is_skipped_with_a_diagnostic_and_the_rest_load() {
let dir = std::env::temp_dir().join(format!("quvyta-assets-bad-{}", std::process::id()));
fs::create_dir_all(&dir).expect("create dir");
fs::write(dir.join("broken.toml"), [0xff, 0xfe, 0x00]).expect("write");
fs::write(dir.join("good.toml"), "ok").expect("write");
let found = read_toml_dir(&dir).expect("readable");
fs::remove_dir_all(&dir).expect("clean");
let names: Vec<&str> = found.files.iter().map(|f| f.1.as_str()).collect();
assert_eq!(names, vec!["good.toml"]);
assert_eq!(found.skipped.len(), 1);
assert!(found.skipped[0].to_string().contains("broken.toml"), "{}", found.skipped[0]);
}
}