nu_plugin_engine/
declaration.rs1use nu_engine::{command_prelude::*, get_eval_expression};
2use nu_plugin_protocol::{CallInfo, EvaluatedCall};
3use nu_protocol::{PluginIdentity, PluginSignature, engine::CommandType};
4use std::sync::Arc;
5
6use crate::{GetPlugin, PluginExecutionCommandContext, PluginSource};
7
8#[derive(Clone)]
10pub struct PluginDeclaration {
11 name: String,
12 signature: PluginSignature,
13 source: PluginSource,
14}
15
16impl PluginDeclaration {
17 pub fn new(plugin: Arc<dyn GetPlugin>, signature: PluginSignature) -> Self {
18 Self {
19 name: signature.sig.name.clone(),
20 signature,
21 source: PluginSource::new(plugin),
22 }
23 }
24}
25
26impl Command for PluginDeclaration {
27 fn name(&self) -> &str {
28 &self.name
29 }
30
31 fn signature(&self) -> Signature {
32 self.signature.sig.clone()
33 }
34
35 fn description(&self) -> &str {
36 self.signature.sig.description.as_str()
37 }
38
39 fn extra_description(&self) -> &str {
40 self.signature.sig.extra_description.as_str()
41 }
42
43 fn search_terms(&self) -> Vec<&str> {
44 self.signature
45 .sig
46 .search_terms
47 .iter()
48 .map(|term| term.as_str())
49 .collect()
50 }
51
52 fn examples(&self) -> Vec<Example> {
53 let mut res = vec![];
54 for e in self.signature.examples.iter() {
55 res.push(Example {
56 example: &e.example,
57 description: &e.description,
58 result: e.result.clone(),
59 })
60 }
61 res
62 }
63
64 fn run(
65 &self,
66 engine_state: &EngineState,
67 stack: &mut Stack,
68 call: &Call,
69 input: PipelineData,
70 ) -> Result<PipelineData, ShellError> {
71 let eval_expression = get_eval_expression(engine_state);
72
73 let evaluated_call =
76 EvaluatedCall::try_from_call(call, engine_state, stack, eval_expression)?;
77
78 let engine_config = stack.get_config(engine_state);
80
81 let plugin = self
83 .source
84 .persistent(None)
85 .and_then(|p| {
86 p.set_gc_config(engine_config.plugin_gc.get(p.identity().name()));
88 p.get_plugin(Some((engine_state, stack)))
89 })
90 .map_err(|err| {
91 let decl = engine_state.get_decl(call.decl_id);
92 ShellError::GenericError {
93 error: format!("Unable to spawn plugin for `{}`", decl.name()),
94 msg: err.to_string(),
95 span: Some(call.head),
96 help: None,
97 inner: vec![],
98 }
99 })?;
100
101 let mut context = PluginExecutionCommandContext::new(
103 self.source.identity.clone(),
104 engine_state,
105 stack,
106 call,
107 );
108
109 plugin.run(
110 CallInfo {
111 name: self.name.clone(),
112 call: evaluated_call,
113 input,
114 },
115 &mut context,
116 )
117 }
118
119 fn command_type(&self) -> CommandType {
120 CommandType::Plugin
121 }
122
123 fn plugin_identity(&self) -> Option<&PluginIdentity> {
124 Some(&self.source.identity)
125 }
126}