Repository: sharkdp/bat (language: rust)

Issue:
output shell completion script by `bat --completion <shell>` command
Currently the autocompletion script comes only with the source.

A better approach, would be something like `bat --completion=bash`.

Here is my current `bash_completion` script executed at login:

```bash
source <($HOME/.local/bin/helm completion bash)
source <($HOME/.local/bin/kustomize completion bash)
source <($HOME/.local/bin/pip completion --bash)
source <($HOME/.local/bin/stern --completion=bash)
source <($HOME/.local/node/bin/npm completion)
source $HOME/.local/bat/autocomplete/bat.bash # this can become `bat --completion=bash` 
```


Discussion / hints:
The bash completion should be placed in this `~/.local/share/bash-completion/completions` directory.

From [github:bash-completion](https://github.com/scop/bash-completion)

> Q. Where should I install my own local completions?
> 
> A. Put them in the completions subdir of $BASH_COMPLETION_USER_DIR (defaults to $XDG_DATA_HOME/bash-completion or ~/.local/share/bash-completion if $XDG_DATA_HOME is not set) to have them loaded automatically on demand when the respective command is being completed. See also the next question's answer for considerations for these files' names, they apply here as well. Alternatively, you can write them directly in ~/.bash_completion which is loaded eagerly by our main script.
> 

For **system wide** installation (e.g. packaging deb, ...) the completion may be placed in `/etc/bash_completion.d/` . 
@abuGit - I don't think you understand my feature request.

I am asking for a completion script *built-in* from `bat completion` command directly. 

Yes, `bat completion` command does not exist - that's what I am asking for.
I would really like this, too, for `zsh`. It's really convenient to be able to do `{tool} completion --shell {zsh|bash|fish}` at install-time to also install/refresh shell completions.
I haven't figured out a good way to get the completions when installing `bat` using `cargo`. This issue would solve the problem imo.
> I haven't figured out a good way to get the completions when installing `bat` using `cargo`. This issue would solve the problem imo.

This worked for me:

```bash
TARGET_DIR=tmp
CMP_SCRIPT=bat.bash

mkdir -p $TARGET_DIR
cargo install --locked --target-dir $TARGET_DIR bat
mkdir -p ~/.local/share/bash-completion/completions
cp $(find $TARGET_DIR -name $CMP_SCRIPT) ~/.local/share/bash-completion/completions/
```

**Edit:** Actually [this method](https://github.com/sharkdp/bat/issues/2892#issuecomment-1987359296) looks cleaner/easier.

Fix patch:
diff --git a/CHANGELOG.md b/CHANGELOG.md
index c0934f8abb..4941340e35 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -11,6 +11,7 @@
 - Add or remove individual style components without replacing all styles #2929 (@eth-p)
 - Automatically choose theme based on the terminal's color scheme, see #2896 (@bash)
 - Add option `--binary=as-text` for printing binary content, see issue #2974 and PR #2976 (@einfachIrgendwer0815)
+- Make shell completions available via `--completion <shell>`, see issue #2057 and PR #3126 (@einfachIrgendwer0815)
 
 ## Bugfixes
 
diff --git a/README.md b/README.md
index c09d0e3674..cbe9d88630 100644
--- a/README.md
+++ b/README.md
@@ -465,6 +465,12 @@ cargo install --locked bat
 Note that additional files like the man page or shell completion
 files can not be installed in this way. They will be generated by `cargo` and should be available in the cargo target folder (under `build`).
 
+Shell completions are also available by running:
+```bash
+bat --completion <shell>
+# see --help for supported shells
+```
+
 ## Customization
 
 ### Highlighting theme
diff --git a/build/application.rs b/build/application.rs
index 459aa5b1cb..addbae0e74 100644
--- a/build/application.rs
+++ b/build/application.rs
@@ -63,5 +63,22 @@ pub fn gen_man_and_comp() -> anyhow::Result<()> {
         out_dir.join("assets/completions/bat.zsh"),
     )?;
 
+    println!(
+        "cargo:rustc-env=BAT_GENERATED_COMPLETION_BASH={}",
+        out_dir.join("assets/completions/bat.bash").display()
+    );
+    println!(
+        "cargo:rustc-env=BAT_GENERATED_COMPLETION_FISH={}",
+        out_dir.join("assets/completions/bat.fish").display()
+    );
+    println!(
+        "cargo:rustc-env=BAT_GENERATED_COMPLETION_PS1={}",
+        out_dir.join("assets/completions/_bat.ps1").display()
+    );
+    println!(
+        "cargo:rustc-env=BAT_GENERATED_COMPLETION_ZSH={}",
+        out_dir.join("assets/completions/bat.zsh").display()
+    );
+
     Ok(())
 }
diff --git a/doc/long-help.txt b/doc/long-help.txt
index 85d595b980..17d3395b00 100644
--- a/doc/long-help.txt
+++ b/doc/long-help.txt
@@ -202,6 +202,9 @@ Options:
           This option exists for POSIX-compliance reasons ('u' is for 'unbuffered'). The output is
           always unbuffered - this option is simply ignored.
 
+      --completion <SHELL>
+          Show shell completion for a certain shell. [possible values: bash, fish, zsh, ps1]
+
       --diagnostic
           Show diagnostic information for bug reports.
 
diff --git a/doc/short-help.txt b/doc/short-help.txt
index ba06ef3065..d67a51d03c 100644
--- a/doc/short-help.txt
+++ b/doc/short-help.txt
@@ -58,6 +58,8 @@ Options:
           Only print the lines from N to M.
   -L, --list-languages
           Display all supported languages.
+      --completion <SHELL>
+          Show shell completion for a certain shell. [possible values: bash, fish, zsh, ps1]
   -h, --help
           Print help (see more with '--help')
   -V, --version
diff --git a/src/bin/bat/clap_app.rs b/src/bin/bat/clap_app.rs
index f5e3948e97..de2db0784d 100644
--- a/src/bin/bat/clap_app.rs
+++ b/src/bin/bat/clap_app.rs
@@ -564,6 +564,17 @@ pub fn build_app(interactive_output: bool) -> Command {
                 .help("Do not load custom assets"),
         );
 
+    #[cfg(feature = "application")]
+    {
+        app = app.arg(
+            Arg::new("completion")
+            .long("completion")
+            .value_name("SHELL")
+            .value_parser(["bash", "fish", "ps1", "zsh"])
+            .help("Show shell completion for a certain shell. [possible values: bash, fish, zsh, ps1]"),
+        );
+    }
+
     #[cfg(feature = "lessopen")]
     {
         app = app
diff --git a/src/bin/bat/completions.rs b/src/bin/bat/completions.rs
new file mode 100644
index 0000000000..9b63a3e995
--- /dev/null
+++ b/src/bin/bat/completions.rs
@@ -0,0 +1,6 @@
+use std::env;
+
+pub const BASH_COMPLETION: &str = include_str!(env!("BAT_GENERATED_COMPLETION_BASH"));
+pub const FISH_COMPLETION: &str = include_str!(env!("BAT_GENERATED_COMPLETION_FISH"));
+pub const PS1_COMPLETION: &str = include_str!(env!("BAT_GENERATED_COMPLETION_PS1"));
+pub const ZSH_COMPLETION: &str = include_str!(env!("BAT_GENERATED_COMPLETION_ZSH"));
diff --git a/src/bin/bat/main.rs b/src/bin/bat/main.rs
index 7b7bafe600..253c388594 100644
--- a/src/bin/bat/main.rs
+++ b/src/bin/bat/main.rs
@@ -3,6 +3,8 @@
 mod app;
 mod assets;
 mod clap_app;
+#[cfg(feature = "application")]
+mod completions;
 mod config;
 mod directories;
 mod input;
@@ -347,6 +349,18 @@ fn run() -> Result<bool> {
         return Ok(true);
     }
 
+    #[cfg(feature = "application")]
+    if let Some(shell) = app.matches.get_one::<String>("completion") {
+        match shell.as_str() {
+            "bash" => println!("{}", completions::BASH_COMPLETION),
+            "fish" => println!("{}", completions::FISH_COMPLETION),
+            "ps1" => println!("{}", completions::PS1_COMPLETION),
+            "zsh" => println!("{}", completions::ZSH_COMPLETION),
+            _ => unreachable!("No completion for shell '{}' available.", shell),
+        }
+        return Ok(true);
+    }
+
     match app.matches.subcommand() {
         Some(("cache", cache_matches)) => {
             // If there is a file named 'cache' in the current working directory,


Test patch: