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

@ -1,6 +1,6 @@
use crate::{query_json::QueryJson, query_web::QueryWeb, query_xml::QueryXml};
use nu_plugin::{EvaluatedCall, Plugin, PluginCommand, SimplePluginCommand};
use nu_protocol::{Category, LabeledError, PluginSignature, Value};
use nu_protocol::{Category, LabeledError, Signature, Value};
#[derive(Default)]
pub struct Query;
@ -32,10 +32,16 @@ pub struct QueryCommand;
impl SimplePluginCommand for QueryCommand {
type Plugin = Query;
fn signature(&self) -> PluginSignature {
PluginSignature::build("query")
.usage("Show all the query commands")
.category(Category::Filters)
fn name(&self) -> &str {
"query"
}
fn usage(&self) -> &str {
"Show all the query commands"
}
fn signature(&self) -> Signature {
Signature::build(PluginCommand::name(self)).category(Category::Filters)
}
fn run(

View File

@ -1,20 +1,23 @@
use crate::Query;
use gjson::Value as gjValue;
use nu_plugin::{EngineInterface, EvaluatedCall, SimplePluginCommand};
use nu_protocol::{
Category, LabeledError, PluginSignature, Record, Span, Spanned, SyntaxShape, Value,
};
use nu_protocol::{Category, LabeledError, Record, Signature, Span, Spanned, SyntaxShape, Value};
pub struct QueryJson;
impl SimplePluginCommand for QueryJson {
type Plugin = Query;
fn signature(&self) -> PluginSignature {
PluginSignature::build("query json")
.usage(
"execute json query on json file (open --raw <file> | query json 'query string')",
)
fn name(&self) -> &str {
"query json"
}
fn usage(&self) -> &str {
"execute json query on json file (open --raw <file> | query json 'query string')"
}
fn signature(&self) -> Signature {
Signature::build(self.name())
.required("query", SyntaxShape::String, "json query")
.category(Category::Filters)
}

View File

@ -1,8 +1,7 @@
use crate::{web_tables::WebTable, Query};
use nu_plugin::{EngineInterface, EvaluatedCall, SimplePluginCommand};
use nu_protocol::{
Category, LabeledError, PluginExample, PluginSignature, Record, Span, Spanned, SyntaxShape,
Value,
Category, Example, LabeledError, Record, Signature, Span, Spanned, SyntaxShape, Value,
};
use scraper::{Html, Selector as ScraperSelector};
@ -11,12 +10,18 @@ pub struct QueryWeb;
impl SimplePluginCommand for QueryWeb {
type Plugin = Query;
fn signature(&self) -> PluginSignature {
PluginSignature::build("query web")
.usage("execute selector query on html/web")
fn name(&self) -> &str {
"query web"
}
fn usage(&self) -> &str {
"execute selector query on html/web"
}
fn signature(&self) -> Signature {
Signature::build(self.name())
.named("query", SyntaxShape::String, "selector query", Some('q'))
.switch("as-html", "return the query output as html", Some('m'))
.plugin_examples(web_examples())
.named(
"attribute",
SyntaxShape::String,
@ -37,6 +42,10 @@ impl SimplePluginCommand for QueryWeb {
.category(Category::Network)
}
fn examples(&self) -> Vec<Example> {
web_examples()
}
fn run(
&self,
_plugin: &Query,
@ -48,27 +57,27 @@ impl SimplePluginCommand for QueryWeb {
}
}
pub fn web_examples() -> Vec<PluginExample> {
pub fn web_examples() -> Vec<Example<'static>> {
vec![
PluginExample {
example: "http get https://phoronix.com | query web --query 'header' | flatten".into(),
description: "Retrieve all `<header>` elements from phoronix.com website".into(),
Example {
example: "http get https://phoronix.com | query web --query 'header' | flatten",
description: "Retrieve all `<header>` elements from phoronix.com website",
result: None,
},
PluginExample {
Example {
example: "http get https://en.wikipedia.org/wiki/List_of_cities_in_India_by_population |
query web --as-table [City 'Population(2011)[3]' 'Population(2001)[3][a]' 'State or unionterritory' 'Ref']".into(),
description: "Retrieve a html table from Wikipedia and parse it into a nushell table using table headers as guides".into(),
query web --as-table [City 'Population(2011)[3]' 'Population(2001)[3][a]' 'State or unionterritory' 'Ref']",
description: "Retrieve a html table from Wikipedia and parse it into a nushell table using table headers as guides",
result: None
},
PluginExample {
example: "http get https://www.nushell.sh | query web --query 'h2, h2 + p' | each {str join} | group 2 | each {rotate --ccw tagline description} | flatten".into(),
description: "Pass multiple css selectors to extract several elements within single query, group the query results together and rotate them to create a table".into(),
Example {
example: "http get https://www.nushell.sh | query web --query 'h2, h2 + p' | each {str join} | group 2 | each {rotate --ccw tagline description} | flatten",
description: "Pass multiple css selectors to extract several elements within single query, group the query results together and rotate them to create a table",
result: None,
},
PluginExample {
example: "http get https://example.org | query web --query a --attribute href".into(),
description: "Retrieve a specific html attribute instead of the default text".into(),
Example {
example: "http get https://example.org | query web --query a --attribute href",
description: "Retrieve a specific html attribute instead of the default text",
result: None,
}
]

View File

@ -1,7 +1,7 @@
use crate::Query;
use nu_plugin::{EngineInterface, EvaluatedCall, SimplePluginCommand};
use nu_protocol::{
record, Category, LabeledError, PluginSignature, Record, Span, Spanned, SyntaxShape, Value,
record, Category, LabeledError, Record, Signature, Span, Spanned, SyntaxShape, Value,
};
use sxd_document::parser;
use sxd_xpath::{Context, Factory};
@ -11,9 +11,16 @@ pub struct QueryXml;
impl SimplePluginCommand for QueryXml {
type Plugin = Query;
fn signature(&self) -> PluginSignature {
PluginSignature::build("query xml")
.usage("execute xpath query on xml")
fn name(&self) -> &str {
"query xml"
}
fn usage(&self) -> &str {
"execute xpath query on xml"
}
fn signature(&self) -> Signature {
Signature::build(self.name())
.required("query", SyntaxShape::String, "xpath query")
.category(Category::Filters)
}