Change PluginCommand API to be more like Command (#12279)

# Description

This is something that was discussed in the core team meeting last
Wednesday. @ayax79 is building `nu-plugin-polars` with all of the
dataframe commands into a plugin, and there are a lot of them, so it
would help to make the API more similar. At the same time, I think the
`Command` API is just better anyway. I don't think the difference is
justified, and the types for core commands have the benefit of requiring
less `.into()` because they often don't own their data

- Broke `signature()` up into `name()`, `usage()`, `extra_usage()`,
`search_terms()`, `examples()`
- `signature()` returns `nu_protocol::Signature`
- `examples()` returns `Vec<nu_protocol::Example>`
- `PluginSignature` and `PluginExample` no longer need to be used by
plugin developers

# User-Facing Changes
Breaking API for plugins yet again 😄
This commit is contained in:
Devyn Cairns
2024-03-27 03:59:57 -07:00
committed by GitHub
parent 03b5e9d853
commit 01d30a416b
45 changed files with 962 additions and 674 deletions

View File

@ -4,20 +4,26 @@ use eml_parser::EmlParser;
use indexmap::IndexMap;
use nu_plugin::{EngineInterface, EvaluatedCall, SimplePluginCommand};
use nu_protocol::{
record, Category, LabeledError, PluginExample, PluginSignature, ShellError, Span, SyntaxShape,
Type, Value,
record, Category, Example, LabeledError, ShellError, Signature, Span, SyntaxShape, Type, Value,
};
const DEFAULT_BODY_PREVIEW: usize = 50;
pub const CMD_NAME: &str = "from eml";
pub struct FromEml;
impl SimplePluginCommand for FromEml {
type Plugin = FromCmds;
fn signature(&self) -> nu_protocol::PluginSignature {
PluginSignature::build(CMD_NAME)
fn name(&self) -> &str {
"from eml"
}
fn usage(&self) -> &str {
"Parse text as .eml and create record."
}
fn signature(&self) -> Signature {
Signature::build(self.name())
.input_output_types(vec![(Type::String, Type::Record(vec![]))])
.named(
"preview-body",
@ -25,11 +31,13 @@ impl SimplePluginCommand for FromEml {
"How many bytes of the body to preview",
Some('b'),
)
.usage("Parse text as .eml and create record.")
.plugin_examples(examples())
.category(Category::Formats)
}
fn examples(&self) -> Vec<Example> {
examples()
}
fn run(
&self,
_plugin: &FromCmds,
@ -45,16 +53,15 @@ impl SimplePluginCommand for FromEml {
}
}
pub fn examples() -> Vec<PluginExample> {
pub fn examples() -> Vec<Example<'static>> {
vec![
PluginExample {
description: "Convert eml structured data into record".into(),
Example {
description: "Convert eml structured data into record",
example: "'From: test@email.com
Subject: Welcome
To: someone@somewhere.com
Test' | from eml"
.into(),
Test' | from eml",
result: Some(Value::test_record(record! {
"Subject" => Value::test_string("Welcome"),
"From" => Value::test_record(record! {
@ -68,14 +75,13 @@ Test' | from eml"
"Body" => Value::test_string("Test"),
})),
},
PluginExample {
description: "Convert eml structured data into record".into(),
Example {
description: "Convert eml structured data into record",
example: "'From: test@email.com
Subject: Welcome
To: someone@somewhere.com
Test' | from eml -b 1"
.into(),
Test' | from eml -b 1",
result: Some(Value::test_record(record! {
"Subject" => Value::test_string("Welcome"),
"From" => Value::test_record(record! {

View File

@ -1,27 +1,36 @@
use crate::FromCmds;
use ical::{parser::ical::component::*, property::Property};
use indexmap::IndexMap;
use nu_plugin::{EngineInterface, EvaluatedCall, SimplePluginCommand};
use nu_protocol::{
record, Category, LabeledError, PluginExample, PluginSignature, ShellError, Span, Type, Value,
record, Category, Example, LabeledError, ShellError, Signature, Span, Type, Value,
};
use std::io::BufReader;
pub const CMD_NAME: &str = "from ics";
pub struct FromIcs;
impl SimplePluginCommand for FromIcs {
type Plugin = FromCmds;
fn signature(&self) -> nu_protocol::PluginSignature {
PluginSignature::build(CMD_NAME)
fn name(&self) -> &str {
"from ics"
}
fn usage(&self) -> &str {
"Parse text as .ics and create table."
}
fn signature(&self) -> Signature {
Signature::build(self.name())
.input_output_types(vec![(Type::String, Type::Table(vec![]))])
.usage("Parse text as .ics and create table.")
.plugin_examples(examples())
.category(Category::Formats)
}
fn examples(&self) -> Vec<Example> {
examples()
}
fn run(
&self,
_plugin: &FromCmds,
@ -71,13 +80,11 @@ impl SimplePluginCommand for FromIcs {
}
}
pub fn examples() -> Vec<PluginExample> {
vec![PluginExample {
example: "
'BEGIN:VCALENDAR
END:VCALENDAR' | from ics"
.into(),
description: "Converts ics formatted string to table".into(),
pub fn examples() -> Vec<Example<'static>> {
vec![Example {
example: "'BEGIN:VCALENDAR
END:VCALENDAR' | from ics",
description: "Converts ics formatted string to table",
result: Some(Value::test_list(vec![Value::test_record(record! {
"properties" => Value::test_list(vec![]),
"events" => Value::test_list(vec![]),

View File

@ -1,24 +1,33 @@
use crate::FromCmds;
use nu_plugin::{EngineInterface, EvaluatedCall, SimplePluginCommand};
use nu_protocol::{
record, Category, LabeledError, PluginExample, PluginSignature, Record, ShellError, Type, Value,
record, Category, Example, LabeledError, Record, ShellError, Signature, Type, Value,
};
pub const CMD_NAME: &str = "from ini";
pub struct FromIni;
impl SimplePluginCommand for FromIni {
type Plugin = FromCmds;
fn signature(&self) -> PluginSignature {
PluginSignature::build(CMD_NAME)
fn name(&self) -> &str {
"from ini"
}
fn usage(&self) -> &str {
"Parse text as .ini and create table."
}
fn signature(&self) -> Signature {
Signature::build(self.name())
.input_output_types(vec![(Type::String, Type::Record(vec![]))])
.usage("Parse text as .ini and create table.")
.plugin_examples(examples())
.category(Category::Formats)
}
fn examples(&self) -> Vec<Example> {
examples()
}
fn run(
&self,
_plugin: &FromCmds,
@ -73,13 +82,12 @@ impl SimplePluginCommand for FromIni {
}
}
pub fn examples() -> Vec<PluginExample> {
vec![PluginExample {
pub fn examples() -> Vec<Example<'static>> {
vec![Example {
example: "'[foo]
a=1
b=2' | from ini"
.into(),
description: "Converts ini formatted string to record".into(),
b=2' | from ini",
description: "Converts ini formatted string to record",
result: Some(Value::test_record(record! {
"foo" => Value::test_record(record! {
"a" => Value::test_string("1"),

View File

@ -1,26 +1,35 @@
use crate::FromCmds;
use ical::{parser::vcard::component::*, property::Property};
use indexmap::IndexMap;
use nu_plugin::{EngineInterface, EvaluatedCall, SimplePluginCommand};
use nu_protocol::{
record, Category, LabeledError, PluginExample, PluginSignature, ShellError, Span, Type, Value,
record, Category, Example, LabeledError, ShellError, Signature, Span, Type, Value,
};
pub const CMD_NAME: &str = "from vcf";
pub struct FromVcf;
impl SimplePluginCommand for FromVcf {
type Plugin = FromCmds;
fn signature(&self) -> PluginSignature {
PluginSignature::build(CMD_NAME)
fn name(&self) -> &str {
"from vcf"
}
fn usage(&self) -> &str {
"Parse text as .vcf and create table."
}
fn signature(&self) -> Signature {
Signature::build(self.name())
.input_output_types(vec![(Type::String, Type::Table(vec![]))])
.usage("Parse text as .vcf and create table.")
.plugin_examples(examples())
.category(Category::Formats)
}
fn examples(&self) -> Vec<Example> {
examples()
}
fn run(
&self,
_plugin: &FromCmds,
@ -68,15 +77,14 @@ impl SimplePluginCommand for FromVcf {
}
}
pub fn examples() -> Vec<PluginExample> {
vec![PluginExample {
pub fn examples() -> Vec<Example<'static>> {
vec![Example {
example: "'BEGIN:VCARD
N:Foo
FN:Bar
EMAIL:foo@bar.com
END:VCARD' | from vcf"
.into(),
description: "Converts ics formatted string to table".into(),
END:VCARD' | from vcf",
description: "Converts ics formatted string to table",
result: Some(Value::test_list(vec![Value::test_record(record! {
"properties" => Value::test_list(
vec![