From 5ad7dcfa34398eab54b4921a1e9c4bcb15a6d762 Mon Sep 17 00:00:00 2001 From: Danilo Bargen Date: Sat, 7 Mar 2020 17:50:12 +0100 Subject: [PATCH 1/8] Argument parsing: Switch from docopt to clap --- .github/workflows/ci.yml | 4 +- Cargo.lock | 104 ++++++++++++++++++++--- Cargo.toml | 2 +- clippy.toml | 2 +- docs/src/usage.md | 3 +- docs/src/usage.txt | 28 +++++++ fish_tealdeer | 2 +- src/cache.rs | 1 - src/main.rs | 174 +++++++++++++++++++++------------------ src/types.rs | 37 ++++++++- src/usage.docopt | 36 -------- 11 files changed, 255 insertions(+), 138 deletions(-) create mode 100644 docs/src/usage.txt delete mode 100644 src/usage.docopt diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index ca3deae1..36d1f553 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -15,7 +15,7 @@ jobs: strategy: matrix: platform: [ubuntu-latest, macos-latest, windows-latest] - rust: [1.53, stable] + rust: [1.54, stable] runs-on: ${{ matrix.platform }} steps: - uses: actions/checkout@v2 @@ -60,7 +60,7 @@ jobs: - uses: actions/checkout@v2 - uses: actions-rs/toolchain@v1 with: - toolchain: 1.53 + toolchain: 1.54 override: true - run: rustup component add rustfmt - uses: actions-rs/cargo@v1 diff --git a/Cargo.lock b/Cargo.lock index 72a085fc..14828afe 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -128,6 +128,36 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" +[[package]] +name = "clap" +version = "3.0.0-beta.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "feff3878564edb93745d58cf63e17b63f24142506e7a20c87a5521ed7bfb1d63" +dependencies = [ + "atty", + "bitflags", + "clap_derive", + "indexmap", + "lazy_static", + "os_str_bytes", + "strsim 0.10.0", + "termcolor", + "textwrap", +] + +[[package]] +name = "clap_derive" +version = "3.0.0-beta.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b15c6b4f786ffb6192ffe65a36855bc1fc2444bcd0945ae16748dcd6ed7d0d3" +dependencies = [ + "heck", + "proc-macro-error", + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "combine" version = "4.6.1" @@ -221,18 +251,6 @@ version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fea41bba32d969b513997752735605054bc0dfa92b4c56bf1189f2e174be7a10" -[[package]] -name = "docopt" -version = "1.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f3f119846c823f9eafcf953a8f6ffb6ed69bf6240883261a7f13b634579a51f" -dependencies = [ - "lazy_static", - "regex", - "serde", - "strsim 0.10.0", -] - [[package]] name = "either" version = "1.6.1" @@ -450,6 +468,15 @@ version = "0.11.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ab5ef0d4909ef3724cc8cce6ccc8572c5c817592e9285f5464f8e86f8bd3726e" +[[package]] +name = "heck" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6d621efb26863f0e9924c6ac577e8275e5e6b77455db64ffa6c65c904e9e132c" +dependencies = [ + "unicode-segmentation", +] + [[package]] name = "hermit-abi" version = "0.1.19" @@ -799,6 +826,15 @@ version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "28988d872ab76095a6e6ac88d99b54fd267702734fd7ffe610ca27f533ddb95a" +[[package]] +name = "os_str_bytes" +version = "4.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "addaa943333a514159c80c97ff4a93306530d965d27e139188283cd13e06a799" +dependencies = [ + "memchr", +] + [[package]] name = "pager" version = "0.16.0" @@ -882,6 +918,30 @@ dependencies = [ "toml", ] +[[package]] +name = "proc-macro-error" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c" +dependencies = [ + "proc-macro-error-attr", + "proc-macro2", + "quote", + "syn", + "version_check", +] + +[[package]] +name = "proc-macro-error-attr" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869" +dependencies = [ + "proc-macro2", + "quote", + "version_check", +] + [[package]] name = "proc-macro-hack" version = "0.5.19" @@ -1223,7 +1283,7 @@ dependencies = [ "app_dirs2", "assert_cmd", "atty", - "docopt", + "clap", "env_logger", "escargot", "filetime", @@ -1262,6 +1322,12 @@ dependencies = [ "winapi-util", ] +[[package]] +name = "textwrap" +version = "0.14.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0066c8d12af8b5acd21e00547c3797fde4e8677254a7ee429176ccebbe93dd80" + [[package]] name = "thiserror" version = "1.0.29" @@ -1400,6 +1466,12 @@ dependencies = [ "tinyvec", ] +[[package]] +name = "unicode-segmentation" +version = "1.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8895849a949e7845e06bd6dc1aa51731a103c42707010a5b591c0038fb73385b" + [[package]] name = "unicode-xid" version = "0.2.2" @@ -1424,6 +1496,12 @@ dependencies = [ "percent-encoding", ] +[[package]] +name = "version_check" +version = "0.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5fecdca9a5291cc2b8dcf7dc02453fee791a280f3743cb0905f8822ae463b3fe" + [[package]] name = "wait-timeout" version = "0.2.0" diff --git a/Cargo.toml b/Cargo.toml index 6eb8fee3..5d053f06 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -19,7 +19,7 @@ path = "src/main.rs" ansi_term = "0.12.0" app_dirs = { version = "2", package = "app_dirs2" } atty = "0.2" -docopt = "1" +clap = { version = "3.0.0-beta.5", features = ["std", "derive", "color", "suggestions" ], default-features = false } env_logger = { version = "0.9", optional = true } log = "0.4" reqwest = { version = "0.11.3", features = ["blocking", "rustls-tls", "rustls-tls-native-roots"], default-features = false } diff --git a/clippy.toml b/clippy.toml index 349b6909..ece14b8d 100644 --- a/clippy.toml +++ b/clippy.toml @@ -1 +1 @@ -msrv = "1.53" +msrv = "1.54" diff --git a/docs/src/usage.md b/docs/src/usage.md index c8fa3086..6fba9338 100644 --- a/docs/src/usage.md +++ b/docs/src/usage.md @@ -4,6 +4,7 @@ Tealdeer is straightforward to use, through the binary named `tldr`. You can view the available options using `tldr --help`: + ``` -{{#include ../../src/usage.docopt}} +{{#include usage.txt}} ``` diff --git a/docs/src/usage.txt b/docs/src/usage.txt new file mode 100644 index 00000000..695eda19 --- /dev/null +++ b/docs/src/usage.txt @@ -0,0 +1,28 @@ +tealdeer 1.4.1 + +Danilo Bargen + +A fast TLDR client + +USAGE: + tldr [OPTIONS] [COMMAND]... + +ARGS: + ... The command to show (e.g. `tar` or `git log`) + +OPTIONS: + -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 + -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 + --show-paths Show file and directory paths used by tealdeer + --config-path Show config file path + --seed-config Create a basic config + --color Control whether to use color [always, auto, never] + -v, --version Print the version + -h, --help Print help information diff --git a/fish_tealdeer b/fish_tealdeer index 1aa95c56..7f2c63fb 100644 --- a/fish_tealdeer +++ b/fish_tealdeer @@ -7,7 +7,7 @@ complete -c tldr -s h -l help -d 'Print the help message.' -f complete -c tldr -s v -l version -d 'Show version information.' -f complete -c tldr -s l -l list -d 'List all commands in the cache.' -f complete -c tldr -s f -l render -d 'Render a specific markdown file.' -r -complete -c tldr -s o -l os -d 'Override the operating system.' -xa 'linux osx sunos windows other' +complete -c tldr -s o -l os -d 'Override the operating system.' -xa 'linux osx sunos windows' complete -c tldr -s u -l update -d 'Update the local cache.' -f complete -c tldr -s c -l clear-cache -d 'Clear the local cache.' -f complete -c tldr -s p -l pager -d 'Use a pager to page output.' -f diff --git a/src/cache.rs b/src/cache.rs index 0161de4f..5bfccb59 100644 --- a/src/cache.rs +++ b/src/cache.rs @@ -201,7 +201,6 @@ impl Cache { OsType::OsX => Some("osx"), OsType::SunOs => Some("sunos"), OsType::Windows => Some("windows"), - OsType::Other => None, } } diff --git a/src/main.rs b/src/main.rs index e87bc5cb..03277dc7 100644 --- a/src/main.rs +++ b/src/main.rs @@ -20,10 +20,9 @@ use std::{env, path::PathBuf, process}; use ansi_term::{Color, Style}; use app_dirs::AppInfo; use atty::Stream; -use docopt::Docopt; +use clap::{AppSettings, Parser}; #[cfg(not(target_os = "windows"))] use pager::Pager; -use serde_derive::Deserialize; mod cache; mod config; @@ -48,31 +47,82 @@ const APP_INFO: AppInfo = AppInfo { name: NAME, author: NAME, }; -const VERSION: &str = env!("CARGO_PKG_VERSION"); -const USAGE: &str = include_str!("usage.docopt"); const ARCHIVE_URL: &str = "https://tldr.sh/assets/tldr.zip"; #[cfg(not(target_os = "windows"))] const PAGER_COMMAND: &str = "less -R"; -#[allow(clippy::struct_excessive_bools)] -#[derive(Debug, Deserialize)] +#[derive(Parser, Debug)] +#[clap(about = "A fast TLDR client", author, version)] +#[clap(setting = AppSettings::ArgRequiredElseHelp)] +#[clap(setting = AppSettings::HelpRequired)] +#[clap(setting = AppSettings::DeriveDisplayOrder)] struct Args { - arg_command: Option>, - flag_help: bool, - flag_version: bool, - flag_list: bool, - flag_render: Option, - flag_os: Option, - flag_update: bool, - flag_clear_cache: bool, - flag_pager: bool, - flag_quiet: bool, - flag_show_paths: bool, - flag_config_path: bool, - flag_seed_config: bool, - flag_markdown: bool, - flag_color: ColorOptions, - flag_language: Option, + /// The command to show (e.g. `tar` or `git log`) + #[clap(min_values = 1)] + command: Vec, + + /// List all commands in the cache + #[clap(short = 'l', long = "list")] + list: bool, + + /// Render a specific markdown file + #[clap( + short = 'f', + long = "render", + value_name = "FILE", + conflicts_with = "command" + )] + render: Option, + + /// Override the operating system [linux, osx, sunos, windows] + #[clap(short = 'o', long = "os", requires = "command")] + os: Option, + + /// Override the language + #[clap(short = 'L', long = "language")] + language: Option, + + /// Update the local cache + #[clap(short = 'u', long = "update")] + update: bool, + + /// Clear the local cache + #[clap(short = 'c', long = "clear-cache")] + clear_cache: bool, + + /// Use a pager to page output + #[clap(short = 'p', long = "pager", requires = "command")] + pager: bool, + + /// Display the raw markdown instead of rendering it + #[clap(short = 'm', long = "markdown", requires = "command")] + markdown: bool, + + /// Suppress informational messages + #[clap(short = 'q', long = "quiet")] + quiet: bool, + + /// Show file and directory paths used by tealdeer + #[clap(long = "show-paths")] + show_paths: bool, + + /// Show config file path + #[clap(long = "config-path")] + config_path: bool, + + /// Create a basic config + #[clap(long = "seed-config")] + seed_config: bool, + + /// Control whether to use color [always, auto, never] + #[clap(long = "color", value_name = "WHEN")] + color: Option, + + /// 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")] + version: bool, } /// Set up display pager @@ -89,7 +139,7 @@ fn configure_pager() { /// The cache should get updated if this was requested by the user, or if auto /// updates are enabled and the cache age is longer than the auto update interval. fn should_update_cache(args: &Args, config: &Config) -> bool { - args.flag_update + args.update || (config.updates.auto_update && Cache::last_update().map_or(true, |ago| ago >= config.updates.auto_update_interval)) } @@ -104,7 +154,7 @@ enum CheckCacheResult { fn check_cache(args: &Args, enable_styles: bool) -> CheckCacheResult { match Cache::freshness() { CacheFreshness::Fresh => CheckCacheResult::CacheFound, - CacheFreshness::Stale(_) if args.flag_quiet => CheckCacheResult::CacheFound, + CacheFreshness::Stale(_) if args.quiet => CheckCacheResult::CacheFound, CacheFreshness::Stale(age) => { let warning_style = if enable_styles { Style::new().fg(Color::Yellow) @@ -313,28 +363,19 @@ fn main() { init_log(); // Parse arguments - let args: Args = Docopt::new(USAGE) - .and_then(|d| d.deserialize()) - .unwrap_or_else(|e| e.exit()); - - // Show version and exit - if args.flag_version { - let os = get_os(); - println!("{} v{} ({})", NAME, VERSION, os); - process::exit(0); - } + let args: Args = Args::parse(); // Show config file and path, pass through - if args.flag_config_path { + if args.config_path { eprintln!("Warning: The --config-path flag is deprecated, use --show-paths instead"); show_config_path(); } - if args.flag_show_paths { + if args.show_paths { show_paths(); } // Create a basic config and exit - if args.flag_seed_config { + if args.seed_config { create_config_and_exit(); } @@ -344,7 +385,7 @@ fn main() { #[cfg(not(target_os = "windows"))] let ansi_support = true; - let enable_styles = match args.flag_color { + let enable_styles = match args.color.unwrap_or(ColorOptions::Auto) { // Attempt to use styling if instructed ColorOptions::Always => true, // Enable styling if: @@ -371,20 +412,20 @@ fn main() { } }; - if args.flag_pager || config.display.use_pager { + if args.pager || config.display.use_pager { configure_pager(); } // Specify target OS - let os: OsType = match args.flag_os { + let os: OsType = match args.os { Some(os) => os, None => get_os(), }; // If a local file was passed in, render it and exit - if let Some(ref file) = args.flag_render { + if let Some(ref file) = args.render { let path = PageLookupResult::with_page(PathBuf::from(file)); - if let Err(msg) = print_page(&path, args.flag_markdown, &config) { + if let Err(msg) = print_page(&path, args.markdown, &config) { eprintln!("{}", msg); process::exit(1); } else { @@ -396,13 +437,13 @@ fn main() { let cache = Cache::new(ARCHIVE_URL, os); // Clear cache, pass through - if args.flag_clear_cache { - clear_cache(args.flag_quiet); + if args.clear_cache { + clear_cache(args.quiet); } // Cache update, pass through let cache_updated = if should_update_cache(&args, &config) { - update_cache(&cache, args.flag_quiet); + update_cache(&cache, args.quiet); true } else { false @@ -410,14 +451,14 @@ fn main() { // Check cache presence and freshness if !cache_updated - && (args.flag_list || args.arg_command.is_some()) + && (args.list || !args.command.is_empty()) && check_cache(&args, enable_styles) == CheckCacheResult::CacheMissing { process::exit(1); } // List cached commands and exit - if args.flag_list { + if args.list { // Get list of pages let pages = cache.list_pages().unwrap_or_else(|e| { eprintln!("Could not get list of pages: {}", e.message()); @@ -430,12 +471,12 @@ fn main() { } // Show command from cache - if let Some(ref command) = args.arg_command { - let command = command.join("-"); + if !args.command.is_empty() { + let command = args.command.join("-"); let languages = args - .flag_language - .map_or_else(get_languages_from_env, |flag_lang| vec![flag_lang]); + .language + .map_or_else(get_languages_from_env, |lang| vec![lang]); // Search for command in cache if let Some(page) = cache.find_page( @@ -443,13 +484,13 @@ fn main() { &languages, config.directories.custom_pages_dir.as_deref(), ) { - if let Err(msg) = print_page(&page, args.flag_markdown, &config) { + if let Err(msg) = print_page(&page, args.markdown, &config) { eprintln!("{}", msg); process::exit(1); } process::exit(0); } else { - if !args.flag_quiet { + if !args.quiet { eprintln!("Page {} not found in cache", &command); eprintln!("Try updating with `tldr --update`, or submit a pull request to:"); eprintln!("https://github.com/tldr-pages/tldr"); @@ -457,36 +498,11 @@ fn main() { process::exit(1); } } - - // Some flags can be run without a command. - if !(args.flag_update || args.flag_clear_cache || args.flag_config_path || args.flag_show_paths) - { - eprintln!("{}", USAGE); - process::exit(1); - } } #[cfg(test)] mod test { - use crate::{get_languages, Args, OsType, USAGE}; - use docopt::{Docopt, Error}; - - fn test_helper(argv: &[&str]) -> Result { - Docopt::new(USAGE).and_then(|d| d.argv(argv).deserialize()) - } - - #[test] - fn test_docopt_os_case_insensitive() { - let argv = ["cp", "--os", "LiNuX"]; - let os = test_helper(&argv).unwrap().flag_os.unwrap(); - assert_eq!(OsType::Linux, os); - } - - #[test] - fn test_docopt_expect_error() { - let argv = ["cp", "--os", "lindows"]; - assert!(!test_helper(&argv).is_ok()); - } + use crate::get_languages; mod language { use super::*; diff --git a/src/types.rs b/src/types.rs index 180185ae..2d938a55 100644 --- a/src/types.rs +++ b/src/types.rs @@ -1,6 +1,6 @@ //! Shared types used in tealdeer. -use std::fmt; +use std::{fmt, str}; use serde_derive::{Deserialize, Serialize}; @@ -12,7 +12,6 @@ pub enum OsType { OsX, SunOs, Windows, - Other, } impl fmt::Display for OsType { @@ -22,7 +21,23 @@ impl fmt::Display for OsType { Self::OsX => write!(f, "macOS / BSD"), Self::SunOs => write!(f, "SunOS"), Self::Windows => write!(f, "Windows"), - Self::Other => write!(f, "Unknown OS"), + } + } +} + +impl str::FromStr for OsType { + type Err = String; + + fn from_str(s: &str) -> Result { + match s { + "linux" => Ok(Self::Linux), + "osx" => Ok(Self::OsX), + "sunos" => Ok(Self::SunOs), + "windows" => Ok(Self::Windows), + other => Err(format!( + "Unknown OS: {}. Possible values: linux, osx, sunos, windows", + other + )), } } } @@ -35,6 +50,22 @@ pub enum ColorOptions { Never, } +impl str::FromStr for ColorOptions { + type Err = String; + + fn from_str(s: &str) -> Result { + match s { + "always" => Ok(Self::Always), + "auto" => Ok(Self::Auto), + "never" => Ok(Self::Never), + other => Err(format!( + "Unknown color option: {}. Possible values: always, auto, never", + other + )), + } + } +} + #[derive(Debug, Eq, PartialEq)] pub enum LineType { Empty, diff --git a/src/usage.docopt b/src/usage.docopt deleted file mode 100644 index 9ba09681..00000000 --- a/src/usage.docopt +++ /dev/null @@ -1,36 +0,0 @@ -Usage: - - tldr [options] ... - tldr [options] - -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] - -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 - --show-paths Show file and directory paths used by tealdeer - --config-path Show config file path (deprecated) - --seed-config Create a basic config - --color Control when to use color [always, auto, never] [default: auto] - -Examples: - - $ tldr tar - $ tldr --list - -To control the cache: - - $ tldr --update - $ tldr --clear-cache - -To render a local file (for testing): - - $ tldr --render /path/to/file.md From 6d77483ad5cf66c054fa07379b2fe27a74e011f7 Mon Sep 17 00:00:00 2001 From: Danilo Bargen Date: Sun, 17 Oct 2021 19:56:40 +0200 Subject: [PATCH 2/8] Implement Default for ColorOptions --- src/config.rs | 2 +- src/main.rs | 2 +- src/types.rs | 6 ++++++ 3 files changed, 8 insertions(+), 2 deletions(-) diff --git a/src/config.rs b/src/config.rs index 758147aa..2f5f62f7 100644 --- a/src/config.rs +++ b/src/config.rs @@ -85,7 +85,7 @@ impl Default for RawStyle { italic: false, } } -} // impl RawStyle +} impl From for Style { fn from(raw_style: RawStyle) -> Self { diff --git a/src/main.rs b/src/main.rs index 03277dc7..92787dec 100644 --- a/src/main.rs +++ b/src/main.rs @@ -385,7 +385,7 @@ fn main() { #[cfg(not(target_os = "windows"))] let ansi_support = true; - let enable_styles = match args.color.unwrap_or(ColorOptions::Auto) { + let enable_styles = match args.color.unwrap_or_default() { // Attempt to use styling if instructed ColorOptions::Always => true, // Enable styling if: diff --git a/src/types.rs b/src/types.rs index 2d938a55..239b3fcb 100644 --- a/src/types.rs +++ b/src/types.rs @@ -66,6 +66,12 @@ impl str::FromStr for ColorOptions { } } +impl Default for ColorOptions { + fn default() -> Self { + Self::Auto + } +} + #[derive(Debug, Eq, PartialEq)] pub enum LineType { Empty, From ee0d32d3de89d7289c03f272d7f6fbe067b1a2fe Mon Sep 17 00:00:00 2001 From: Danilo Bargen Date: Sun, 9 May 2021 19:50:39 +0200 Subject: [PATCH 3/8] CI: Ensure that usage string is always up to date --- .github/workflows/ci.yml | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 36d1f553..160d9aed 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -67,3 +67,27 @@ jobs: with: command: fmt args: --all -- --check + + docs: + name: build docs + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + - name: Setup mdBook + uses: peaceiris/actions-mdbook@v1 + with: + mdbook-version: '0.4.4' + - uses: actions-rs/toolchain@v1 + with: + toolchain: stable + override: true + - name: Build + uses: actions-rs/cargo@v1 + with: + command: build + - name: Ensure that docs can be built + run: cd docs && mdbook build + - name: Generate usage string + run: cargo run -- --help > docs/src/usage-actual.txt + - name: Ensure that usage string is up to date + run: diff docs/src/usage{,-actual}.txt From 8833b6b40179eef6161035d10d7e218694facca1 Mon Sep 17 00:00:00 2001 From: Danilo Bargen Date: Sun, 17 Oct 2021 20:53:12 +0200 Subject: [PATCH 4/8] Rename -m / --markdown to -r / --raw That flag name is clearer: We output raw page data without processing. --- bash_tealdeer | 2 +- docs/src/usage.txt | 2 +- fish_tealdeer | 2 +- src/main.rs | 22 ++++++++++++++++++---- tests/lib.rs | 2 +- zsh_tealdeer | 2 +- 6 files changed, 23 insertions(+), 9 deletions(-) diff --git a/bash_tealdeer b/bash_tealdeer index aadcc05a..6ed44cdb 100644 --- a/bash_tealdeer +++ b/bash_tealdeer @@ -6,7 +6,7 @@ _tealdeer() _init_completion || return case $prev in - -h|--help|-v|--version|-l|--list|-u|--update|-c|--clear-cache|-p|--pager|-m|--markdown|--show-paths|--seed-config|-q|--quiet) + -h|--help|-v|--version|-l|--list|-u|--update|-c|--clear-cache|-p|--pager|-r|--raw|--show-paths|--seed-config|-q|--quiet) return ;; -f|--render) diff --git a/docs/src/usage.txt b/docs/src/usage.txt index 695eda19..3f5f24a9 100644 --- a/docs/src/usage.txt +++ b/docs/src/usage.txt @@ -18,7 +18,7 @@ OPTIONS: -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 + -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 --config-path Show config file path diff --git a/fish_tealdeer b/fish_tealdeer index 7f2c63fb..cad6cc2e 100644 --- a/fish_tealdeer +++ b/fish_tealdeer @@ -11,7 +11,7 @@ complete -c tldr -s o -l os -d 'Override the operating system.' -xa 'li complete -c tldr -s u -l update -d 'Update the local cache.' -f complete -c tldr -s c -l clear-cache -d 'Clear the local cache.' -f complete -c tldr -s p -l pager -d 'Use a pager to page output.' -f -complete -c tldr -s m -l markdown -d 'Display the raw markdown instead of rendering it.' -f +complete -c tldr -s r -l raw -d 'Display the raw markdown instead of rendering it.' -f complete -c tldr -s q -l quiet -d 'Suppress informational messages.' -f complete -c tldr -l show-paths -d 'Show file and directory paths used by tealdeer.' -f complete -c tldr -l seed-config -d 'Create a basic config.' -f diff --git a/src/main.rs b/src/main.rs index 92787dec..15ccac54 100644 --- a/src/main.rs +++ b/src/main.rs @@ -95,7 +95,11 @@ struct Args { pager: bool, /// Display the raw markdown instead of rendering it - #[clap(short = 'm', long = "markdown", requires = "command")] + #[clap(short = 'r', long = "--raw", requires = "command")] + raw: bool, + + /// Deprecated alias of `raw` + #[clap(long = "markdown", short = 'm', requires = "command", hidden = true)] markdown: bool, /// Suppress informational messages @@ -363,7 +367,17 @@ fn main() { init_log(); // Parse arguments - let args: Args = Args::parse(); + let args = { + let mut args = Args::parse(); + + // Handle renamed arguments + if args.markdown { + args.raw = true; + eprintln!("Warning: The -m / --markdown flag is deprecated, use -r / --raw instead"); + } + + args + }; // Show config file and path, pass through if args.config_path { @@ -425,7 +439,7 @@ fn main() { // If a local file was passed in, render it and exit if let Some(ref file) = args.render { let path = PageLookupResult::with_page(PathBuf::from(file)); - if let Err(msg) = print_page(&path, args.markdown, &config) { + if let Err(msg) = print_page(&path, args.raw, &config) { eprintln!("{}", msg); process::exit(1); } else { @@ -484,7 +498,7 @@ fn main() { &languages, config.directories.custom_pages_dir.as_deref(), ) { - if let Err(msg) = print_page(&page, args.markdown, &config) { + if let Err(msg) = print_page(&page, args.raw, &config) { eprintln!("{}", msg); process::exit(1); } diff --git a/tests/lib.rs b/tests/lib.rs index b6cdff26..6ff88d2b 100644 --- a/tests/lib.rs +++ b/tests/lib.rs @@ -339,7 +339,7 @@ fn test_markdown_rendering() { let expected = include_str!("which-markdown.expected"); testenv .command() - .args(["-m", "which"]) + .args(["--raw", "which"]) .assert() .success() .stdout(diff(expected)); diff --git a/zsh_tealdeer b/zsh_tealdeer index 96e40f02..0674063b 100644 --- a/zsh_tealdeer +++ b/zsh_tealdeer @@ -24,7 +24,7 @@ _tealdeer() { "($I -u --update)"{-u,--update}"[Update the local cache]" "($I -c --clear-cache)"{-c,--clear-cache}"[Clear the local cache]" "($I -p --pager)"{-p,--pager}"[Use a pager to page output]" - "($I -m --markdown)"{-m,--markdown}"[Display the raw markdown instead of rendering it]" + "($I -r --raw)"{-r,--raw}"[Display the raw markdown instead of rendering it]" "($I -q --quiet)"{-q,--quiet}"[Suppress informational messages]" "($I)--show-paths[Show file and directory paths used by tealdeer]" "($I)--seed-config[Create a basic config]" From fc726011d1b92b83e2cc3257108a47f14a72390c Mon Sep 17 00:00:00 2001 From: Danilo Bargen Date: Sun, 17 Oct 2021 21:16:50 +0200 Subject: [PATCH 5/8] Move free-standing get_os function to OsType::current --- src/main.rs | 36 +----------------------------------- src/types.rs | 36 ++++++++++++++++++++++++++++++++++++ 2 files changed, 37 insertions(+), 35 deletions(-) diff --git a/src/main.rs b/src/main.rs index 15ccac54..03a6d680 100644 --- a/src/main.rs +++ b/src/main.rs @@ -292,40 +292,6 @@ fn init_log() { #[cfg(not(feature = "logging"))] fn init_log() {} -#[cfg(target_os = "linux")] -fn get_os() -> OsType { - OsType::Linux -} - -#[cfg(any( - target_os = "macos", - target_os = "freebsd", - target_os = "netbsd", - target_os = "openbsd", - target_os = "dragonfly" -))] -fn get_os() -> OsType { - OsType::OsX -} - -#[cfg(target_os = "windows")] -fn get_os() -> OsType { - OsType::Windows -} - -#[cfg(not(any( - target_os = "linux", - target_os = "macos", - target_os = "freebsd", - target_os = "netbsd", - target_os = "openbsd", - target_os = "dragonfly", - target_os = "windows" -)))] -fn get_os() -> OsType { - OsType::Other -} - fn get_languages(env_lang: Option<&str>, env_language: Option<&str>) -> Vec { // Language list according to // https://github.com/tldr-pages/tldr/blob/master/CLIENT-SPECIFICATION.md#language @@ -433,7 +399,7 @@ fn main() { // Specify target OS let os: OsType = match args.os { Some(os) => os, - None => get_os(), + None => OsType::current(), }; // If a local file was passed in, render it and exit diff --git a/src/types.rs b/src/types.rs index 239b3fcb..3e6a1617 100644 --- a/src/types.rs +++ b/src/types.rs @@ -42,6 +42,42 @@ impl str::FromStr for OsType { } } +impl OsType { + #[cfg(target_os = "linux")] + pub fn current() -> Self { + Self::Linux + } + + #[cfg(any( + target_os = "macos", + target_os = "freebsd", + target_os = "netbsd", + target_os = "openbsd", + target_os = "dragonfly" + ))] + pub fn current() -> Self { + Self::OsX + } + + #[cfg(target_os = "windows")] + pub fn current() -> Self { + Self::Windows + } + + #[cfg(not(any( + target_os = "linux", + target_os = "macos", + target_os = "freebsd", + target_os = "netbsd", + target_os = "openbsd", + target_os = "dragonfly", + target_os = "windows" + )))] + pub fn current() -> Self { + Self::Other + } +} + #[derive(Debug, Eq, PartialEq, Copy, Clone, Deserialize)] #[serde(rename_all = "lowercase")] pub enum ColorOptions { From 6823e271a0efab4daaa30f527b56eac53b6efc9e Mon Sep 17 00:00:00 2001 From: Danilo Bargen Date: Sun, 17 Oct 2021 22:10:06 +0200 Subject: [PATCH 6/8] Disable clap colors for now May be re-introduced if clap adds a `DisableColoredHelp` setting. Relevant discussion: - https://github.com/clap-rs/clap/pull/2845#issuecomment-945185102 - https://github.com/dbrgn/tealdeer/pull/108#issuecomment-945182471 --- Cargo.lock | 2 -- Cargo.toml | 2 +- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 14828afe..85a67a54 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -134,14 +134,12 @@ version = "3.0.0-beta.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "feff3878564edb93745d58cf63e17b63f24142506e7a20c87a5521ed7bfb1d63" dependencies = [ - "atty", "bitflags", "clap_derive", "indexmap", "lazy_static", "os_str_bytes", "strsim 0.10.0", - "termcolor", "textwrap", ] diff --git a/Cargo.toml b/Cargo.toml index 5d053f06..7a025f8f 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -19,7 +19,7 @@ path = "src/main.rs" ansi_term = "0.12.0" app_dirs = { version = "2", package = "app_dirs2" } atty = "0.2" -clap = { version = "3.0.0-beta.5", features = ["std", "derive", "color", "suggestions" ], default-features = false } +clap = { version = "3.0.0-beta.5", features = ["std", "derive", "suggestions" ], default-features = false } env_logger = { version = "0.9", optional = true } log = "0.4" reqwest = { version = "0.11.3", features = ["blocking", "rustls-tls", "rustls-tls-native-roots"], default-features = false } From 371f1d2ace99f4cf7077c27cf65908ca5b8a2acd Mon Sep 17 00:00:00 2001 From: Danilo Bargen Date: Sun, 17 Oct 2021 22:20:39 +0200 Subject: [PATCH 7/8] Help: Add a link to the online docs --- docs/src/usage.txt | 2 ++ src/main.rs | 3 +++ 2 files changed, 5 insertions(+) diff --git a/docs/src/usage.txt b/docs/src/usage.txt index 3f5f24a9..85d089c9 100644 --- a/docs/src/usage.txt +++ b/docs/src/usage.txt @@ -26,3 +26,5 @@ OPTIONS: --color Control whether to use color [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/. diff --git a/src/main.rs b/src/main.rs index 03a6d680..7b74e646 100644 --- a/src/main.rs +++ b/src/main.rs @@ -56,6 +56,9 @@ const PAGER_COMMAND: &str = "less -R"; #[clap(setting = AppSettings::ArgRequiredElseHelp)] #[clap(setting = AppSettings::HelpRequired)] #[clap(setting = AppSettings::DeriveDisplayOrder)] +#[clap( + after_help = "To view the user documentation, please visit https://dbrgn.github.io/tealdeer/." +)] struct Args { /// The command to show (e.g. `tar` or `git log`) #[clap(min_values = 1)] From 618ecaf71fbadc8de5d408f01d7cb251abf65d1f Mon Sep 17 00:00:00 2001 From: Danilo Bargen Date: Sun, 17 Oct 2021 22:23:35 +0200 Subject: [PATCH 8/8] Add @niklasmohrin to crate authors --- Cargo.toml | 5 ++++- docs/src/usage.txt | 2 +- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 7a025f8f..ba563968 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,5 +1,8 @@ [package] -authors = ["Danilo Bargen "] +authors = [ + "Danilo Bargen ", + "Niklas Mohrin ", +] description = "Fetch and show tldr help pages for many CLI commands. Full featured offline client with caching support." homepage = "https://github.com/dbrgn/tealdeer/" license = "MIT/Apache-2.0" diff --git a/docs/src/usage.txt b/docs/src/usage.txt index 85d089c9..7e135624 100644 --- a/docs/src/usage.txt +++ b/docs/src/usage.txt @@ -1,6 +1,6 @@ tealdeer 1.4.1 -Danilo Bargen +Danilo Bargen , Niklas Mohrin A fast TLDR client