Skip to main content

brush_builtins/
factory.rs

1use std::collections::HashMap;
2
3#[allow(clippy::wildcard_imports)]
4use super::*;
5
6#[allow(unused_imports, reason = "not all builtins are used in all configs")]
7use brush_core::builtins::{self, builtin, decl_builtin, raw_arg_builtin, simple_builtin};
8
9/// Identifies well-known sets of builtins.
10#[derive(Clone, Copy, Eq, PartialEq)]
11pub enum BuiltinSet {
12    /// Identifies builtins appropriate for POSIX `sh` compatibility.
13    ShMode,
14    /// Identifies builtins appropriate for a more full-featured `bash`-compatible shell.
15    BashMode,
16}
17
18/// Returns the default set of built-in commands.
19///
20/// # Arguments
21///
22/// * `set` - The set of built-ins to return.
23#[allow(clippy::too_many_lines)]
24pub fn default_builtins<SE: brush_core::ShellExtensions>(
25    set: BuiltinSet,
26) -> HashMap<String, builtins::Registration<SE>> {
27    let mut m = HashMap::<String, builtins::Registration<SE>>::new();
28
29    //
30    // POSIX special builtins
31    //
32    // N.B. There seems to be some inconsistency as to whether 'times'
33    // should be a special built-in.
34    //
35
36    #[cfg(feature = "builtin.break")]
37    m.insert(
38        "break".into(),
39        builtin::<break_::BreakCommand, SE>().special(),
40    );
41    #[cfg(feature = "builtin.colon")]
42    m.insert(
43        ":".into(),
44        simple_builtin::<colon::ColonCommand, SE>().special(),
45    );
46    #[cfg(feature = "builtin.continue")]
47    m.insert(
48        "continue".into(),
49        builtin::<continue_::ContinueCommand, SE>().special(),
50    );
51    #[cfg(feature = "builtin.dot")]
52    m.insert(".".into(), builtin::<dot::DotCommand, SE>().special());
53    #[cfg(feature = "builtin.eval")]
54    m.insert("eval".into(), builtin::<eval::EvalCommand, SE>().special());
55    #[cfg(all(feature = "builtin.exec", unix))]
56    m.insert("exec".into(), builtin::<exec::ExecCommand, SE>().special());
57    #[cfg(feature = "builtin.exit")]
58    m.insert("exit".into(), builtin::<exit::ExitCommand, SE>().special());
59    #[cfg(feature = "builtin.export")]
60    m.insert(
61        "export".into(),
62        decl_builtin::<export::ExportCommand, SE>().special(),
63    );
64    #[cfg(feature = "builtin.return")]
65    m.insert(
66        "return".into(),
67        builtin::<return_::ReturnCommand, SE>().special(),
68    );
69    #[cfg(feature = "builtin.set")]
70    m.insert("set".into(), builtin::<set::SetCommand, SE>().special());
71    #[cfg(feature = "builtin.shift")]
72    m.insert(
73        "shift".into(),
74        builtin::<shift::ShiftCommand, SE>().special(),
75    );
76    #[cfg(feature = "builtin.trap")]
77    m.insert("trap".into(), builtin::<trap::TrapCommand, SE>().special());
78    #[cfg(feature = "builtin.unset")]
79    m.insert(
80        "unset".into(),
81        builtin::<unset::UnsetCommand, SE>().special(),
82    );
83
84    #[cfg(feature = "builtin.declare")]
85    m.insert(
86        "readonly".into(),
87        decl_builtin::<declare::DeclareCommand, SE>().special(),
88    );
89    #[cfg(feature = "builtin.times")]
90    m.insert(
91        "times".into(),
92        builtin::<times::TimesCommand, SE>().special(),
93    );
94
95    //
96    // Non-special builtins
97    //
98
99    #[cfg(feature = "builtin.alias")]
100    m.insert("alias".into(), builtin::<alias::AliasCommand, SE>()); // TODO(alias): should be exec_declaration_builtin
101    #[cfg(feature = "builtin.bg")]
102    m.insert("bg".into(), builtin::<bg::BgCommand, SE>());
103    #[cfg(feature = "builtin.cd")]
104    m.insert("cd".into(), builtin::<cd::CdCommand, SE>());
105    #[cfg(feature = "builtin.command")]
106    m.insert("command".into(), builtin::<command::CommandCommand, SE>());
107    #[cfg(feature = "builtin.false")]
108    m.insert("false".into(), simple_builtin::<false_::FalseCommand, SE>());
109    #[cfg(feature = "builtin.fg")]
110    m.insert("fg".into(), builtin::<fg::FgCommand, SE>());
111    #[cfg(feature = "builtin.getopts")]
112    m.insert("getopts".into(), builtin::<getopts::GetOptsCommand, SE>());
113    #[cfg(feature = "builtin.hash")]
114    m.insert("hash".into(), builtin::<hash::HashCommand, SE>());
115    #[cfg(feature = "builtin.help")]
116    m.insert("help".into(), builtin::<help::HelpCommand, SE>());
117    #[cfg(feature = "builtin.jobs")]
118    m.insert("jobs".into(), builtin::<jobs::JobsCommand, SE>());
119    #[cfg(all(feature = "builtin.kill", unix))]
120    m.insert("kill".into(), builtin::<kill::KillCommand, SE>());
121    #[cfg(feature = "builtin.declare")]
122    m.insert(
123        "local".into(),
124        decl_builtin::<declare::DeclareCommand, SE>(),
125    );
126    #[cfg(feature = "builtin.pwd")]
127    m.insert("pwd".into(), builtin::<pwd::PwdCommand, SE>());
128    #[cfg(feature = "builtin.read")]
129    m.insert("read".into(), builtin::<read::ReadCommand, SE>());
130    #[cfg(feature = "builtin.true")]
131    m.insert("true".into(), simple_builtin::<true_::TrueCommand, SE>());
132    #[cfg(feature = "builtin.type")]
133    m.insert("type".into(), builtin::<type_::TypeCommand, SE>());
134    #[cfg(all(feature = "builtin.ulimit", unix))]
135    m.insert("ulimit".into(), builtin::<ulimit::ULimitCommand, SE>());
136    #[cfg(all(feature = "builtin.umask", unix))]
137    m.insert("umask".into(), builtin::<umask::UmaskCommand, SE>());
138    #[cfg(feature = "builtin.unalias")]
139    m.insert("unalias".into(), builtin::<unalias::UnaliasCommand, SE>());
140    #[cfg(feature = "builtin.wait")]
141    m.insert("wait".into(), builtin::<wait::WaitCommand, SE>());
142
143    #[cfg(feature = "builtin.fc")]
144    m.insert("fc".into(), builtin::<fc::FcCommand, SE>());
145
146    if matches!(set, BuiltinSet::BashMode) {
147        #[cfg(feature = "builtin.builtin")]
148        m.insert(
149            "builtin".into(),
150            raw_arg_builtin::<builtin_::BuiltinCommand, SE>(),
151        );
152        #[cfg(feature = "builtin.declare")]
153        m.insert(
154            "declare".into(),
155            decl_builtin::<declare::DeclareCommand, SE>(),
156        );
157        #[cfg(feature = "builtin.echo")]
158        m.insert("echo".into(), builtin::<echo::EchoCommand, SE>());
159        #[cfg(feature = "builtin.enable")]
160        m.insert("enable".into(), builtin::<enable::EnableCommand, SE>());
161        #[cfg(feature = "builtin.let")]
162        m.insert("let".into(), builtin::<let_::LetCommand, SE>());
163        #[cfg(feature = "builtin.mapfile")]
164        m.insert("mapfile".into(), builtin::<mapfile::MapFileCommand, SE>());
165        #[cfg(feature = "builtin.mapfile")]
166        m.insert("readarray".into(), builtin::<mapfile::MapFileCommand, SE>());
167        #[cfg(all(feature = "builtin.printf", any(unix, windows)))]
168        m.insert("printf".into(), builtin::<printf::PrintfCommand, SE>());
169        #[cfg(feature = "builtin.shopt")]
170        m.insert("shopt".into(), builtin::<shopt::ShoptCommand, SE>());
171        #[cfg(feature = "builtin.dot")]
172        m.insert("source".into(), builtin::<dot::DotCommand, SE>().special());
173        #[cfg(all(feature = "builtin.suspend", unix))]
174        m.insert("suspend".into(), builtin::<suspend::SuspendCommand, SE>());
175        #[cfg(feature = "builtin.test")]
176        m.insert("test".into(), builtin::<test::TestCommand, SE>());
177        #[cfg(feature = "builtin.test")]
178        m.insert("[".into(), builtin::<test::TestCommand, SE>());
179        #[cfg(feature = "builtin.declare")]
180        m.insert(
181            "typeset".into(),
182            decl_builtin::<declare::DeclareCommand, SE>(),
183        );
184
185        // Completion builtins
186        #[cfg(feature = "builtin.complete")]
187        m.insert(
188            "complete".into(),
189            builtin::<complete::CompleteCommand, SE>(),
190        );
191        #[cfg(feature = "builtin.compgen")]
192        m.insert("compgen".into(), builtin::<complete::CompGenCommand, SE>());
193        #[cfg(feature = "builtin.compopt")]
194        m.insert("compopt".into(), builtin::<complete::CompOptCommand, SE>());
195
196        // Dir stack builtins
197        #[cfg(feature = "builtin.dirs")]
198        m.insert("dirs".into(), builtin::<dirs::DirsCommand, SE>());
199        #[cfg(feature = "builtin.popd")]
200        m.insert("popd".into(), builtin::<popd::PopdCommand, SE>());
201        #[cfg(feature = "builtin.pushd")]
202        m.insert("pushd".into(), builtin::<pushd::PushdCommand, SE>());
203
204        // Input configuration builtins
205        #[cfg(feature = "builtin.bind")]
206        m.insert("bind".into(), builtin::<bind::BindCommand, SE>());
207
208        // History
209        #[cfg(feature = "builtin.history")]
210        m.insert("history".into(), builtin::<history::HistoryCommand, SE>());
211
212        #[cfg(feature = "builtin.caller")]
213        m.insert("caller".into(), builtin::<caller::CallerCommand, SE>());
214
215        // TODO(disown): implement disown builtin
216        m.insert(
217            "disown".into(),
218            builtin::<unimp::UnimplementedCommand, SE>(),
219        );
220
221        // TODO(logout): implement logout builtin
222        m.insert(
223            "logout".into(),
224            builtin::<unimp::UnimplementedCommand, SE>(),
225        );
226    }
227
228    m
229}