1use std::env;
2use std::fs::File;
3use std::io::prelude::*;
4use std::path::Path;
5use substring::Substring;
6use walkdir::WalkDir;
7
8#[cfg(windows)]
9const LINE_ENDING: &'static str = "\r\n";
10#[cfg(not(windows))]
11const LINE_ENDING: &'static str = "\n";
12
13const CARET: char = '^';
14
15fn normalize_entries<S: Into<String>>(content: S) -> Vec<String> {
18 let cst_ending = format!("{}{}", CARET, LINE_ENDING);
19 let entries = content
20 .into()
21 .trim_end()
22 .trim_end_matches(CARET)
23 .split(cst_ending.as_str())
24 .map(|s| s.to_string())
25 .collect::<Vec<String>>();
26
27 return entries;
28}
29
30pub fn get_entry<S: Into<String>>(content: S, key: usize) -> Option<String> {
42 let entries = normalize_entries(content);
43
44 for entry in entries {
46 if entry.contains(&key.to_string()) {
47 let start_index = entry.find(CARET)?;
48 let line = entry.substring(start_index + 1, entry.len());
49 return Some(line.to_string());
50 }
51 }
52
53 return None;
55}
56
57pub struct UIText {
58 language: String,
59}
60
61impl UIText {
74 pub fn new<S: Into<String>>(language: S) -> UIText {
75 UIText {
76 language: language.into(),
77 }
78 }
79
80 pub fn get_text(&self, id: usize, key: usize) -> Option<String> {
81 let language_dir = format!(
82 "{}/uitext/{}.dir/",
83 env::current_dir().unwrap().display(),
84 self.language
85 );
86
87 for entry in WalkDir::new(&language_dir)
88 .sort_by_file_name()
89 .into_iter()
90 .filter_map(|e| e.ok())
91 {
92 let f_name = entry.file_name().to_string_lossy();
93 let find_id = format!("_{}_", id);
94 if f_name.contains(&find_id) && f_name.ends_with(".cst") {
95 let mut open_file =
96 match File::open(Path::new(format!("{}/{}", language_dir, f_name).as_str())) {
97 Err(_) => panic!("couldn't open {}", f_name),
98 Ok(file) => file,
99 };
100 let mut contents = String::new();
101 match open_file.read_to_string(&mut contents) {
102 Ok(_) => return Some(get_entry(contents, key)?),
103 Err(why) => panic!("couldn't read {}: {}", f_name, why),
104 }
105 }
106 }
107 return None;
108 }
109}
110
111#[cfg(test)]
112mod tests {
113 use crate::{get_entry, normalize_entries, UIText};
114
115 #[cfg(windows)]
116 const LINE_ENDING: &'static str = "\r\n";
117 #[cfg(not(windows))]
118 const LINE_ENDING: &'static str = "\n";
119
120 #[test]
121 fn get_uitext() {
122 let ui_text = UIText::new("lorem");
123 let expected = "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Proin ac dictum orci, at tincidunt nulla. Donec aliquet, eros non interdum posuere, ipsum sapien molestie nunc, nec facilisis libero ipsum et risus. In sed lorem vel ipsum placerat viverra.".to_string();
124 dbg!(ui_text.get_text(101, 1));
125 assert_eq!(ui_text.get_text(101, 1).unwrap(), expected);
126 }
127
128 #[test]
129 fn is_normalized() {
130 let example = format!(
131 "1 ^The quick brown fox^{}2 ^jumps over the lazy dog^{}",
132 LINE_ENDING, LINE_ENDING
133 );
134 let input = normalize_entries(example);
135 let expected = [
136 "1 ^The quick brown fox".to_string(),
137 "2 ^jumps over the lazy dog".to_string(),
138 ];
139 assert_eq!(input, expected);
140 }
141
142 #[test]
143 fn test_entry() {
144 let example = format!(
145 "# comment{}1 ^The quick brown fox^{}2 ^jumps over the lazy dog^{}",
146 LINE_ENDING, LINE_ENDING, LINE_ENDING
147 );
148 let expected = "jumps over the lazy dog".to_string();
149 dbg!(get_entry(&example, 2));
150 assert_eq!(get_entry(example, 2).unwrap(), expected);
151 }
152}