You've already forked uutils-args
mirror of
https://github.com/uutils/uutils-args.git
synced 2026-06-10 16:13:08 -07:00
Merge pull request #65 from tertsdiepraam/nu-completions
Basic nushell completions
This commit is contained in:
@@ -16,6 +16,7 @@
|
||||
mod fish;
|
||||
mod man;
|
||||
mod md;
|
||||
mod nu;
|
||||
mod zsh;
|
||||
|
||||
/// A description of a CLI command
|
||||
@@ -72,6 +73,7 @@ pub fn render(c: &Command, shell: &str) -> String {
|
||||
"md" => md::render(c),
|
||||
"fish" => fish::render(c),
|
||||
"zsh" => zsh::render(c),
|
||||
"nu" | "nushell" => nu::render(c),
|
||||
"man" => man::render(c),
|
||||
"sh" | "bash" | "csh" | "elvish" | "powershell" => panic!("shell '{shell}' completion is not implemented yet!"),
|
||||
_ => panic!("unknown option '{shell}'! Expected one of: \"md\", \"fish\", \"zsh\", \"man\", \"sh\", \"bash\", \"csh\", \"elvish\", \"powershell\""),
|
||||
|
||||
@@ -0,0 +1,85 @@
|
||||
// For the full copyright and license information, please view the LICENSE
|
||||
// file that was distributed with this source code.
|
||||
|
||||
use crate::{Arg, Command, Flag, Value, ValueHint};
|
||||
use std::fmt::Write;
|
||||
|
||||
/// Create completion script for `nushell`
|
||||
pub fn render(c: &Command) -> String {
|
||||
let mut args = Vec::new();
|
||||
let command_name = c.name;
|
||||
let mut complete_commands = Vec::new();
|
||||
let indent = " ".repeat(4);
|
||||
|
||||
for arg in &c.args {
|
||||
let hint = if let Some((cmd, hint_name)) = render_completion_command(command_name, arg) {
|
||||
complete_commands.push(cmd);
|
||||
hint_name
|
||||
} else {
|
||||
"".into()
|
||||
};
|
||||
|
||||
for Flag { flag, value } in &arg.short {
|
||||
let value = if let Value::Required(_) | Value::Optional(_) = value {
|
||||
format!(": string{hint}")
|
||||
} else {
|
||||
"".into()
|
||||
};
|
||||
args.push((format!("-{flag}{value}"), arg.help));
|
||||
}
|
||||
for Flag { flag, value } in &arg.long {
|
||||
let value = if let Value::Required(_) | Value::Optional(_) = value {
|
||||
format!(": string{hint}")
|
||||
} else {
|
||||
"".into()
|
||||
};
|
||||
args.push((format!("--{flag}{value}"), arg.help));
|
||||
}
|
||||
}
|
||||
let longest_arg = args.iter().map(|a| a.0.len()).max().unwrap_or_default();
|
||||
let mut arg_str = String::new();
|
||||
for (a, h) in args {
|
||||
writeln!(arg_str, "{indent}{a:<longest_arg$} # {h}").unwrap();
|
||||
}
|
||||
template(c.name, &complete_commands.join("\n"), &arg_str)
|
||||
}
|
||||
|
||||
fn render_completion_command(command_name: &str, arg: &Arg) -> Option<(String, String)> {
|
||||
let val = arg.value.as_ref()?;
|
||||
|
||||
// It could be that there is only a `dd` style argument. In that case, nu won't support it;
|
||||
let arg_name = arg.long.first().or(arg.short.first())?.flag;
|
||||
|
||||
render_value_hint(val).map(|hint| {
|
||||
let name = format!("nu-complete {command_name} {arg_name}");
|
||||
let cmd = format!("def \"{name}\" [] {{\n {hint}\n}}");
|
||||
let hint_str = format!("@\"{name}\"");
|
||||
(cmd, hint_str)
|
||||
})
|
||||
}
|
||||
|
||||
fn render_value_hint(value: &ValueHint) -> Option<String> {
|
||||
match value {
|
||||
ValueHint::Strings(s) => {
|
||||
let vals = s
|
||||
.iter()
|
||||
.map(|s| format!("\"{s}\""))
|
||||
.collect::<Vec<_>>()
|
||||
.join(", ");
|
||||
Some(format!("[{vals}]"))
|
||||
}
|
||||
// The path arguments could be improved, but nu currently does not give
|
||||
// us enough context to improve the default completions.
|
||||
ValueHint::Unknown
|
||||
| ValueHint::AnyPath
|
||||
| ValueHint::FilePath
|
||||
| ValueHint::ExecutablePath
|
||||
| ValueHint::DirPath
|
||||
| ValueHint::Username
|
||||
| ValueHint::Hostname => None,
|
||||
}
|
||||
}
|
||||
|
||||
fn template(name: &str, complete_commands: &str, args: &str) -> String {
|
||||
format!("{complete_commands}\n\nexport extern \"{name}\" [\n{args}]\n")
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
use std::path::PathBuf;
|
||||
|
||||
use uutils_args::{Arguments, Options, Value};
|
||||
|
||||
#[derive(Value)]
|
||||
enum Number {
|
||||
#[value]
|
||||
One,
|
||||
#[value]
|
||||
Two,
|
||||
#[value]
|
||||
Three,
|
||||
}
|
||||
|
||||
#[derive(Arguments)]
|
||||
enum Arg {
|
||||
/// Give it nothing!
|
||||
#[arg("-f", "--flag")]
|
||||
Flag,
|
||||
|
||||
// Completion is derived from the `Number` type, through the `Value` trait
|
||||
/// Give it a number!
|
||||
#[arg("-n N", "--number=N")]
|
||||
Number(Number),
|
||||
|
||||
// Completion is derived from the `PathBuf` type
|
||||
/// Give it a path!
|
||||
#[arg("-p P", "--path=P")]
|
||||
Path(PathBuf),
|
||||
}
|
||||
|
||||
struct Settings;
|
||||
|
||||
impl Options<Arg> for Settings {
|
||||
fn apply(&mut self, _arg: Arg) {
|
||||
panic!("Compile with the 'parse-is-complete' feature!")
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {
|
||||
Settings.parse(std::env::args_os());
|
||||
}
|
||||
Reference in New Issue
Block a user