forked from extern/nushell
Refactor rarely changing engine state into its own struct (#3612)
* WIP * Finish up EngineState refactor * Fix Windows calls * Fix Windows calls * Fix Windows calls
This commit is contained in:
@ -27,23 +27,23 @@ impl CommandArgs {
|
||||
}
|
||||
|
||||
pub fn host(&self) -> Arc<parking_lot::Mutex<Box<dyn Host>>> {
|
||||
self.context.host.clone()
|
||||
self.context.host().clone()
|
||||
}
|
||||
|
||||
pub fn current_errors(&self) -> Arc<Mutex<Vec<ShellError>>> {
|
||||
self.context.current_errors.clone()
|
||||
self.context.current_errors().clone()
|
||||
}
|
||||
|
||||
pub fn ctrl_c(&self) -> Arc<AtomicBool> {
|
||||
self.context.ctrl_c.clone()
|
||||
self.context.ctrl_c().clone()
|
||||
}
|
||||
|
||||
pub fn configs(&self) -> Arc<Mutex<ConfigHolder>> {
|
||||
self.context.configs.clone()
|
||||
self.context.configs().clone()
|
||||
}
|
||||
|
||||
pub fn shell_manager(&self) -> ShellManager {
|
||||
self.context.shell_manager.clone()
|
||||
self.context.shell_manager().clone()
|
||||
}
|
||||
|
||||
pub fn nth(&self, pos: usize) -> Option<&SpannedExpression> {
|
||||
|
@ -60,7 +60,7 @@ pub fn run_block(
|
||||
ctx.clear_errors();
|
||||
return Err(err.clone());
|
||||
}
|
||||
if ctx.ctrl_c.load(Ordering::SeqCst) {
|
||||
if ctx.ctrl_c().load(Ordering::SeqCst) {
|
||||
return Ok(InputStream::empty());
|
||||
}
|
||||
}
|
||||
@ -96,7 +96,7 @@ pub fn run_block(
|
||||
ctx.clear_errors();
|
||||
return Err(err.clone());
|
||||
}
|
||||
if ctx.ctrl_c.load(Ordering::SeqCst) {
|
||||
if ctx.ctrl_c().load(Ordering::SeqCst) {
|
||||
// This early return doesn't return the result
|
||||
// we have so far, but breaking out of this loop
|
||||
// causes lifetime issues. A future contribution
|
||||
|
@ -79,7 +79,7 @@ impl Iterator for InternalIterator {
|
||||
match item {
|
||||
Ok(ReturnSuccess::Action(action)) => match action {
|
||||
CommandAction::ChangePath(path) => {
|
||||
self.context.shell_manager.set_path(path);
|
||||
self.context.shell_manager().set_path(path);
|
||||
}
|
||||
CommandAction::Exit(code) => std::process::exit(code), // TODO: save history.txt
|
||||
CommandAction::Error(err) => {
|
||||
@ -135,16 +135,16 @@ impl Iterator for InternalIterator {
|
||||
}
|
||||
CommandAction::EnterValueShell(value) => {
|
||||
self.context
|
||||
.shell_manager
|
||||
.shell_manager()
|
||||
.insert_at_current(Box::new(ValueShell::new(value)));
|
||||
}
|
||||
CommandAction::EnterShell(location) => {
|
||||
let mode = if self.context.shell_manager.is_interactive() {
|
||||
let mode = if self.context.shell_manager().is_interactive() {
|
||||
FilesystemShellMode::Cli
|
||||
} else {
|
||||
FilesystemShellMode::Script
|
||||
};
|
||||
self.context.shell_manager.insert_at_current(Box::new(
|
||||
self.context.shell_manager().insert_at_current(Box::new(
|
||||
match FilesystemShell::with_location(location, mode) {
|
||||
Ok(v) => v,
|
||||
Err(err) => {
|
||||
@ -172,14 +172,14 @@ impl Iterator for InternalIterator {
|
||||
}
|
||||
}
|
||||
CommandAction::PreviousShell => {
|
||||
self.context.shell_manager.prev();
|
||||
self.context.shell_manager().prev();
|
||||
}
|
||||
CommandAction::NextShell => {
|
||||
self.context.shell_manager.next();
|
||||
self.context.shell_manager().next();
|
||||
}
|
||||
CommandAction::LeaveShell(code) => {
|
||||
self.context.shell_manager.remove_at_current();
|
||||
if self.context.shell_manager.is_empty() {
|
||||
self.context.shell_manager().remove_at_current();
|
||||
if self.context.shell_manager().is_empty() {
|
||||
std::process::exit(code); // TODO: save history.txt
|
||||
}
|
||||
}
|
||||
|
@ -30,7 +30,7 @@ pub fn nu(
|
||||
UntaggedValue::filepath(default_history_path()).into_value(&tag),
|
||||
);
|
||||
|
||||
if let Some(global_cfg) = &ctx.configs.lock().global_config {
|
||||
if let Some(global_cfg) = &ctx.configs().lock().global_config {
|
||||
nu_dict.insert_value(
|
||||
"config",
|
||||
UntaggedValue::row(global_cfg.vars.clone()).into_value(&tag),
|
||||
|
@ -20,8 +20,7 @@ use std::sync::atomic::AtomicBool;
|
||||
use std::{path::Path, sync::Arc};
|
||||
|
||||
#[derive(Clone, Default)]
|
||||
pub struct EvaluationContext {
|
||||
pub scope: Scope,
|
||||
pub struct EngineState {
|
||||
pub host: Arc<parking_lot::Mutex<Box<dyn Host>>>,
|
||||
pub current_errors: Arc<Mutex<Vec<ShellError>>>,
|
||||
pub ctrl_c: Arc<AtomicBool>,
|
||||
@ -31,6 +30,11 @@ pub struct EvaluationContext {
|
||||
/// Windows-specific: keep track of previous cwd on each drive
|
||||
pub windows_drives_previous_cwd: Arc<Mutex<std::collections::HashMap<String, String>>>,
|
||||
}
|
||||
#[derive(Clone, Default)]
|
||||
pub struct EvaluationContext {
|
||||
pub scope: Scope,
|
||||
engine_state: Arc<EngineState>,
|
||||
}
|
||||
|
||||
impl EvaluationContext {
|
||||
pub fn new(
|
||||
@ -44,12 +48,14 @@ impl EvaluationContext {
|
||||
) -> Self {
|
||||
Self {
|
||||
scope,
|
||||
host,
|
||||
current_errors,
|
||||
ctrl_c,
|
||||
configs,
|
||||
shell_manager,
|
||||
windows_drives_previous_cwd,
|
||||
engine_state: Arc::new(EngineState {
|
||||
host,
|
||||
current_errors,
|
||||
ctrl_c,
|
||||
configs,
|
||||
shell_manager,
|
||||
windows_drives_previous_cwd,
|
||||
}),
|
||||
}
|
||||
}
|
||||
|
||||
@ -61,12 +67,14 @@ impl EvaluationContext {
|
||||
|
||||
EvaluationContext {
|
||||
scope,
|
||||
host: Arc::new(parking_lot::Mutex::new(Box::new(host))),
|
||||
current_errors: Arc::new(Mutex::new(vec![])),
|
||||
ctrl_c: Arc::new(AtomicBool::new(false)),
|
||||
configs: Arc::new(Mutex::new(ConfigHolder::new())),
|
||||
shell_manager: ShellManager::basic(),
|
||||
windows_drives_previous_cwd: Arc::new(Mutex::new(std::collections::HashMap::new())),
|
||||
engine_state: Arc::new(EngineState {
|
||||
host: Arc::new(parking_lot::Mutex::new(Box::new(host))),
|
||||
current_errors: Arc::new(Mutex::new(vec![])),
|
||||
ctrl_c: Arc::new(AtomicBool::new(false)),
|
||||
configs: Arc::new(Mutex::new(ConfigHolder::new())),
|
||||
shell_manager: ShellManager::basic(),
|
||||
windows_drives_previous_cwd: Arc::new(Mutex::new(std::collections::HashMap::new())),
|
||||
}),
|
||||
}
|
||||
}
|
||||
|
||||
@ -74,12 +82,38 @@ impl EvaluationContext {
|
||||
self.with_errors(|errors| errors.push(error))
|
||||
}
|
||||
|
||||
pub fn host(&self) -> &Arc<parking_lot::Mutex<Box<dyn Host>>> {
|
||||
&self.engine_state.host
|
||||
}
|
||||
|
||||
pub fn current_errors(&self) -> &Arc<Mutex<Vec<ShellError>>> {
|
||||
&self.engine_state.current_errors
|
||||
}
|
||||
|
||||
pub fn ctrl_c(&self) -> &Arc<AtomicBool> {
|
||||
&self.engine_state.ctrl_c
|
||||
}
|
||||
|
||||
pub fn configs(&self) -> &Arc<Mutex<ConfigHolder>> {
|
||||
&self.engine_state.configs
|
||||
}
|
||||
|
||||
pub fn shell_manager(&self) -> &ShellManager {
|
||||
&self.engine_state.shell_manager
|
||||
}
|
||||
|
||||
pub fn windows_drives_previous_cwd(
|
||||
&self,
|
||||
) -> &Arc<Mutex<std::collections::HashMap<String, String>>> {
|
||||
&self.engine_state.windows_drives_previous_cwd
|
||||
}
|
||||
|
||||
pub fn clear_errors(&self) {
|
||||
self.current_errors.lock().clear()
|
||||
self.engine_state.current_errors.lock().clear()
|
||||
}
|
||||
|
||||
pub fn get_errors(&self) -> Vec<ShellError> {
|
||||
self.current_errors.lock().clone()
|
||||
self.engine_state.current_errors.lock().clone()
|
||||
}
|
||||
|
||||
pub fn configure<T>(
|
||||
@ -91,13 +125,13 @@ impl EvaluationContext {
|
||||
}
|
||||
|
||||
pub fn with_host<T>(&self, block: impl FnOnce(&mut dyn Host) -> T) -> T {
|
||||
let mut host = self.host.lock();
|
||||
let mut host = self.engine_state.host.lock();
|
||||
|
||||
block(&mut *host)
|
||||
}
|
||||
|
||||
pub fn with_errors<T>(&self, block: impl FnOnce(&mut Vec<ShellError>) -> T) -> T {
|
||||
let mut errors = self.current_errors.lock();
|
||||
let mut errors = self.engine_state.current_errors.lock();
|
||||
|
||||
block(&mut *errors)
|
||||
}
|
||||
@ -209,9 +243,9 @@ impl EvaluationContext {
|
||||
self.scope.set_exit_scripts(exit_scripts);
|
||||
|
||||
match cfg_path {
|
||||
ConfigPath::Global(_) => self.configs.lock().set_global_cfg(cfg),
|
||||
ConfigPath::Global(_) => self.engine_state.configs.lock().set_global_cfg(cfg),
|
||||
ConfigPath::Local(_) => {
|
||||
self.configs.lock().add_local_cfg(cfg);
|
||||
self.engine_state.configs.lock().add_local_cfg(cfg);
|
||||
}
|
||||
}
|
||||
|
||||
@ -221,7 +255,7 @@ impl EvaluationContext {
|
||||
// folder as the config.toml
|
||||
|
||||
// Let's open the config
|
||||
let global_config = self.configs.lock().global_config();
|
||||
let global_config = self.engine_state.configs.lock().global_config();
|
||||
// Get the root syntax_theme value
|
||||
let syntax_theme = global_config.var("syntax_theme");
|
||||
// If we have a syntax_theme let's process it
|
||||
@ -246,16 +280,18 @@ impl EvaluationContext {
|
||||
let mut reader = BufReader::new(syntax_theme_file);
|
||||
let theme = ThemedPalette::new(&mut reader).unwrap_or_default();
|
||||
// eprintln!("Theme: [{:?}]", theme);
|
||||
self.configs.lock().set_syntax_colors(theme);
|
||||
self.engine_state.configs.lock().set_syntax_colors(theme);
|
||||
} else {
|
||||
// If the file was missing, use the default
|
||||
self.configs
|
||||
self.engine_state
|
||||
.configs
|
||||
.lock()
|
||||
.set_syntax_colors(ThemedPalette::default())
|
||||
}
|
||||
} else {
|
||||
// if there's no syntax_theme, use the default
|
||||
self.configs
|
||||
self.engine_state
|
||||
.configs
|
||||
.lock()
|
||||
.set_syntax_colors(ThemedPalette::default())
|
||||
};
|
||||
@ -336,7 +372,7 @@ impl EvaluationContext {
|
||||
}
|
||||
|
||||
//Unload config
|
||||
self.configs.lock().remove_cfg(cfg_path);
|
||||
self.engine_state.configs.lock().remove_cfg(cfg_path);
|
||||
self.scope.exit_scope_with_tag(&tag);
|
||||
}
|
||||
|
||||
@ -353,7 +389,7 @@ impl EvaluationContext {
|
||||
e
|
||||
));
|
||||
let text = script.into();
|
||||
self.host.lock().print_err(err, &text);
|
||||
self.engine_state.host.lock().print_err(err, &text);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -3,14 +3,14 @@ use nu_source::Text;
|
||||
use crate::EvaluationContext;
|
||||
|
||||
pub fn maybe_print_errors(context: &EvaluationContext, source: Text) -> bool {
|
||||
let errors = context.current_errors.clone();
|
||||
let errors = context.current_errors().clone();
|
||||
let mut errors = errors.lock();
|
||||
|
||||
if errors.len() > 0 {
|
||||
let error = errors[0].clone();
|
||||
*errors = vec![];
|
||||
|
||||
context.host.lock().print_err(error, &source);
|
||||
context.host().lock().print_err(error, &source);
|
||||
true
|
||||
} else {
|
||||
false
|
||||
|
@ -42,12 +42,12 @@ pub fn run_script_in_dir(
|
||||
ctx: &EvaluationContext,
|
||||
) -> Result<(), Box<dyn Error>> {
|
||||
//Save path before to switch back to it after executing script
|
||||
let path_before = ctx.shell_manager.path();
|
||||
let path_before = ctx.shell_manager().path();
|
||||
|
||||
ctx.shell_manager
|
||||
ctx.shell_manager()
|
||||
.set_path(dir.to_string_lossy().to_string());
|
||||
run_script_standalone(script, false, ctx, false)?;
|
||||
ctx.shell_manager.set_path(path_before);
|
||||
ctx.shell_manager().set_path(path_before);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
@ -118,9 +118,9 @@ pub fn process_script(
|
||||
.as_ref()
|
||||
.map(NamedArguments::is_empty)
|
||||
.unwrap_or(true)
|
||||
&& canonicalize(ctx.shell_manager.path(), name).is_ok()
|
||||
&& canonicalize(ctx.shell_manager().path(), name).is_ok()
|
||||
&& Path::new(&name).is_dir()
|
||||
&& !ctx.host.lock().is_external_cmd(name)
|
||||
&& !ctx.host().lock().is_external_cmd(name)
|
||||
{
|
||||
let tag = Tag {
|
||||
anchor: Some(AnchorLocation::Source(line.into())),
|
||||
@ -133,11 +133,11 @@ pub fn process_script(
|
||||
if name.ends_with(':') {
|
||||
// This looks like a drive shortcut. We need to a) switch drives and b) go back to the previous directory we were viewing on that drive
|
||||
// But first, we need to save where we are now
|
||||
let current_path = ctx.shell_manager.path();
|
||||
let current_path = ctx.shell_manager().path();
|
||||
|
||||
let split_path: Vec<_> = current_path.split(':').collect();
|
||||
if split_path.len() > 1 {
|
||||
ctx.windows_drives_previous_cwd
|
||||
ctx.windows_drives_previous_cwd()
|
||||
.lock()
|
||||
.insert(split_path[0].to_string(), current_path);
|
||||
}
|
||||
@ -146,7 +146,7 @@ pub fn process_script(
|
||||
let new_drive: Vec<_> = name.split(':').collect();
|
||||
|
||||
if let Some(val) =
|
||||
ctx.windows_drives_previous_cwd.lock().get(new_drive[0])
|
||||
ctx.windows_drives_previous_cwd().lock().get(new_drive[0])
|
||||
{
|
||||
val.to_string()
|
||||
} else {
|
||||
@ -169,7 +169,7 @@ pub fn process_script(
|
||||
}),
|
||||
};
|
||||
|
||||
return match ctx.shell_manager.cd(cd_args, tag) {
|
||||
return match ctx.shell_manager().cd(cd_args, tag) {
|
||||
Err(e) => LineResult::Error(line.to_string(), e),
|
||||
Ok(stream) => {
|
||||
let iter = InternalIterator {
|
||||
@ -244,7 +244,7 @@ pub fn process_script(
|
||||
..
|
||||
}) => return LineResult::Error(line.to_string(), e),
|
||||
Some(_item) => {
|
||||
if ctx.ctrl_c.load(Ordering::SeqCst) {
|
||||
if ctx.ctrl_c().load(Ordering::SeqCst) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -267,7 +267,7 @@ pub fn run_script_standalone(
|
||||
exit_on_error: bool,
|
||||
) -> Result<(), Box<dyn Error>> {
|
||||
context
|
||||
.shell_manager
|
||||
.shell_manager()
|
||||
.enter_script_mode()
|
||||
.map_err(Box::new)?;
|
||||
let line = process_script(&script_text, context, redirect_stdin, 0, false);
|
||||
@ -275,7 +275,7 @@ pub fn run_script_standalone(
|
||||
match line {
|
||||
LineResult::Success(line) => {
|
||||
let error_code = {
|
||||
let errors = context.current_errors.clone();
|
||||
let errors = context.current_errors().clone();
|
||||
let errors = errors.lock();
|
||||
|
||||
if errors.len() > 0 {
|
||||
@ -293,7 +293,7 @@ pub fn run_script_standalone(
|
||||
|
||||
LineResult::Error(line, err) => {
|
||||
context
|
||||
.host
|
||||
.host()
|
||||
.lock()
|
||||
.print_err(err, &Text::from(line.clone()));
|
||||
|
||||
@ -307,7 +307,7 @@ pub fn run_script_standalone(
|
||||
}
|
||||
|
||||
//exit script mode shell
|
||||
context.shell_manager.remove_at_current();
|
||||
context.shell_manager().remove_at_current();
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
Reference in New Issue
Block a user