1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83
//! Plugin System
use log::warn;
use crate::{
prelude::ShellConfig,
shell::{Context, Runtime, Shell},
};
#[derive(Debug)]
pub struct PluginMeta {
pub name: String,
pub description: String,
pub help: Option<String>,
}
impl PluginMeta {
pub fn new<S: ToString>(name: S, description: S, help: Option<S>) -> Self {
Self {
name: name.to_string(),
description: description.to_string(),
help: help.map(|s| s.to_string()),
}
}
}
/// How should the plugin be handled if it errors during initialization
#[derive(Debug)]
pub enum FailMode {
/// Display a warning but continue with shell initialization
Warn,
/// Abort entire shell initialization process and crash
Abort,
}
impl Default for PluginMeta {
fn default() -> Self {
Self {
name: String::from("unnamed plugin"),
description: String::from("a plugin for shrs"),
help: None,
}
}
}
/// Implement this trait to build your own plugins
pub trait Plugin {
/// Plugin initialization
///
/// Hook onto the initialization of the shell and add any hooks, functions, state variables
/// that you would like
fn init(&self, shell: &mut ShellConfig) -> anyhow::Result<()>;
/// Plugin post initialization
///
/// Gets called once after the shell has completed initialization process, giving access to
/// shell, context, and runtime state
fn post_init(&self, _sh: &Shell, _ctx: &mut Context, _rt: &mut Runtime) -> anyhow::Result<()> {
Ok(())
}
/// Return metadata related to the plugin
fn meta(&self) -> PluginMeta {
// TODO this is currently an optional method to make migrating all the existing plugins a
// bit easier. Could remove the default implementation in the future
warn!("Using default plugin metadata. Please specify this information for your plugin by implementing Plugin::meta()");
PluginMeta::default()
}
/// Get the fail mode for this plugin
///
/// Provide implementation for this if you want non-default behavior
fn fail_mode(&self) -> FailMode {
// Default to more strict fail mode to let users know faster there's a bug
//
// Should consider more how good of an idea this is
FailMode::Abort
}
}
/// Extension trait to make [ShellConfig] support plugins
pub trait ShellPlugin {
fn with_plugin(&mut self, plugin: impl Plugin);
}