1use std::collections::HashMap;
4use std::path::PathBuf;
5
6pub use shell_builder::State as ShellBuilderState;
7
8use super::Shell;
9use crate::shell::KeyBindingsHelper;
10use crate::{
11 ProfileLoadBehavior, RcLoadBehavior, ShellFd, ShellVariable, builtins, callstack, completion,
12 env, error, extensions, functions, jobs, openfiles, options, pathcache, traps,
13};
14
15impl<SE: extensions::ShellExtensions, S: shell_builder::IsComplete> ShellBuilder<SE, S> {
16 pub async fn build(self) -> Result<Shell<SE>, error::Error> {
28 let mut options = self.build_settings();
29
30 let profile = std::mem::take(&mut options.profile);
31 let rc = std::mem::take(&mut options.rc);
32
33 let mut shell = Shell::new(options)?;
35
36 if !profile.skip() || !rc.skip() {
40 shell.load_config(&profile, &rc).await?;
41 }
42
43 Ok(shell)
44 }
45}
46
47impl<SE: extensions::ShellExtensions, S: shell_builder::State> ShellBuilder<SE, S> {
48 pub fn disable_option(mut self, option: impl Into<String>) -> Self {
50 self.disabled_options.push(option.into());
51 self
52 }
53
54 pub fn enable_option(mut self, option: impl Into<String>) -> Self {
56 self.enabled_options.push(option.into());
57 self
58 }
59
60 pub fn disable_options(mut self, options: impl IntoIterator<Item: Into<String>>) -> Self {
62 self.disabled_options
63 .extend(options.into_iter().map(Into::into));
64 self
65 }
66
67 pub fn enable_options(mut self, options: impl IntoIterator<Item: Into<String>>) -> Self {
69 self.enabled_options
70 .extend(options.into_iter().map(Into::into));
71 self
72 }
73
74 pub fn disable_shopt_option(mut self, option: impl Into<String>) -> Self {
76 self.disabled_shopt_options.push(option.into());
77 self
78 }
79
80 pub fn enable_shopt_option(mut self, option: impl Into<String>) -> Self {
82 self.enabled_shopt_options.push(option.into());
83 self
84 }
85
86 pub fn disable_shopt_options(mut self, options: impl IntoIterator<Item: Into<String>>) -> Self {
88 self.disabled_shopt_options
89 .extend(options.into_iter().map(Into::into));
90 self
91 }
92
93 pub fn enable_shopt_options(mut self, options: impl IntoIterator<Item: Into<String>>) -> Self {
95 self.enabled_shopt_options
96 .extend(options.into_iter().map(Into::into));
97 self
98 }
99
100 pub fn builtin(mut self, name: impl Into<String>, reg: builtins::Registration<SE>) -> Self {
102 self.builtins.insert(name.into(), reg);
103 self
104 }
105
106 pub fn builtins(
108 mut self,
109 builtins: impl IntoIterator<Item = (String, builtins::Registration<SE>)>,
110 ) -> Self {
111 self.builtins.extend(builtins);
112 self
113 }
114
115 pub fn var(mut self, name: impl Into<String>, variable: ShellVariable) -> Self {
117 self.vars.insert(name.into(), variable);
118 self
119 }
120}
121
122#[derive(Default, bon::Builder)]
124#[builder(
125 builder_type(
126 name = ShellBuilder,
127 doc {
128 }),
130 finish_fn(
131 name = build_settings,
132 vis = "pub(self)",
133 ),
134 start_fn(
135 vis = "pub(self)"
136 )
137)]
138pub struct CreateOptions<SE: extensions::ShellExtensions = extensions::DefaultShellExtensions> {
139 #[builder(field)]
141 pub disabled_options: Vec<String>,
142 #[builder(field)]
144 pub enabled_options: Vec<String>,
145 #[builder(field)]
147 pub disabled_shopt_options: Vec<String>,
148 #[builder(field)]
150 pub enabled_shopt_options: Vec<String>,
151 #[builder(field)]
153 pub builtins: HashMap<String, builtins::Registration<SE>>,
154 #[builder(field)]
158 pub vars: HashMap<String, ShellVariable>,
159 #[builder(default)]
161 pub error_formatter: SE::ErrorFormatter,
162 #[builder(default)]
164 pub disallow_overwriting_regular_files_via_output_redirection: bool,
165 #[builder(default)]
167 pub do_not_execute_commands: bool,
168 #[builder(default)]
170 pub exit_after_one_command: bool,
171 #[builder(default)]
173 pub interactive: bool,
174 #[builder(default)]
176 pub login: bool,
177 #[builder(default)]
179 pub no_editing: bool,
180 #[builder(default)]
182 pub profile: ProfileLoadBehavior,
183 #[builder(default)]
185 pub rc: RcLoadBehavior,
186 #[builder(default)]
189 pub do_not_inherit_env: bool,
190 #[builder(default)]
192 pub skip_well_known_vars: bool,
193 #[builder(default)]
195 pub fds: HashMap<ShellFd, openfiles::OpenFile>,
196 #[builder(default)]
198 pub external_cmd_leads_session: bool,
199 #[builder(default)]
204 pub kill_external_commands_on_drop: bool,
205 pub working_dir: Option<PathBuf>,
208 #[builder(default)]
210 pub posix: bool,
211 #[builder(default)]
213 pub print_commands_and_arguments: bool,
214 #[builder(default)]
216 pub read_commands_from_stdin: bool,
217 pub shell_name: Option<String>,
219 pub shell_args: Option<Vec<String>>,
221 pub shell_product_display_str: Option<String>,
224 #[builder(default)]
226 pub sh_mode: bool,
227 #[builder(default)]
229 pub treat_unset_variables_as_error: bool,
230 #[builder(default)]
232 pub exit_on_nonzero_command_exit: bool,
233 #[builder(default)]
235 pub disable_pathname_expansion: bool,
236 #[builder(default)]
238 pub verbose: bool,
239 #[builder(default)]
241 pub parser: crate::parser::ParserImpl,
242 #[builder(default)]
244 pub command_string_mode: bool,
245 pub max_function_call_depth: Option<usize>,
247 pub key_bindings: Option<KeyBindingsHelper>,
249 pub shell_version: Option<String>,
251}
252
253impl<SE: extensions::ShellExtensions> Default for Shell<SE> {
254 fn default() -> Self {
255 Self {
256 error_formatter: SE::ErrorFormatter::default(),
257 traps: traps::TrapHandlerConfig::default(),
258 open_files: openfiles::OpenFiles::default(),
259 working_dir: PathBuf::default(),
260 env: env::ShellEnvironment::default(),
261 funcs: functions::FunctionEnv::default(),
262 options: options::RuntimeOptions::default(),
263 jobs: jobs::JobManager::default(),
264 aliases: HashMap::default(),
265 last_exit_status: 0,
266 last_exit_status_change_count: 0,
267 last_pipeline_statuses: vec![0],
268 depth: 0,
269 name: None,
270 args: vec![],
271 version: None,
272 product_display_str: None,
273 call_stack: callstack::CallStack::new(),
274 directory_stack: vec![],
275 completion: completion::State::default(),
276 builtins: HashMap::default(),
277 program_location_cache: pathcache::PathCache::default(),
278 last_stopwatch_time: std::time::SystemTime::now(),
279 last_stopwatch_offset: 0,
280 parser_impl: crate::parser::ParserImpl::default(),
281 key_bindings: None,
282 history: None,
283 }
284 }
285}
286
287impl Shell {
288 pub fn builder() -> ShellBuilder<extensions::DefaultShellExtensions, shell_builder::Empty> {
290 CreateOptions::builder()
291 }
292
293 pub fn builder_with_extensions<SE: extensions::ShellExtensions>()
296 -> ShellBuilder<SE, shell_builder::Empty> {
297 CreateOptions::builder()
298 }
299}