Allow querying multiple platforms (#300)

This commit is contained in:
JJ Style 2023-08-27 21:52:20 +00:00 committed by GitHub
commit 9e1489bbc5
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 191 additions and 36 deletions

View file

@ -9,21 +9,22 @@ ARGS:
<COMMAND>... The command to show (e.g. `tar` or `git log`)
OPTIONS:
-l, --list List all commands in the cache
-f, --render <FILE> Render a specific markdown file
-p, --platform <PLATFORM> Override the operating system [possible values: linux, macos,
windows, sunos, osx, android]
-L, --language <LANGUAGE> Override the language
-u, --update Update the local cache
--no-auto-update If auto update is configured, disable it for this run
-c, --clear-cache Clear the local cache
--pager Use a pager to page output
-r, --raw Display the raw markdown instead of rendering it
-q, --quiet Suppress informational messages
--show-paths Show file and directory paths used by tealdeer
--seed-config Create a basic config
--color <WHEN> Control whether to use color [possible values: always, auto, never]
-v, --version Print the version
-h, --help Print help information
-l, --list List all commands in the cache
-f, --render <FILE> Render a specific markdown file
-p, --platform <PLATFORMS> Override the operating system [possible values: linux, macos,
windows, sunos, osx, android]
-L, --language <LANGUAGE> Override the language
-u, --update Update the local cache
--no-auto-update If auto update is configured, disable it for this run
-c, --clear-cache Clear the local cache
--pager Use a pager to page output
-r, --raw Display the raw markdown instead of rendering it
-q, --quiet Suppress informational messages
--show-paths Show file and directory paths used by tealdeer
--seed-config Create a basic config
--color <WHEN> Control whether to use color [possible values: always, auto,
never]
-v, --version Print the version
-h, --help Print help information
To view the user documentation, please visit https://dbrgn.github.io/tealdeer/.

View file

@ -20,7 +20,6 @@ static TLDR_OLD_PAGES_DIR: &str = "tldr-master";
#[derive(Debug)]
pub struct Cache {
platform: PlatformType,
cache_dir: PathBuf,
}
@ -86,12 +85,11 @@ pub enum CacheFreshness {
}
impl Cache {
pub fn new<P>(platform: PlatformType, cache_dir: P) -> Self
pub fn new<P>(cache_dir: P) -> Self
where
P: Into<PathBuf>,
{
Self {
platform,
cache_dir: cache_dir.into(),
}
}
@ -211,8 +209,8 @@ impl Cache {
}
/// Return the platform directory.
fn get_platform_dir(&self) -> &'static str {
match self.platform {
fn get_platform_dir(platform: PlatformType) -> &'static str {
match platform {
PlatformType::Linux => "linux",
PlatformType::OsX => "osx",
PlatformType::SunOs => "sunos",
@ -247,6 +245,7 @@ impl Cache {
name: &str,
languages: &[String],
custom_pages_dir: Option<&Path>,
platforms: &[PlatformType],
) -> Option<PageLookupResult> {
let page_filename = format!("{name}.md");
let patch_filename = format!("{name}.patch");
@ -275,12 +274,14 @@ impl Cache {
let patch_path = Self::find_patch(&patch_filename, custom_pages_dir);
// Try to find a platform specific path next, append custom patch to it.
let platform_dir = self.get_platform_dir();
if let Some(page) =
Self::find_page_for_platform(&page_filename, &pages_dir, platform_dir, &lang_dirs)
{
return Some(PageLookupResult::with_page(page).with_optional_patch(patch_path));
// Try to find a platform specific path next, in the order supplied by the user, and append custom patch to it.
for &platform in platforms {
let platform_dir = Cache::get_platform_dir(platform);
if let Some(page) =
Self::find_page_for_platform(&page_filename, &pages_dir, platform_dir, &lang_dirs)
{
return Some(PageLookupResult::with_page(page).with_optional_patch(patch_path));
}
}
// Did not find platform specific results, fall back to "common"
@ -289,10 +290,17 @@ impl Cache {
}
/// Return the available pages.
pub fn list_pages(&self, custom_pages_dir: Option<&Path>) -> Vec<String> {
pub fn list_pages(
&self,
custom_pages_dir: Option<&Path>,
platforms: &[PlatformType],
) -> Vec<String> {
// Determine platforms directory and platform
let platforms_dir = self.pages_dir().join("pages");
let platform_dir = self.get_platform_dir();
let platform_dirs: Vec<&'static str> = platforms
.iter()
.map(|&p| Self::get_platform_dir(p))
.collect();
// Closure that allows the WalkDir instance to traverse platform
// specific and common page directories, but not others.
@ -303,7 +311,7 @@ impl Cache {
None => return false,
};
if file_type.is_dir() {
return file_name == "common" || file_name == platform_dir;
return file_name == "common" || platform_dirs.contains(&file_name);
} else if file_type.is_file() {
return true;
}

View file

@ -2,7 +2,7 @@
use std::path::PathBuf;
use clap::{AppSettings, ArgGroup, Parser};
use clap::{AppSettings, ArgAction, ArgGroup, Parser};
use crate::types::{ColorOptions, PlatformType};
@ -39,9 +39,10 @@ pub(crate) struct Args {
#[clap(
short = 'p',
long = "platform",
action = ArgAction::Append,
possible_values = ["linux", "macos", "windows", "sunos", "osx", "android"],
)]
pub platform: Option<PlatformType>,
pub platforms: Option<Vec<PlatformType>>,
/// Override the language
#[clap(short = 'L', long = "language")]

View file

@ -283,8 +283,11 @@ fn main() {
create_config_and_exit(enable_styles);
}
// Specify target OS
let platform: PlatformType = args.platform.unwrap_or_else(PlatformType::current);
let fallback_platforms: &[PlatformType] = &[PlatformType::current()];
let platforms = args
.platforms
.as_ref()
.map_or(fallback_platforms, Vec::as_slice);
// If a local file was passed in, render it and exit
if let Some(file) = args.render {
@ -298,7 +301,7 @@ fn main() {
}
// Instantiate cache. This will not yet create the cache directory!
let cache = Cache::new(platform, &config.directories.cache_dir.path);
let cache = Cache::new(&config.directories.cache_dir.path);
// Clear cache, pass through
if args.clear_cache {
@ -328,7 +331,10 @@ fn main() {
.custom_pages_dir
.as_ref()
.map(PathWithSource::path);
println!("{}", cache.list_pages(custom_pages_dir).join("\n"));
println!(
"{}",
cache.list_pages(custom_pages_dir, platforms).join("\n")
);
process::exit(0);
}
@ -353,6 +359,7 @@ fn main() {
.custom_pages_dir
.as_ref()
.map(PathWithSource::path),
platforms,
) {
if let Err(ref e) =
print_page(&lookup_result, args.raw, enable_styles, args.pager, &config)

View file

@ -562,6 +562,71 @@ fn test_pager_flag_enable() {
.success();
}
#[test]
fn test_multiple_platform_command_search() {
let testenv = TestEnv::new();
testenv.add_os_entry("linux", "linux-only", "this command only exists for linux");
testenv.add_os_entry(
"linux",
"windows-and-linux",
"# windows-and-linux \n\n > linux version",
);
testenv.add_os_entry(
"windows",
"windows-and-linux",
"# windows-and-linux \n\n > windows version",
);
testenv
.command()
.args(["--platform", "windows", "--platform", "linux", "linux-only"])
.assert()
.success();
// test order of platforms supplied if preserved
testenv
.command()
.args([
"--platform",
"windows",
"--platform",
"linux",
"windows-and-linux",
])
.assert()
.success()
.stdout(contains("windows version"));
testenv
.command()
.args([
"--platform",
"linux",
"--platform",
"windows",
"windows-and-linux",
])
.assert()
.success()
.stdout(contains("linux version"));
}
#[test]
fn test_multiple_platform_command_search_not_found() {
let testenv = TestEnv::new();
testenv.add_os_entry(
"windows",
"windows-only",
"this command only exists for Windows",
);
testenv
.command()
.args(["--platform", "macos", "--platform", "linux", "windows-only"])
.assert()
.stderr(contains("Page `windows-only` not found in cache."));
}
#[test]
fn test_list_flag_rendering() {
let testenv = TestEnv::new();
@ -604,6 +669,79 @@ fn test_list_flag_rendering() {
.stdout("bar\nbaz\nfaz\nfiz\nfoo\nqux\n");
}
#[test]
fn test_multi_platform_list_flag_rendering() {
let testenv = TestEnv::new();
// set custom pages directory
testenv.write_config(format!(
"[directories]\ncustom_pages_dir = '{}'",
testenv.custom_pages_dir.path().to_str().unwrap()
));
testenv.add_entry("common", "");
testenv
.command()
.args(["--list"])
.assert()
.success()
.stdout("common\n");
testenv
.command()
.args(["--platform", "linux", "--list"])
.assert()
.success()
.stdout("common\n");
testenv
.command()
.args(["--platform", "windows", "--list"])
.assert()
.success()
.stdout("common\n");
testenv.add_os_entry("linux", "rm", "");
testenv.add_os_entry("linux", "ls", "");
testenv.add_os_entry("windows", "del", "");
testenv.add_os_entry("windows", "dir", "");
testenv.add_os_entry("linux", "winux", "");
testenv.add_os_entry("windows", "winux", "");
// test `--list` for `--platform linux` by itself
testenv
.command()
.args(["--platform", "linux", "--list"])
.assert()
.success()
.stdout("common\nls\nrm\nwinux\n");
// test `--list` for `--platform windows` by itself
testenv
.command()
.args(["--platform", "windows", "--list"])
.assert()
.success()
.stdout("common\ndel\ndir\nwinux\n");
// test `--list` for `--platform linux --platform windows`
testenv
.command()
.args(["--platform", "linux", "--platform", "windows", "--list"])
.assert()
.success()
.stdout("common\ndel\ndir\nls\nrm\nwinux\n");
// test `--list` for `--platform windows --platform linux`
testenv
.command()
.args(["--platform", "linux", "--platform", "windows", "--list"])
.assert()
.success()
.stdout("common\ndel\ndir\nls\nrm\nwinux\n");
}
#[test]
fn test_autoupdate_cache() {
let testenv = TestEnv::new();