nu_protocol/engine/
command.rs1use serde::{Deserialize, Serialize};
2
3use super::{EngineState, Stack, StateWorkingSet};
4use crate::{
5 Alias, BlockId, DeprecationEntry, DynamicCompletionCallRef, DynamicSuggestion, Example,
6 OutDest, PipelineData, ShellError, Signature, Span, Value, engine::Call,
7};
8use std::{
9 any::Any,
10 borrow::Cow,
11 fmt::{Debug, Display},
12};
13
14#[derive(Debug, Clone, PartialEq, Eq)]
15pub enum ArgType<'a> {
16 Flag(Cow<'a, str>),
17 Positional(usize),
18}
19
20impl<'a> Display for ArgType<'a> {
21 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
22 match self {
23 ArgType::Flag(flag_name) => match flag_name {
24 Cow::Borrowed(v) => write!(f, "{v}"),
25 Cow::Owned(v) => write!(f, "{v}"),
26 },
27 ArgType::Positional(idx) => write!(f, "{idx}"),
28 }
29 }
30}
31
32#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
33pub enum CommandType {
34 Builtin,
35 Custom,
36 Keyword,
37 External,
38 Alias,
39 Plugin,
40}
41
42impl Display for CommandType {
43 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
44 let str = match self {
45 CommandType::Builtin => "built-in",
46 CommandType::Custom => "custom",
47 CommandType::Keyword => "keyword",
48 CommandType::External => "external",
49 CommandType::Alias => "alias",
50 CommandType::Plugin => "plugin",
51 };
52 write!(f, "{str}")
53 }
54}
55
56pub trait Command: Send + Sync + CommandClone + Any {
57 fn name(&self) -> &str;
58
59 fn signature(&self) -> Signature;
60
61 fn description(&self) -> &str;
65
66 fn extra_description(&self) -> &str {
70 ""
71 }
72
73 fn run(
74 &self,
75 engine_state: &EngineState,
76 stack: &mut Stack,
77 call: &Call,
78 input: PipelineData,
79 ) -> Result<PipelineData, ShellError>;
80
81 #[allow(unused_variables)]
85 fn run_const(
86 &self,
87 working_set: &StateWorkingSet,
88 call: &Call,
89 input: PipelineData,
90 ) -> Result<PipelineData, ShellError> {
91 Err(ShellError::MissingConstEvalImpl { span: call.head })
92 }
93
94 fn examples(&self) -> Vec<Example<'_>> {
95 Vec::new()
96 }
97
98 fn search_terms(&self) -> Vec<&str> {
100 vec![]
101 }
102
103 fn attributes(&self) -> Vec<(String, Value)> {
104 vec![]
105 }
106
107 fn is_const(&self) -> bool {
109 false
110 }
111
112 fn is_sub(&self) -> bool {
114 self.name().contains(' ')
115 }
116
117 fn block_id(&self) -> Option<BlockId> {
119 None
120 }
121
122 fn as_alias(&self) -> Option<&Alias> {
124 None
125 }
126
127 #[cfg(feature = "plugin")]
129 fn plugin_identity(&self) -> Option<&crate::PluginIdentity> {
130 None
131 }
132
133 fn command_type(&self) -> CommandType {
134 CommandType::Builtin
135 }
136
137 fn is_builtin(&self) -> bool {
138 self.command_type() == CommandType::Builtin
139 }
140
141 fn is_custom(&self) -> bool {
142 self.command_type() == CommandType::Custom
143 }
144
145 fn is_keyword(&self) -> bool {
146 self.command_type() == CommandType::Keyword
147 }
148
149 fn is_known_external(&self) -> bool {
150 self.command_type() == CommandType::External
151 }
152
153 fn decl_span(&self) -> Option<Span> {
157 None
158 }
159
160 fn is_alias(&self) -> bool {
161 self.command_type() == CommandType::Alias
162 }
163
164 fn is_plugin(&self) -> bool {
165 self.command_type() == CommandType::Plugin
166 }
167
168 fn deprecation_info(&self) -> Vec<DeprecationEntry> {
169 vec![]
170 }
171
172 fn pipe_redirection(&self) -> (Option<OutDest>, Option<OutDest>) {
173 (None, None)
174 }
175
176 #[allow(unused_variables)]
187 #[expect(deprecated)]
188 fn get_dynamic_completion(
189 &self,
190 engine_state: &EngineState,
191 stack: &mut Stack,
192 call: DynamicCompletionCallRef,
193 arg_type: &ArgType,
194 _experimental: ExperimentalMarker,
195 ) -> Result<Option<Vec<DynamicSuggestion>>, ShellError> {
196 Ok(None)
197 }
198
199 fn requires_ast_for_arguments(&self) -> bool {
202 false
203 }
204}
205
206pub trait CommandClone {
207 fn clone_box(&self) -> Box<dyn Command>;
208}
209
210impl<T> CommandClone for T
211where
212 T: 'static + Command + Clone,
213{
214 fn clone_box(&self) -> Box<dyn Command> {
215 Box::new(self.clone())
216 }
217}
218
219impl Clone for Box<dyn Command> {
220 fn clone(&self) -> Box<dyn Command> {
221 self.clone_box()
222 }
223}
224
225#[derive(Debug, Clone, Copy, PartialEq, Eq)]
230#[deprecated(note = "this method is very experimental, likely to change")]
231pub struct ExperimentalMarker;