| Crates.io | completers |
| lib.rs | completers |
| version | 0.0.5 |
| created_at | 2025-05-02 07:52:54.005993+00 |
| updated_at | 2025-08-25 06:36:38.149842+00 |
| description | A tiny Rust-native shell completion solution. |
| homepage | |
| repository | https://github.com/PRO-2684/completers |
| max_upload_size | |
| id | 1657400 |
| size | 27,042 |
[!WARNING] This crate is still a prototype, and is subject to BREAKING changes without notice.
A tiny Rust-native shell completion solution.
See examples for a few examples of how to use this crate.
First, define a completion handler function that takes a [Completion] struct as an argument and returns a vector of completion candidates:
use completers::Completion;
fn handler(_completion: Completion) -> Vec<String> {
vec![]
}
Then, call [handle_completion] BEFORE any other command that writes to stdout in your main function:
use completers::{Completion, handle_completion};
fn main() {
handle_completion(handler);
// Other logic
}
#
# fn handler(_completion: Completion) -> Vec<String> {
# vec![]
# }
To delegate completion, we should first match against [Completion::init()]:
use completers::{CompletersError, Completion};
use std::process::exit;
fn main() -> Result<(), CompletersError> {
match Completion::init() {
Ok(Some(completion)) => {
delegate_completion(completion)?;
}
Ok(None) => {
// No completion request, do nothing
}
Err(e) => {
eprintln!("Error: {e}");
exit(1);
}
};
// Do your job
Ok(())
}
#
# fn delegate_completion(mut comp: Completion) -> Result<(), CompletersError> {
# Ok(())
# }
Then, construct or mutate the [Completion] object in the delegate function. We'll delegate to cargo build --example for example:
# use completers::{CompletersError, Completion};
# use std::process::exit;
#
/// Delegates completion to `cargo build --example`, exit if successful.
fn delegate_completion(mut comp: Completion) -> Result<(), CompletersError> {
let old_words_count = comp.words.len();
comp.words.remove(0); // Discard program name
let mut new_words = vec![
"cargo".to_string(),
"build".to_string(),
"--example".to_string(),
];
new_words.append(&mut comp.words);
comp.words = new_words;
comp.word_index += comp.words.len();
comp.word_index -= old_words_count;
comp.line = comp.words.join(" ");
comp.cursor_index = comp
.words
.iter()
.take(comp.word_index)
.map(|word| word.len())
.sum::<usize>()
+ comp.word_index
+ comp.words[comp.word_index].len();
comp.delegate();
Ok(())
}
[!NOTE] By using
completers, we assume that you've gotbash-completioninstalled. Some features such as completion delegate won't work without it.
Generate and evaluate the shell code via:
source <(COMPLETE=bash my_binary)
You should be able to complete your commands now. To enable completion across all your terminal sessions, you can add the above code to your completions directory, like:
mkdir -p ~/.local/share/bash-completion/completions # Create the directory if it doesn't exist
echo 'source <(COMPLETE=bash my_binary)' > ~/.local/share/bash-completion/completions/my_binary
You can also use /usr/share/bash-completion/completions/ as the directory, if you want the completion to be available system-wise.
Instructions for lazy loading completions will be updated once nushell/nushell#4874 is resolved. For now, you'll have to:
COMPLETE=nu my_binary o> somewhere/handy.nu
And then source the file from your ($nu.default-config-dir)/config.nu:
source somewhere/handy.nu
Note that completions will only work for my_binary, and not ./my_binary or /path/to/my_binary.
completers BinaryCurrently, the completers binary does nothing.
See CAVEATS.md for a list of known problems, and see MECHANISM.md for a detailed explanation of how this works, in case you're curious.
clap, whose code and API is used as a reference. When clap's Rust-Native Completion Engine is stablized, this crate will be deprecated in favor of it.complete-alias, whose shell code helped a lot.prototype