use std::{ collections::BTreeMap, sync::{atomic::AtomicU64, Mutex}, }; use handle_custom_value::HandleCustomValue; use nu_plugin::{serve_plugin, EngineInterface, MsgPackSerializer, Plugin, PluginCommand}; mod cool_custom_value; mod handle_custom_value; mod second_custom_value; mod drop_check; mod generate; mod generate2; mod handle_get; mod handle_make; mod handle_update; mod update; mod update_arg; use drop_check::{DropCheck, DropCheckValue}; use generate::Generate; use generate2::Generate2; use handle_get::HandleGet; use handle_make::HandleMake; use handle_update::HandleUpdate; use nu_protocol::{CustomValue, LabeledError, Spanned, Value}; use update::Update; use update_arg::UpdateArg; #[derive(Default)] pub struct CustomValuePlugin { counter: AtomicU64, handles: Mutex<BTreeMap<u64, Value>>, } impl CustomValuePlugin { pub fn new() -> Self { Self::default() } } impl Plugin for CustomValuePlugin { fn commands(&self) -> Vec<Box<dyn PluginCommand<Plugin = Self>>> { vec![ Box::new(Generate), Box::new(Generate2), Box::new(Update), Box::new(UpdateArg), Box::new(DropCheck), Box::new(HandleGet), Box::new(HandleMake), Box::new(HandleUpdate), ] } fn custom_value_to_base_value( &self, _engine: &EngineInterface, custom_value: Spanned<Box<dyn CustomValue>>, ) -> Result<Value, LabeledError> { // HandleCustomValue depends on the plugin state to get. if let Some(handle) = custom_value .item .as_any() .downcast_ref::<HandleCustomValue>() { Ok(self .handles .lock() .map_err(|err| LabeledError::new(err.to_string()))? .get(&handle.0) .cloned() .unwrap_or_else(|| Value::nothing(custom_value.span))) } else { custom_value .item .to_base_value(custom_value.span) .map_err(|err| err.into()) } } fn custom_value_dropped( &self, _engine: &EngineInterface, custom_value: Box<dyn CustomValue>, ) -> Result<(), LabeledError> { // This is how we implement our drop behavior. if let Some(drop_check) = custom_value.as_any().downcast_ref::<DropCheckValue>() { drop_check.notify(); } else if let Some(handle) = custom_value.as_any().downcast_ref::<HandleCustomValue>() { if let Ok(mut handles) = self.handles.lock() { handles.remove(&handle.0); } } Ok(()) } } fn main() { serve_plugin(&CustomValuePlugin::default(), MsgPackSerializer {}) }