You've already forked uutils-args
mirror of
https://github.com/uutils/uutils-args.git
synced 2026-06-10 16:13:08 -07:00
nu completion: support value options
This commit is contained in:
+58
-24
@@ -1,36 +1,39 @@
|
||||
// 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};
|
||||
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 {
|
||||
short,
|
||||
long,
|
||||
help,
|
||||
value: _value,
|
||||
} in &c.args
|
||||
{
|
||||
for Flag { flag, value } in short {
|
||||
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 {
|
||||
": string"
|
||||
format!(": string{hint}")
|
||||
} else {
|
||||
""
|
||||
"".into()
|
||||
};
|
||||
args.push((format!("-{flag}{value}"), help));
|
||||
args.push((format!("-{flag}{value}"), arg.help));
|
||||
}
|
||||
for Flag { flag, value } in long {
|
||||
for Flag { flag, value } in &arg.long {
|
||||
let value = if let Value::Required(_) | Value::Optional(_) = value {
|
||||
": string"
|
||||
format!(": string{hint}")
|
||||
} else {
|
||||
""
|
||||
"".into()
|
||||
};
|
||||
args.push((format!("--{flag}{value}"), help));
|
||||
args.push((format!("--{flag}{value}"), arg.help));
|
||||
}
|
||||
}
|
||||
let longest_arg = args.iter().map(|a| a.0.len()).max().unwrap_or_default();
|
||||
@@ -38,14 +41,45 @@ pub fn render(c: &Command) -> String {
|
||||
for (a, h) in args {
|
||||
writeln!(arg_str, "{indent}{a:<longest_arg$} # {h}").unwrap();
|
||||
}
|
||||
template(c.name, &arg_str)
|
||||
template(c.name, &complete_commands.join("\n"), &arg_str)
|
||||
}
|
||||
|
||||
fn template(name: &str, args: &str) -> String {
|
||||
format!(
|
||||
"\
|
||||
export extern {name} [\n{args}\
|
||||
]\n\
|
||||
"
|
||||
)
|
||||
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")
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user