Skip to content

Commit

Permalink
Add shell completion subcommand
Browse files Browse the repository at this point in the history
  • Loading branch information
ede1998 committed Nov 1, 2024
1 parent 555cde0 commit e45aa68
Show file tree
Hide file tree
Showing 5 changed files with 65 additions and 1 deletion.
10 changes: 10 additions & 0 deletions Cargo.lock

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

1 change: 1 addition & 0 deletions fclones/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ bytesize = "1.1"
byte-unit = "4.0"
chrono = { version = "0.4", default-features = false, features = ["serde", "clock", "std"] }
clap = { version = "4.4", features = ["derive", "cargo", "wrap_help"] }
clap_complete = "4.4"
console = "0.15"
crossbeam-channel = "0.5"
crossbeam-utils = "0.8"
Expand Down
13 changes: 13 additions & 0 deletions fclones/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -163,6 +163,19 @@ are also attached directly to [Releases](https://github.com/pkolaczk/fclones/rel

The build will write the binary to `.cargo/bin/fclones`.

### Shell completions

`fclones` supports shell completions but you have to set it up manually at the moment,
which can be done by adding the script printed by the `fclones complete` subcommand to your shell configuration.
All shells supported by [clap_complete](https://docs.rs/clap_complete/latest/clap_complete/aot/enum.Shell.html) are supported.
At the time of writing this includes:

- Bash: Add `eval "$(fclones complete bash)"` to your `~/.bashrc`
- Zsh: Add `source <(fclones complete zsh)` to your `~/.zshrc`
- Fish: Add `fclones complete fish | source` to your `~/.config/fish/config.fish`
- Elvish
- Powershell

## Usage

`fclones` offers separate commands for finding and removing files. This way, you can inspect
Expand Down
12 changes: 12 additions & 0 deletions fclones/src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -729,6 +729,12 @@ pub enum Command {
#[arg()]
target: PathBuf,
},

/// Print shell completion script to stdout.
Complete {
/// Shell for which the completion script is generated.
shell: clap_complete::Shell,
},
}

impl Command {
Expand Down Expand Up @@ -801,4 +807,10 @@ mod test {
config.command,
Command::Move { target, .. } if target == PathBuf::from("target"));
}

#[test]
fn test_complete_command() {
let config: Config = Config::try_parse_from(vec!["fclones", "complete", "zsh"]).unwrap();
assert_matches!(config.command, Command::Complete { shell } if shell == clap_complete::Shell::Zsh);
}
}
30 changes: 29 additions & 1 deletion fclones/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ use std::process::exit;
use std::sync::Arc;
use std::{fs, io};

use clap::Parser;
use clap::{CommandFactory, Parser};
use console::style;
use fallible_iterator::FallibleIterator;
use itertools::Itertools;
Expand Down Expand Up @@ -243,6 +243,17 @@ pub fn run_dedupe(op: DedupeOp, config: DedupeConfig, log: &dyn Log) -> Result<(
result.map_err(|e| Error::new(format!("Failed to read file list: {e}")))
}

fn generate_completions(shell: clap_complete::Shell, output: &mut dyn std::io::Write) {
clap_complete::generate(
shell,
&mut Config::command(),
std::env::args()
.next()
.unwrap_or_else(|| "fclones".to_owned()),
output,
);
}

fn main() {
let config: Config = Config::parse();
if let Err(e) = config.command.validate() {
Expand Down Expand Up @@ -283,6 +294,10 @@ fn main() {
let target = Arc::new(fclones::Path::from(cwd)).resolve(target);
run_dedupe(DedupeOp::Move(Arc::new(target)), config, &log)
}
Command::Complete { shell } => {
generate_completions(shell, &mut std::io::stdout());
Ok(())
}
};

if let Err(e) = result {
Expand Down Expand Up @@ -316,4 +331,17 @@ mod test {
"error message"
);
}

#[test]
fn test_no_panic_in_completion_script_generation() {
use clap::ValueEnum;
for shell in clap_complete::Shell::value_variants() {
let mut script = Vec::new();

super::generate_completions(*shell, &mut script);

let script = String::from_utf8(script).unwrap();
assert!(!script.is_empty());
}
}
}

0 comments on commit e45aa68

Please sign in to comment.