Repository: sharkdp/bat (language: rust)

Issue:
Add --diagnostic option to bat itself
The bug report issue templates asks to run https://github.com/sharkdp/bat/blob/master/diagnostics/info.sh or add the Windows version, as well as add the bat version. It would be much easier to have a `--diagnostic` command in bat directly, like e.g. `jrnl` has it:
```
❯ jrnl --diagnostic
jrnl: v2.4.5
Python: 3.8.6 (default, Sep 30 2020, 04:00:38) 
[GCC 10.2.0]
OS: Linux 5.9.10-arch1-1
```


Discussion / hints:
Yes. I have been thinking about a command-line option like this for a while, and I believe that's a great idea. Thanks for writing it down.

Advantages over the existing shell script:
- cross-platform
- much easier for the user to execute
- direct access to the `bat` config file, environment variables etc. that `bat` *actually sees* when executed
- possibility to also print out additional command line arguments that might have been passed via an alias (e.g. running `bat --diagnostic` with `alias bat="bat --theme=1337"`) or a shell function. This will work independent from the shell. No need to have bash/zsh/fish-specific code.

Disadvantages:
- Adds some dependencies, most probably
I am working on this
Any ideas for how we can detect the shell aliases from within bat? Or will the original script still be needed?
> Any ideas for how we can detect the shell aliases from within bat? Or will the original script still be needed?

I was hoping that alias and wrapper detection would not be needed anymore. As I understand it, we mostly want this to see if a user has set something like
```bash
alias bat="bat --pager='less --some-weird-option'"
```

If that user then notices an error when running `bat -p somefile.rb`, we will ask him/her to add the `--diagnostic` option:
```
bat -p somefile.rb --diagnostic
```

My current implementation then simply looks at all command-line options and would generate a report like this:

---

## Software version

bat 0.17.1

## Operating system

Linux 5.9.1-arch1-1

## Command-line

```bash
bat '--pager=less --some-weird-option' -p somefile.rb --diagnostic 
```

## Environment variables

```PAGER=less
BAT_PAGER=<not set>
BAT_CONFIG_PATH=<not set>
BAT_STYLE=<not set>
BAT_THEME=<not set>
BAT_TABS=<not set>

```

---

We would not be able to see which command-line options came from the alias and which were passed on the command-line, but the user would probably tell us that `bat -p somefile.rb` doesn't work.

What do you think? Are there other situations where alias/wrapper detection would still be helpful?
There are some nice ideas in `git bugreport` that we could implement as well.

Fix patch:
diff --git a/.github/workflows/CICD.yml b/.github/workflows/CICD.yml
index 21bdbf47f4..e8dbbbfca5 100644
--- a/.github/workflows/CICD.yml
+++ b/.github/workflows/CICD.yml
@@ -226,7 +226,13 @@ jobs:
       with:
         use-cross: ${{ steps.vars.outputs.CARGO_USE_CROSS }}
         command: run
-        args: --target=${{ matrix.job.target }} ${{ matrix.job.cargo-options }} -- --paging=never --color=always --theme=ansi-dark Cargo.toml src/config.rs
+        args: --target=${{ matrix.job.target }} ${{ matrix.job.cargo-options }} -- --paging=never --color=always --theme=ansi Cargo.toml src/config.rs
+    - name: bat diagnostics output
+      uses: actions-rs/cargo@v1
+      with:
+        use-cross: ${{ steps.vars.outputs.CARGO_USE_CROSS }}
+        command: run
+        args: --target=${{ matrix.job.target }} ${{ matrix.job.cargo-options }} -- --paging=never --color=always --theme=ansi Cargo.toml src/config.rs --diagnostic
     - name: Check features regex-onig
       uses: actions-rs/cargo@v1
       with:
diff --git a/Cargo.lock b/Cargo.lock
index 9d34c3c443..ced057ca99 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -98,6 +98,7 @@ dependencies = [
  "ansi_term 0.12.1",
  "assert_cmd",
  "atty",
+ "bugreport",
  "clap",
  "clircle",
  "console",
@@ -193,6 +194,16 @@ dependencies = [
  "memchr",
 ]
 
+[[package]]
+name = "bugreport"
+version = "0.3.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "116762017f173ea5d8103e75533f6bdb62cb6f2257c9c95672beb085a70daed8"
+dependencies = [
+ "snailquote",
+ "sys-info",
+]
+
 [[package]]
 name = "byte-tools"
 version = "0.3.1"
@@ -1070,6 +1081,16 @@ version = "1.0.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "b6fa3938c99da4914afedd13bf3d79bcb6c277d1b2c398d23257a304d9e1b074"
 
+[[package]]
+name = "snailquote"
+version = "0.3.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f34b729d802f52194598858ac852c3fb3b33f6e026cd03195072ccb7bf3fc810"
+dependencies = [
+ "thiserror",
+ "unicode_categories",
+]
+
 [[package]]
 name = "std_prelude"
 version = "0.2.12"
@@ -1084,9 +1105,9 @@ checksum = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a"
 
 [[package]]
 name = "syn"
-version = "1.0.42"
+version = "1.0.55"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9c51d92969d209b54a98397e1b91c8ae82d8c87a7bb87df0b29aa2ad81454228"
+checksum = "a571a711dddd09019ccc628e1b17fe87c59b09d513c06c026877aa708334f37a"
 dependencies = [
  "proc-macro2",
  "quote",
@@ -1116,6 +1137,16 @@ dependencies = [
  "yaml-rust",
 ]
 
+[[package]]
+name = "sys-info"
+version = "0.7.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e5cfbd84f86389198ade41b439f72a5b1b3a8ba728e61cd589e1720d0df44c39"
+dependencies = [
+ "cc",
+ "libc",
+]
+
 [[package]]
 name = "tempdir"
 version = "0.3.7"
@@ -1156,6 +1187,26 @@ dependencies = [
  "unicode-width",
 ]
 
+[[package]]
+name = "thiserror"
+version = "1.0.22"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0e9ae34b84616eedaaf1e9dd6026dbe00dcafa92aa0c8077cb69df1fcfe5e53e"
+dependencies = [
+ "thiserror-impl",
+]
+
+[[package]]
+name = "thiserror-impl"
+version = "1.0.22"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9ba20f23e85b10754cd195504aebf6a27e2e6cbe28c17778a0c930724628dd56"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn",
+]
+
 [[package]]
 name = "thread_local"
 version = "1.0.1"
@@ -1219,6 +1270,12 @@ version = "0.2.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "f7fe0bb3479651439c9112f72b6c505038574c9fbb575ed1bf3b797fa39dd564"
 
+[[package]]
+name = "unicode_categories"
+version = "0.1.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "39ec24b3121d976906ece63c9daad25b85969647682eee313cb5779fdd69e14e"
+
 [[package]]
 name = "url"
 version = "2.1.1"
diff --git a/Cargo.toml b/Cargo.toml
index 212db77ae4..18216303a0 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -51,6 +51,7 @@ serde_yaml = "0.8"
 semver = "0.11"
 path_abs = { version = "0.5", default-features = false }
 clircle = "0.2.0"
+bugreport = "0.3"
 
 [dependencies.git2]
 version = "0.13"
diff --git a/src/bin/bat/clap_app.rs b/src/bin/bat/clap_app.rs
index 4e642760c8..87cb2a65e8 100644
--- a/src/bin/bat/clap_app.rs
+++ b/src/bin/bat/clap_app.rs
@@ -477,6 +477,13 @@ pub fn build_app(interactive_output: bool) -> ClapApp<'static, 'static> {
                 .hidden(true)
                 .help("Show bat's cache directory."),
         )
+        .arg(
+            Arg::with_name("diagnostic")
+                .long("diagnostic")
+                .alias("diagnostics")
+                .hidden_short_help(true)
+                .help("Show diagnostic information for bug reports.")
+        )
         .help_message("Print this help message.")
         .version_message("Show version information.");
 
diff --git a/src/bin/bat/main.rs b/src/bin/bat/main.rs
index af8ca7873f..e2862fe975 100644
--- a/src/bin/bat/main.rs
+++ b/src/bin/bat/main.rs
@@ -35,8 +35,7 @@ use bat::{
     error::*,
     input::Input,
     style::{StyleComponent, StyleComponents},
-    MappingTarget,
-    PagingMode,
+    MappingTarget, PagingMode,
 };
 
 const THEME_PREVIEW_DATA: &[u8] = include_bytes!("../../../assets/theme_preview.rs");
@@ -228,6 +227,36 @@ fn run_controller(inputs: Vec<Input>, config: &Config) -> Result<bool> {
 fn run() -> Result<bool> {
     let app = App::new()?;
 
+    if app.matches.is_present("diagnostic") {
+        use bugreport::{bugreport, collector::*, format::Markdown};
+
+        bugreport!()
+            .info(SoftwareVersion::default())
+            .info(OperatingSystem::default())
+            .info(CommandLine::default())
+            .info(EnvironmentVariables::list(&[
+                "SHELL",
+                "PAGER",
+                "BAT_CACHE_PATH",
+                "BAT_CONFIG_PATH",
+                "BAT_OPTS",
+                "BAT_PAGER",
+                "BAT_STYLE",
+                "BAT_TABS",
+                "BAT_THEME",
+                "XDG_CONFIG_HOME",
+                "XDG_CACHE_HOME",
+                "COLORTERM",
+                "NO_COLOR",
+            ]))
+            .info(FileContent::new("Config file", config_file()))
+            .info(CompileTimeInformation::default())
+            .info(CommandOutput::new("Less version", "less", &["--version"]))
+            .print::<Markdown>();
+
+        return Ok(true);
+    }
+
     match app.matches.subcommand() {
         ("cache", Some(cache_matches)) => {
             // If there is a file named 'cache' in the current working directory,


Test patch: