Compare commits

...

3 commits

Author SHA1 Message Date
Danilo Bargen
4a92bed585 Improve API by introducing a PlatformType struct 2021-12-06 00:35:18 +01:00
Danilo Bargen
3b69359757 Support all platform when listing pages 2021-12-06 00:35:18 +01:00
Danilo Bargen
1c05333de6 Allow setting platform to all
The goal is supporting the special `all` platform that results in pages
for all platforms being listed when calling `--list`. It's part of the
tldr client specification.

However, `All` should not be a variant of the `PlatformType` enum,
because `Current` isn't a `PlatformType` either. Thus, we accept the
string `all` but convert it into the current platform when parsing.

For consistency, the same is done when no platform is specified, by
introducing yet another possible value `current` which is used by
default. This way, we get rid of the `Option`.

To simplify handling of os / platform arguments, a conflict between
`--platform` and `--os` was introduced.
2021-12-06 00:35:14 +01:00
5 changed files with 110 additions and 31 deletions

View file

@ -14,7 +14,7 @@ OPTIONS:
-l, --list List all commands in the cache -l, --list List all commands in the cache
-f, --render <FILE> Render a specific markdown file -f, --render <FILE> Render a specific markdown file
-p, --platform <PLATFORM> Override the operating system [possible values: linux, macos, -p, --platform <PLATFORM> Override the operating system [possible values: linux, macos,
windows, sunos, osx] windows, sunos, all]
-o, --os <OS> Deprecated alias of `platform` -o, --os <OS> Deprecated alias of `platform`
-L, --language <LANGUAGE> Override the language -L, --language <LANGUAGE> Override the language
-u, --update Update the local cache -u, --update Update the local cache

View file

@ -16,7 +16,7 @@ use zip::ZipArchive;
use crate::{ use crate::{
error::TealdeerError::{self, CacheError, UpdateError}, error::TealdeerError::{self, CacheError, UpdateError},
types::{PathSource, PlatformType}, types::{PathSource, PlatformStrategy, PlatformType},
}; };
static CACHE_DIR_ENV_VAR: &str = "TEALDEER_CACHE_DIR"; static CACHE_DIR_ENV_VAR: &str = "TEALDEER_CACHE_DIR";
@ -27,7 +27,7 @@ static TLDR_OLD_PAGES_DIR: &str = "tldr-master";
#[derive(Debug)] #[derive(Debug)]
pub struct Cache { pub struct Cache {
url: String, url: String,
platform: PlatformType, platform: PlatformStrategy,
} }
#[derive(Debug)] #[derive(Debug)]
@ -64,7 +64,7 @@ pub enum CacheFreshness {
} }
impl Cache { impl Cache {
pub fn new<S>(url: S, platform: PlatformType) -> Self pub fn new<S>(url: S, platform: PlatformStrategy) -> Self
where where
S: Into<String>, S: Into<String>,
{ {
@ -196,11 +196,11 @@ impl Cache {
/// Return the platform directory. /// Return the platform directory.
fn get_platform_dir(&self) -> &'static str { fn get_platform_dir(&self) -> &'static str {
match self.platform { match self.platform.platform_type {
PlatformType::Linux => "linux", PlatformType::Linux { .. } => "linux",
PlatformType::OsX => "osx", PlatformType::OsX { .. } => "osx",
PlatformType::SunOs => "sunos", PlatformType::SunOs { .. } => "sunos",
PlatformType::Windows => "windows", PlatformType::Windows { .. } => "windows",
} }
} }
@ -305,7 +305,7 @@ impl Cache {
let mut pages = WalkDir::new(platforms_dir) let mut pages = WalkDir::new(platforms_dir)
.min_depth(1) // Skip root directory .min_depth(1) // Skip root directory
.into_iter() .into_iter()
.filter_entry(|e| should_walk(e)) // Filter out pages for other architectures .filter_entry(|e| self.platform.list_all || should_walk(e)) // Filter out pages for other architectures
.filter_map(Result::ok) // Convert results to options, filter out errors .filter_map(Result::ok) // Convert results to options, filter out errors
.filter_map(|e| { .filter_map(|e| {
let path = e.path(); let path = e.path();

View file

@ -40,7 +40,7 @@ use crate::{
error::TealdeerError::ConfigError, error::TealdeerError::ConfigError,
extensions::Dedup, extensions::Dedup,
output::print_page, output::print_page,
types::{ColorOptions, PlatformType}, types::{ColorOptions, PlatformStrategy, PlatformType},
utils::{print_error, print_warning}, utils::{print_error, print_warning},
}; };
@ -80,22 +80,28 @@ struct Args {
)] )]
render: Option<PathBuf>, render: Option<PathBuf>,
/// Override the operating system /// Override the operating system [possible values: linux, macos, windows, sunos, all]
#[clap( #[clap(
short = 'p', short = 'p',
long = "platform", long = "platform",
possible_values = ["linux", "macos", "windows", "sunos", "osx"], possible_values = ["linux", "macos", "windows", "sunos", "osx", "current", "all"],
default_value = "current",
hide_possible_values = true,
hide_default_value = true,
)] )]
platform: Option<PlatformType>, platform: PlatformStrategy,
/// Deprecated alias of `platform` /// Deprecated alias of `platform`
#[clap( #[clap(
short = 'o', short = 'o',
long = "os", long = "os",
possible_values = ["linux", "macos", "windows", "sunos", "osx"], conflicts_with = "platform",
possible_values = ["linux", "macos", "windows", "sunos", "osx", "current", "all"],
default_value = "current",
hide_possible_values = true, hide_possible_values = true,
hide_default_value = true,
)] )]
os: Option<PlatformType>, os: PlatformStrategy,
/// Override the language /// Override the language
#[clap(short = 'L', long = "language")] #[clap(short = 'L', long = "language")]
@ -400,13 +406,14 @@ fn main() {
"The -m / --markdown flag is deprecated, use -r / --raw instead", "The -m / --markdown flag is deprecated, use -r / --raw instead",
); );
} }
if args.os.is_some() { let default_platform = PlatformType::current();
if args.os.platform_type != default_platform || args.os.list_all {
print_warning( print_warning(
enable_styles, enable_styles,
"The -o / --os flag is deprecated, use -p / --platform instead", "The -o / --os flag is deprecated, use -p / --platform instead",
); );
args.platform = args.os;
} }
args.platform = args.platform.or(args.os);
// Show config file and path, pass through // Show config file and path, pass through
if args.config_path { if args.config_path {
@ -442,9 +449,6 @@ fn main() {
configure_pager(enable_styles); configure_pager(enable_styles);
} }
// Specify target OS
let platform: PlatformType = args.platform.unwrap_or_else(PlatformType::current);
// If a local file was passed in, render it and exit // If a local file was passed in, render it and exit
if let Some(file) = args.render { if let Some(file) = args.render {
let path = PageLookupResult::with_page(file); let path = PageLookupResult::with_page(file);
@ -457,7 +461,7 @@ fn main() {
} }
// Initialize cache // Initialize cache
let cache = Cache::new(ARCHIVE_URL, platform); let cache = Cache::new(ARCHIVE_URL, args.platform);
// Clear cache, pass through // Clear cache, pass through
if args.clear_cache { if args.clear_cache {

View file

@ -2,10 +2,10 @@
use std::{fmt, str}; use std::{fmt, str};
use serde_derive::{Deserialize, Serialize}; use serde::Deserialize;
#[derive(Debug, Eq, PartialEq, Copy, Clone, Serialize, Deserialize)] /// The platform types supported by tldr.
#[serde(rename_all = "lowercase")] #[derive(Debug, Eq, PartialEq, Copy, Clone)]
#[allow(dead_code)] #[allow(dead_code)]
pub enum PlatformType { pub enum PlatformType {
Linux, Linux,
@ -25,17 +25,58 @@ impl fmt::Display for PlatformType {
} }
} }
impl str::FromStr for PlatformType { /// The platform lookup strategy.
///
/// Includes both the platform type, as well as
#[derive(Debug, Copy, Clone)]
pub struct PlatformStrategy {
/// The platform type that should be looked up.
pub platform_type: PlatformType,
/// Flag indicating whether all pages should be listed or not. This is only
/// used when the special platform type `all` is specified by the user.
pub list_all: bool,
}
impl PlatformStrategy {
pub fn new(platform_type: PlatformType) -> Self {
Self {
platform_type,
list_all: false,
}
}
/// Return a `PlatformStrategy` containing the current platform as the
/// target platform type.
pub fn current() -> Self {
Self {
platform_type: PlatformType::current(),
list_all: false,
}
}
/// Like `current()`, but when listing the pages, return the pages for all
/// platforms, not just for the current platform.
pub fn all() -> Self {
Self {
platform_type: PlatformType::current(),
list_all: true,
}
}
}
impl str::FromStr for PlatformStrategy {
type Err = String; type Err = String;
fn from_str(s: &str) -> Result<Self, Self::Err> { fn from_str(s: &str) -> Result<Self, Self::Err> {
match s { match s {
"linux" => Ok(Self::Linux), "linux" => Ok(PlatformStrategy::new(PlatformType::Linux)),
"osx" | "macos" => Ok(Self::OsX), "osx" | "macos" => Ok(PlatformStrategy::new(PlatformType::OsX)),
"sunos" => Ok(Self::SunOs), "windows" => Ok(PlatformStrategy::new(PlatformType::Windows)),
"windows" => Ok(Self::Windows), "sunos" => Ok(PlatformStrategy::new(PlatformType::SunOs)),
"current" => Ok(PlatformStrategy::current()),
"all" => Ok(PlatformStrategy::all()),
other => Err(format!( other => Err(format!(
"Unknown OS: {}. Possible values: linux, macos, osx, sunos, windows", "Unknown platform: {}. Possible values: linux, macos, osx, windows, sunos, current, all",
other other
)), )),
} }

View file

@ -523,6 +523,40 @@ fn test_list_flag_rendering() {
.stdout("bar\nbaz\nfoo\nqux\n"); .stdout("bar\nbaz\nfoo\nqux\n");
} }
#[test]
fn test_list_platform_filtering() {
let testenv = TestEnv::new();
testenv.add_os_entry("common", "a-common", "");
testenv.add_os_entry("windows", "a-windows", "");
testenv.add_os_entry("linux", "a-linux", "");
testenv.add_os_entry("linux", "b-linux", "");
// Filter: linux
testenv
.command()
.args(["--list", "--platform", "linux"])
.assert()
.success()
.stdout("a-common\na-linux\nb-linux\n");
// Filter: windows
testenv
.command()
.args(["--list", "--platform", "windows"])
.assert()
.success()
.stdout("a-common\na-windows\n");
// Filter: all
testenv
.command()
.args(["--list", "--platform", "all"])
.assert()
.success()
.stdout("a-common\na-linux\na-windows\nb-linux\n");
}
#[test] #[test]
fn test_autoupdate_cache() { fn test_autoupdate_cache() {
let testenv = TestEnv::new(); let testenv = TestEnv::new();