diff --git a/src/cache.rs b/src/cache.rs index 1689ec31..1490513a 100644 --- a/src/cache.rs +++ b/src/cache.rs @@ -140,38 +140,51 @@ impl Cache { } } + /// Check for pages for a given platform in one of the given languages. + fn find_page_for_platform( + &self, + name: &str, + cache_dir: &PathBuf, + platform: &str, + language_dirs: &[String], + ) -> Option { + language_dirs + .iter() + .map(|lang_dir| cache_dir.join(lang_dir).join(platform).join(name)) + .find(|path| path.exists() && path.is_file()) + } + /// Search for a page and return the path to it. - pub fn find_page(&self, name: &str) -> Option { - // Build page file name + pub fn find_page(&self, name: &str, languages: &[String]) -> Option { let page_filename = format!("{}.md", name); // Get platform dir - let platforms_dir = match Self::get_cache_dir() { - Ok(cache_dir) => cache_dir.join("tldr-master").join("pages"), + let cache_dir = match Self::get_cache_dir() { + Ok(cache_dir) => cache_dir.join("tldr-master"), _ => return None, }; - // Determine platform - let platform = self.get_platform_dir(); + let lang_dirs: Vec = languages + .iter() + .map(|lang| { + if lang == "en" { + String::from("pages") + } else { + format!("pages.{}", lang) + } + }) + .collect(); - // Search for the page in the platform specific directory - if let Some(pf) = platform { - let path = platforms_dir.join(&pf).join(&page_filename); - if path.exists() && path.is_file() { - return Some(path); + // Try to find a platform specific path first. + if let Some(pf) = self.get_platform_dir() { + let pf_path = self.find_page_for_platform(&page_filename, &cache_dir, pf, &lang_dirs); + if pf_path.is_some() { + return pf_path; } } - // If platform is not supported or if platform specific page does not exist, - // look up the page in the "common" directory. - let path = platforms_dir.join("common").join(&page_filename); - - // Return it if it exists, otherwise give up and return `None` - if path.exists() && path.is_file() { - Some(path) - } else { - None - } + // Did not find platform specific results, fall back to "common" + self.find_page_for_platform(&page_filename, &cache_dir, "common", &lang_dirs) } /// Return the available pages. diff --git a/src/main.rs b/src/main.rs index 3d8622de..b3f01d33 100644 --- a/src/main.rs +++ b/src/main.rs @@ -57,18 +57,19 @@ Usage: Options: - -h --help Show this screen - -v --version Show version information - -l --list List all commands in the cache - -f --render Render a specific markdown file - -o --os Override the operating system [linux, osx, sunos, windows] - -u --update Update the local cache - -c --clear-cache Clear the local cache - -p --pager Use a pager to page output - -m --markdown Display the raw markdown instead of rendering it - -q --quiet Suppress informational messages - --config-path Show config file path - --seed-config Create a basic config + -h --help Show this screen + -v --version Show version information + -l --list List all commands in the cache + -f --render Render a specific markdown file + -o --os Override the operating system [linux, osx, sunos, windows] + -L --language Override the language settings + -u --update Update the local cache + -c --clear-cache Clear the local cache + -p --pager Use a pager to page output + -m --markdown Display the raw markdown instead of rendering it + -q --quiet Suppress informational messages + --config-path Show config file path + --seed-config Create a basic config Examples: @@ -103,6 +104,7 @@ struct Args { flag_config_path: bool, flag_seed_config: bool, flag_markdown: bool, + flag_language: Option, } /// Print page by path @@ -376,6 +378,38 @@ fn main() { process::exit(0); } + // Language list according to + // https://github.com/tldr-pages/tldr/blob/master/CLIENT-SPECIFICATION.md#language + let languages = if let Some(ref lang) = args.flag_language { + // Language overwritten by console argument + vec![lang.clone()] + } else if let Ok(lang) = std::env::var("LANG") { + let locales = std::env::var("LANGUAGE").unwrap_or_default(); + let mut locales: Vec<&str> = locales.split(':').collect(); + // According to the client specification, these should be appended + locales.push(&lang[..]); + locales.push("en"); + + let mut lang_list = Vec::new(); + for locale in locales.iter() { + if locale.len() >= 5 && locale.chars().nth(2) == Some('_') { + // Language with county code + lang_list.push(&locale[..5]); + } + if locale.len() >= 2 { + // Language code + lang_list.push(&locale[..2]); + } + } + + lang_list.dedup(); + lang_list.iter().map(|&s| String::from(s)).collect() + } else { + // Even if the LANGUAGES environment variable is set, + // the specification wants to only look for English pages. + vec!["en".into()] + }; + // Show command from cache if let Some(ref command) = args.arg_command { let command = command.join("-"); @@ -386,7 +420,7 @@ fn main() { } // Search for command in cache - if let Some(path) = cache.find_page(&command) { + if let Some(path) = cache.find_page(&command, &languages) { if let Err(msg) = print_page(&path, args.flag_markdown, &config) { eprintln!("{}", msg); process::exit(1);