nushell/src/commands/help.rs

179 lines
7.4 KiB
Rust
Raw Normal View History

use crate::commands::PerItemCommand;
use crate::data::{command_dict, TaggedDictBuilder};
use crate::errors::ShellError;
use crate::parser::registry::{self, NamedType, PositionalType};
use crate::prelude::*;
use nu_source::SpannedItem;
pub struct Help;
impl PerItemCommand for Help {
fn name(&self) -> &str {
"help"
}
fn signature(&self) -> registry::Signature {
2019-10-28 06:15:35 +01:00
Signature::build("help").rest(SyntaxShape::Any, "the name of command(s) to get help on")
}
fn usage(&self) -> &str {
"Display help information about commands."
}
fn run(
&self,
call_info: &CallInfo,
2019-09-03 11:36:23 +02:00
registry: &CommandRegistry,
_raw_args: &RawCommandArgs,
_input: Value,
) -> Result<OutputStream, ShellError> {
let tag = &call_info.name_tag;
2019-09-24 09:56:03 +02:00
match call_info.args.nth(0) {
Some(Value {
value: UntaggedValue::Primitive(Primitive::String(document)),
2019-09-03 11:36:23 +02:00
tag,
2019-09-24 09:56:03 +02:00
}) => {
let mut help = VecDeque::new();
2019-09-03 11:36:23 +02:00
if document == "commands" {
let mut sorted_names = registry.names();
sorted_names.sort();
for cmd in sorted_names {
let mut short_desc = TaggedDictBuilder::new(tag.clone());
2019-09-03 11:36:23 +02:00
let value = command_dict(registry.get_command(&cmd).unwrap(), tag.clone());
short_desc.insert_untagged("name", cmd);
short_desc.insert_untagged(
2019-09-03 11:36:23 +02:00
"description",
2019-11-04 16:47:03 +01:00
value
.get_data_by_key("usage".spanned_unknown())
.unwrap()
.as_string()
.unwrap(),
2019-09-03 11:36:23 +02:00
);
help.push_back(ReturnSuccess::value(short_desc.into_value()));
2019-09-03 11:36:23 +02:00
}
} else {
if let Some(command) = registry.get_command(document) {
let mut long_desc = String::new();
long_desc.push_str(&command.usage());
long_desc.push_str("\n");
let signature = command.signature();
let mut one_liner = String::new();
one_liner.push_str(&signature.name);
one_liner.push_str(" ");
2019-10-28 06:15:35 +01:00
for positional in &signature.positional {
match &positional.0 {
PositionalType::Mandatory(name, _m) => {
one_liner.push_str(&format!("<{}> ", name));
}
PositionalType::Optional(name, _o) => {
one_liner.push_str(&format!("({}) ", name));
}
}
}
2019-09-03 11:36:23 +02:00
if signature.rest_positional.is_some() {
2019-10-28 06:15:35 +01:00
one_liner.push_str(&format!(" ...args",));
}
2019-10-28 06:15:35 +01:00
2019-11-06 03:28:26 +01:00
if signature.named.len() > 0 {
one_liner.push_str("{flags} ");
}
long_desc.push_str(&format!("\nUsage:\n > {}\n", one_liner));
2019-10-28 06:15:35 +01:00
if signature.positional.len() > 0 || signature.rest_positional.is_some() {
long_desc.push_str("\nparameters:\n");
for positional in signature.positional {
match positional.0 {
PositionalType::Mandatory(name, _m) => {
long_desc
.push_str(&format!(" <{}> {}\n", name, positional.1));
}
PositionalType::Optional(name, _o) => {
long_desc
.push_str(&format!(" ({}) {}\n", name, positional.1));
}
}
}
if signature.rest_positional.is_some() {
long_desc.push_str(&format!(
" ...args{} {}\n",
if signature.rest_positional.is_some() {
":"
} else {
""
},
signature.rest_positional.unwrap().1
));
}
}
if signature.named.len() > 0 {
long_desc.push_str("\nflags:\n");
for (flag, ty) in signature.named {
2019-10-28 06:15:35 +01:00
match ty.0 {
NamedType::Switch => {
2019-10-28 06:15:35 +01:00
long_desc.push_str(&format!(
" --{}{} {}\n",
flag,
if ty.1.len() > 0 { ":" } else { "" },
ty.1
));
}
NamedType::Mandatory(m) => {
long_desc.push_str(&format!(
2019-10-28 06:15:35 +01:00
" --{} <{}> (required parameter){} {}\n",
flag,
m,
if ty.1.len() > 0 { ":" } else { "" },
ty.1
));
}
NamedType::Optional(o) => {
2019-10-28 06:15:35 +01:00
long_desc.push_str(&format!(
" --{} <{}>{} {}\n",
flag,
o,
if ty.1.len() > 0 { ":" } else { "" },
ty.1
));
}
}
}
}
help.push_back(ReturnSuccess::value(
UntaggedValue::string(long_desc).into_value(tag.clone()),
));
}
2019-09-03 11:36:23 +02:00
}
Ok(help.to_output_stream())
}
_ => {
let msg = r#"Welcome to Nushell.
2019-09-12 20:33:52 +02:00
Here are some tips to help you get started.
2019-09-12 20:33:52 +02:00
* help commands - list all available commands
* help <command name> - display help about a particular command
You can also learn more at https://book.nushell.sh"#;
let mut output_stream = VecDeque::new();
output_stream.push_back(ReturnSuccess::value(
UntaggedValue::string(msg).into_value(tag),
));
Ok(output_stream.to_output_stream())
2019-09-03 11:36:23 +02:00
}
}
}
}