forked from extern/nushell
History, more test coverage improvements, and refactorings. (#3217)
Improvements overall to Nu. Also among the changes here, we can also be more confident towards incorporating `3041`. End to end tests for checking envs properly exported to externals is not added here (since it's in the other PR) A few things added in this PR (probably forgetting some too) * no writes happen to history during test runs. * environment syncing end to end coverage added. * clean up / refactorings few areas. * testing API for finer control (can write tests passing more than one pipeline) * can pass environment variables in tests that nu will inherit when running. * No longer needed. * no longer under a module. No need to use super.
This commit is contained in:
committed by
GitHub
parent
b243b3ee1d
commit
8fc8fc89aa
@ -1,20 +0,0 @@
|
||||
use crate::basic_shell_manager;
|
||||
use crate::env::basic_host::BasicHost;
|
||||
use crate::EvaluationContext;
|
||||
use crate::Scope;
|
||||
use parking_lot::Mutex;
|
||||
use std::error::Error;
|
||||
use std::sync::atomic::AtomicBool;
|
||||
use std::sync::Arc;
|
||||
|
||||
pub fn basic_evaluation_context() -> Result<EvaluationContext, Box<dyn Error>> {
|
||||
Ok(EvaluationContext {
|
||||
scope: Scope::new(),
|
||||
host: Arc::new(parking_lot::Mutex::new(Box::new(BasicHost))),
|
||||
current_errors: Arc::new(Mutex::new(vec![])),
|
||||
ctrl_c: Arc::new(AtomicBool::new(false)),
|
||||
user_recently_used_autoenv_untrust: Arc::new(AtomicBool::new(false)),
|
||||
shell_manager: basic_shell_manager::basic_shell_manager()?,
|
||||
windows_drives_previous_cwd: Arc::new(Mutex::new(std::collections::HashMap::new())),
|
||||
})
|
||||
}
|
@ -1,14 +0,0 @@
|
||||
use crate::filesystem::filesystem_shell::FilesystemShell;
|
||||
use crate::shell::shell_manager::ShellManager;
|
||||
|
||||
use parking_lot::Mutex;
|
||||
use std::error::Error;
|
||||
use std::sync::atomic::AtomicUsize;
|
||||
use std::sync::Arc;
|
||||
|
||||
pub fn basic_shell_manager() -> Result<ShellManager, Box<dyn Error>> {
|
||||
Ok(ShellManager {
|
||||
current_shell: Arc::new(AtomicUsize::new(0)),
|
||||
shells: Arc::new(Mutex::new(vec![Box::new(FilesystemShell::basic()?)])),
|
||||
})
|
||||
}
|
28
crates/nu-engine/src/env/basic_host.rs
vendored
28
crates/nu-engine/src/env/basic_host.rs
vendored
@ -7,6 +7,21 @@ use std::ffi::OsString;
|
||||
#[derive(Debug)]
|
||||
pub struct BasicHost;
|
||||
|
||||
pub fn print_err(err: ShellError, source: &Text) {
|
||||
if let Some(diag) = err.into_diagnostic() {
|
||||
let source = source.to_string();
|
||||
let mut files = codespan_reporting::files::SimpleFiles::new();
|
||||
files.add("shell", source);
|
||||
|
||||
let writer = termcolor::StandardStream::stderr(termcolor::ColorChoice::Auto);
|
||||
let config = codespan_reporting::term::Config::default();
|
||||
|
||||
let _ = std::panic::catch_unwind(move || {
|
||||
let _ = codespan_reporting::term::emit(&mut writer.lock(), &config, &files, &diag);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
impl Host for BasicHost {
|
||||
fn stdout(&mut self, out: &str) {
|
||||
match out {
|
||||
@ -23,18 +38,7 @@ impl Host for BasicHost {
|
||||
}
|
||||
|
||||
fn print_err(&mut self, err: ShellError, source: &Text) {
|
||||
if let Some(diag) = err.into_diagnostic() {
|
||||
let source = source.to_string();
|
||||
let mut files = codespan_reporting::files::SimpleFiles::new();
|
||||
files.add("shell", source);
|
||||
|
||||
let writer = termcolor::StandardStream::stderr(termcolor::ColorChoice::Auto);
|
||||
let config = codespan_reporting::term::Config::default();
|
||||
|
||||
let _ = std::panic::catch_unwind(move || {
|
||||
let _ = codespan_reporting::term::emit(&mut writer.lock(), &config, &files, &diag);
|
||||
});
|
||||
}
|
||||
print_err(err, source);
|
||||
}
|
||||
|
||||
#[allow(unused_variables)]
|
||||
|
@ -1,13 +1,24 @@
|
||||
use crate::evaluate::scope::Scope;
|
||||
use crate::history_path::history_path;
|
||||
use nu_data::config::NuConfig;
|
||||
use nu_errors::ShellError;
|
||||
use nu_protocol::{Primitive, TaggedDictBuilder, UntaggedValue, Value};
|
||||
use nu_source::Tag;
|
||||
|
||||
pub fn nu(scope: &Scope, tag: impl Into<Tag>) -> Result<Value, ShellError> {
|
||||
let env = &scope.get_env_vars();
|
||||
let tag = tag.into();
|
||||
|
||||
let env = &scope.get_env_vars();
|
||||
|
||||
let config = if let Some(Value {
|
||||
value: UntaggedValue::Primitive(Primitive::FilePath(path)),
|
||||
..
|
||||
}) = scope.get_var("config-path")
|
||||
{
|
||||
NuConfig::with(Some(path).map(|p| p.into_os_string()))
|
||||
} else {
|
||||
NuConfig::new()
|
||||
};
|
||||
|
||||
let mut nu_dict = TaggedDictBuilder::new(&tag);
|
||||
|
||||
let mut dict = TaggedDictBuilder::new(&tag);
|
||||
@ -18,16 +29,10 @@ pub fn nu(scope: &Scope, tag: impl Into<Tag>) -> Result<Value, ShellError> {
|
||||
}
|
||||
nu_dict.insert_value("env", dict.into_value());
|
||||
|
||||
let config_file = match scope.get_var("config-path") {
|
||||
Some(Value {
|
||||
value: UntaggedValue::Primitive(Primitive::FilePath(path)),
|
||||
..
|
||||
}) => Some(path),
|
||||
_ => None,
|
||||
};
|
||||
|
||||
let config = nu_data::config::read(&tag, &config_file)?;
|
||||
nu_dict.insert_value("config", UntaggedValue::row(config).into_value(&tag));
|
||||
nu_dict.insert_value(
|
||||
"config",
|
||||
UntaggedValue::row(config.vars.clone()).into_value(&tag),
|
||||
);
|
||||
|
||||
let mut table = vec![];
|
||||
for v in env.iter() {
|
||||
@ -49,15 +54,9 @@ pub fn nu(scope: &Scope, tag: impl Into<Tag>) -> Result<Value, ShellError> {
|
||||
let temp = std::env::temp_dir();
|
||||
nu_dict.insert_value("temp-dir", UntaggedValue::filepath(temp).into_value(&tag));
|
||||
|
||||
let config = if let Some(path) = config_file {
|
||||
path
|
||||
} else {
|
||||
nu_data::config::default_path()?
|
||||
};
|
||||
|
||||
nu_dict.insert_value(
|
||||
"config-path",
|
||||
UntaggedValue::filepath(config).into_value(&tag),
|
||||
UntaggedValue::filepath(nu_data::config::path::source_file(&config)).into_value(&tag),
|
||||
);
|
||||
|
||||
#[cfg(feature = "rustyline-support")]
|
||||
@ -69,11 +68,9 @@ pub fn nu(scope: &Scope, tag: impl Into<Tag>) -> Result<Value, ShellError> {
|
||||
);
|
||||
}
|
||||
|
||||
let config: Box<dyn nu_data::config::Conf> = Box::new(nu_data::config::NuConfig::new());
|
||||
let history = history_path(&config);
|
||||
nu_dict.insert_value(
|
||||
"history-path",
|
||||
UntaggedValue::filepath(history).into_value(&tag),
|
||||
UntaggedValue::filepath(nu_data::config::path::history(&config)).into_value(&tag),
|
||||
);
|
||||
|
||||
Ok(nu_dict.into_value())
|
||||
|
@ -1,13 +1,13 @@
|
||||
use crate::call_info::UnevaluatedCallInfo;
|
||||
use crate::command_args::CommandArgs;
|
||||
use crate::env::host::Host;
|
||||
use crate::env::{basic_host::BasicHost, host::Host};
|
||||
use crate::evaluate::scope::Scope;
|
||||
use crate::shell::shell_manager::ShellManager;
|
||||
use crate::whole_stream_command::Command;
|
||||
use indexmap::IndexMap;
|
||||
use nu_errors::ShellError;
|
||||
use nu_protocol::hir;
|
||||
use nu_source::Tag;
|
||||
use nu_source::{Tag, Text};
|
||||
use nu_stream::{InputStream, OutputStream};
|
||||
use parking_lot::Mutex;
|
||||
use std::sync::atomic::AtomicBool;
|
||||
@ -27,6 +27,18 @@ pub struct EvaluationContext {
|
||||
}
|
||||
|
||||
impl EvaluationContext {
|
||||
pub fn basic() -> Result<EvaluationContext, ShellError> {
|
||||
Ok(EvaluationContext {
|
||||
scope: Scope::new(),
|
||||
host: Arc::new(parking_lot::Mutex::new(Box::new(BasicHost))),
|
||||
current_errors: Arc::new(Mutex::new(vec![])),
|
||||
ctrl_c: Arc::new(AtomicBool::new(false)),
|
||||
user_recently_used_autoenv_untrust: Arc::new(AtomicBool::new(false)),
|
||||
shell_manager: ShellManager::basic()?,
|
||||
windows_drives_previous_cwd: Arc::new(Mutex::new(std::collections::HashMap::new())),
|
||||
})
|
||||
}
|
||||
|
||||
pub fn from_args(args: &CommandArgs) -> EvaluationContext {
|
||||
EvaluationContext {
|
||||
scope: args.scope.clone(),
|
||||
@ -121,3 +133,18 @@ impl EvaluationContext {
|
||||
output
|
||||
}
|
||||
}
|
||||
|
||||
pub fn maybe_print_errors(context: &EvaluationContext, source: Text) -> bool {
|
||||
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);
|
||||
true
|
||||
} else {
|
||||
false
|
||||
}
|
||||
}
|
||||
|
@ -1,22 +0,0 @@
|
||||
use nu_data::config::Conf;
|
||||
use std::path::PathBuf;
|
||||
|
||||
const DEFAULT_LOCATION: &str = "history.txt";
|
||||
|
||||
pub fn history_path(config: &dyn Conf) -> PathBuf {
|
||||
let default_path = nu_data::config::user_data()
|
||||
.map(|mut p| {
|
||||
p.push(DEFAULT_LOCATION);
|
||||
p
|
||||
})
|
||||
.unwrap_or_else(|_| PathBuf::from(DEFAULT_LOCATION));
|
||||
|
||||
config
|
||||
.var("history-path")
|
||||
.map_or(default_path.clone(), |custom_path| {
|
||||
match custom_path.as_string() {
|
||||
Ok(path) => PathBuf::from(path),
|
||||
Err(_) => default_path,
|
||||
}
|
||||
})
|
||||
}
|
@ -1,25 +1,19 @@
|
||||
pub mod basic_evaluation_context;
|
||||
pub mod basic_shell_manager;
|
||||
mod call_info;
|
||||
mod command_args;
|
||||
pub mod deserializer;
|
||||
pub mod documentation;
|
||||
mod env;
|
||||
mod evaluate;
|
||||
mod evaluation_context;
|
||||
pub mod evaluation_context;
|
||||
mod example;
|
||||
pub mod filesystem;
|
||||
mod history_path;
|
||||
mod maybe_text_codec;
|
||||
pub mod plugin;
|
||||
pub mod print;
|
||||
mod runnable_context;
|
||||
pub mod script;
|
||||
pub mod shell;
|
||||
mod whole_stream_command;
|
||||
|
||||
pub use crate::basic_evaluation_context::basic_evaluation_context;
|
||||
pub use crate::basic_shell_manager::basic_shell_manager;
|
||||
pub use crate::call_info::UnevaluatedCallInfo;
|
||||
pub use crate::command_args::{
|
||||
CommandArgs, EvaluatedCommandArgs, EvaluatedWholeStreamCommandArgs, RawCommandArgs,
|
||||
@ -36,7 +30,6 @@ pub use crate::example::Example;
|
||||
pub use crate::filesystem::dir_info::{DirBuilder, DirInfo, FileInfo};
|
||||
pub use crate::filesystem::filesystem_shell::FilesystemShell;
|
||||
pub use crate::filesystem::path;
|
||||
pub use crate::history_path::history_path;
|
||||
pub use crate::maybe_text_codec::{MaybeTextCodec, StringOrBinary};
|
||||
pub use crate::runnable_context::RunnableContext;
|
||||
pub use crate::shell::help_shell::{command_dict, HelpShell};
|
||||
|
@ -1,18 +0,0 @@
|
||||
use nu_source::Text;
|
||||
|
||||
use crate::EvaluationContext;
|
||||
|
||||
pub fn maybe_print_errors(context: &EvaluationContext, source: Text) -> bool {
|
||||
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);
|
||||
true
|
||||
} else {
|
||||
false
|
||||
}
|
||||
}
|
@ -1,5 +1,5 @@
|
||||
use crate::path::canonicalize;
|
||||
use crate::run_block;
|
||||
use crate::{path::canonicalize, print::maybe_print_errors};
|
||||
use crate::{MaybeTextCodec, StringOrBinary};
|
||||
use futures::StreamExt;
|
||||
use futures_codec::FramedRead;
|
||||
@ -11,7 +11,7 @@ use nu_protocol::hir::{
|
||||
use nu_protocol::{Primitive, ReturnSuccess, UntaggedValue, Value};
|
||||
use nu_stream::{InputStream, ToInputStream};
|
||||
|
||||
use crate::EvaluationContext;
|
||||
use crate::{evaluation_context, EvaluationContext};
|
||||
use log::{debug, trace};
|
||||
use nu_source::{Span, Tag, Text};
|
||||
use std::iter::Iterator;
|
||||
@ -244,19 +244,16 @@ pub async fn run_script_standalone(
|
||||
}
|
||||
};
|
||||
|
||||
maybe_print_errors(&context, Text::from(line));
|
||||
evaluation_context::maybe_print_errors(&context, Text::from(line));
|
||||
if error_code != 0 && exit_on_error {
|
||||
std::process::exit(error_code);
|
||||
}
|
||||
}
|
||||
|
||||
LineResult::Error(line, err) => {
|
||||
context
|
||||
.host
|
||||
.lock()
|
||||
.print_err(err, &Text::from(line.clone()));
|
||||
context.with_host(|host| host.print_err(err, &Text::from(line.clone())));
|
||||
|
||||
maybe_print_errors(&context, Text::from(line));
|
||||
evaluation_context::maybe_print_errors(&context, Text::from(line));
|
||||
if exit_on_error {
|
||||
std::process::exit(1);
|
||||
}
|
||||
|
@ -1,10 +1,12 @@
|
||||
use crate::command_args::EvaluatedWholeStreamCommandArgs;
|
||||
use crate::maybe_text_codec::StringOrBinary;
|
||||
use crate::shell::Shell;
|
||||
use futures::Stream;
|
||||
use nu_stream::OutputStream;
|
||||
|
||||
use crate::filesystem::filesystem_shell::FilesystemShell;
|
||||
use crate::shell::shell_args::{CdArgs, CopyArgs, LsArgs, MkdirArgs, MvArgs, RemoveArgs};
|
||||
use crate::shell::Shell;
|
||||
|
||||
use encoding_rs::Encoding;
|
||||
use nu_errors::ShellError;
|
||||
use nu_source::{Span, Tag};
|
||||
@ -20,6 +22,13 @@ pub struct ShellManager {
|
||||
}
|
||||
|
||||
impl ShellManager {
|
||||
pub fn basic() -> Result<Self, ShellError> {
|
||||
Ok(ShellManager {
|
||||
current_shell: Arc::new(AtomicUsize::new(0)),
|
||||
shells: Arc::new(Mutex::new(vec![Box::new(FilesystemShell::basic()?)])),
|
||||
})
|
||||
}
|
||||
|
||||
pub fn insert_at_current(&self, shell: Box<dyn Shell + Send>) {
|
||||
self.shells.lock().push(shell);
|
||||
self.current_shell
|
||||
|
Reference in New Issue
Block a user