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