1use std::{collections::HashMap, path::PathBuf};
4
5pub use shell_builder::State as ShellBuilderState;
6
7use super::Shell;
8use crate::{
9 ProfileLoadBehavior, RcLoadBehavior, ShellFd, ShellVariable, builtins, callstack, completion,
10 env, error, extensions, functions, jobs, openfiles, options, pathcache,
11 shell::KeyBindingsHelper, traps,
12};
13
14impl<SE: extensions::ShellExtensions, S: shell_builder::IsComplete> ShellBuilder<SE, S> {
15 pub async fn build(self) -> Result<Shell<SE>, error::Error> {
18 let mut options = self.build_settings();
19
20 let profile = std::mem::take(&mut options.profile);
21 let rc = std::mem::take(&mut options.rc);
22
23 let mut shell = Shell::new(options)?;
25
26 if !profile.skip() || !rc.skip() {
28 shell.load_config(&profile, &rc).await?;
29 }
30
31 Ok(shell)
32 }
33}
34
35impl<SE: extensions::ShellExtensions, S: shell_builder::State> ShellBuilder<SE, S> {
36 pub fn disable_option(mut self, option: impl Into<String>) -> Self {
38 self.disabled_options.push(option.into());
39 self
40 }
41
42 pub fn enable_option(mut self, option: impl Into<String>) -> Self {
44 self.enabled_options.push(option.into());
45 self
46 }
47
48 pub fn disable_options(mut self, options: impl IntoIterator<Item: Into<String>>) -> Self {
50 self.disabled_options
51 .extend(options.into_iter().map(Into::into));
52 self
53 }
54
55 pub fn enable_options(mut self, options: impl IntoIterator<Item: Into<String>>) -> Self {
57 self.enabled_options
58 .extend(options.into_iter().map(Into::into));
59 self
60 }
61
62 pub fn disable_shopt_option(mut self, option: impl Into<String>) -> Self {
64 self.disabled_shopt_options.push(option.into());
65 self
66 }
67
68 pub fn enable_shopt_option(mut self, option: impl Into<String>) -> Self {
70 self.enabled_shopt_options.push(option.into());
71 self
72 }
73
74 pub fn disable_shopt_options(mut self, options: impl IntoIterator<Item: Into<String>>) -> Self {
76 self.disabled_shopt_options
77 .extend(options.into_iter().map(Into::into));
78 self
79 }
80
81 pub fn enable_shopt_options(mut self, options: impl IntoIterator<Item: Into<String>>) -> Self {
83 self.enabled_shopt_options
84 .extend(options.into_iter().map(Into::into));
85 self
86 }
87
88 pub fn builtin(mut self, name: impl Into<String>, reg: builtins::Registration<SE>) -> Self {
90 self.builtins.insert(name.into(), reg);
91 self
92 }
93
94 pub fn builtins(
96 mut self,
97 builtins: impl IntoIterator<Item = (String, builtins::Registration<SE>)>,
98 ) -> Self {
99 self.builtins.extend(builtins);
100 self
101 }
102
103 pub fn var(mut self, name: impl Into<String>, variable: ShellVariable) -> Self {
105 self.vars.insert(name.into(), variable);
106 self
107 }
108}
109
110#[derive(Default, bon::Builder)]
112#[builder(
113 builder_type(
114 name = ShellBuilder,
115 doc {
116 }),
118 finish_fn(
119 name = build_settings,
120 vis = "pub(self)",
121 ),
122 start_fn(
123 vis = "pub(self)"
124 )
125)]
126pub struct CreateOptions<SE: extensions::ShellExtensions = extensions::DefaultShellExtensions> {
127 #[builder(field)]
129 pub disabled_options: Vec<String>,
130 #[builder(field)]
132 pub enabled_options: Vec<String>,
133 #[builder(field)]
135 pub disabled_shopt_options: Vec<String>,
136 #[builder(field)]
138 pub enabled_shopt_options: Vec<String>,
139 #[builder(field)]
141 pub builtins: HashMap<String, builtins::Registration<SE>>,
142 #[builder(field)]
145 pub vars: HashMap<String, ShellVariable>,
146 #[builder(default)]
148 pub error_formatter: SE::ErrorFormatter,
149 #[builder(default)]
151 pub disallow_overwriting_regular_files_via_output_redirection: bool,
152 #[builder(default)]
154 pub do_not_execute_commands: bool,
155 #[builder(default)]
157 pub exit_after_one_command: bool,
158 #[builder(default)]
160 pub interactive: bool,
161 #[builder(default)]
163 pub login: bool,
164 #[builder(default)]
166 pub no_editing: bool,
167 #[builder(default)]
169 pub profile: ProfileLoadBehavior,
170 #[builder(default)]
172 pub rc: RcLoadBehavior,
173 #[builder(default)]
175 pub do_not_inherit_env: bool,
176 #[builder(default)]
178 pub skip_well_known_vars: bool,
179 #[builder(default)]
181 pub fds: HashMap<ShellFd, openfiles::OpenFile>,
182 #[builder(default)]
184 pub external_cmd_leads_session: bool,
185 pub working_dir: Option<PathBuf>,
188 #[builder(default)]
190 pub posix: bool,
191 #[builder(default)]
193 pub print_commands_and_arguments: bool,
194 #[builder(default)]
196 pub read_commands_from_stdin: bool,
197 pub shell_name: Option<String>,
199 pub shell_args: Option<Vec<String>>,
201 pub shell_product_display_str: Option<String>,
203 #[builder(default)]
205 pub sh_mode: bool,
206 #[builder(default)]
208 pub treat_unset_variables_as_error: bool,
209 #[builder(default)]
211 pub exit_on_nonzero_command_exit: bool,
212 #[builder(default)]
214 pub disable_pathname_expansion: bool,
215 #[builder(default)]
217 pub verbose: bool,
218 #[builder(default)]
220 pub parser: crate::parser::ParserImpl,
221 #[builder(default)]
223 pub command_string_mode: bool,
224 pub max_function_call_depth: Option<usize>,
226 pub key_bindings: Option<KeyBindingsHelper>,
228 pub shell_version: Option<String>,
230}
231
232impl<SE: extensions::ShellExtensions> Default for Shell<SE> {
233 fn default() -> Self {
234 Self {
235 error_formatter: SE::ErrorFormatter::default(),
236 traps: traps::TrapHandlerConfig::default(),
237 open_files: openfiles::OpenFiles::default(),
238 working_dir: PathBuf::default(),
239 env: env::ShellEnvironment::default(),
240 funcs: functions::FunctionEnv::default(),
241 options: options::RuntimeOptions::default(),
242 jobs: jobs::JobManager::default(),
243 aliases: HashMap::default(),
244 last_exit_status: 0,
245 last_exit_status_change_count: 0,
246 last_pipeline_statuses: vec![0],
247 depth: 0,
248 name: None,
249 args: vec![],
250 version: None,
251 product_display_str: None,
252 call_stack: callstack::CallStack::new(),
253 directory_stack: vec![],
254 completion_config: completion::Config::default(),
255 builtins: HashMap::default(),
256 program_location_cache: pathcache::PathCache::default(),
257 last_stopwatch_time: std::time::SystemTime::now(),
258 last_stopwatch_offset: 0,
259 parser_impl: crate::parser::ParserImpl::default(),
260 key_bindings: None,
261 history: None,
262 }
263 }
264}
265
266impl Shell {
267 pub fn builder() -> ShellBuilder<extensions::DefaultShellExtensions, shell_builder::Empty> {
269 CreateOptions::builder()
270 }
271
272 pub fn builder_with_extensions<SE: extensions::ShellExtensions>()
274 -> ShellBuilder<SE, shell_builder::Empty> {
275 CreateOptions::builder()
276 }
277}