Skip to content

Commit

Permalink
Update to clap v4
Browse files Browse the repository at this point in the history
  • Loading branch information
dbrgn committed Feb 11, 2024
1 parent 2e731d7 commit 59f919b
Show file tree
Hide file tree
Showing 5 changed files with 97 additions and 87 deletions.
56 changes: 29 additions & 27 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ path = "src/main.rs"
anyhow = "1"
app_dirs = { version = "2", package = "app_dirs2" }
atty = "0.2"
clap = { version = "3", features = ["std", "derive", "suggestions", "color"], default-features = false }
clap = { version = "4", features = ["std", "derive", "help", "usage", "cargo", "error-context", "color", "wrap_help"], default-features = false }
env_logger = { version = "0.10", optional = true }
log = "0.4"
reqwest = { version = "0.11.3", features = ["blocking"], default-features = false }
Expand Down
61 changes: 34 additions & 27 deletions src/cli.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,32 +2,38 @@

use std::path::PathBuf;

use clap::{AppSettings, ArgAction, ArgGroup, Parser};
use clap::{
arg,
builder::{ArgAction, EnumValueParser},
command, ArgGroup, Parser,
};

use crate::types::{ColorOptions, PlatformType};

// Note: flag names are specified explicitly in clap attributes
// to improve readability and allow contributors to grep names like "clear-cache"
#[derive(Parser, Debug)]
#[clap(about = "A fast TLDR client", author, version)]
#[clap(
after_help = "To view the user documentation, please visit https://dbrgn.github.io/tealdeer/."
#[command(
about = "A fast TLDR client",
version = "1.2.3",
author,
disable_version_flag = true,
after_help = "To view the user documentation, please visit https://dbrgn.github.io/tealdeer/.",
arg_required_else_help = true,
help_expected = true,
group = ArgGroup::new("command_or_file").args(&["command", "render"]),
)]
#[clap(setting = AppSettings::DeriveDisplayOrder)]
#[clap(arg_required_else_help(true))]
#[clap(disable_colored_help(true))]
#[clap(group = ArgGroup::new("command_or_file").args(&["command", "render"]))]
pub(crate) struct Args {
pub(crate) struct Cli {
/// The command to show (e.g. `tar` or `git log`)
#[clap(min_values = 1)]
#[arg(num_args(1..))]
pub command: Vec<String>,

/// List all commands in the cache
#[clap(short = 'l', long = "list")]
#[arg(short = 'l', long = "list")]
pub list: bool,

/// Render a specific markdown file
#[clap(
#[arg(
short = 'f',
long = "render",
value_name = "FILE",
Expand All @@ -36,61 +42,62 @@ pub(crate) struct Args {
pub render: Option<PathBuf>,

/// Override the operating system
#[clap(
#[arg(
short = 'p',
long = "platform",
action = ArgAction::Append,
possible_values = ["linux", "macos", "windows", "sunos", "osx", "android"],
value_parser = EnumValueParser::<PlatformType>::new(),
)]
pub platforms: Option<Vec<PlatformType>>,

/// Override the language
#[clap(short = 'L', long = "language")]
#[arg(short = 'L', long = "language")]
pub language: Option<String>,

/// Update the local cache
#[clap(short = 'u', long = "update")]
#[arg(short = 'u', long = "update")]
pub update: bool,

/// If auto update is configured, disable it for this run
#[clap(long = "no-auto-update", requires = "command_or_file")]
#[arg(long = "no-auto-update", requires = "command_or_file")]
pub no_auto_update: bool,

/// Clear the local cache
#[clap(short = 'c', long = "clear-cache")]
#[arg(short = 'c', long = "clear-cache")]
pub clear_cache: bool,

/// Use a pager to page output
#[clap(long = "pager", requires = "command_or_file")]
#[arg(long = "pager", requires = "command_or_file")]
pub pager: bool,

/// Display the raw markdown instead of rendering it
#[clap(short = 'r', long = "--raw", requires = "command_or_file")]
#[arg(short = 'r', long = "raw", requires = "command_or_file")]
pub raw: bool,

/// Suppress informational messages
#[clap(short = 'q', long = "quiet")]
#[arg(short = 'q', long = "quiet")]
pub quiet: bool,

/// Show file and directory paths used by tealdeer
#[clap(long = "show-paths")]
#[arg(long = "show-paths")]
pub show_paths: bool,

/// Create a basic config
#[clap(long = "seed-config")]
#[arg(long = "seed-config")]
pub seed_config: bool,

/// Control whether to use color
#[clap(
#[arg(
long = "color",
value_name = "WHEN",
possible_values = ["always", "auto", "never"]
value_parser = EnumValueParser::<ColorOptions>::new(),
)]
//possible_values = ["always", "auto", "never"]
pub color: Option<ColorOptions>,

/// Print the version
// Note: We override the version flag because clap uses `-V` by default,
// while TLDR specification requires `-v` to be used.
#[clap(short = 'v', long = "version")]
pub version: bool,
#[arg(short = 'v', long = "version", action = ArgAction::Version)]
pub version: Option<bool>,
}
8 changes: 4 additions & 4 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ mod utils;

use crate::{
cache::{Cache, CacheFreshness, PageLookupResult, TLDR_PAGES_DIR},
cli::Args,
cli::Cli,
config::{get_config_dir, get_config_path, make_default_config, Config, PathWithSource},
extensions::Dedup,
output::print_page,
Expand All @@ -65,7 +65,7 @@ const ARCHIVE_URL: &str = "https://tldr.sh/assets/tldr.zip";

/// The cache should be updated if it was explicitly requested,
/// or if an automatic update is due and allowed.
fn should_update_cache(cache: &Cache, args: &Args, config: &Config) -> bool {
fn should_update_cache(cache: &Cache, args: &Cli, config: &Config) -> bool {
args.update
|| (!args.no_auto_update
&& config.updates.auto_update
Expand All @@ -81,7 +81,7 @@ enum CheckCacheResult {
}

/// Check the cache for freshness. If it's stale or missing, show a warning.
fn check_cache(cache: &Cache, args: &Args, enable_styles: bool) -> CheckCacheResult {
fn check_cache(cache: &Cache, args: &Cli, enable_styles: bool) -> CheckCacheResult {
match cache.freshness() {
CacheFreshness::Fresh => CheckCacheResult::CacheFound,
CacheFreshness::Stale(_) if args.quiet => CheckCacheResult::CacheFound,
Expand Down Expand Up @@ -243,7 +243,7 @@ fn main() {
init_log();

// Parse arguments
let args = Args::parse();
let args = Cli::parse();

// Determine the usage of styles
#[cfg(target_os = "windows")]
Expand Down
57 changes: 29 additions & 28 deletions src/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@

use std::{fmt, str};

use anyhow::{anyhow, Result};
use serde_derive::{Deserialize, Serialize};

#[derive(Debug, Eq, PartialEq, Copy, Clone, Serialize, Deserialize)]
Expand All @@ -11,8 +10,8 @@ use serde_derive::{Deserialize, Serialize};
pub enum PlatformType {
Linux,
OsX,
SunOs,
Windows,
SunOs,
Android,
}

Expand All @@ -28,20 +27,24 @@ impl fmt::Display for PlatformType {
}
}

impl str::FromStr for PlatformType {
type Err = anyhow::Error;

fn from_str(s: &str) -> Result<Self, Self::Err> {
match s {
"linux" => Ok(Self::Linux),
"osx" | "macos" => Ok(Self::OsX),
"sunos" => Ok(Self::SunOs),
"windows" => Ok(Self::Windows),
"android" => Ok(Self::Android),
other => Err(anyhow!(
"Unknown OS: {}. Possible values: linux, macos, osx, sunos, windows, android",
other
)),
impl clap::ValueEnum for PlatformType {
fn value_variants<'a>() -> &'a [Self] {
&[
Self::Linux,
Self::OsX,
Self::Windows,
Self::SunOs,
Self::Android,
]
}

fn to_possible_value<'a>(&self) -> Option<clap::builder::PossibleValue> {
match self {
Self::Linux => Some(clap::builder::PossibleValue::new("linux")),
Self::OsX => Some(clap::builder::PossibleValue::new("osx").alias("macos")),
Self::Windows => Some(clap::builder::PossibleValue::new("windows")),
Self::SunOs => Some(clap::builder::PossibleValue::new("sunos")),
Self::Android => Some(clap::builder::PossibleValue::new("android")),
}
}
}
Expand Down Expand Up @@ -96,18 +99,16 @@ pub enum ColorOptions {
Never,
}

impl str::FromStr for ColorOptions {
type Err = anyhow::Error;

fn from_str(s: &str) -> Result<Self> {
match s {
"always" => Ok(Self::Always),
"auto" => Ok(Self::Auto),
"never" => Ok(Self::Never),
other => Err(anyhow!(
"Unknown color option: {}. Possible values: always, auto, never",
other
)),
impl clap::ValueEnum for ColorOptions {
fn value_variants<'a>() -> &'a [Self] {
&[Self::Always, Self::Auto, Self::Never]
}

fn to_possible_value<'a>(&self) -> Option<clap::builder::PossibleValue> {
match self {
Self::Always => Some(clap::builder::PossibleValue::new("always")),
Self::Auto => Some(clap::builder::PossibleValue::new("auto")),
Self::Never => Some(clap::builder::PossibleValue::new("never")),
}
}
}
Expand Down

0 comments on commit 59f919b

Please sign in to comment.