Skip to content

Commit df9c835

Browse files
authored
refactor: split shell.rs => shell/*.rs (reubeno#945)
Moves most of `brush-core/src/shell.rs` into granular modules under `brush-core/src/shell` for better manageability.
1 parent 094b828 commit df9c835

19 files changed

Lines changed: 2026 additions & 1833 deletions

brush-core/src/shell.rs

Lines changed: 151 additions & 1833 deletions
Large diffs are not rendered by default.

brush-core/src/shell/builder.rs

Lines changed: 270 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,270 @@
1+
//! Module defining the builder for creating shell instances.
2+
3+
use std::{collections::HashMap, path::PathBuf};
4+
5+
pub use shell_builder::State as ShellBuilderState;
6+
7+
use super::Shell;
8+
use crate::{
9+
ProfileLoadBehavior, RcLoadBehavior, ShellFd, ShellVariable, builtins, callstack, completion,
10+
env, error, extensions, functions, jobs, openfiles, options, pathcache,
11+
shell::KeyBindingsHelper, traps,
12+
};
13+
14+
impl<SE: extensions::ShellExtensions, S: shell_builder::IsComplete> ShellBuilder<SE, S> {
15+
/// Returns a new shell instance created with the options provided. Runs any
16+
/// configuration loading as well.
17+
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+
// Construct the shell.
24+
let mut shell = Shell::new(options)?;
25+
26+
// Load profiles/configuration, unless skipped.
27+
if !profile.skip() || !rc.skip() {
28+
shell.load_config(&profile, &rc).await?;
29+
}
30+
31+
Ok(shell)
32+
}
33+
}
34+
35+
impl<SE: extensions::ShellExtensions, S: shell_builder::State> ShellBuilder<SE, S> {
36+
/// Add a disabled option
37+
pub fn disable_option(mut self, option: impl Into<String>) -> Self {
38+
self.disabled_options.push(option.into());
39+
self
40+
}
41+
42+
/// Add an enabled option
43+
pub fn enable_option(mut self, option: impl Into<String>) -> Self {
44+
self.enabled_options.push(option.into());
45+
self
46+
}
47+
48+
/// Add many disabled options
49+
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+
/// Add many enabled options
56+
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+
/// Add a disabled shopt option
63+
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+
/// Add an enabled shopt option
69+
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+
/// Add many disabled shopt options
75+
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+
/// Add many enabled shopt options
82+
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+
/// Add a single builtin registration
89+
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+
/// Add many builtin registrations
95+
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+
/// Adds a single variable to be initialized in the shell.
104+
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+
/// Options for creating a new shell.
111+
#[derive(Default, bon::Builder)]
112+
#[builder(
113+
builder_type(
114+
name = ShellBuilder,
115+
doc {
116+
/// Builder for [Shell]
117+
}),
118+
finish_fn(
119+
name = build_settings,
120+
vis = "pub(self)",
121+
),
122+
start_fn(
123+
vis = "pub(self)"
124+
)
125+
)]
126+
pub struct CreateOptions<SE: extensions::ShellExtensions = extensions::DefaultShellExtensions> {
127+
/// Disabled options.
128+
#[builder(field)]
129+
pub disabled_options: Vec<String>,
130+
/// Enabled options.
131+
#[builder(field)]
132+
pub enabled_options: Vec<String>,
133+
/// Disabled shopt options.
134+
#[builder(field)]
135+
pub disabled_shopt_options: Vec<String>,
136+
/// Enabled shopt options.
137+
#[builder(field)]
138+
pub enabled_shopt_options: Vec<String>,
139+
/// Registered builtins.
140+
#[builder(field)]
141+
pub builtins: HashMap<String, builtins::Registration<SE>>,
142+
/// Provides a set of variables to be initialized in the shell. If present, they
143+
/// are assigned *after* inherited or well-known variables are set (when applicable).
144+
#[builder(field)]
145+
pub vars: HashMap<String, ShellVariable>,
146+
/// Error behavior implementation.
147+
#[builder(default)]
148+
pub error_formatter: SE::ErrorFormatter,
149+
/// Disallow overwriting regular files via output redirection.
150+
#[builder(default)]
151+
pub disallow_overwriting_regular_files_via_output_redirection: bool,
152+
/// Do not execute commands.
153+
#[builder(default)]
154+
pub do_not_execute_commands: bool,
155+
/// Exit after one command.
156+
#[builder(default)]
157+
pub exit_after_one_command: bool,
158+
/// Whether the shell is interactive.
159+
#[builder(default)]
160+
pub interactive: bool,
161+
/// Whether the shell is a login shell.
162+
#[builder(default)]
163+
pub login: bool,
164+
/// Whether to skip using a readline-like interface for input.
165+
#[builder(default)]
166+
pub no_editing: bool,
167+
/// System profile loading behavior.
168+
#[builder(default)]
169+
pub profile: ProfileLoadBehavior,
170+
/// Rc file loading behavior.
171+
#[builder(default)]
172+
pub rc: RcLoadBehavior,
173+
/// Whether to skip inheriting environment variables from the calling process.
174+
#[builder(default)]
175+
pub do_not_inherit_env: bool,
176+
/// Whether to skip initializing well-known variables.
177+
#[builder(default)]
178+
pub skip_well_known_vars: bool,
179+
/// Provides a set of initial open files to be tracked by the shell.
180+
#[builder(default)]
181+
pub fds: HashMap<ShellFd, openfiles::OpenFile>,
182+
/// Whether to launch external commands as session leaders.
183+
#[builder(default)]
184+
pub external_cmd_leads_session: bool,
185+
/// Initial working dir for the shell. If left unspecified, will be populated from
186+
/// the host environment.
187+
pub working_dir: Option<PathBuf>,
188+
/// Whether the shell is in POSIX compliance mode.
189+
#[builder(default)]
190+
pub posix: bool,
191+
/// Whether to print commands and arguments as they are read.
192+
#[builder(default)]
193+
pub print_commands_and_arguments: bool,
194+
/// Whether commands are being read from stdin.
195+
#[builder(default)]
196+
pub read_commands_from_stdin: bool,
197+
/// The name of the shell.
198+
pub shell_name: Option<String>,
199+
/// Base positional arguments for the shell (not including the shell name).
200+
pub shell_args: Option<Vec<String>>,
201+
/// Optionally provides a display string describing the version and variant of the shell.
202+
pub shell_product_display_str: Option<String>,
203+
/// Whether to run in maximal POSIX sh compatibility mode.
204+
#[builder(default)]
205+
pub sh_mode: bool,
206+
/// Whether to treat expansion of unset variables as an error.
207+
#[builder(default)]
208+
pub treat_unset_variables_as_error: bool,
209+
/// Whether to enable error-on-exit behavior.
210+
#[builder(default)]
211+
pub exit_on_nonzero_command_exit: bool,
212+
/// Whether to print verbose output.
213+
#[builder(default)]
214+
pub verbose: bool,
215+
/// Whether the shell is in command string mode (-c).
216+
#[builder(default)]
217+
pub command_string_mode: bool,
218+
/// Maximum function call depth.
219+
pub max_function_call_depth: Option<usize>,
220+
/// Key bindings helper for the shell to use.
221+
pub key_bindings: Option<KeyBindingsHelper>,
222+
/// Brush implementation version.
223+
pub shell_version: Option<String>,
224+
}
225+
226+
impl<SE: extensions::ShellExtensions> Default for Shell<SE> {
227+
fn default() -> Self {
228+
Self {
229+
error_formatter: SE::ErrorFormatter::default(),
230+
traps: traps::TrapHandlerConfig::default(),
231+
open_files: openfiles::OpenFiles::default(),
232+
working_dir: PathBuf::default(),
233+
env: env::ShellEnvironment::default(),
234+
funcs: functions::FunctionEnv::default(),
235+
options: options::RuntimeOptions::default(),
236+
jobs: jobs::JobManager::default(),
237+
aliases: HashMap::default(),
238+
last_exit_status: 0,
239+
last_exit_status_change_count: 0,
240+
last_pipeline_statuses: vec![0],
241+
depth: 0,
242+
name: None,
243+
args: vec![],
244+
version: None,
245+
product_display_str: None,
246+
call_stack: callstack::CallStack::new(),
247+
directory_stack: vec![],
248+
completion_config: completion::Config::default(),
249+
builtins: HashMap::default(),
250+
program_location_cache: pathcache::PathCache::default(),
251+
last_stopwatch_time: std::time::SystemTime::now(),
252+
last_stopwatch_offset: 0,
253+
key_bindings: None,
254+
history: None,
255+
}
256+
}
257+
}
258+
259+
impl Shell {
260+
/// Create an instance of [Shell] using the builder syntax
261+
pub fn builder() -> ShellBuilder<extensions::DefaultShellExtensions, shell_builder::Empty> {
262+
CreateOptions::builder()
263+
}
264+
265+
/// Create an instance of [Shell] using the builder syntax, with custom extensions.
266+
pub fn builder_with_extensions<SE: extensions::ShellExtensions>()
267+
-> ShellBuilder<SE, shell_builder::Empty> {
268+
CreateOptions::builder()
269+
}
270+
}
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
//! Builtin command management for shell instances.
2+
3+
use std::collections::HashMap;
4+
5+
use crate::{builtins, extensions};
6+
7+
impl<SE: extensions::ShellExtensions> crate::Shell<SE> {
8+
/// Register a builtin to the shell's environment.
9+
///
10+
/// # Arguments
11+
///
12+
/// * `name` - The in-shell name of the builtin.
13+
/// * `registration` - The registration handle for the builtin.
14+
pub fn register_builtin<S: Into<String>>(
15+
&mut self,
16+
name: S,
17+
registration: builtins::Registration<SE>,
18+
) {
19+
self.builtins.insert(name.into(), registration);
20+
}
21+
22+
/// Tries to retrieve a mutable reference to an existing builtin registration.
23+
/// Returns `None` if no such registration exists.
24+
///
25+
/// # Arguments
26+
///
27+
/// * `name` - The name of the builtin to lookup.
28+
pub fn builtin_mut(&mut self, name: &str) -> Option<&mut builtins::Registration<SE>> {
29+
self.builtins.get_mut(name)
30+
}
31+
32+
/// Returns the registered builtins for the shell.
33+
pub const fn builtins(&self) -> &HashMap<String, builtins::Registration<SE>> {
34+
&self.builtins
35+
}
36+
}

0 commit comments

Comments
 (0)