mirror of
https://github.com/nushell/nushell
synced 2024-11-10 23:24:14 +00:00
Add search terms to Command and Signature (#4980)
* Add search terms to command * Rename Signature desc to usage To be named uniformly with extra_usage * Throw in foldl search term for reduce * Add missing usage to post * Add search terms to signature * Try to add capnp Signature serialization
This commit is contained in:
parent
0c9dd6a29a
commit
2873e943b3
32 changed files with 269 additions and 100 deletions
|
@ -17,7 +17,6 @@ impl Command for Do {
|
|||
|
||||
fn signature(&self) -> nu_protocol::Signature {
|
||||
Signature::build("do")
|
||||
.desc(self.usage())
|
||||
.required("block", SyntaxShape::Any, "the block to run")
|
||||
.switch(
|
||||
"ignore-errors",
|
||||
|
|
|
@ -7,6 +7,8 @@ use nu_protocol::{
|
|||
|
||||
use nu_engine::{get_full_help, CallExt};
|
||||
|
||||
use std::borrow::Borrow;
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct Help;
|
||||
|
||||
|
@ -96,14 +98,22 @@ fn help(
|
|||
let mut vals = vec![];
|
||||
|
||||
let decl = engine_state.get_decl(decl_id);
|
||||
let sig = decl.signature();
|
||||
let sig = decl.signature().update_from_command(decl.borrow());
|
||||
|
||||
let key = sig.name;
|
||||
let usage = sig.usage;
|
||||
let search_terms = sig.search_terms;
|
||||
let matches_term = if search_terms.is_empty() {
|
||||
search_terms
|
||||
.iter()
|
||||
.any(|term| term.to_lowercase().contains(&search_string))
|
||||
} else {
|
||||
false
|
||||
};
|
||||
|
||||
let key = sig.name.clone();
|
||||
let c = sig.usage.clone();
|
||||
let e = sig.extra_usage.clone();
|
||||
if key.to_lowercase().contains(&search_string)
|
||||
|| c.to_lowercase().contains(&search_string)
|
||||
|| e.to_lowercase().contains(&search_string)
|
||||
|| usage.to_lowercase().contains(&search_string)
|
||||
|| matches_term
|
||||
{
|
||||
cols.push("name".into());
|
||||
vals.push(Value::String {
|
||||
|
@ -136,10 +146,20 @@ fn help(
|
|||
});
|
||||
|
||||
cols.push("usage".into());
|
||||
vals.push(Value::String { val: c, span: head });
|
||||
vals.push(Value::String {
|
||||
val: usage,
|
||||
span: head,
|
||||
});
|
||||
|
||||
cols.push("extra_usage".into());
|
||||
vals.push(Value::String { val: e, span: head });
|
||||
cols.push("search_terms".into());
|
||||
vals.push(if search_terms.is_empty() {
|
||||
Value::nothing(head)
|
||||
} else {
|
||||
Value::String {
|
||||
val: search_terms.join(", "),
|
||||
span: head,
|
||||
}
|
||||
});
|
||||
|
||||
found_cmds_vec.push(Value::Record {
|
||||
cols,
|
||||
|
@ -163,11 +183,11 @@ fn help(
|
|||
let mut vals = vec![];
|
||||
|
||||
let decl = engine_state.get_decl(decl_id);
|
||||
let sig = decl.signature();
|
||||
let sig = decl.signature().update_from_command(decl.borrow());
|
||||
|
||||
let key = sig.name.clone();
|
||||
let c = sig.usage.clone();
|
||||
let e = sig.extra_usage.clone();
|
||||
let key = sig.name;
|
||||
let usage = sig.usage;
|
||||
let search_terms = sig.search_terms;
|
||||
|
||||
cols.push("name".into());
|
||||
vals.push(Value::String {
|
||||
|
@ -200,10 +220,20 @@ fn help(
|
|||
});
|
||||
|
||||
cols.push("usage".into());
|
||||
vals.push(Value::String { val: c, span: head });
|
||||
vals.push(Value::String {
|
||||
val: usage,
|
||||
span: head,
|
||||
});
|
||||
|
||||
cols.push("extra_usage".into());
|
||||
vals.push(Value::String { val: e, span: head });
|
||||
cols.push("search_terms".into());
|
||||
vals.push(if search_terms.is_empty() {
|
||||
Value::nothing(head)
|
||||
} else {
|
||||
Value::String {
|
||||
val: search_terms.join(", "),
|
||||
span: head,
|
||||
}
|
||||
});
|
||||
|
||||
found_cmds_vec.push(Value::Record {
|
||||
cols,
|
||||
|
|
|
@ -20,7 +20,6 @@ impl Command for ViewSource {
|
|||
|
||||
fn signature(&self) -> nu_protocol::Signature {
|
||||
Signature::build("view-source")
|
||||
.desc(self.usage())
|
||||
.required("item", SyntaxShape::Any, "name or block to view")
|
||||
.category(Category::Core)
|
||||
}
|
||||
|
|
|
@ -36,6 +36,10 @@ impl Command for Reduce {
|
|||
"Aggregate a list table to a single value using an accumulator block."
|
||||
}
|
||||
|
||||
fn search_terms(&self) -> Vec<&str> {
|
||||
vec!["map", "fold", "foldl"]
|
||||
}
|
||||
|
||||
fn examples(&self) -> Vec<Example> {
|
||||
vec![
|
||||
Example {
|
||||
|
|
|
@ -27,7 +27,6 @@ impl Command for SubCommand {
|
|||
|
||||
fn signature(&self) -> Signature {
|
||||
Signature::build("fetch")
|
||||
.desc("Load from a URL into a cell, convert to table if possible (avoid by appending '--raw').")
|
||||
.required(
|
||||
"URL",
|
||||
SyntaxShape::String,
|
||||
|
@ -45,15 +44,33 @@ impl Command for SubCommand {
|
|||
"the password when authenticating",
|
||||
Some('p'),
|
||||
)
|
||||
.named("timeout", SyntaxShape::Int, "timeout period in seconds", Some('t'))
|
||||
.named("headers",SyntaxShape::Any, "custom headers you want to add ", Some('H'))
|
||||
.switch("raw", "fetch contents as text rather than a table", Some('r'))
|
||||
.named(
|
||||
"timeout",
|
||||
SyntaxShape::Int,
|
||||
"timeout period in seconds",
|
||||
Some('t'),
|
||||
)
|
||||
.named(
|
||||
"headers",
|
||||
SyntaxShape::Any,
|
||||
"custom headers you want to add ",
|
||||
Some('H'),
|
||||
)
|
||||
.switch(
|
||||
"raw",
|
||||
"fetch contents as text rather than a table",
|
||||
Some('r'),
|
||||
)
|
||||
.filter()
|
||||
.category(Category::Network)
|
||||
}
|
||||
|
||||
fn usage(&self) -> &str {
|
||||
"Fetch the contents from a URL (HTTP GET operation)."
|
||||
"Fetch the contents from a URL."
|
||||
}
|
||||
|
||||
fn extra_usage(&self) -> &str {
|
||||
"Performs HTTP GET operation."
|
||||
}
|
||||
|
||||
fn run(
|
||||
|
|
|
@ -24,7 +24,6 @@ impl Command for SubCommand {
|
|||
|
||||
fn signature(&self) -> Signature {
|
||||
Signature::build("post")
|
||||
.desc("Post content to a URL and retrieve data as a table if possible.")
|
||||
.required("path", SyntaxShape::String, "the URL to post to")
|
||||
.required("body", SyntaxShape::Any, "the contents of the post body")
|
||||
.named(
|
||||
|
@ -70,9 +69,15 @@ impl Command for SubCommand {
|
|||
.filter()
|
||||
.category(Category::Network)
|
||||
}
|
||||
|
||||
fn usage(&self) -> &str {
|
||||
"Post a body to a URL (HTTP POST operation)."
|
||||
"Post a body to a URL."
|
||||
}
|
||||
|
||||
fn extra_usage(&self) -> &str {
|
||||
"Performs HTTP POST operation."
|
||||
}
|
||||
|
||||
fn run(
|
||||
&self,
|
||||
engine_state: &EngineState,
|
||||
|
|
|
@ -16,7 +16,6 @@ impl Command for Ps {
|
|||
|
||||
fn signature(&self) -> Signature {
|
||||
Signature::build("ps")
|
||||
.desc("View information about system processes.")
|
||||
.switch(
|
||||
"long",
|
||||
"list all available columns for each entry",
|
||||
|
|
|
@ -14,10 +14,7 @@ impl Command for Sys {
|
|||
}
|
||||
|
||||
fn signature(&self) -> Signature {
|
||||
Signature::build("sys")
|
||||
.desc("View information about the current system.")
|
||||
.filter()
|
||||
.category(Category::System)
|
||||
Signature::build("sys").filter().category(Category::System)
|
||||
}
|
||||
|
||||
fn usage(&self) -> &str {
|
||||
|
|
|
@ -4,6 +4,8 @@ use nu_protocol::{
|
|||
engine::{EngineState, Stack},
|
||||
Example, IntoPipelineData, Signature, Span, Value,
|
||||
};
|
||||
|
||||
use std::borrow::Borrow;
|
||||
use std::collections::HashMap;
|
||||
|
||||
const COMMANDS_DOCS_DIR: &str = "docs/commands";
|
||||
|
@ -51,10 +53,12 @@ fn generate_doc(
|
|||
});
|
||||
}
|
||||
|
||||
let signature = command.signature().update_from_command(command.borrow());
|
||||
|
||||
cols.push("documentation".to_owned());
|
||||
vals.push(Value::String {
|
||||
val: get_documentation(
|
||||
&command.signature(),
|
||||
&signature,
|
||||
&command.examples(),
|
||||
engine_state,
|
||||
stack,
|
||||
|
@ -177,6 +181,13 @@ pub fn get_documentation(
|
|||
}
|
||||
}
|
||||
|
||||
if !sig.search_terms.is_empty() {
|
||||
long_desc.push_str(&format!(
|
||||
"Search terms: {}\n\n",
|
||||
sig.search_terms.join(", ")
|
||||
));
|
||||
}
|
||||
|
||||
long_desc.push_str(&format!("Usage:\n > {}\n", sig.call_signature()));
|
||||
|
||||
if !subcommands.is_empty() {
|
||||
|
|
|
@ -817,6 +817,7 @@ pub fn create_scope(
|
|||
|
||||
let decl = engine_state.get_decl(*decl_id);
|
||||
let signature = decl.signature();
|
||||
|
||||
cols.push("category".to_string());
|
||||
vals.push(Value::String {
|
||||
val: signature.category.to_string(),
|
||||
|
@ -1026,6 +1027,17 @@ pub fn create_scope(
|
|||
span,
|
||||
});
|
||||
|
||||
let search_terms = decl.search_terms();
|
||||
cols.push("search_terms".to_string());
|
||||
vals.push(if search_terms.is_empty() {
|
||||
Value::nothing(span)
|
||||
} else {
|
||||
Value::String {
|
||||
val: search_terms.join(", "),
|
||||
span,
|
||||
}
|
||||
});
|
||||
|
||||
commands.push(Value::Record { cols, vals, span })
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1884,20 +1884,17 @@ pub mod signature {
|
|||
!self.reader.get_pointer_field(2).is_null()
|
||||
}
|
||||
#[inline]
|
||||
pub fn get_required_positional(
|
||||
self,
|
||||
) -> ::capnp::Result<::capnp::struct_list::Reader<'a, crate::plugin_capnp::argument::Owned>>
|
||||
{
|
||||
pub fn get_search_terms(self) -> ::capnp::Result<::capnp::text_list::Reader<'a>> {
|
||||
::capnp::traits::FromPointerReader::get_from_pointer(
|
||||
&self.reader.get_pointer_field(3),
|
||||
::core::option::Option::None,
|
||||
)
|
||||
}
|
||||
pub fn has_required_positional(&self) -> bool {
|
||||
pub fn has_search_terms(&self) -> bool {
|
||||
!self.reader.get_pointer_field(3).is_null()
|
||||
}
|
||||
#[inline]
|
||||
pub fn get_optional_positional(
|
||||
pub fn get_required_positional(
|
||||
self,
|
||||
) -> ::capnp::Result<::capnp::struct_list::Reader<'a, crate::plugin_capnp::argument::Owned>>
|
||||
{
|
||||
|
@ -1906,31 +1903,44 @@ pub mod signature {
|
|||
::core::option::Option::None,
|
||||
)
|
||||
}
|
||||
pub fn has_optional_positional(&self) -> bool {
|
||||
pub fn has_required_positional(&self) -> bool {
|
||||
!self.reader.get_pointer_field(4).is_null()
|
||||
}
|
||||
#[inline]
|
||||
pub fn get_rest(self) -> ::capnp::Result<crate::plugin_capnp::argument::Reader<'a>> {
|
||||
pub fn get_optional_positional(
|
||||
self,
|
||||
) -> ::capnp::Result<::capnp::struct_list::Reader<'a, crate::plugin_capnp::argument::Owned>>
|
||||
{
|
||||
::capnp::traits::FromPointerReader::get_from_pointer(
|
||||
&self.reader.get_pointer_field(5),
|
||||
::core::option::Option::None,
|
||||
)
|
||||
}
|
||||
pub fn has_rest(&self) -> bool {
|
||||
pub fn has_optional_positional(&self) -> bool {
|
||||
!self.reader.get_pointer_field(5).is_null()
|
||||
}
|
||||
#[inline]
|
||||
pub fn get_rest(self) -> ::capnp::Result<crate::plugin_capnp::argument::Reader<'a>> {
|
||||
::capnp::traits::FromPointerReader::get_from_pointer(
|
||||
&self.reader.get_pointer_field(6),
|
||||
::core::option::Option::None,
|
||||
)
|
||||
}
|
||||
pub fn has_rest(&self) -> bool {
|
||||
!self.reader.get_pointer_field(6).is_null()
|
||||
}
|
||||
#[inline]
|
||||
pub fn get_named(
|
||||
self,
|
||||
) -> ::capnp::Result<::capnp::struct_list::Reader<'a, crate::plugin_capnp::flag::Owned>>
|
||||
{
|
||||
::capnp::traits::FromPointerReader::get_from_pointer(
|
||||
&self.reader.get_pointer_field(6),
|
||||
&self.reader.get_pointer_field(7),
|
||||
::core::option::Option::None,
|
||||
)
|
||||
}
|
||||
pub fn has_named(&self) -> bool {
|
||||
!self.reader.get_pointer_field(6).is_null()
|
||||
!self.reader.get_pointer_field(7).is_null()
|
||||
}
|
||||
#[inline]
|
||||
pub fn get_is_filter(self) -> bool {
|
||||
|
@ -2068,12 +2078,40 @@ pub mod signature {
|
|||
!self.builder.get_pointer_field(2).is_null()
|
||||
}
|
||||
#[inline]
|
||||
pub fn get_search_terms(self) -> ::capnp::Result<::capnp::text_list::Builder<'a>> {
|
||||
::capnp::traits::FromPointerBuilder::get_from_pointer(
|
||||
self.builder.get_pointer_field(3),
|
||||
::core::option::Option::None,
|
||||
)
|
||||
}
|
||||
#[inline]
|
||||
pub fn set_search_terms(
|
||||
&mut self,
|
||||
value: ::capnp::text_list::Reader<'a>,
|
||||
) -> ::capnp::Result<()> {
|
||||
::capnp::traits::SetPointerBuilder::set_pointer_builder(
|
||||
self.builder.get_pointer_field(3),
|
||||
value,
|
||||
false,
|
||||
)
|
||||
}
|
||||
#[inline]
|
||||
pub fn init_search_terms(self, size: u32) -> ::capnp::text_list::Builder<'a> {
|
||||
::capnp::traits::FromPointerBuilder::init_pointer(
|
||||
self.builder.get_pointer_field(3),
|
||||
size,
|
||||
)
|
||||
}
|
||||
pub fn has_search_terms(&self) -> bool {
|
||||
!self.builder.get_pointer_field(3).is_null()
|
||||
}
|
||||
#[inline]
|
||||
pub fn get_required_positional(
|
||||
self,
|
||||
) -> ::capnp::Result<::capnp::struct_list::Builder<'a, crate::plugin_capnp::argument::Owned>>
|
||||
{
|
||||
::capnp::traits::FromPointerBuilder::get_from_pointer(
|
||||
self.builder.get_pointer_field(3),
|
||||
self.builder.get_pointer_field(4),
|
||||
::core::option::Option::None,
|
||||
)
|
||||
}
|
||||
|
@ -2083,7 +2121,7 @@ pub mod signature {
|
|||
value: ::capnp::struct_list::Reader<'a, crate::plugin_capnp::argument::Owned>,
|
||||
) -> ::capnp::Result<()> {
|
||||
::capnp::traits::SetPointerBuilder::set_pointer_builder(
|
||||
self.builder.get_pointer_field(3),
|
||||
self.builder.get_pointer_field(4),
|
||||
value,
|
||||
false,
|
||||
)
|
||||
|
@ -2094,12 +2132,12 @@ pub mod signature {
|
|||
size: u32,
|
||||
) -> ::capnp::struct_list::Builder<'a, crate::plugin_capnp::argument::Owned> {
|
||||
::capnp::traits::FromPointerBuilder::init_pointer(
|
||||
self.builder.get_pointer_field(3),
|
||||
self.builder.get_pointer_field(4),
|
||||
size,
|
||||
)
|
||||
}
|
||||
pub fn has_required_positional(&self) -> bool {
|
||||
!self.builder.get_pointer_field(3).is_null()
|
||||
!self.builder.get_pointer_field(4).is_null()
|
||||
}
|
||||
#[inline]
|
||||
pub fn get_optional_positional(
|
||||
|
@ -2107,7 +2145,7 @@ pub mod signature {
|
|||
) -> ::capnp::Result<::capnp::struct_list::Builder<'a, crate::plugin_capnp::argument::Owned>>
|
||||
{
|
||||
::capnp::traits::FromPointerBuilder::get_from_pointer(
|
||||
self.builder.get_pointer_field(4),
|
||||
self.builder.get_pointer_field(5),
|
||||
::core::option::Option::None,
|
||||
)
|
||||
}
|
||||
|
@ -2117,7 +2155,7 @@ pub mod signature {
|
|||
value: ::capnp::struct_list::Reader<'a, crate::plugin_capnp::argument::Owned>,
|
||||
) -> ::capnp::Result<()> {
|
||||
::capnp::traits::SetPointerBuilder::set_pointer_builder(
|
||||
self.builder.get_pointer_field(4),
|
||||
self.builder.get_pointer_field(5),
|
||||
value,
|
||||
false,
|
||||
)
|
||||
|
@ -2128,17 +2166,17 @@ pub mod signature {
|
|||
size: u32,
|
||||
) -> ::capnp::struct_list::Builder<'a, crate::plugin_capnp::argument::Owned> {
|
||||
::capnp::traits::FromPointerBuilder::init_pointer(
|
||||
self.builder.get_pointer_field(4),
|
||||
self.builder.get_pointer_field(5),
|
||||
size,
|
||||
)
|
||||
}
|
||||
pub fn has_optional_positional(&self) -> bool {
|
||||
!self.builder.get_pointer_field(4).is_null()
|
||||
!self.builder.get_pointer_field(5).is_null()
|
||||
}
|
||||
#[inline]
|
||||
pub fn get_rest(self) -> ::capnp::Result<crate::plugin_capnp::argument::Builder<'a>> {
|
||||
::capnp::traits::FromPointerBuilder::get_from_pointer(
|
||||
self.builder.get_pointer_field(5),
|
||||
self.builder.get_pointer_field(6),
|
||||
::core::option::Option::None,
|
||||
)
|
||||
}
|
||||
|
@ -2148,17 +2186,17 @@ pub mod signature {
|
|||
value: crate::plugin_capnp::argument::Reader<'_>,
|
||||
) -> ::capnp::Result<()> {
|
||||
::capnp::traits::SetPointerBuilder::set_pointer_builder(
|
||||
self.builder.get_pointer_field(5),
|
||||
self.builder.get_pointer_field(6),
|
||||
value,
|
||||
false,
|
||||
)
|
||||
}
|
||||
#[inline]
|
||||
pub fn init_rest(self) -> crate::plugin_capnp::argument::Builder<'a> {
|
||||
::capnp::traits::FromPointerBuilder::init_pointer(self.builder.get_pointer_field(5), 0)
|
||||
::capnp::traits::FromPointerBuilder::init_pointer(self.builder.get_pointer_field(6), 0)
|
||||
}
|
||||
pub fn has_rest(&self) -> bool {
|
||||
!self.builder.get_pointer_field(5).is_null()
|
||||
!self.builder.get_pointer_field(6).is_null()
|
||||
}
|
||||
#[inline]
|
||||
pub fn get_named(
|
||||
|
@ -2166,7 +2204,7 @@ pub mod signature {
|
|||
) -> ::capnp::Result<::capnp::struct_list::Builder<'a, crate::plugin_capnp::flag::Owned>>
|
||||
{
|
||||
::capnp::traits::FromPointerBuilder::get_from_pointer(
|
||||
self.builder.get_pointer_field(6),
|
||||
self.builder.get_pointer_field(7),
|
||||
::core::option::Option::None,
|
||||
)
|
||||
}
|
||||
|
@ -2176,7 +2214,7 @@ pub mod signature {
|
|||
value: ::capnp::struct_list::Reader<'a, crate::plugin_capnp::flag::Owned>,
|
||||
) -> ::capnp::Result<()> {
|
||||
::capnp::traits::SetPointerBuilder::set_pointer_builder(
|
||||
self.builder.get_pointer_field(6),
|
||||
self.builder.get_pointer_field(7),
|
||||
value,
|
||||
false,
|
||||
)
|
||||
|
@ -2187,12 +2225,12 @@ pub mod signature {
|
|||
size: u32,
|
||||
) -> ::capnp::struct_list::Builder<'a, crate::plugin_capnp::flag::Owned> {
|
||||
::capnp::traits::FromPointerBuilder::init_pointer(
|
||||
self.builder.get_pointer_field(6),
|
||||
self.builder.get_pointer_field(7),
|
||||
size,
|
||||
)
|
||||
}
|
||||
pub fn has_named(&self) -> bool {
|
||||
!self.builder.get_pointer_field(6).is_null()
|
||||
!self.builder.get_pointer_field(7).is_null()
|
||||
}
|
||||
#[inline]
|
||||
pub fn get_is_filter(self) -> bool {
|
||||
|
@ -2226,14 +2264,14 @@ pub mod signature {
|
|||
}
|
||||
impl Pipeline {
|
||||
pub fn get_rest(&self) -> crate::plugin_capnp::argument::Pipeline {
|
||||
::capnp::capability::FromTypelessPipeline::new(self._typeless.get_pointer_field(5))
|
||||
::capnp::capability::FromTypelessPipeline::new(self._typeless.get_pointer_field(6))
|
||||
}
|
||||
}
|
||||
mod _private {
|
||||
use capnp::private::layout;
|
||||
pub const STRUCT_SIZE: layout::StructSize = layout::StructSize {
|
||||
data: 1,
|
||||
pointers: 7,
|
||||
pointers: 8,
|
||||
};
|
||||
pub const TYPE_ID: u64 = 0xec96_eeb4_8cb7_90fa;
|
||||
}
|
||||
|
|
|
@ -55,13 +55,14 @@ struct Signature {
|
|||
name @0 :Text;
|
||||
usage @1 :Text;
|
||||
extraUsage @2 :Text;
|
||||
requiredPositional @3 :List(Argument);
|
||||
optionalPositional @4 :List(Argument);
|
||||
searchTerms @3 :List(Text);
|
||||
requiredPositional @4 :List(Argument);
|
||||
optionalPositional @5 :List(Argument);
|
||||
# Optional value. Check for existence when deserializing
|
||||
rest @5 :Argument;
|
||||
named @6 :List(Flag);
|
||||
isFilter @7 :Bool;
|
||||
category @8 :Category;
|
||||
rest @6 :Argument;
|
||||
named @7 :List(Flag);
|
||||
isFilter @8 :Bool;
|
||||
category @9 :Category;
|
||||
}
|
||||
|
||||
enum Category {
|
||||
|
|
|
@ -30,6 +30,17 @@ pub(crate) fn serialize_signature(signature: &Signature, mut builder: signature:
|
|||
_ => builder.set_category(PluginCategory::Default),
|
||||
}
|
||||
|
||||
// Serializing list of search terms
|
||||
let mut search_terms_builder = builder
|
||||
.reborrow()
|
||||
.init_search_terms(signature.search_terms.len() as u32);
|
||||
|
||||
signature
|
||||
.search_terms
|
||||
.iter()
|
||||
.enumerate()
|
||||
.for_each(|(index, term)| search_terms_builder.set(index as u32, term.as_str()));
|
||||
|
||||
// Serializing list of required arguments
|
||||
let mut required_list = builder
|
||||
.reborrow()
|
||||
|
@ -136,6 +147,17 @@ pub(crate) fn deserialize_signature(reader: signature::Reader) -> Result<Signatu
|
|||
PluginCategory::Generators => Category::Generators,
|
||||
};
|
||||
|
||||
// Deserializing list of search terms
|
||||
let search_terms = reader
|
||||
.get_search_terms()
|
||||
.map_err(|e| ShellError::PluginFailedToDecode(e.to_string()))?
|
||||
.iter()
|
||||
.map(|term| {
|
||||
term.map_err(|e| ShellError::PluginFailedToDecode(e.to_string()))
|
||||
.map(|term| term.to_string())
|
||||
})
|
||||
.collect::<Result<Vec<String>, ShellError>>()?;
|
||||
|
||||
// Deserializing required arguments
|
||||
let required_list = reader
|
||||
.get_required_positional()
|
||||
|
@ -181,6 +203,7 @@ pub(crate) fn deserialize_signature(reader: signature::Reader) -> Result<Signatu
|
|||
name: name.to_string(),
|
||||
usage: usage.to_string(),
|
||||
extra_usage: extra_usage.to_string(),
|
||||
search_terms,
|
||||
required_positional,
|
||||
optional_positional,
|
||||
rest_positional,
|
||||
|
@ -349,7 +372,8 @@ mod tests {
|
|||
#[test]
|
||||
fn value_round_trip_2() {
|
||||
let signature = Signature::build("test-1")
|
||||
.desc("Signature test 1 for plugin. Returns Value::Nothing")
|
||||
.usage("Signature test 1 for plugin. Returns Value::Nothing")
|
||||
.search_terms(vec!["a".into(), "b".into()])
|
||||
.required("a", SyntaxShape::Int, "required integer value")
|
||||
.required("b", SyntaxShape::String, "required string value")
|
||||
.optional("opt", SyntaxShape::Boolean, "Optional boolean")
|
||||
|
@ -368,6 +392,12 @@ mod tests {
|
|||
assert_eq!(signature.is_filter, returned_signature.is_filter);
|
||||
assert_eq!(signature.category, returned_signature.category);
|
||||
|
||||
signature
|
||||
.search_terms
|
||||
.iter()
|
||||
.zip(returned_signature.search_terms.iter())
|
||||
.for_each(|(lhs, rhs)| assert_eq!(lhs, rhs));
|
||||
|
||||
signature
|
||||
.required_positional
|
||||
.iter()
|
||||
|
|
|
@ -61,6 +61,11 @@ pub trait Command: Send + Sync + CommandClone {
|
|||
fn get_block_id(&self) -> Option<BlockId> {
|
||||
None
|
||||
}
|
||||
|
||||
// Related terms to help with command search
|
||||
fn search_terms(&self) -> Vec<&str> {
|
||||
vec![]
|
||||
}
|
||||
}
|
||||
|
||||
pub trait CommandClone {
|
||||
|
|
|
@ -11,6 +11,7 @@ use std::{
|
|||
|
||||
use crate::Value;
|
||||
|
||||
use std::borrow::Borrow;
|
||||
use std::path::Path;
|
||||
|
||||
#[cfg(feature = "plugin")]
|
||||
|
@ -527,11 +528,7 @@ impl EngineState {
|
|||
.map(|id| {
|
||||
let decl = self.get_decl(id);
|
||||
|
||||
let mut signature = (*decl).signature();
|
||||
signature.usage = decl.usage().to_string();
|
||||
signature.extra_usage = decl.extra_usage().to_string();
|
||||
|
||||
signature
|
||||
(*decl).signature().update_from_command(decl.borrow())
|
||||
})
|
||||
.collect()
|
||||
}
|
||||
|
@ -549,9 +546,7 @@ impl EngineState {
|
|||
.map(|id| {
|
||||
let decl = self.get_decl(id);
|
||||
|
||||
let mut signature = (*decl).signature();
|
||||
signature.usage = decl.usage().to_string();
|
||||
signature.extra_usage = decl.extra_usage().to_string();
|
||||
let signature = (*decl).signature().update_from_command(decl.borrow());
|
||||
|
||||
(
|
||||
signature,
|
||||
|
|
|
@ -95,6 +95,7 @@ pub struct Signature {
|
|||
pub name: String,
|
||||
pub usage: String,
|
||||
pub extra_usage: String,
|
||||
pub search_terms: Vec<String>,
|
||||
pub required_positional: Vec<PositionalArg>,
|
||||
pub optional_positional: Vec<PositionalArg>,
|
||||
pub rest_positional: Option<PositionalArg>,
|
||||
|
@ -135,6 +136,7 @@ impl Signature {
|
|||
name: name.into(),
|
||||
usage: String::new(),
|
||||
extra_usage: String::new(),
|
||||
search_terms: vec![],
|
||||
required_positional: vec![],
|
||||
optional_positional: vec![],
|
||||
rest_positional: None,
|
||||
|
@ -144,13 +146,38 @@ impl Signature {
|
|||
category: Category::Default,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn build(name: impl Into<String>) -> Signature {
|
||||
Signature::new(name.into())
|
||||
}
|
||||
|
||||
/// Add a description to the signature
|
||||
pub fn desc(mut self, usage: impl Into<String>) -> Signature {
|
||||
self.usage = usage.into();
|
||||
pub fn usage(mut self, msg: impl Into<String>) -> Signature {
|
||||
self.usage = msg.into();
|
||||
self
|
||||
}
|
||||
|
||||
/// Add an extra description to the signature
|
||||
pub fn extra_usage(mut self, msg: impl Into<String>) -> Signature {
|
||||
self.extra_usage = msg.into();
|
||||
self
|
||||
}
|
||||
|
||||
/// Add search terms to the signature
|
||||
pub fn search_terms(mut self, terms: Vec<String>) -> Signature {
|
||||
self.search_terms = terms;
|
||||
self
|
||||
}
|
||||
|
||||
/// Update signature's fields from a Command trait implementation
|
||||
pub fn update_from_command(mut self, command: &dyn Command) -> Signature {
|
||||
self.search_terms = command
|
||||
.search_terms()
|
||||
.into_iter()
|
||||
.map(|term| term.to_string())
|
||||
.collect();
|
||||
self.extra_usage = command.extra_usage().to_string();
|
||||
self.usage = command.usage().to_string();
|
||||
self
|
||||
}
|
||||
|
||||
|
|
|
@ -9,14 +9,14 @@ fn test_signature() {
|
|||
assert_eq!(signature, from_build);
|
||||
|
||||
// constructing signature with description
|
||||
let signature = Signature::new("signature").desc("example usage");
|
||||
let signature = Signature::new("signature").usage("example usage");
|
||||
assert_eq!(signature.usage, "example usage".to_string())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_signature_chained() {
|
||||
let signature = Signature::new("new_signature")
|
||||
.desc("description")
|
||||
.usage("description")
|
||||
.required("required", SyntaxShape::String, "required description")
|
||||
.optional("optional", SyntaxShape::String, "optional description")
|
||||
.required_named(
|
||||
|
@ -129,7 +129,7 @@ fn test_signature_same_name() {
|
|||
#[test]
|
||||
fn test_signature_round_trip() {
|
||||
let signature = Signature::new("new_signature")
|
||||
.desc("description")
|
||||
.usage("description")
|
||||
.required("first", SyntaxShape::String, "first required")
|
||||
.required("second", SyntaxShape::Int, "second required")
|
||||
.optional("optional", SyntaxShape::String, "optional description")
|
||||
|
|
|
@ -9,7 +9,7 @@ impl Plugin for Example {
|
|||
// plugin is registered to nushell
|
||||
vec![
|
||||
Signature::build("nu-example-1")
|
||||
.desc("Signature test 1 for plugin. Returns Value::Nothing")
|
||||
.usage("Signature test 1 for plugin. Returns Value::Nothing")
|
||||
.required("a", SyntaxShape::Int, "required integer value")
|
||||
.required("b", SyntaxShape::String, "required string value")
|
||||
.switch("flag", "a flag for the signature", Some('f'))
|
||||
|
@ -18,7 +18,7 @@ impl Plugin for Example {
|
|||
.rest("rest", SyntaxShape::String, "rest value string")
|
||||
.category(Category::Experimental),
|
||||
Signature::build("nu-example-2")
|
||||
.desc("Signature test 2 for plugin. Returns list of records")
|
||||
.usage("Signature test 2 for plugin. Returns list of records")
|
||||
.required("a", SyntaxShape::Int, "required integer value")
|
||||
.required("b", SyntaxShape::String, "required string value")
|
||||
.switch("flag", "a flag for the signature", Some('f'))
|
||||
|
@ -27,7 +27,7 @@ impl Plugin for Example {
|
|||
.rest("rest", SyntaxShape::String, "rest value string")
|
||||
.category(Category::Experimental),
|
||||
Signature::build("nu-example-3")
|
||||
.desc("Signature test 3 for plugin. Returns labeled error")
|
||||
.usage("Signature test 3 for plugin. Returns labeled error")
|
||||
.required("a", SyntaxShape::Int, "required integer value")
|
||||
.required("b", SyntaxShape::String, "required string value")
|
||||
.switch("flag", "a flag for the signature", Some('f'))
|
||||
|
|
|
@ -5,7 +5,7 @@ use nu_protocol::{Category, Signature, Spanned, SyntaxShape, Value};
|
|||
impl Plugin for GStat {
|
||||
fn signature(&self) -> Vec<Signature> {
|
||||
vec![Signature::build("gstat")
|
||||
.desc("Get the git status of a repo")
|
||||
.usage("Get the git status of a repo")
|
||||
.optional("path", SyntaxShape::Filepath, "path to repo")
|
||||
.category(Category::Custom("Prompt".to_string()))]
|
||||
}
|
||||
|
|
|
@ -6,7 +6,7 @@ use nu_protocol::{ast::CellPath, Signature, SyntaxShape, Value};
|
|||
impl Plugin for Inc {
|
||||
fn signature(&self) -> Vec<Signature> {
|
||||
vec![Signature::build("inc")
|
||||
.desc("Increment a value or version. Optionally use the column of a table.")
|
||||
.usage("Increment a value or version. Optionally use the column of a table.")
|
||||
.optional("cell_path", SyntaxShape::CellPath, "cell path to update")
|
||||
.switch(
|
||||
"major",
|
||||
|
|
|
@ -6,21 +6,21 @@ impl Plugin for Query {
|
|||
fn signature(&self) -> Vec<Signature> {
|
||||
vec![
|
||||
Signature::build("query")
|
||||
.desc("Show all the query commands")
|
||||
.usage("Show all the query commands")
|
||||
.category(Category::Filters),
|
||||
|
||||
Signature::build("query json")
|
||||
.desc("execute json query on json file (open --raw <file> | query json 'query string')")
|
||||
.usage("execute json query on json file (open --raw <file> | query json 'query string')")
|
||||
.required("query", SyntaxShape::String, "json query")
|
||||
.category(Category::Filters),
|
||||
|
||||
Signature::build("query xml")
|
||||
.desc("execute xpath query on xml")
|
||||
.usage("execute xpath query on xml")
|
||||
.required("query", SyntaxShape::String, "xpath query")
|
||||
.category(Category::Filters),
|
||||
|
||||
Signature::build("query web")
|
||||
.desc("execute selector query on html/web")
|
||||
.usage("execute selector query on html/web")
|
||||
.named("query", SyntaxShape::String, "selector query", Some('q'))
|
||||
.switch("as-html", "return the query output as html", Some('m'))
|
||||
.named(
|
||||
|
|
|
@ -129,7 +129,7 @@ fn display(model: &Model) -> Result<(), Box<dyn Error>> {
|
|||
impl Plugin for SubCommand {
|
||||
fn config(&mut self) -> Result<Signature, ShellError> {
|
||||
Ok(Signature::build("chart bar")
|
||||
.desc("Bar charts")
|
||||
.usage("Bar charts")
|
||||
.switch("acc", "accumulate values", Some('a'))
|
||||
.optional(
|
||||
"columns",
|
||||
|
|
|
@ -127,7 +127,7 @@ fn display(model: &Model) -> Result<(), Box<dyn Error>> {
|
|||
impl Plugin for SubCommand {
|
||||
fn config(&mut self) -> Result<Signature, ShellError> {
|
||||
Ok(Signature::build("chart line")
|
||||
.desc("Line charts")
|
||||
.usage("Line charts")
|
||||
.switch("acc", "accumulate values", Some('a'))
|
||||
.optional(
|
||||
"columns",
|
||||
|
|
|
@ -10,7 +10,7 @@ use nu_source::Tag;
|
|||
impl Plugin for FromBson {
|
||||
fn config(&mut self) -> Result<Signature, ShellError> {
|
||||
Ok(Signature::build("from bson")
|
||||
.desc("Convert from .bson binary into table")
|
||||
.usage("Convert from .bson binary into table")
|
||||
.filter())
|
||||
}
|
||||
|
||||
|
|
|
@ -10,7 +10,7 @@ use nu_source::Tag;
|
|||
impl Plugin for FromMp4 {
|
||||
fn config(&mut self) -> Result<Signature, ShellError> {
|
||||
Ok(Signature::build("from mp4")
|
||||
.desc("Get meta-data of mp4 file")
|
||||
.usage("Get meta-data of mp4 file")
|
||||
.filter())
|
||||
}
|
||||
|
||||
|
|
|
@ -33,7 +33,7 @@ impl Plugin for FromSqlite {
|
|||
"Only convert specified tables",
|
||||
Some('t'),
|
||||
)
|
||||
.desc("Convert from sqlite binary into table")
|
||||
.usage("Convert from sqlite binary into table")
|
||||
.filter())
|
||||
}
|
||||
|
||||
|
|
|
@ -9,7 +9,7 @@ use crate::handler::s3_helper;
|
|||
impl Plugin for handler::Handler {
|
||||
fn config(&mut self) -> Result<Signature, ShellError> {
|
||||
Ok(Signature::build("s3")
|
||||
.desc("Load S3 resource into a cell, convert to table if possible (avoid by appending '--raw' or '-R')")
|
||||
.usage("Load S3 resource into a cell, convert to table if possible (avoid by appending '--raw' or '-R')")
|
||||
.required(
|
||||
"RESOURCE",
|
||||
SyntaxShape::String,
|
||||
|
|
|
@ -7,7 +7,7 @@ use crate::start::Start;
|
|||
impl Plugin for Start {
|
||||
fn config(&mut self) -> Result<Signature, ShellError> {
|
||||
Ok(Signature::build("start")
|
||||
.desc("Opens each file/directory/URL using the default application")
|
||||
.usage("Opens each file/directory/URL using the default application")
|
||||
.rest(
|
||||
"rest",
|
||||
SyntaxShape::String,
|
||||
|
|
|
@ -10,7 +10,7 @@ use nu_source::Tag;
|
|||
impl Plugin for ToBson {
|
||||
fn config(&mut self) -> Result<Signature, ShellError> {
|
||||
Ok(Signature::build("to bson")
|
||||
.desc("Convert table into .bson binary")
|
||||
.usage("Convert table into .bson binary")
|
||||
.filter())
|
||||
}
|
||||
|
||||
|
|
|
@ -10,7 +10,7 @@ use nu_source::Tag;
|
|||
impl Plugin for ToSqlite {
|
||||
fn config(&mut self) -> Result<Signature, ShellError> {
|
||||
Ok(Signature::build("to sqlite")
|
||||
.desc("Convert table into sqlite binary")
|
||||
.usage("Convert table into sqlite binary")
|
||||
.filter())
|
||||
}
|
||||
|
||||
|
|
|
@ -7,7 +7,7 @@ use crate::TreeViewer;
|
|||
|
||||
impl Plugin for TreeViewer {
|
||||
fn config(&mut self) -> Result<Signature, ShellError> {
|
||||
Ok(Signature::build("tree").desc("View the contents of the pipeline as a tree."))
|
||||
Ok(Signature::build("tree").usage("View the contents of the pipeline as a tree."))
|
||||
}
|
||||
|
||||
fn sink(&mut self, _call_info: CallInfo, input: Vec<Value>) {
|
||||
|
|
|
@ -415,7 +415,7 @@ impl Command for Nu {
|
|||
|
||||
fn signature(&self) -> Signature {
|
||||
Signature::build("nu")
|
||||
.desc("The nushell language and shell.")
|
||||
.usage("The nushell language and shell.")
|
||||
.switch("stdin", "redirect the stdin", None)
|
||||
.switch("login", "start as a login shell", Some('l'))
|
||||
.switch("interactive", "start as an interactive shell", Some('i'))
|
||||
|
|
Loading…
Reference in a new issue