Skip to content

Commit ee0c6d6

Browse files
authored
Add Metadata to plugin protocol reference, and version() to the guide (#1455)
* Plugin protocol reference: add `Metadata` call + response * Plugin guide: add `version()` * update the python plugin example too, it's kind of out of sync though?
1 parent 7499667 commit ee0c6d6

File tree

2 files changed

+68
-3
lines changed

2 files changed

+68
-3
lines changed

contributor-book/plugin_protocol_reference.md

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,18 @@ These are messages sent from the engine to the plugin. [`Hello`](#hello) and [`S
9595

9696
The body of this message is a 2-tuple (array): (`id`, `call`). The engine sends unique IDs for each plugin call it makes. The ID is needed to send the [`CallResponse`](#callresponse).
9797

98+
#### `Metadata` plugin call
99+
100+
Ask the plugin to send metadata about itself. Takes no arguments. Returns [`Metadata`](#metadata-plugin-call-response) or [`Error`](#error-plugin-call-response)
101+
102+
Example:
103+
104+
```json
105+
{
106+
"Call": [0, "Metadata"]
107+
}
108+
```
109+
98110
#### `Signature` plugin call
99111

100112
Ask the plugin to send its command signatures. Takes no arguments. Returns [`Signature`](#signature-plugin-call-response) or [`Error`](#error-plugin-call-response)
@@ -584,6 +596,29 @@ Example:
584596
}
585597
```
586598

599+
#### `Metadata` plugin call response
600+
601+
A successful response to a [`Metadata` plugin call](#metadata-plugin-call). The body contains fields that describe the plugin, none of which are required:
602+
603+
| Field | Type | Usage |
604+
| ----------- | ------- | ------------------------------------------------------------------------------------------------------------- |
605+
| **version** | string? | The version of the plugin (not the protocol!). [SemVer](https://semver.org) is recommended, but not required. |
606+
607+
Example:
608+
609+
```json
610+
{
611+
"CallResponse": [
612+
0,
613+
{
614+
"Metadata": {
615+
"version": "1.2.3"
616+
}
617+
}
618+
]
619+
}
620+
```
621+
587622
#### `Signature` plugin call response
588623

589624
A successful response to a [`Signature` plugin call](#signature-plugin-call). The body is an array of [signatures](https://docs.rs/nu-protocol/latest/nu_protocol/struct.PluginSignature.html).

contributor-book/plugins.md

Lines changed: 33 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,10 @@ use nu_protocol::{LabeledError, Signature, Type, Value};
7070
struct LenPlugin;
7171

7272
impl Plugin for LenPlugin {
73+
fn version(&self) -> String {
74+
env!("CARGO_PKG_VERSION").into()
75+
}
76+
7377
fn commands(&self) -> Vec<Box<dyn PluginCommand<Plugin = Self>>> {
7478
vec![
7579
Box::new(Len),
@@ -219,6 +223,10 @@ Above that, let's have a look at the definition of `LenPlugin`, which implements
219223
struct LenPlugin;
220224

221225
impl Plugin for LenPlugin {
226+
fn version(&self) -> String {
227+
env!("CARGO_PKG_VERSION").into()
228+
}
229+
222230
fn commands(&self) -> Vec<Box<dyn PluginCommand<Plugin = Self>>> {
223231
vec![
224232
Box::new(Len),
@@ -229,7 +237,9 @@ impl Plugin for LenPlugin {
229237

230238
Again, we use a unit struct for `LenPlugin`, but this is the recommended place to put plugin state if needed. All commands also get a reference to the plugin type. This is what we eventually pass to `serve_plugin()` in `main()`.
231239

232-
The only required method in `Plugin` is `commands()`, which initializes the plugin's commands. A boxed `dyn` reference is used so that we can keep all of the different command types in the single list. Dispatch by command name is automatically handled in `serve_plugin()` by looking at the name defined in the signature - in our case, that's `len`. A plugin can contain many commands, so if you end up adding more, just add them to the list returned by `commands()`.
240+
`Plugin` has two required methods: `version()`, which reports the plugin's version back to Nu, and `commands()`, which initializes the plugin's commands. A boxed `dyn` reference is used so that we can keep all of the different command types in the single list. Dispatch by command name is automatically handled in `serve_plugin()` by looking at the name defined in the signature - in our case, that's `len`. A plugin can contain many commands, so if you end up adding more, just add them to the list returned by `commands()`.
241+
242+
For the version, we just use the `CARGO_PKG_VERSION` environment variable available at compile-time in order to get our plugin's version from Cargo.
233243

234244
Lastly, let's look at the top of the file:
235245

@@ -402,6 +412,10 @@ use nu_protocol::{Signature, Type, Value};
402412
struct MotdPlugin;
403413

404414
impl Plugin for MotdPlugin {
415+
fn version(&self) -> String {
416+
env!("CARGO_PKG_VERSION").into()
417+
}
418+
405419
fn commands(&self) -> Vec<Box<dyn PluginCommand<Plugin = Self>>> {
406420
vec![
407421
Box::new(Motd),
@@ -471,6 +485,10 @@ use nu_protocol::{PipelineData, Signature, SyntaxShape, Type, Value};
471485
struct MyEachPlugin;
472486

473487
impl Plugin for MyEachPlugin {
488+
fn version(&self) -> String {
489+
env!("CARGO_PKG_VERSION").into()
490+
}
491+
474492
fn commands(&self) -> Vec<Box<dyn PluginCommand<Plugin = Self>>> {
475493
vec![
476494
Box::new(MyEach),
@@ -1050,7 +1068,13 @@ if __name__ == "__main__":
10501068
break
10511069
elif "Call" in input:
10521070
[id, call] = input["Call"]
1053-
if call == "Signature":
1071+
if plugin_call == "Metadata":
1072+
send_response(id, {
1073+
"Metadata": {
1074+
"version": "0.1.0",
1075+
}
1076+
})
1077+
elif call == "Signature":
10541078
send_response(id, {"Signature": [signature()]})
10551079
elif "Run" in call:
10561080
handle_call(id, call["Run"])
@@ -1077,7 +1101,13 @@ if __name__ == "__main__":
10771101
break
10781102
elif "Call" in input:
10791103
[id, call] = input["Call"]
1080-
if call == "Signature":
1104+
if plugin_call == "Metadata":
1105+
send_response(id, {
1106+
"Metadata": {
1107+
"version": "0.1.0",
1108+
}
1109+
})
1110+
elif call == "Signature":
10811111
send_response(id, {"Signature": [signature()]})
10821112
elif "Run" in call:
10831113
handle_call(id, call["Run"])

0 commit comments

Comments
 (0)