mirror of
https://github.com/nushell/nushell.git
synced 2025-03-26 15:26:51 +01:00
parent
058ef69da3
commit
e5b136f70d
@ -58,7 +58,7 @@ pub fn search_paths() -> Vec<std::path::PathBuf> {
|
||||
}
|
||||
|
||||
pub fn create_default_context(interactive: bool) -> Result<EvaluationContext, Box<dyn Error>> {
|
||||
let mut context = EvaluationContext::basic()?;
|
||||
let context = EvaluationContext::basic()?;
|
||||
|
||||
{
|
||||
use crate::commands::*;
|
||||
@ -69,6 +69,7 @@ pub fn create_default_context(interactive: bool) -> Result<EvaluationContext, Bo
|
||||
whole_stream_command(Set),
|
||||
whole_stream_command(SetEnv),
|
||||
whole_stream_command(Def),
|
||||
whole_stream_command(Source),
|
||||
// System/file operations
|
||||
whole_stream_command(Exec),
|
||||
whole_stream_command(Pwd),
|
||||
@ -325,7 +326,7 @@ pub async fn run_script_file(
|
||||
|
||||
let _ = run_startup_commands(&mut context, &config).await;
|
||||
|
||||
run_script_standalone(file_contents, redirect_stdin, &mut context, true).await?;
|
||||
run_script_standalone(file_contents, redirect_stdin, &context, true).await?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
@ -497,7 +498,7 @@ pub async fn cli(mut context: EvaluationContext) -> Result<(), Box<dyn Error>> {
|
||||
LineResult::Success(_) => {
|
||||
process_script(
|
||||
&session_text[line_start..],
|
||||
&mut context,
|
||||
&context,
|
||||
false,
|
||||
line_start,
|
||||
true,
|
||||
@ -648,7 +649,7 @@ async fn run_startup_commands(
|
||||
pub async fn run_script_standalone(
|
||||
script_text: String,
|
||||
redirect_stdin: bool,
|
||||
context: &mut EvaluationContext,
|
||||
context: &EvaluationContext,
|
||||
exit_on_error: bool,
|
||||
) -> Result<(), Box<dyn Error>> {
|
||||
let line = process_script(&script_text, context, redirect_stdin, 0, false).await;
|
||||
@ -888,7 +889,7 @@ pub enum LineResult {
|
||||
ClearHistory,
|
||||
}
|
||||
|
||||
pub async fn parse_and_eval(line: &str, ctx: &mut EvaluationContext) -> Result<String, ShellError> {
|
||||
pub async fn parse_and_eval(line: &str, ctx: &EvaluationContext) -> Result<String, ShellError> {
|
||||
// FIXME: do we still need this?
|
||||
let line = if let Some(s) = line.strip_suffix('\n') {
|
||||
s
|
||||
@ -917,7 +918,7 @@ pub async fn parse_and_eval(line: &str, ctx: &mut EvaluationContext) -> Result<S
|
||||
/// Process the line by parsing the text to turn it into commands, classify those commands so that we understand what is being called in the pipeline, and then run this pipeline
|
||||
pub async fn process_script(
|
||||
script_text: &str,
|
||||
ctx: &mut EvaluationContext,
|
||||
ctx: &EvaluationContext,
|
||||
redirect_stdin: bool,
|
||||
span_offset: usize,
|
||||
cli_mode: bool,
|
||||
@ -926,7 +927,6 @@ pub async fn process_script(
|
||||
LineResult::Success(script_text.to_string())
|
||||
} else {
|
||||
let line = chomp_newline(script_text);
|
||||
ctx.raw_input = line.to_string();
|
||||
|
||||
let (block, err) = nu_parser::parse(&line, span_offset, &ctx.scope);
|
||||
|
||||
@ -1067,7 +1067,6 @@ pub async fn process_script(
|
||||
current_errors: ctx.current_errors.clone(),
|
||||
scope: ctx.scope.clone(),
|
||||
name: Tag::unknown(),
|
||||
raw_input: line.to_string(),
|
||||
};
|
||||
|
||||
if let Ok(mut output_stream) =
|
||||
|
@ -108,6 +108,7 @@ pub(crate) mod size;
|
||||
pub(crate) mod skip;
|
||||
pub(crate) mod sleep;
|
||||
pub(crate) mod sort_by;
|
||||
pub(crate) mod source;
|
||||
pub(crate) mod split;
|
||||
pub(crate) mod split_by;
|
||||
pub(crate) mod str_;
|
||||
@ -255,6 +256,7 @@ pub(crate) use size::Size;
|
||||
pub(crate) use skip::{Skip, SkipUntil, SkipWhile};
|
||||
pub(crate) use sleep::Sleep;
|
||||
pub(crate) use sort_by::SortBy;
|
||||
pub(crate) use source::Source;
|
||||
pub(crate) use split::{Split, SplitChars, SplitColumn, SplitRow};
|
||||
pub(crate) use split_by::SplitBy;
|
||||
pub(crate) use str_::{
|
||||
|
@ -35,7 +35,6 @@ impl WholeStreamCommand for Command {
|
||||
ctrl_c: args.ctrl_c,
|
||||
current_errors: args.current_errors,
|
||||
name: args.call_info.name_tag,
|
||||
raw_input: args.raw_input,
|
||||
})
|
||||
.await
|
||||
}
|
||||
|
@ -47,7 +47,7 @@ pub(crate) async fn run_internal_command(
|
||||
.then(move |item| {
|
||||
let head = head.clone();
|
||||
let command = command.clone();
|
||||
let mut context = context.clone();
|
||||
let context = context.clone();
|
||||
async move {
|
||||
match item {
|
||||
Ok(ReturnSuccess::Action(action)) => match action {
|
||||
@ -188,6 +188,29 @@ pub(crate) async fn run_internal_command(
|
||||
context.scope.add_env_var(name, value);
|
||||
InputStream::from_stream(futures::stream::iter(vec![]))
|
||||
}
|
||||
CommandAction::SourceScript(filename) => {
|
||||
let contents = std::fs::read_to_string(&filename);
|
||||
if let Ok(contents) = contents {
|
||||
let result = crate::cli::run_script_standalone(
|
||||
contents, true, &context, false,
|
||||
)
|
||||
.await;
|
||||
|
||||
if let Err(err) = result {
|
||||
return InputStream::one(
|
||||
UntaggedValue::Error(err.into()).into_untagged_value(),
|
||||
);
|
||||
}
|
||||
InputStream::from_stream(futures::stream::iter(vec![]))
|
||||
} else {
|
||||
InputStream::one(
|
||||
UntaggedValue::Error(ShellError::untagged_runtime_error(
|
||||
format!("could not source '{}'", filename),
|
||||
))
|
||||
.into_untagged_value(),
|
||||
)
|
||||
}
|
||||
}
|
||||
CommandAction::AddPlugins(path) => {
|
||||
match crate::plugin::scan(vec![std::path::PathBuf::from(path)]) {
|
||||
Ok(plugins) => {
|
||||
|
@ -43,7 +43,6 @@ pub struct CommandArgs {
|
||||
pub call_info: UnevaluatedCallInfo,
|
||||
pub scope: Scope,
|
||||
pub input: InputStream,
|
||||
pub raw_input: String,
|
||||
}
|
||||
|
||||
#[derive(Getters, Clone)]
|
||||
@ -67,7 +66,6 @@ impl RawCommandArgs {
|
||||
call_info: self.call_info,
|
||||
scope: self.scope,
|
||||
input: input.into(),
|
||||
raw_input: String::default(),
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -116,7 +114,6 @@ pub struct RunnableContext {
|
||||
pub current_errors: Arc<Mutex<Vec<ShellError>>>,
|
||||
pub scope: Scope,
|
||||
pub name: Tag,
|
||||
pub raw_input: String,
|
||||
}
|
||||
|
||||
impl RunnableContext {
|
||||
|
@ -38,7 +38,6 @@ impl WholeStreamCommand for SubCommand {
|
||||
ctrl_c: args.ctrl_c,
|
||||
current_errors: args.current_errors,
|
||||
name: args.call_info.name_tag,
|
||||
raw_input: args.raw_input,
|
||||
},
|
||||
average,
|
||||
)
|
||||
|
@ -31,7 +31,6 @@ impl WholeStreamCommand for SubCommand {
|
||||
ctrl_c: args.ctrl_c,
|
||||
current_errors: args.current_errors,
|
||||
name: args.call_info.name_tag,
|
||||
raw_input: args.raw_input,
|
||||
},
|
||||
ceil_big_int,
|
||||
ceil_big_decimal,
|
||||
|
@ -31,7 +31,6 @@ impl WholeStreamCommand for SubCommand {
|
||||
ctrl_c: args.ctrl_c,
|
||||
current_errors: args.current_errors,
|
||||
name: args.call_info.name_tag,
|
||||
raw_input: args.raw_input,
|
||||
},
|
||||
floor_big_int,
|
||||
floor_big_decimal,
|
||||
|
@ -31,7 +31,6 @@ impl WholeStreamCommand for SubCommand {
|
||||
ctrl_c: args.ctrl_c,
|
||||
current_errors: args.current_errors,
|
||||
name: args.call_info.name_tag,
|
||||
raw_input: args.raw_input,
|
||||
},
|
||||
maximum,
|
||||
)
|
||||
|
@ -35,7 +35,6 @@ impl WholeStreamCommand for SubCommand {
|
||||
ctrl_c: args.ctrl_c,
|
||||
current_errors: args.current_errors,
|
||||
name: args.call_info.name_tag,
|
||||
raw_input: args.raw_input,
|
||||
},
|
||||
median,
|
||||
)
|
||||
|
@ -31,7 +31,6 @@ impl WholeStreamCommand for SubCommand {
|
||||
ctrl_c: args.ctrl_c,
|
||||
current_errors: args.current_errors,
|
||||
name: args.call_info.name_tag,
|
||||
raw_input: args.raw_input,
|
||||
},
|
||||
minimum,
|
||||
)
|
||||
|
@ -31,7 +31,6 @@ impl WholeStreamCommand for SubCommand {
|
||||
ctrl_c: args.ctrl_c,
|
||||
current_errors: args.current_errors,
|
||||
name: args.call_info.name_tag,
|
||||
raw_input: args.raw_input,
|
||||
},
|
||||
mode,
|
||||
)
|
||||
|
@ -34,7 +34,6 @@ impl WholeStreamCommand for SubCommand {
|
||||
ctrl_c: args.ctrl_c,
|
||||
current_errors: args.current_errors,
|
||||
name: args.call_info.name_tag,
|
||||
raw_input: args.raw_input,
|
||||
},
|
||||
product,
|
||||
)
|
||||
|
@ -35,7 +35,6 @@ impl WholeStreamCommand for SubCommand {
|
||||
ctrl_c: args.ctrl_c,
|
||||
current_errors: args.current_errors,
|
||||
name: args.call_info.name_tag,
|
||||
raw_input: args.raw_input,
|
||||
},
|
||||
summation,
|
||||
)
|
||||
|
@ -88,7 +88,6 @@ impl WholeStreamCommand for RunExternalCommand {
|
||||
ctrl_c: args.ctrl_c.clone(),
|
||||
current_errors: Arc::new(Mutex::new(vec![])),
|
||||
windows_drives_previous_cwd: Arc::new(Mutex::new(std::collections::HashMap::new())),
|
||||
raw_input: String::default(),
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -165,7 +165,7 @@ async fn save(raw_args: CommandArgs) -> Result<OutputStream, ShellError> {
|
||||
let host = raw_args.host.clone();
|
||||
let ctrl_c = raw_args.ctrl_c.clone();
|
||||
let current_errors = raw_args.current_errors.clone();
|
||||
let mut shell_manager = raw_args.shell_manager.clone();
|
||||
let shell_manager = raw_args.shell_manager.clone();
|
||||
|
||||
let head = raw_args.call_info.args.head.clone();
|
||||
let (
|
||||
|
48
crates/nu-cli/src/commands/source.rs
Normal file
48
crates/nu-cli/src/commands/source.rs
Normal file
@ -0,0 +1,48 @@
|
||||
use crate::commands::WholeStreamCommand;
|
||||
use crate::prelude::*;
|
||||
|
||||
use nu_errors::ShellError;
|
||||
use nu_protocol::{CommandAction, ReturnSuccess, Signature, SyntaxShape};
|
||||
use nu_source::Tagged;
|
||||
|
||||
pub struct Source;
|
||||
|
||||
#[derive(Deserialize)]
|
||||
pub struct SourceArgs {
|
||||
pub filename: Tagged<String>,
|
||||
}
|
||||
|
||||
#[async_trait]
|
||||
impl WholeStreamCommand for Source {
|
||||
fn name(&self) -> &str {
|
||||
"source"
|
||||
}
|
||||
|
||||
fn signature(&self) -> Signature {
|
||||
Signature::build("source").required(
|
||||
"filename",
|
||||
SyntaxShape::String,
|
||||
"the filepath to the script file to source",
|
||||
)
|
||||
}
|
||||
|
||||
fn usage(&self) -> &str {
|
||||
"Runs a script file in the current context."
|
||||
}
|
||||
|
||||
async fn run(&self, args: CommandArgs) -> Result<OutputStream, ShellError> {
|
||||
source(args).await
|
||||
}
|
||||
|
||||
fn examples(&self) -> Vec<Example> {
|
||||
vec![]
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn source(args: CommandArgs) -> Result<OutputStream, ShellError> {
|
||||
let (SourceArgs { filename }, _) = args.process().await?;
|
||||
|
||||
Ok(OutputStream::one(ReturnSuccess::action(
|
||||
CommandAction::SourceScript(filename.item),
|
||||
)))
|
||||
}
|
@ -16,7 +16,6 @@ pub struct EvaluationContext {
|
||||
pub host: Arc<parking_lot::Mutex<Box<dyn Host>>>,
|
||||
pub current_errors: Arc<Mutex<Vec<ShellError>>>,
|
||||
pub ctrl_c: Arc<AtomicBool>,
|
||||
pub raw_input: String,
|
||||
pub user_recently_used_autoenv_untrust: Arc<AtomicBool>,
|
||||
pub(crate) shell_manager: ShellManager,
|
||||
|
||||
@ -34,7 +33,6 @@ impl EvaluationContext {
|
||||
shell_manager: raw_args.shell_manager.clone(),
|
||||
user_recently_used_autoenv_untrust: Arc::new(AtomicBool::new(false)),
|
||||
windows_drives_previous_cwd: Arc::new(Mutex::new(std::collections::HashMap::new())),
|
||||
raw_input: String::default(),
|
||||
}
|
||||
}
|
||||
|
||||
@ -47,7 +45,6 @@ impl EvaluationContext {
|
||||
shell_manager: args.shell_manager.clone(),
|
||||
user_recently_used_autoenv_untrust: Arc::new(AtomicBool::new(false)),
|
||||
windows_drives_previous_cwd: Arc::new(Mutex::new(std::collections::HashMap::new())),
|
||||
raw_input: String::default(),
|
||||
}
|
||||
}
|
||||
|
||||
@ -62,7 +59,6 @@ impl EvaluationContext {
|
||||
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())),
|
||||
raw_input: String::default(),
|
||||
})
|
||||
}
|
||||
|
||||
@ -82,7 +78,7 @@ impl EvaluationContext {
|
||||
self.current_errors.lock().push(err);
|
||||
}
|
||||
|
||||
pub(crate) fn maybe_print_errors(&mut self, source: Text) -> bool {
|
||||
pub(crate) fn maybe_print_errors(&self, source: Text) -> bool {
|
||||
let errors = self.current_errors.clone();
|
||||
let mut errors = errors.lock();
|
||||
|
||||
@ -105,7 +101,7 @@ impl EvaluationContext {
|
||||
block(config, &mut *self);
|
||||
}
|
||||
|
||||
pub(crate) fn with_host<T>(&mut self, block: impl FnOnce(&mut dyn Host) -> T) -> T {
|
||||
pub(crate) fn with_host<T>(&self, block: impl FnOnce(&mut dyn Host) -> T) -> T {
|
||||
let mut host = self.host.lock();
|
||||
|
||||
block(&mut *host)
|
||||
@ -117,7 +113,7 @@ impl EvaluationContext {
|
||||
block(&mut *errors)
|
||||
}
|
||||
|
||||
pub fn add_commands(&mut self, commands: Vec<Command>) {
|
||||
pub fn add_commands(&self, commands: Vec<Command>) {
|
||||
for command in commands {
|
||||
self.scope.add_command(command.name().to_string(), command);
|
||||
}
|
||||
@ -156,7 +152,6 @@ impl EvaluationContext {
|
||||
call_info: self.call_info(args, name_tag),
|
||||
scope: self.scope.clone(),
|
||||
input,
|
||||
raw_input: self.raw_input.clone(),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -26,7 +26,7 @@ use serde::Deserialize;
|
||||
pub fn test_examples(cmd: Command) -> Result<(), ShellError> {
|
||||
let examples = cmd.examples();
|
||||
|
||||
let mut base_context = EvaluationContext::basic()?;
|
||||
let base_context = EvaluationContext::basic()?;
|
||||
|
||||
base_context.add_commands(vec![
|
||||
// Mocks
|
||||
@ -89,7 +89,7 @@ pub fn test_examples(cmd: Command) -> Result<(), ShellError> {
|
||||
pub fn test(cmd: impl WholeStreamCommand + 'static) -> Result<(), ShellError> {
|
||||
let examples = cmd.examples();
|
||||
|
||||
let mut base_context = EvaluationContext::basic()?;
|
||||
let base_context = EvaluationContext::basic()?;
|
||||
|
||||
base_context.add_commands(vec![
|
||||
whole_stream_command(Echo {}),
|
||||
@ -144,7 +144,7 @@ pub fn test(cmd: impl WholeStreamCommand + 'static) -> Result<(), ShellError> {
|
||||
pub fn test_anchors(cmd: Command) -> Result<(), ShellError> {
|
||||
let examples = cmd.examples();
|
||||
|
||||
let mut base_context = EvaluationContext::basic()?;
|
||||
let base_context = EvaluationContext::basic()?;
|
||||
|
||||
base_context.add_commands(vec![
|
||||
// Minimal restricted commands to aid in testing
|
||||
@ -192,7 +192,7 @@ pub fn test_anchors(cmd: Command) -> Result<(), ShellError> {
|
||||
}
|
||||
|
||||
/// Parse and run a nushell pipeline
|
||||
fn parse_line(line: &str, ctx: &mut EvaluationContext) -> Result<ClassifiedBlock, ShellError> {
|
||||
fn parse_line(line: &str, ctx: &EvaluationContext) -> Result<ClassifiedBlock, ShellError> {
|
||||
//FIXME: do we still need this?
|
||||
let line = if let Some(line) = line.strip_suffix('\n') {
|
||||
line
|
||||
|
@ -33,7 +33,7 @@ impl ShellManager {
|
||||
})
|
||||
}
|
||||
|
||||
pub fn insert_at_current(&mut self, shell: Box<dyn Shell + Send>) {
|
||||
pub fn insert_at_current(&self, shell: Box<dyn Shell + Send>) {
|
||||
self.shells.lock().push(shell);
|
||||
self.current_shell
|
||||
.store(self.shells.lock().len() - 1, Ordering::SeqCst);
|
||||
@ -44,7 +44,7 @@ impl ShellManager {
|
||||
self.current_shell.load(Ordering::SeqCst)
|
||||
}
|
||||
|
||||
pub fn remove_at_current(&mut self) {
|
||||
pub fn remove_at_current(&self) {
|
||||
{
|
||||
let mut shells = self.shells.lock();
|
||||
if shells.len() > 0 {
|
||||
@ -78,7 +78,7 @@ impl ShellManager {
|
||||
env[self.current_shell()].pwd(args)
|
||||
}
|
||||
|
||||
pub fn set_path(&mut self, path: String) {
|
||||
pub fn set_path(&self, path: String) {
|
||||
self.shells.lock()[self.current_shell()].set_path(path)
|
||||
}
|
||||
|
||||
@ -93,7 +93,7 @@ impl ShellManager {
|
||||
}
|
||||
|
||||
pub fn save(
|
||||
&mut self,
|
||||
&self,
|
||||
full_path: &PathBuf,
|
||||
save_data: &[u8],
|
||||
name: Span,
|
||||
@ -101,7 +101,7 @@ impl ShellManager {
|
||||
self.shells.lock()[self.current_shell()].save(full_path, save_data, name)
|
||||
}
|
||||
|
||||
pub fn next(&mut self) {
|
||||
pub fn next(&self) {
|
||||
{
|
||||
let shell_len = self.shells.lock().len();
|
||||
if self.current_shell() == (shell_len - 1) {
|
||||
@ -114,7 +114,7 @@ impl ShellManager {
|
||||
self.set_path(self.path())
|
||||
}
|
||||
|
||||
pub fn prev(&mut self) {
|
||||
pub fn prev(&self) {
|
||||
{
|
||||
let shell_len = self.shells.lock().len();
|
||||
if self.current_shell() == 0 {
|
||||
|
@ -26,6 +26,8 @@ pub enum CommandAction {
|
||||
AddEnvVariable(String, String),
|
||||
/// Add plugins from path given
|
||||
AddPlugins(String),
|
||||
/// Run the given script in the current context (given filename)
|
||||
SourceScript(String),
|
||||
/// Go to the previous shell in the shell ring buffer
|
||||
PreviousShell,
|
||||
/// Go to the next shell in the shell ring buffer
|
||||
@ -49,6 +51,7 @@ impl PrettyDebug for CommandAction {
|
||||
CommandAction::EnterHelpShell(v) => b::typed("enter help shell", v.pretty()),
|
||||
CommandAction::AddVariable(..) => b::description("add variable"),
|
||||
CommandAction::AddEnvVariable(..) => b::description("add environment variable"),
|
||||
CommandAction::SourceScript(..) => b::description("source script"),
|
||||
CommandAction::AddPlugins(..) => b::description("add plugins"),
|
||||
CommandAction::PreviousShell => b::description("previous shell"),
|
||||
CommandAction::NextShell => b::description("next shell"),
|
||||
|
Loading…
Reference in New Issue
Block a user