mirror of
https://github.com/nushell/nushell.git
synced 2025-04-30 16:14:27 +02:00
# Description This allows plugins to report their version (and potentially other metadata in the future). The version is shown in `plugin list` and in `version`. The metadata is stored in the registry file, and reflects whatever was retrieved on `plugin add`, not necessarily the running binary. This can help you to diagnose if there's some kind of mismatch with what you expect. We could potentially use this functionality to show a warning or error if a plugin being run does not have the same version as what was in the cache file, suggesting `plugin add` be run again, but I haven't done that at this point. It is optional, and it requires the plugin author to make some code changes if they want to provide it, since I can't automatically determine the version of the calling crate or anything tricky like that to do it. Example: ``` > plugin list | select name version is_running pid ╭───┬────────────────┬─────────┬────────────┬─────╮ │ # │ name │ version │ is_running │ pid │ ├───┼────────────────┼─────────┼────────────┼─────┤ │ 0 │ example │ 0.93.1 │ false │ │ │ 1 │ gstat │ 0.93.1 │ false │ │ │ 2 │ inc │ 0.93.1 │ false │ │ │ 3 │ python_example │ 0.1.0 │ false │ │ ╰───┴────────────────┴─────────┴────────────┴─────╯ ``` cc @maxim-uvarov (he asked for it) # User-Facing Changes - `plugin list` gets a `version` column - `version` shows plugin versions when available - plugin authors *should* add `fn metadata()` to their `impl Plugin`, but don't have to # Tests + Formatting Tested the low level stuff and also the `plugin list` column. # After Submitting - [ ] update plugin guide docs - [ ] update plugin protocol docs (`Metadata` call & response) - [ ] update plugin template (`fn metadata()` should be easy) - [ ] release notes
83 lines
1.9 KiB
Rust
83 lines
1.9 KiB
Rust
use std::{
|
|
any::Any,
|
|
sync::{Arc, OnceLock},
|
|
};
|
|
|
|
use nu_plugin_engine::{GetPlugin, PluginInterface};
|
|
use nu_protocol::{
|
|
engine::{EngineState, Stack},
|
|
PluginGcConfig, PluginIdentity, PluginMetadata, RegisteredPlugin, ShellError,
|
|
};
|
|
|
|
pub struct FakePersistentPlugin {
|
|
identity: PluginIdentity,
|
|
plugin: OnceLock<PluginInterface>,
|
|
}
|
|
|
|
impl FakePersistentPlugin {
|
|
pub fn new(identity: PluginIdentity) -> FakePersistentPlugin {
|
|
FakePersistentPlugin {
|
|
identity,
|
|
plugin: OnceLock::new(),
|
|
}
|
|
}
|
|
|
|
pub fn initialize(&self, interface: PluginInterface) {
|
|
self.plugin.set(interface).unwrap_or_else(|_| {
|
|
panic!("Tried to initialize an already initialized FakePersistentPlugin");
|
|
})
|
|
}
|
|
}
|
|
|
|
impl RegisteredPlugin for FakePersistentPlugin {
|
|
fn identity(&self) -> &PluginIdentity {
|
|
&self.identity
|
|
}
|
|
|
|
fn is_running(&self) -> bool {
|
|
true
|
|
}
|
|
|
|
fn pid(&self) -> Option<u32> {
|
|
None
|
|
}
|
|
|
|
fn metadata(&self) -> Option<PluginMetadata> {
|
|
None
|
|
}
|
|
|
|
fn set_metadata(&self, _metadata: Option<PluginMetadata>) {}
|
|
|
|
fn set_gc_config(&self, _gc_config: &PluginGcConfig) {
|
|
// We don't have a GC
|
|
}
|
|
|
|
fn stop(&self) -> Result<(), ShellError> {
|
|
// We can't stop
|
|
Ok(())
|
|
}
|
|
|
|
fn reset(&self) -> Result<(), ShellError> {
|
|
// We can't stop
|
|
Ok(())
|
|
}
|
|
|
|
fn as_any(self: Arc<Self>) -> Arc<dyn Any + Send + Sync> {
|
|
self
|
|
}
|
|
}
|
|
|
|
impl GetPlugin for FakePersistentPlugin {
|
|
fn get_plugin(
|
|
self: Arc<Self>,
|
|
_context: Option<(&EngineState, &mut Stack)>,
|
|
) -> Result<PluginInterface, ShellError> {
|
|
self.plugin
|
|
.get()
|
|
.cloned()
|
|
.ok_or_else(|| ShellError::PluginFailedToLoad {
|
|
msg: "FakePersistentPlugin was not initialized".into(),
|
|
})
|
|
}
|
|
}
|