forked from extern/nushell
# Description Adds a `nu-plugin-test-support` crate with an interface that supports testing plugins. Unlike in reality, these plugins run in the same process on separate threads. This will allow testing aspects of the plugin internal state and handling serialized plugin custom values easily. We still serialize their custom values and all of the engine to plugin logic is still in play, so from a logical perspective this should still expose any bugs that would have been caused by that. The only difference is that it doesn't run in a different process, and doesn't try to serialize everything to the final wire format for stdin/stdout. TODO still: - [x] Clean up warnings about private types exposed in trait definition - [x] Automatically deserialize plugin custom values in the result so they can be inspected - [x] Automatic plugin examples test function - [x] Write a bit more documentation - [x] More tests - [x] Add MIT License file to new crate # User-Facing Changes Plugin developers get a nice way to test their plugins. # Tests + Formatting Run the tests with `cargo test -p nu-plugin-test-support -- --show-output` to see some examples of what the failing test output for examples can look like. I used the `difference` crate (MIT licensed) to make it look nice. - 🟢 `toolkit fmt` - 🟢 `toolkit clippy` - 🟢 `toolkit test` - 🟢 `toolkit test stdlib` # After Submitting - [ ] Add a section to the book about testing - [ ] Test some of the example plugins this way - [ ] Add example tests to nu_plugin_template so plugin developers have something to start with
88 lines
2.9 KiB
Rust
88 lines
2.9 KiB
Rust
#![allow(clippy::needless_doctest_main)]
|
|
//! # Nu Plugin: Plugin library for Nushell
|
|
//!
|
|
//! This crate contains the interface necessary to build Nushell plugins in Rust.
|
|
//! Additionally, it contains public, but undocumented, items used by Nushell itself
|
|
//! to interface with Nushell plugins. This documentation focuses on the interface
|
|
//! needed to write an independent plugin.
|
|
//!
|
|
//! Nushell plugins are stand-alone applications that communicate with Nushell
|
|
//! over stdin and stdout using a standardizes serialization framework to exchange
|
|
//! the typed data that Nushell commands utilize natively.
|
|
//!
|
|
//! A typical plugin application will define a struct that implements the [`Plugin`]
|
|
//! trait and then, in its main method, pass that [`Plugin`] to the [`serve_plugin()`]
|
|
//! function, which will handle all of the input and output serialization when
|
|
//! invoked by Nushell.
|
|
//!
|
|
//! ```rust,no_run
|
|
//! use nu_plugin::{EvaluatedCall, MsgPackSerializer, serve_plugin};
|
|
//! use nu_plugin::{Plugin, PluginCommand, SimplePluginCommand, EngineInterface};
|
|
//! use nu_protocol::{PluginSignature, LabeledError, Value};
|
|
//!
|
|
//! struct MyPlugin;
|
|
//! struct MyCommand;
|
|
//!
|
|
//! impl Plugin for MyPlugin {
|
|
//! fn commands(&self) -> Vec<Box<dyn PluginCommand<Plugin = Self>>> {
|
|
//! vec![Box::new(MyCommand)]
|
|
//! }
|
|
//! }
|
|
//!
|
|
//! impl SimplePluginCommand for MyCommand {
|
|
//! type Plugin = MyPlugin;
|
|
//!
|
|
//! fn signature(&self) -> PluginSignature {
|
|
//! todo!();
|
|
//! }
|
|
//!
|
|
//! fn run(
|
|
//! &self,
|
|
//! plugin: &MyPlugin,
|
|
//! engine: &EngineInterface,
|
|
//! call: &EvaluatedCall,
|
|
//! input: &Value
|
|
//! ) -> Result<Value, LabeledError> {
|
|
//! todo!();
|
|
//! }
|
|
//! }
|
|
//!
|
|
//! fn main() {
|
|
//! serve_plugin(&MyPlugin{}, MsgPackSerializer)
|
|
//! }
|
|
//! ```
|
|
//!
|
|
//! Nushell's source tree contains a
|
|
//! [Plugin Example](https://github.com/nushell/nushell/tree/main/crates/nu_plugin_example)
|
|
//! that demonstrates the full range of plugin capabilities.
|
|
mod plugin;
|
|
mod protocol;
|
|
mod sequence;
|
|
mod serializers;
|
|
mod util;
|
|
|
|
pub use plugin::{
|
|
serve_plugin, EngineInterface, Plugin, PluginCommand, PluginEncoder, PluginRead, PluginWrite,
|
|
SimplePluginCommand,
|
|
};
|
|
pub use protocol::EvaluatedCall;
|
|
pub use serializers::{json::JsonSerializer, msgpack::MsgPackSerializer};
|
|
|
|
// Used by other nu crates.
|
|
#[doc(hidden)]
|
|
pub use plugin::{
|
|
get_signature, serve_plugin_io, EngineInterfaceManager, GetPlugin, Interface, InterfaceManager,
|
|
PersistentPlugin, PluginDeclaration, PluginExecutionCommandContext, PluginExecutionContext,
|
|
PluginInterface, PluginInterfaceManager, PluginSource, ServePluginError,
|
|
};
|
|
#[doc(hidden)]
|
|
pub use protocol::{PluginCustomValue, PluginInput, PluginOutput};
|
|
#[doc(hidden)]
|
|
pub use serializers::EncodingType;
|
|
|
|
// Used by external benchmarks.
|
|
#[doc(hidden)]
|
|
pub use plugin::Encoder;
|
|
#[doc(hidden)]
|
|
pub use protocol::PluginCallResponse;
|