1use crate::config::LIB_CFG;
7#[cfg(feature = "lang-detection")]
8use crate::config::TMPL_FILTER_GET_LANG_ALL;
9use crate::error::LibCfgError;
10#[cfg(feature = "lang-detection")]
11use lingua;
12#[cfg(feature = "lang-detection")]
13use lingua::IsoCode639_1;
14use parking_lot::RwLock;
15use std::borrow::Cow;
16use std::collections::BTreeMap;
17use std::env;
18#[cfg(feature = "lang-detection")]
19use std::str::FromStr;
20#[cfg(target_family = "windows")]
21use windows_sys::Win32::Globalization::GetUserDefaultLocaleName;
22#[cfg(target_family = "windows")]
23use windows_sys::Win32::System::SystemServices::LOCALE_NAME_MAX_LENGTH;
24
25pub const ENV_VAR_TPNOTE_SCHEME: &str = "TPNOTE_SCHEME";
28
29pub const ENV_VAR_TPNOTE_EXTENSION_DEFAULT: &str = "TPNOTE_EXTENSION_DEFAULT";
32
33pub const ENV_VAR_TPNOTE_LANG: &str = "TPNOTE_LANG";
38
39pub const ENV_VAR_TPNOTE_LANG_DETECTION: &str = "TPNOTE_LANG_DETECTION";
43
44pub const ENV_VAR_TPNOTE_USER: &str = "TPNOTE_USER";
48
49const ENV_VAR_LOGNAME: &str = "LOGNAME";
51
52const ENV_VAR_USERNAME: &str = "USERNAME";
54
55const ENV_VAR_USER: &str = "USER";
57
58#[cfg(not(target_family = "windows"))]
60const ENV_VAR_LANG: &str = "LANG";
61
62#[derive(Debug, PartialEq)]
63#[allow(dead_code)]
64pub(crate) enum FilterGetLang {
66 Disabled,
68 AllLanguages,
71 #[cfg(feature = "lang-detection")]
74 SomeLanguages(Vec<IsoCode639_1>),
75 #[cfg(not(feature = "lang-detection"))]
78 SomeLanguages(Vec<String>),
79 Error(LibCfgError),
81}
82
83#[derive(Debug)]
86#[allow(dead_code)]
87pub(crate) struct Settings {
88 pub current_scheme: usize,
90 pub author: String,
92 pub lang: String,
95 pub extension_default: String,
97 pub filter_get_lang: FilterGetLang,
99 pub filter_map_lang_btmap: Option<BTreeMap<String, String>>,
103}
104
105const DEFAULT_SETTINGS: Settings = Settings {
106 current_scheme: 0,
107 author: String::new(),
108 lang: String::new(),
109 extension_default: String::new(),
110 filter_get_lang: FilterGetLang::Disabled,
111 filter_map_lang_btmap: None,
112};
113
114impl Default for Settings {
115 #[cfg(not(any(test, doc)))]
116 fn default() -> Self {
118 DEFAULT_SETTINGS
119 }
120
121 #[cfg(any(test, doc))]
122 fn default() -> Self {
125 let mut settings = DEFAULT_SETTINGS;
126 settings.author = String::from("testuser");
127 settings.lang = String::from("ab-AB");
128 settings.extension_default = String::from("md");
129 settings
130 }
131}
132
133#[cfg(not(test))]
135pub(crate) static SETTINGS: RwLock<Settings> = RwLock::new(DEFAULT_SETTINGS);
136
137#[cfg(test)]
138pub(crate) static SETTINGS: RwLock<Settings> = RwLock::new(DEFAULT_SETTINGS);
140
141pub fn set_test_default_settings() -> Result<(), LibCfgError> {
145 let mut settings = SETTINGS.write();
146 settings.update(SchemeSource::Force("default"), None)
147}
148
149#[derive(Debug, Clone)]
151pub(crate) enum SchemeSource<'a> {
152 Force(&'a str),
154 SchemeSyncDefault,
156 SchemeNewDefault(&'a str),
158}
159
160impl Settings {
161 pub(crate) fn update(
177 &mut self,
178 scheme_source: SchemeSource,
179 force_lang: Option<&str>,
180 ) -> Result<(), LibCfgError> {
181 self.update_current_scheme(scheme_source)?;
182 self.update_author();
183 self.update_extension_default();
184 self.update_lang(force_lang);
185 self.update_filter_get_lang(force_lang.is_some());
186 self.update_filter_map_lang_btmap();
187 self.update_env_lang_detection(force_lang.is_some());
188
189 log::trace!(
190 "`SETTINGS` updated (reading config + env. vars.):\n{:#?}",
191 self
192 );
193
194 if let FilterGetLang::Error(e) = &self.filter_get_lang {
195 Err(e.clone())
196 } else {
197 Ok(())
198 }
199 }
200
201 fn update_current_scheme(&mut self, scheme_source: SchemeSource) -> Result<(), LibCfgError> {
203 let lib_cfg = LIB_CFG.read_recursive();
204
205 let scheme = match scheme_source {
206 SchemeSource::Force(s) => Cow::Borrowed(s),
207 SchemeSource::SchemeSyncDefault => Cow::Borrowed(&*lib_cfg.scheme_sync_default),
208 SchemeSource::SchemeNewDefault(s) => match env::var(ENV_VAR_TPNOTE_SCHEME) {
209 Ok(ed_env) if !ed_env.is_empty() => Cow::Owned(ed_env),
210 Err(_) | Ok(_) => Cow::Borrowed(s),
211 },
212 };
213 self.current_scheme = lib_cfg.scheme_idx(scheme.as_ref())?;
214 Ok(())
215 }
216
217 fn update_author(&mut self) {
220 let author = env::var(ENV_VAR_TPNOTE_USER).unwrap_or_else(|_| {
221 env::var(ENV_VAR_LOGNAME).unwrap_or_else(|_| {
222 env::var(ENV_VAR_USERNAME)
223 .unwrap_or_else(|_| env::var(ENV_VAR_USER).unwrap_or_default())
224 })
225 });
226
227 self.author = author;
229 }
230
231 fn update_extension_default(&mut self) {
235 let ext = match env::var(ENV_VAR_TPNOTE_EXTENSION_DEFAULT) {
237 Ok(ed_env) if !ed_env.is_empty() => ed_env,
238 Err(_) | Ok(_) => {
239 let lib_cfg = LIB_CFG.read_recursive();
240 lib_cfg.scheme[self.current_scheme]
241 .filename
242 .extension_default
243 .to_string()
244 }
245 };
246 self.extension_default = ext;
247 }
248
249 fn update_lang(&mut self, force_lang: Option<&str>) {
253 if let Some(l) = force_lang {
255 if !l.is_empty() {
256 self.lang = l.to_string();
257 return;
258 }
259 }
260
261 let mut lang = String::new();
264 let tpnotelang = env::var(ENV_VAR_TPNOTE_LANG).ok();
266 #[cfg(not(target_family = "windows"))]
268 if let Some(tpnotelang) = tpnotelang {
269 lang = tpnotelang;
270 } else {
271 if let Ok(lang_env) = env::var(ENV_VAR_LANG) {
274 if !lang_env.is_empty() {
275 let mut language = "";
277 let mut territory = "";
279 if let Some((l, lang_env)) = lang_env.split_once('_') {
280 language = l;
281 if let Some((t, _codeset)) = lang_env.split_once('.') {
282 territory = t;
283 }
284 }
285 lang = language.to_string();
286 lang.push('-');
287 lang.push_str(territory);
288 }
289 }
290 }
291
292 #[cfg(target_family = "windows")]
295 if let Some(tpnotelang) = tpnotelang {
296 lang = tpnotelang;
297 } else {
298 let mut buf = [0u16; LOCALE_NAME_MAX_LENGTH as usize];
299 let len = unsafe { GetUserDefaultLocaleName(buf.as_mut_ptr(), buf.len() as i32) };
300 if len > 0 {
301 lang = String::from_utf16_lossy(&buf[..((len - 1) as usize)]);
302 }
303 };
304
305 self.lang = lang;
307 }
308
309 #[cfg(feature = "lang-detection")]
318 fn update_filter_get_lang(&mut self, force_lang: bool) {
319 if force_lang {
320 self.filter_get_lang = FilterGetLang::Disabled;
321 return;
322 }
323
324 let lib_cfg = LIB_CFG.read_recursive();
325
326 let mut all_languages_selected = false;
327 match lib_cfg.scheme[self.current_scheme]
329 .tmpl
330 .filter
331 .get_lang
332 .iter()
333 .filter(|&l| {
335 if l == TMPL_FILTER_GET_LANG_ALL {
336 all_languages_selected = true;
337 false
339 } else {
340 true
342 }
343 })
344 .map(|l| {
345 IsoCode639_1::from_str(l).map_err(|_| {
346 let mut all_langs = lingua::Language::all()
349 .iter()
350 .map(|l| {
351 let mut s = l.iso_code_639_1().to_string();
352 s.push_str(", ");
353 s
354 })
355 .collect::<Vec<String>>();
356 all_langs.sort();
357 let mut all_langs = all_langs.into_iter().collect::<String>();
358 all_langs.truncate(all_langs.len() - ", ".len());
359 LibCfgError::ParseLanguageCode {
361 language_code: l.into(),
362 all_langs,
363 }
364 })
365 })
366 .collect::<Result<Vec<IsoCode639_1>, LibCfgError>>()
367 {
368 Ok(mut iso_codes) => {
370 if all_languages_selected {
371 self.filter_get_lang = FilterGetLang::AllLanguages;
373 } else {
374 if !self.lang.is_empty() {
377 if let Some((lang_subtag, _)) = self.lang.split_once('-') {
378 if let Ok(iso_code) = IsoCode639_1::from_str(lang_subtag) {
379 if !iso_codes.contains(&iso_code) {
380 iso_codes.push(iso_code);
381 }
382 }
383 }
384 }
385
386 self.filter_get_lang = match iso_codes.len() {
388 0 => FilterGetLang::Disabled,
389 1 => FilterGetLang::Error(LibCfgError::NotEnoughLanguageCodes {
390 language_code: iso_codes[0].to_string(),
391 }),
392 _ => FilterGetLang::SomeLanguages(iso_codes),
393 }
394 }
395 }
396 Err(e) =>
398 {
400 self.filter_get_lang = FilterGetLang::Error(e);
401 }
402 }
403 }
404
405 #[cfg(not(feature = "lang-detection"))]
406 fn update_filter_get_lang(&mut self, _force_lang: bool) {
408 self.filter_get_lang = FilterGetLang::Disabled;
409 }
410
411 fn update_filter_map_lang_btmap(&mut self) {
415 let mut btm = BTreeMap::new();
416 let lib_cfg = LIB_CFG.read_recursive();
417 for l in &lib_cfg.scheme[self.current_scheme].tmpl.filter.map_lang {
418 if l.len() >= 2 {
419 btm.insert(l[0].to_string(), l[1].to_string());
420 };
421 }
422 if !self.lang.is_empty() {
424 if let Some((lang_subtag, _)) = self.lang.split_once('-') {
425 if !lang_subtag.is_empty() && !btm.contains_key(lang_subtag) {
427 btm.insert(lang_subtag.to_string(), self.lang.to_string());
428 }
429 };
430 }
431
432 self.filter_map_lang_btmap = Some(btm);
434 }
435
436 #[cfg(feature = "lang-detection")]
442 fn update_env_lang_detection(&mut self, force_lang: bool) {
443 if let Ok(env_var) = env::var(ENV_VAR_TPNOTE_LANG_DETECTION) {
444 if env_var.is_empty() {
445 self.filter_get_lang = FilterGetLang::Disabled;
447 self.filter_map_lang_btmap = None;
448 log::debug!(
449 "Empty env. var. `{}` disables the `lang-detection` feature.",
450 ENV_VAR_TPNOTE_LANG_DETECTION
451 );
452 return;
453 }
454
455 let mut hm: BTreeMap<String, String> = BTreeMap::new();
457 let mut all_languages_selected = false;
458 match env_var
459 .split(',')
460 .map(|t| {
461 let t = t.trim();
462 if let Some((lang_subtag, _)) = t.split_once('-') {
463 if !lang_subtag.is_empty() && !hm.contains_key(lang_subtag) {
465 hm.insert(lang_subtag.to_string(), t.to_string());
466 };
467 lang_subtag
468 } else {
469 t
470 }
471 })
472 .filter(|&l| {
474 if l == TMPL_FILTER_GET_LANG_ALL {
475 all_languages_selected = true;
476 false
478 } else {
479 true
481 }
482 })
483 .map(|l| {
484 IsoCode639_1::from_str(l.trim()).map_err(|_| {
485 let mut all_langs = lingua::Language::all()
488 .iter()
489 .map(|l| {
490 let mut s = l.iso_code_639_1().to_string();
491 s.push_str(", ");
492 s
493 })
494 .collect::<Vec<String>>();
495 all_langs.sort();
496 let mut all_langs = all_langs.into_iter().collect::<String>();
497 all_langs.truncate(all_langs.len() - ", ".len());
498 LibCfgError::ParseLanguageCode {
500 language_code: l.into(),
501 all_langs,
502 }
503 })
504 })
505 .collect::<Result<Vec<IsoCode639_1>, LibCfgError>>()
506 {
507 Ok(mut iso_codes) => {
509 if !self.lang.is_empty() {
512 if let Some(lang_subtag) = self.lang.split('-').next() {
513 if let Ok(iso_code) = IsoCode639_1::from_str(lang_subtag) {
514 if !iso_codes.contains(&iso_code) {
515 iso_codes.push(iso_code);
516 }
517 if lang_subtag != self.lang && !hm.contains_key(lang_subtag) {
519 hm.insert(lang_subtag.to_string(), self.lang.to_string());
520 }
521 }
522 }
523 }
524 if all_languages_selected {
526 self.filter_get_lang = FilterGetLang::AllLanguages;
527 } else {
528 self.filter_get_lang = match iso_codes.len() {
529 0 => FilterGetLang::Disabled,
530 1 => FilterGetLang::Error(LibCfgError::NotEnoughLanguageCodes {
531 language_code: iso_codes[0].to_string(),
532 }),
533 _ => FilterGetLang::SomeLanguages(iso_codes),
534 }
535 }
536 self.filter_map_lang_btmap = Some(hm);
537 }
538 Err(e) =>
540 {
542 self.filter_get_lang = FilterGetLang::Error(e);
543 }
544 }
545
546 if force_lang {
549 self.filter_get_lang = FilterGetLang::Disabled;
550 }
551 }
552 }
553
554 #[cfg(not(feature = "lang-detection"))]
556 fn update_env_lang_detection(&mut self, _force_lang: bool) {
557 if let Ok(env_var) = env::var(ENV_VAR_TPNOTE_LANG_DETECTION) {
558 if !env_var.is_empty() {
559 self.filter_get_lang = FilterGetLang::Disabled;
560 self.filter_map_lang_btmap = None;
561 log::debug!(
562 "Ignoring the env. var. `{}`. The `lang-detection` feature \
563 is not included in this build.",
564 ENV_VAR_TPNOTE_LANG_DETECTION
565 );
566 }
567 }
568 }
569}
570#[cfg(test)]
571mod tests {
572 use super::*;
573 #[test]
577 fn test_update_author_setting() {
578 let mut settings = Settings::default();
579 unsafe {
580 env::set_var(ENV_VAR_LOGNAME, "testauthor");
581 }
582 settings.update_author();
583 assert_eq!(settings.author, "testauthor");
584 }
585
586 #[test]
587 fn test_update_extension_default_setting() {
588 let mut settings = Settings::default();
589 unsafe {
590 env::set_var(ENV_VAR_TPNOTE_EXTENSION_DEFAULT, "markdown");
591 }
592 settings.update_extension_default();
593 assert_eq!(settings.extension_default, "markdown");
594
595 let mut settings = Settings::default();
596 unsafe {
597 std::env::remove_var(ENV_VAR_TPNOTE_EXTENSION_DEFAULT);
598 }
599 settings.update_extension_default();
600 assert_eq!(settings.extension_default, "md");
601 }
602
603 #[test]
604 #[cfg(not(target_family = "windows"))]
605 fn test_update_lang_setting() {
606 let mut settings = Settings::default();
608 unsafe {
609 env::remove_var(ENV_VAR_TPNOTE_LANG);
610 env::set_var(ENV_VAR_LANG, "en_GB.UTF-8");
611 }
612 settings.update_lang(None);
613 assert_eq!(settings.lang, "en-GB");
614
615 let mut settings = Settings::default();
617 unsafe {
618 env::remove_var(ENV_VAR_TPNOTE_LANG);
619 env::set_var(ENV_VAR_LANG, "");
620 }
621 settings.update_lang(None);
622 assert_eq!(settings.lang, "");
623
624 let mut settings = Settings::default();
626 unsafe {
627 env::set_var(ENV_VAR_TPNOTE_LANG, "it-IT");
628 env::set_var(ENV_VAR_LANG, "en_GB.UTF-8");
629 }
630 settings.update_lang(None);
631 assert_eq!(settings.lang, "it-IT");
632 }
633
634 #[test]
635 #[cfg(feature = "lang-detection")]
636 fn test_update_filter_get_lang_setting() {
637 let mut settings = Settings {
639 lang: "en-GB".to_string(),
640 ..Default::default()
641 };
642 settings.update_filter_get_lang(false);
643
644 if let FilterGetLang::SomeLanguages(ofgl) = settings.filter_get_lang {
645 let output_filter_get_lang = ofgl
646 .iter()
647 .map(|l| {
648 let mut l = l.to_string();
649 l.push(' ');
650 l
651 })
652 .collect::<String>();
653 assert_eq!(output_filter_get_lang, "en fr de ");
654 } else {
655 panic!("Wrong variant: {:?}", settings.filter_get_lang);
656 }
657
658 let mut settings = Settings {
661 lang: "it-IT".to_string(),
662 ..Default::default()
663 };
664 settings.update_filter_get_lang(false);
665
666 if let FilterGetLang::SomeLanguages(ofgl) = settings.filter_get_lang {
667 let output_filter_get_lang = ofgl
668 .iter()
669 .map(|l| {
670 let mut l = l.to_string();
671 l.push(' ');
672 l
673 })
674 .collect::<String>();
675 assert_eq!(output_filter_get_lang, "en fr de it ");
676 } else {
677 panic!("Wrong variant: {:?}", settings.filter_get_lang);
678 }
679 }
680
681 #[test]
682 fn test_update_filter_map_lang_hmap_setting() {
683 let mut settings = Settings {
685 lang: "it-IT".to_string(),
686 ..Default::default()
687 };
688 settings.update_filter_map_lang_btmap();
689
690 let output_filter_map_lang = settings.filter_map_lang_btmap.unwrap();
691
692 assert_eq!(output_filter_map_lang.get("de").unwrap(), "de-DE");
693 assert_eq!(output_filter_map_lang.get("et").unwrap(), "et-ET");
694 assert_eq!(output_filter_map_lang.get("it").unwrap(), "it-IT");
695
696 let mut settings = Settings {
699 lang: "it".to_string(),
700 ..Default::default()
701 };
702 settings.update_filter_map_lang_btmap();
703
704 let output_filter_map_lang = settings.filter_map_lang_btmap.unwrap();
705
706 assert_eq!(output_filter_map_lang.get("de").unwrap(), "de-DE");
707 assert_eq!(output_filter_map_lang.get("et").unwrap(), "et-ET");
708 assert_eq!(output_filter_map_lang.get("it"), None);
709 }
710
711 #[test]
712 #[cfg(feature = "lang-detection")]
713 fn test_update_env_lang_detection() {
714 let mut settings = Settings {
717 lang: "en-GB".to_string(),
718 ..Default::default()
719 };
720 unsafe { env::set_var(ENV_VAR_TPNOTE_LANG_DETECTION, "fr-FR, de-DE, hu") };
721 settings.update_env_lang_detection(false);
722
723 if let FilterGetLang::SomeLanguages(ofgl) = settings.filter_get_lang {
724 let output_filter_get_lang = ofgl
725 .iter()
726 .map(|l| {
727 let mut l = l.to_string();
728 l.push(' ');
729 l
730 })
731 .collect::<String>();
732 assert_eq!(output_filter_get_lang, "fr de hu en ");
733 } else {
734 panic!("Wrong variant: {:?}", settings.filter_get_lang);
735 }
736
737 let output_filter_map_lang = settings.filter_map_lang_btmap.unwrap();
738 assert_eq!(output_filter_map_lang.get("de").unwrap(), "de-DE");
739 assert_eq!(output_filter_map_lang.get("fr").unwrap(), "fr-FR");
740 assert_eq!(output_filter_map_lang.get("en").unwrap(), "en-GB");
741
742 let mut settings = Settings {
745 lang: "en-GB".to_string(),
746 ..Default::default()
747 };
748 unsafe { env::set_var(ENV_VAR_TPNOTE_LANG_DETECTION, "de-DE, de-AT, en-US") };
749 settings.update_env_lang_detection(false);
750
751 if let FilterGetLang::SomeLanguages(ofgl) = settings.filter_get_lang {
752 let output_filter_get_lang = ofgl
753 .iter()
754 .map(|l| {
755 let mut l = l.to_string();
756 l.push(' ');
757 l
758 })
759 .collect::<String>();
760 assert_eq!(output_filter_get_lang, "de de en ");
761 } else {
762 panic!("Wrong variant: {:?}", settings.filter_get_lang);
763 }
764 let output_filter_map_lang = settings.filter_map_lang_btmap.unwrap();
765 assert_eq!(output_filter_map_lang.get("de").unwrap(), "de-DE");
766 assert_eq!(output_filter_map_lang.get("en").unwrap(), "en-US");
767
768 let mut settings = Settings {
771 lang: "en-GB".to_string(),
772 ..Default::default()
773 };
774 unsafe { env::set_var(ENV_VAR_TPNOTE_LANG_DETECTION, "de-DE, +all, en-US") };
775 settings.update_env_lang_detection(false);
776
777 assert!(matches!(
778 settings.filter_get_lang,
779 FilterGetLang::AllLanguages
780 ));
781 let output_filter_map_lang = settings.filter_map_lang_btmap.unwrap();
782 assert_eq!(output_filter_map_lang.get("de").unwrap(), "de-DE");
783 assert_eq!(output_filter_map_lang.get("en").unwrap(), "en-US");
784
785 let mut settings = Settings {
788 lang: "en-GB".to_string(),
789 ..Default::default()
790 };
791 unsafe { env::set_var(ENV_VAR_TPNOTE_LANG_DETECTION, "de-DE, de-AT, en") };
792 settings.update_env_lang_detection(false);
793
794 if let FilterGetLang::SomeLanguages(ofgl) = settings.filter_get_lang {
795 let output_filter_get_lang = ofgl
796 .iter()
797 .map(|l| {
798 let mut l = l.to_string();
799 l.push(' ');
800 l
801 })
802 .collect::<String>();
803 assert_eq!(output_filter_get_lang, "de de en ");
804 } else {
805 panic!("Wrong variant: {:?}", settings.filter_get_lang);
806 }
807 let output_filter_map_lang = settings.filter_map_lang_btmap.unwrap();
808 assert_eq!(output_filter_map_lang.get("de").unwrap(), "de-DE");
809 assert_eq!(output_filter_map_lang.get("en").unwrap(), "en-GB");
810
811 let mut settings = Settings {
814 lang: "en-GB".to_string(),
815 ..Default::default()
816 };
817 unsafe { env::set_var(ENV_VAR_TPNOTE_LANG_DETECTION, "de-DE, +all, de-AT, en") };
818 settings.update_env_lang_detection(false);
819
820 assert!(matches!(
821 settings.filter_get_lang,
822 FilterGetLang::AllLanguages
823 ));
824 let output_filter_map_lang = settings.filter_map_lang_btmap.unwrap();
825 assert_eq!(output_filter_map_lang.get("de").unwrap(), "de-DE");
826 assert_eq!(output_filter_map_lang.get("en").unwrap(), "en-GB");
827
828 let mut settings = Settings {
830 lang: "en-GB".to_string(),
831 ..Default::default()
832 };
833 unsafe { env::set_var(ENV_VAR_TPNOTE_LANG_DETECTION, "fr-FR, de-DE, hu") };
834 settings.update_env_lang_detection(true);
835
836 assert_eq!(settings.filter_get_lang, FilterGetLang::Disabled);
838
839 let output_filter_map_lang = settings.filter_map_lang_btmap.unwrap();
840 assert_eq!(output_filter_map_lang.get("de").unwrap(), "de-DE");
841 assert_eq!(output_filter_map_lang.get("fr").unwrap(), "fr-FR");
842 assert_eq!(output_filter_map_lang.get("en").unwrap(), "en-GB");
843
844 let mut settings = Settings {
847 lang: "".to_string(),
848 ..Default::default()
849 };
850 unsafe { env::set_var(ENV_VAR_TPNOTE_LANG_DETECTION, "") };
851 settings.update_env_lang_detection(false);
852
853 assert!(matches!(settings.filter_get_lang, FilterGetLang::Disabled));
854 assert!(settings.filter_map_lang_btmap.is_none());
855
856 let mut settings = Settings {
859 lang: "xy-XY".to_string(),
860 ..Default::default()
861 };
862 unsafe { env::set_var(ENV_VAR_TPNOTE_LANG_DETECTION, "en-GB, fr") };
863 settings.update_env_lang_detection(false);
864
865 if let FilterGetLang::SomeLanguages(ofgl) = settings.filter_get_lang {
866 let output_filter_get_lang = ofgl
867 .iter()
868 .map(|l| {
869 let mut l = l.to_string();
870 l.push(' ');
871 l
872 })
873 .collect::<String>();
874 assert_eq!(output_filter_get_lang, "en fr ");
875 } else {
876 panic!("Wrong variant: {:?}", settings.filter_get_lang);
877 }
878 let output_filter_map_lang = settings.filter_map_lang_btmap.unwrap();
879 assert_eq!(output_filter_map_lang.get("en").unwrap(), "en-GB");
880
881 let mut settings = Settings {
884 lang: "en-GB".to_string(),
885 ..Default::default()
886 };
887 unsafe {
888 env::set_var(ENV_VAR_TPNOTE_LANG_DETECTION, "de-DE, xy-XY");
889 }
890 settings.update_env_lang_detection(false);
891
892 assert!(matches!(settings.filter_get_lang, FilterGetLang::Error(..)));
893 assert!(settings.filter_map_lang_btmap.is_none());
894 let mut settings = Settings {
897 lang: "en-GB".to_string(),
898 ..Default::default()
899 };
900 unsafe {
901 env::set_var(ENV_VAR_TPNOTE_LANG_DETECTION, "");
902 }
903 settings.update_env_lang_detection(false);
904
905 assert!(matches!(settings.filter_get_lang, FilterGetLang::Disabled));
906 assert!(settings.filter_map_lang_btmap.is_none());
907 }
908}