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