Repository: dbrgn/tealdeer (rust)

Issue:
Cannot combine `-f / --render` with other options
This command fails, even though it should work:

    cargo run -- --raw -f tar.md

This is a regression introduced by #108, because of the `requires`-constraints in commands like `raw`.

First, write a regression test to catch this bug.

Then find out how to tell clap that "either a command or a -f file is required".

Pull request:
Introduce command_or_file arg group
This allows to say "this command line parameter requires either a command or a raw file".

Fixes #219.

(Clap is pretty awesome!)

Patch:
diff --git a/src/main.rs b/src/main.rs
index 45419f9..45aa050 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -20,7 +20,7 @@ use std::{env, path::PathBuf, process};
 
 use app_dirs::AppInfo;
 use atty::Stream;
-use clap::{AppSettings, Parser};
+use clap::{AppSettings, ArgGroup, Parser};
 #[cfg(not(target_os = "windows"))]
 use pager::Pager;
 
@@ -61,6 +61,7 @@ const ARCHIVE_URL: &str = "https://tldr.sh/assets/tldr.zip";
 #[clap(
     after_help = "To view the user documentation, please visit https://dbrgn.github.io/tealdeer/."
 )]
+#[clap(group = ArgGroup::new("command_or_file").args(&["command", "render"]))]
 struct Args {
     /// The command to show (e.g. `tar` or `git log`)
     #[clap(min_values = 1)]
@@ -83,7 +84,6 @@ struct Args {
     #[clap(
         short = 'p',
         long = "platform",
-        requires = "command",
         possible_values = ["linux", "macos", "windows", "sunos", "osx"],
     )]
     platform: Option<PlatformType>,
@@ -92,7 +92,6 @@ struct Args {
     #[clap(
         short = 'o',
         long = "os",
-        requires = "command",
         possible_values = ["linux", "macos", "windows", "sunos", "osx"],
         hide_possible_values = true,
     )]
@@ -111,15 +110,20 @@ struct Args {
     clear_cache: bool,
 
     /// Use a pager to page output
-    #[clap(long = "pager", requires = "command")]
+    #[clap(long = "pager", requires = "command_or_file")]
     pager: bool,
 
     /// Display the raw markdown instead of rendering it
-    #[clap(short = 'r', long = "--raw", requires = "command")]
+    #[clap(short = 'r', long = "--raw", requires = "command_or_file")]
     raw: bool,
 
     /// Deprecated alias of `raw`
-    #[clap(long = "markdown", short = 'm', requires = "command", hidden = true)]
+    #[clap(
+        long = "markdown",
+        short = 'm',
+        requires = "command_or_file",
+        hidden = true
+    )]
     markdown: bool,
 
     /// Suppress informational messages


Test patch:
diff --git a/tests/lib.rs b/tests/lib.rs
index 7d52beb..de6d346 100644
--- a/tests/lib.rs
+++ b/tests/lib.rs
@@ -709,3 +709,34 @@ fn test_lowercased_page_lookup() {
     // Lookup `eyeD3`, should succeed as well
     testenv.command().args(["eyeD3"]).assert().success();
 }
+
+/// Regression test for #219: It should be possible to combine `--raw` and `-f`.
+#[test]
+fn test_raw_render_file() {
+    let testenv = TestEnv::new();
+
+    // Create input file
+    let file_path = testenv.input_dir.path().join("inkscape.md");
+    let mut file = File::create(&file_path).unwrap();
+    file.write_all(include_bytes!("inkscape-v1.md")).unwrap();
+
+    // Base args
+    let mut args = vec!["--color", "never", "-f", file_path.to_str().unwrap()];
+
+    // Default render
+    testenv
+        .command()
+        .args(&args)
+        .assert()
+        .success()
+        .stdout(diff(include_str!("inkscape-default-no-color.expected")));
+
+    // Raw render
+    args.push("--raw");
+    testenv
+        .command()
+        .args(&args)
+        .assert()
+        .success()
+        .stdout(diff(include_str!("inkscape-v1.md")));
+}