nu_protocol/engine/
command.rs1use super::{EngineState, Stack, StateWorkingSet};
2use crate::{
3 Alias, BlockId, DeprecationEntry, Example, OutDest, PipelineData, ShellError, Signature, Value,
4 engine::Call,
5};
6use std::fmt::Display;
7
8#[derive(Debug, Clone, Copy, PartialEq, Eq)]
9pub enum CommandType {
10 Builtin,
11 Custom,
12 Keyword,
13 External,
14 Alias,
15 Plugin,
16}
17
18impl Display for CommandType {
19 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
20 let str = match self {
21 CommandType::Builtin => "built-in",
22 CommandType::Custom => "custom",
23 CommandType::Keyword => "keyword",
24 CommandType::External => "external",
25 CommandType::Alias => "alias",
26 CommandType::Plugin => "plugin",
27 };
28 write!(f, "{str}")
29 }
30}
31
32pub trait Command: Send + Sync + CommandClone {
33 fn name(&self) -> &str;
34
35 fn signature(&self) -> Signature;
36
37 fn description(&self) -> &str;
41
42 fn extra_description(&self) -> &str {
46 ""
47 }
48
49 fn run(
50 &self,
51 engine_state: &EngineState,
52 stack: &mut Stack,
53 call: &Call,
54 input: PipelineData,
55 ) -> Result<PipelineData, ShellError>;
56
57 #[allow(unused_variables)]
61 fn run_const(
62 &self,
63 working_set: &StateWorkingSet,
64 call: &Call,
65 input: PipelineData,
66 ) -> Result<PipelineData, ShellError> {
67 Err(ShellError::MissingConstEvalImpl { span: call.head })
68 }
69
70 fn examples(&self) -> Vec<Example> {
71 Vec::new()
72 }
73
74 fn search_terms(&self) -> Vec<&str> {
76 vec![]
77 }
78
79 fn attributes(&self) -> Vec<(String, Value)> {
80 vec![]
81 }
82
83 fn is_const(&self) -> bool {
85 false
86 }
87
88 fn is_sub(&self) -> bool {
90 self.name().contains(' ')
91 }
92
93 fn block_id(&self) -> Option<BlockId> {
95 None
96 }
97
98 fn as_alias(&self) -> Option<&Alias> {
100 None
101 }
102
103 #[cfg(feature = "plugin")]
105 fn plugin_identity(&self) -> Option<&crate::PluginIdentity> {
106 None
107 }
108
109 fn command_type(&self) -> CommandType {
110 CommandType::Builtin
111 }
112
113 fn is_builtin(&self) -> bool {
114 self.command_type() == CommandType::Builtin
115 }
116
117 fn is_custom(&self) -> bool {
118 self.command_type() == CommandType::Custom
119 }
120
121 fn is_keyword(&self) -> bool {
122 self.command_type() == CommandType::Keyword
123 }
124
125 fn is_known_external(&self) -> bool {
126 self.command_type() == CommandType::External
127 }
128
129 fn is_alias(&self) -> bool {
130 self.command_type() == CommandType::Alias
131 }
132
133 fn is_plugin(&self) -> bool {
134 self.command_type() == CommandType::Plugin
135 }
136
137 fn deprecation_info(&self) -> Vec<DeprecationEntry> {
138 vec![]
139 }
140
141 fn pipe_redirection(&self) -> (Option<OutDest>, Option<OutDest>) {
142 (None, None)
143 }
144
145 fn requires_ast_for_arguments(&self) -> bool {
148 false
149 }
150}
151
152pub trait CommandClone {
153 fn clone_box(&self) -> Box<dyn Command>;
154}
155
156impl<T> CommandClone for T
157where
158 T: 'static + Command + Clone,
159{
160 fn clone_box(&self) -> Box<dyn Command> {
161 Box::new(self.clone())
162 }
163}
164
165impl Clone for Box<dyn Command> {
166 fn clone(&self) -> Box<dyn Command> {
167 self.clone_box()
168 }
169}