mirror of
https://github.com/nushell/nushell.git
synced 2024-11-29 03:44:19 +01:00
Refactor scope (#2602)
* Refactor scope to have parents * Refactor scope to have parents * Refactor scope to have parents * Clippy Co-authored-by: Jonathan Turner <jonathan@pop-os.localdomain>
This commit is contained in:
parent
9dc88f8a95
commit
cb7723f423
@ -9,7 +9,7 @@ use crate::EnvironmentSyncer;
|
|||||||
use futures_codec::FramedRead;
|
use futures_codec::FramedRead;
|
||||||
use nu_errors::ShellError;
|
use nu_errors::ShellError;
|
||||||
use nu_protocol::hir::{ClassifiedCommand, Expression, InternalCommand, Literal, NamedArguments};
|
use nu_protocol::hir::{ClassifiedCommand, Expression, InternalCommand, Literal, NamedArguments};
|
||||||
use nu_protocol::{Primitive, ReturnSuccess, UntaggedValue, Value};
|
use nu_protocol::{Primitive, ReturnSuccess, Scope, UntaggedValue, Value};
|
||||||
|
|
||||||
use log::{debug, trace};
|
use log::{debug, trace};
|
||||||
#[cfg(feature = "rustyline-support")]
|
#[cfg(feature = "rustyline-support")]
|
||||||
@ -395,9 +395,7 @@ pub async fn cli(mut context: EvaluationContext) -> Result<(), Box<dyn Error>> {
|
|||||||
&prompt_block.block,
|
&prompt_block.block,
|
||||||
&mut context,
|
&mut context,
|
||||||
InputStream::empty(),
|
InputStream::empty(),
|
||||||
&Value::nothing(),
|
Scope::from_env(env),
|
||||||
&IndexMap::new(),
|
|
||||||
&env,
|
|
||||||
)
|
)
|
||||||
.await
|
.await
|
||||||
{
|
{
|
||||||
@ -862,9 +860,7 @@ pub async fn parse_and_eval(line: &str, ctx: &mut EvaluationContext) -> Result<S
|
|||||||
&classified_block.block,
|
&classified_block.block,
|
||||||
ctx,
|
ctx,
|
||||||
input_stream,
|
input_stream,
|
||||||
&Value::nothing(),
|
Scope::from_env(env),
|
||||||
&IndexMap::new(),
|
|
||||||
&env,
|
|
||||||
)
|
)
|
||||||
.await?
|
.await?
|
||||||
.collect_string(Tag::unknown())
|
.collect_string(Tag::unknown())
|
||||||
@ -1021,9 +1017,7 @@ pub async fn process_line(
|
|||||||
&classified_block.block,
|
&classified_block.block,
|
||||||
ctx,
|
ctx,
|
||||||
input_stream,
|
input_stream,
|
||||||
&Value::nothing(),
|
Scope::from_env(env),
|
||||||
&IndexMap::new(),
|
|
||||||
&env,
|
|
||||||
)
|
)
|
||||||
.await
|
.await
|
||||||
{
|
{
|
||||||
|
@ -318,7 +318,7 @@ fn create_default_command_args(context: &RunnableContextWithoutInput) -> RawComm
|
|||||||
external_redirection: ExternalRedirection::Stdout,
|
external_redirection: ExternalRedirection::Stdout,
|
||||||
},
|
},
|
||||||
name_tag: context.name.clone(),
|
name_tag: context.name.clone(),
|
||||||
scope: Scope::new(),
|
scope: Scope::create(),
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -83,16 +83,18 @@ async fn benchmark(
|
|||||||
let scope = raw_args.call_info.scope.clone();
|
let scope = raw_args.call_info.scope.clone();
|
||||||
let (BenchmarkArgs { block, passthrough }, input) = raw_args.process(®istry).await?;
|
let (BenchmarkArgs { block, passthrough }, input) = raw_args.process(®istry).await?;
|
||||||
|
|
||||||
let mut env = scope.env.clone();
|
let env = scope.env();
|
||||||
let name = generate_free_name(&env);
|
let name = generate_free_name(&env);
|
||||||
|
let mut env = IndexMap::new();
|
||||||
env.insert(name, generate_random_env_value());
|
env.insert(name, generate_random_env_value());
|
||||||
|
let scope = Scope::append_env(scope, env);
|
||||||
|
|
||||||
let start_time = Instant::now();
|
let start_time = Instant::now();
|
||||||
|
|
||||||
#[cfg(feature = "rich-benchmark")]
|
#[cfg(feature = "rich-benchmark")]
|
||||||
let start = time().await;
|
let start = time().await;
|
||||||
|
|
||||||
let result = run_block(&block, &mut context, input, &scope.it, &scope.vars, &env).await;
|
let result = run_block(&block, &mut context, input, scope.clone()).await;
|
||||||
let output = result?.into_vec().await;
|
let output = result?.into_vec().await;
|
||||||
|
|
||||||
#[cfg(feature = "rich-benchmark")]
|
#[cfg(feature = "rich-benchmark")]
|
||||||
@ -108,7 +110,7 @@ async fn benchmark(
|
|||||||
|
|
||||||
let real_time = into_big_int(end_time - start_time);
|
let real_time = into_big_int(end_time - start_time);
|
||||||
indexmap.insert("real time".to_string(), real_time);
|
indexmap.insert("real time".to_string(), real_time);
|
||||||
benchmark_output(indexmap, output, passthrough, &tag, &mut context, &scope).await
|
benchmark_output(indexmap, output, passthrough, &tag, &mut context, scope).await
|
||||||
}
|
}
|
||||||
// return advanced stats
|
// return advanced stats
|
||||||
#[cfg(feature = "rich-benchmark")]
|
#[cfg(feature = "rich-benchmark")]
|
||||||
@ -127,7 +129,7 @@ async fn benchmark(
|
|||||||
let idle_time = into_big_int(end.idle() - start.idle());
|
let idle_time = into_big_int(end.idle() - start.idle());
|
||||||
indexmap.insert("idle time".to_string(), idle_time);
|
indexmap.insert("idle time".to_string(), idle_time);
|
||||||
|
|
||||||
benchmark_output(indexmap, output, passthrough, &tag, &mut context, &scope).await
|
benchmark_output(indexmap, output, passthrough, &tag, &mut context, scope).await
|
||||||
} else {
|
} else {
|
||||||
Err(ShellError::untagged_runtime_error(
|
Err(ShellError::untagged_runtime_error(
|
||||||
"Could not retreive CPU time",
|
"Could not retreive CPU time",
|
||||||
@ -141,7 +143,7 @@ async fn benchmark_output<T, Output>(
|
|||||||
passthrough: Option<Block>,
|
passthrough: Option<Block>,
|
||||||
tag: T,
|
tag: T,
|
||||||
context: &mut EvaluationContext,
|
context: &mut EvaluationContext,
|
||||||
scope: &Scope,
|
scope: Arc<Scope>,
|
||||||
) -> Result<OutputStream, ShellError>
|
) -> Result<OutputStream, ShellError>
|
||||||
where
|
where
|
||||||
T: Into<Tag> + Copy,
|
T: Into<Tag> + Copy,
|
||||||
@ -161,15 +163,7 @@ where
|
|||||||
// add autoview for an empty block
|
// add autoview for an empty block
|
||||||
let time_block = add_implicit_autoview(time_block);
|
let time_block = add_implicit_autoview(time_block);
|
||||||
|
|
||||||
let _ = run_block(
|
let _ = run_block(&time_block, context, benchmark_output, scope).await?;
|
||||||
&time_block,
|
|
||||||
context,
|
|
||||||
benchmark_output,
|
|
||||||
&scope.it,
|
|
||||||
&scope.vars,
|
|
||||||
&scope.env,
|
|
||||||
)
|
|
||||||
.await?;
|
|
||||||
context.clear_errors();
|
context.clear_errors();
|
||||||
|
|
||||||
Ok(block_output.into())
|
Ok(block_output.into())
|
||||||
|
@ -6,16 +6,14 @@ use crate::stream::InputStream;
|
|||||||
use futures::stream::TryStreamExt;
|
use futures::stream::TryStreamExt;
|
||||||
use nu_errors::ShellError;
|
use nu_errors::ShellError;
|
||||||
use nu_protocol::hir::{Block, ClassifiedCommand, Commands};
|
use nu_protocol::hir::{Block, ClassifiedCommand, Commands};
|
||||||
use nu_protocol::{ReturnSuccess, UntaggedValue, Value};
|
use nu_protocol::{ReturnSuccess, Scope, UntaggedValue, Value};
|
||||||
use std::sync::atomic::Ordering;
|
use std::sync::atomic::Ordering;
|
||||||
|
|
||||||
pub(crate) async fn run_block(
|
pub(crate) async fn run_block(
|
||||||
block: &Block,
|
block: &Block,
|
||||||
ctx: &mut EvaluationContext,
|
ctx: &mut EvaluationContext,
|
||||||
mut input: InputStream,
|
mut input: InputStream,
|
||||||
it: &Value,
|
scope: Arc<Scope>,
|
||||||
vars: &IndexMap<String, Value>,
|
|
||||||
env: &IndexMap<String, String>,
|
|
||||||
) -> Result<InputStream, ShellError> {
|
) -> Result<InputStream, ShellError> {
|
||||||
let mut output: Result<InputStream, ShellError> = Ok(InputStream::empty());
|
let mut output: Result<InputStream, ShellError> = Ok(InputStream::empty());
|
||||||
for pipeline in &block.block {
|
for pipeline in &block.block {
|
||||||
@ -54,7 +52,7 @@ pub(crate) async fn run_block(
|
|||||||
return Err(e);
|
return Err(e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
output = run_pipeline(pipeline, ctx, input, it, vars, env).await;
|
output = run_pipeline(pipeline, ctx, input, scope.clone()).await;
|
||||||
|
|
||||||
input = InputStream::empty();
|
input = InputStream::empty();
|
||||||
}
|
}
|
||||||
@ -66,9 +64,7 @@ async fn run_pipeline(
|
|||||||
commands: &Commands,
|
commands: &Commands,
|
||||||
ctx: &mut EvaluationContext,
|
ctx: &mut EvaluationContext,
|
||||||
mut input: InputStream,
|
mut input: InputStream,
|
||||||
it: &Value,
|
scope: Arc<Scope>,
|
||||||
vars: &IndexMap<String, Value>,
|
|
||||||
env: &IndexMap<String, String>,
|
|
||||||
) -> Result<InputStream, ShellError> {
|
) -> Result<InputStream, ShellError> {
|
||||||
for item in commands.list.clone() {
|
for item in commands.list.clone() {
|
||||||
input = match item {
|
input = match item {
|
||||||
@ -77,13 +73,13 @@ async fn run_pipeline(
|
|||||||
}
|
}
|
||||||
|
|
||||||
ClassifiedCommand::Expr(expr) => {
|
ClassifiedCommand::Expr(expr) => {
|
||||||
run_expression_block(*expr, ctx, it, vars, env).await?
|
run_expression_block(*expr, ctx, scope.clone()).await?
|
||||||
}
|
}
|
||||||
|
|
||||||
ClassifiedCommand::Error(err) => return Err(err.into()),
|
ClassifiedCommand::Error(err) => return Err(err.into()),
|
||||||
|
|
||||||
ClassifiedCommand::Internal(left) => {
|
ClassifiedCommand::Internal(left) => {
|
||||||
run_internal_command(left, ctx, input, it, vars, env).await?
|
run_internal_command(left, ctx, input, scope.clone()).await?
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -6,14 +6,12 @@ use log::{log_enabled, trace};
|
|||||||
use futures::stream::once;
|
use futures::stream::once;
|
||||||
use nu_errors::ShellError;
|
use nu_errors::ShellError;
|
||||||
use nu_protocol::hir::SpannedExpression;
|
use nu_protocol::hir::SpannedExpression;
|
||||||
use nu_protocol::Value;
|
use nu_protocol::Scope;
|
||||||
|
|
||||||
pub(crate) async fn run_expression_block(
|
pub(crate) async fn run_expression_block(
|
||||||
expr: SpannedExpression,
|
expr: SpannedExpression,
|
||||||
context: &mut EvaluationContext,
|
context: &mut EvaluationContext,
|
||||||
it: &Value,
|
scope: Arc<Scope>,
|
||||||
vars: &IndexMap<String, Value>,
|
|
||||||
env: &IndexMap<String, String>,
|
|
||||||
) -> Result<InputStream, ShellError> {
|
) -> Result<InputStream, ShellError> {
|
||||||
if log_enabled!(log::Level::Trace) {
|
if log_enabled!(log::Level::Trace) {
|
||||||
trace!(target: "nu::run::expr", "->");
|
trace!(target: "nu::run::expr", "->");
|
||||||
@ -21,7 +19,7 @@ pub(crate) async fn run_expression_block(
|
|||||||
}
|
}
|
||||||
|
|
||||||
let registry = context.registry().clone();
|
let registry = context.registry().clone();
|
||||||
let output = evaluate_baseline_expr(&expr, ®istry, it, vars, env).await?;
|
let output = evaluate_baseline_expr(&expr, ®istry, scope).await?;
|
||||||
|
|
||||||
Ok(once(async { Ok(output) }).to_input_stream())
|
Ok(once(async { Ok(output) }).to_input_stream())
|
||||||
}
|
}
|
||||||
|
@ -21,7 +21,7 @@ pub(crate) async fn run_external_command(
|
|||||||
command: ExternalCommand,
|
command: ExternalCommand,
|
||||||
context: &mut EvaluationContext,
|
context: &mut EvaluationContext,
|
||||||
input: InputStream,
|
input: InputStream,
|
||||||
scope: &Scope,
|
scope: Arc<Scope>,
|
||||||
external_redirection: ExternalRedirection,
|
external_redirection: ExternalRedirection,
|
||||||
) -> Result<InputStream, ShellError> {
|
) -> Result<InputStream, ShellError> {
|
||||||
trace!(target: "nu::run::external", "-> {}", command.name);
|
trace!(target: "nu::run::external", "-> {}", command.name);
|
||||||
@ -41,7 +41,7 @@ async fn run_with_stdin(
|
|||||||
command: ExternalCommand,
|
command: ExternalCommand,
|
||||||
context: &mut EvaluationContext,
|
context: &mut EvaluationContext,
|
||||||
input: InputStream,
|
input: InputStream,
|
||||||
scope: &Scope,
|
scope: Arc<Scope>,
|
||||||
external_redirection: ExternalRedirection,
|
external_redirection: ExternalRedirection,
|
||||||
) -> Result<InputStream, ShellError> {
|
) -> Result<InputStream, ShellError> {
|
||||||
let path = context.shell_manager.path();
|
let path = context.shell_manager.path();
|
||||||
@ -50,9 +50,7 @@ async fn run_with_stdin(
|
|||||||
|
|
||||||
let mut command_args = vec![];
|
let mut command_args = vec![];
|
||||||
for arg in command.args.iter() {
|
for arg in command.args.iter() {
|
||||||
let value =
|
let value = evaluate_baseline_expr(arg, &context.registry, scope.clone()).await?;
|
||||||
evaluate_baseline_expr(arg, &context.registry, &scope.it, &scope.vars, &scope.env)
|
|
||||||
.await?;
|
|
||||||
|
|
||||||
// Skip any arguments that don't really exist, treating them as optional
|
// Skip any arguments that don't really exist, treating them as optional
|
||||||
// FIXME: we may want to preserve the gap in the future, though it's hard to say
|
// FIXME: we may want to preserve the gap in the future, though it's hard to say
|
||||||
@ -138,7 +136,7 @@ fn spawn(
|
|||||||
args: &[String],
|
args: &[String],
|
||||||
input: InputStream,
|
input: InputStream,
|
||||||
external_redirection: ExternalRedirection,
|
external_redirection: ExternalRedirection,
|
||||||
scope: &Scope,
|
scope: Arc<Scope>,
|
||||||
) -> Result<InputStream, ShellError> {
|
) -> Result<InputStream, ShellError> {
|
||||||
let command = command.clone();
|
let command = command.clone();
|
||||||
|
|
||||||
@ -169,7 +167,7 @@ fn spawn(
|
|||||||
trace!(target: "nu::run::external", "cwd = {:?}", &path);
|
trace!(target: "nu::run::external", "cwd = {:?}", &path);
|
||||||
|
|
||||||
process.env_clear();
|
process.env_clear();
|
||||||
process.envs(scope.env.iter());
|
process.envs(scope.env());
|
||||||
|
|
||||||
// We want stdout regardless of what
|
// We want stdout regardless of what
|
||||||
// we are doing ($it case or pipe stdin)
|
// we are doing ($it case or pipe stdin)
|
||||||
@ -580,7 +578,7 @@ mod tests {
|
|||||||
cmd,
|
cmd,
|
||||||
&mut ctx,
|
&mut ctx,
|
||||||
input,
|
input,
|
||||||
&Scope::new(),
|
Scope::create(),
|
||||||
ExternalRedirection::Stdout
|
ExternalRedirection::Stdout
|
||||||
)
|
)
|
||||||
.await
|
.await
|
||||||
|
@ -11,20 +11,13 @@ pub(crate) async fn run_internal_command(
|
|||||||
command: InternalCommand,
|
command: InternalCommand,
|
||||||
context: &mut EvaluationContext,
|
context: &mut EvaluationContext,
|
||||||
input: InputStream,
|
input: InputStream,
|
||||||
it: &Value,
|
scope: Arc<Scope>,
|
||||||
vars: &IndexMap<String, Value>,
|
|
||||||
env: &IndexMap<String, String>,
|
|
||||||
) -> Result<InputStream, ShellError> {
|
) -> Result<InputStream, ShellError> {
|
||||||
if log_enabled!(log::Level::Trace) {
|
if log_enabled!(log::Level::Trace) {
|
||||||
trace!(target: "nu::run::internal", "->");
|
trace!(target: "nu::run::internal", "->");
|
||||||
trace!(target: "nu::run::internal", "{}", command.name);
|
trace!(target: "nu::run::internal", "{}", command.name);
|
||||||
}
|
}
|
||||||
|
|
||||||
let scope = Scope {
|
|
||||||
it: it.clone(),
|
|
||||||
vars: vars.clone(),
|
|
||||||
env: env.clone(),
|
|
||||||
};
|
|
||||||
let objects: InputStream = trace_stream!(target: "nu::trace_stream::internal", "input" = input);
|
let objects: InputStream = trace_stream!(target: "nu::trace_stream::internal", "input" = input);
|
||||||
let internal_command = context.expect_command(&command.name);
|
let internal_command = context.expect_command(&command.name);
|
||||||
|
|
||||||
@ -38,7 +31,7 @@ pub(crate) async fn run_internal_command(
|
|||||||
internal_command?,
|
internal_command?,
|
||||||
Tag::unknown_anchor(command.name_span),
|
Tag::unknown_anchor(command.name_span),
|
||||||
command.args.clone(),
|
command.args.clone(),
|
||||||
&scope,
|
scope.clone(),
|
||||||
objects,
|
objects,
|
||||||
)
|
)
|
||||||
.await?
|
.await?
|
||||||
@ -48,8 +41,6 @@ pub(crate) async fn run_internal_command(
|
|||||||
//let context = Arc::new(context.clone());
|
//let context = Arc::new(context.clone());
|
||||||
let context = context.clone();
|
let context = context.clone();
|
||||||
let command = Arc::new(command);
|
let command = Arc::new(command);
|
||||||
let scope = Arc::new(scope);
|
|
||||||
// let scope = scope.clone();
|
|
||||||
|
|
||||||
Ok(InputStream::from_stream(
|
Ok(InputStream::from_stream(
|
||||||
result
|
result
|
||||||
@ -90,7 +81,7 @@ pub(crate) async fn run_internal_command(
|
|||||||
external_redirection: ExternalRedirection::Stdout,
|
external_redirection: ExternalRedirection::Stdout,
|
||||||
},
|
},
|
||||||
name_tag: Tag::unknown_anchor(command.name_span),
|
name_tag: Tag::unknown_anchor(command.name_span),
|
||||||
scope: (&*scope).clone(),
|
scope,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
let result = converter
|
let result = converter
|
||||||
|
@ -130,7 +130,7 @@ async fn run_filter(
|
|||||||
UntaggedValue::Primitive(Primitive::EndOfStream).into_untagged_value()
|
UntaggedValue::Primitive(Primitive::EndOfStream).into_untagged_value()
|
||||||
]);
|
]);
|
||||||
|
|
||||||
let args = args.evaluate_once_with_scope(®istry, &scope).await?;
|
let args = args.evaluate_once_with_scope(®istry, scope).await?;
|
||||||
|
|
||||||
let real_path = Path::new(&path);
|
let real_path = Path::new(&path);
|
||||||
let ext = real_path.extension();
|
let ext = real_path.extension();
|
||||||
|
@ -17,27 +17,12 @@ use std::sync::atomic::AtomicBool;
|
|||||||
pub struct UnevaluatedCallInfo {
|
pub struct UnevaluatedCallInfo {
|
||||||
pub args: hir::Call,
|
pub args: hir::Call,
|
||||||
pub name_tag: Tag,
|
pub name_tag: Tag,
|
||||||
pub scope: Scope,
|
pub scope: Arc<Scope>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl UnevaluatedCallInfo {
|
impl UnevaluatedCallInfo {
|
||||||
pub async fn evaluate(self, registry: &CommandRegistry) -> Result<CallInfo, ShellError> {
|
pub async fn evaluate(self, registry: &CommandRegistry) -> Result<CallInfo, ShellError> {
|
||||||
let args = evaluate_args(&self.args, registry, &self.scope).await?;
|
let args = evaluate_args(&self.args, registry, self.scope.clone()).await?;
|
||||||
|
|
||||||
Ok(CallInfo {
|
|
||||||
args,
|
|
||||||
name_tag: self.name_tag,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
pub async fn evaluate_with_new_it(
|
|
||||||
self,
|
|
||||||
registry: &CommandRegistry,
|
|
||||||
it: &Value,
|
|
||||||
) -> Result<CallInfo, ShellError> {
|
|
||||||
let mut scope = self.scope.clone();
|
|
||||||
scope.it = it.clone();
|
|
||||||
let args = evaluate_args(&self.args, registry, &scope).await?;
|
|
||||||
|
|
||||||
Ok(CallInfo {
|
Ok(CallInfo {
|
||||||
args,
|
args,
|
||||||
@ -115,7 +100,7 @@ impl CommandArgs {
|
|||||||
pub async fn evaluate_once_with_scope(
|
pub async fn evaluate_once_with_scope(
|
||||||
self,
|
self,
|
||||||
registry: &CommandRegistry,
|
registry: &CommandRegistry,
|
||||||
scope: &Scope,
|
scope: Arc<Scope>,
|
||||||
) -> Result<EvaluatedWholeStreamCommandArgs, ShellError> {
|
) -> Result<EvaluatedWholeStreamCommandArgs, ShellError> {
|
||||||
let host = self.host.clone();
|
let host = self.host.clone();
|
||||||
let ctrl_c = self.ctrl_c.clone();
|
let ctrl_c = self.ctrl_c.clone();
|
||||||
@ -215,37 +200,6 @@ impl EvaluatedWholeStreamCommandArgs {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Getters)]
|
|
||||||
#[get = "pub"]
|
|
||||||
pub struct EvaluatedFilterCommandArgs {
|
|
||||||
args: EvaluatedCommandArgs,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Deref for EvaluatedFilterCommandArgs {
|
|
||||||
type Target = EvaluatedCommandArgs;
|
|
||||||
fn deref(&self) -> &Self::Target {
|
|
||||||
&self.args
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl EvaluatedFilterCommandArgs {
|
|
||||||
pub fn new(
|
|
||||||
host: Arc<parking_lot::Mutex<dyn Host>>,
|
|
||||||
ctrl_c: Arc<AtomicBool>,
|
|
||||||
shell_manager: ShellManager,
|
|
||||||
call_info: CallInfo,
|
|
||||||
) -> EvaluatedFilterCommandArgs {
|
|
||||||
EvaluatedFilterCommandArgs {
|
|
||||||
args: EvaluatedCommandArgs {
|
|
||||||
host,
|
|
||||||
ctrl_c,
|
|
||||||
shell_manager,
|
|
||||||
call_info,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Getters, new)]
|
#[derive(Getters, new)]
|
||||||
#[get = "pub(crate)"]
|
#[get = "pub(crate)"]
|
||||||
pub struct EvaluatedCommandArgs {
|
pub struct EvaluatedCommandArgs {
|
||||||
@ -381,69 +335,6 @@ impl Command {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct FnFilterCommand {
|
|
||||||
name: String,
|
|
||||||
func: fn(EvaluatedFilterCommandArgs) -> Result<OutputStream, ShellError>,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[async_trait]
|
|
||||||
impl WholeStreamCommand for FnFilterCommand {
|
|
||||||
fn name(&self) -> &str {
|
|
||||||
&self.name
|
|
||||||
}
|
|
||||||
|
|
||||||
fn usage(&self) -> &str {
|
|
||||||
"usage"
|
|
||||||
}
|
|
||||||
|
|
||||||
async fn run(
|
|
||||||
&self,
|
|
||||||
CommandArgs {
|
|
||||||
host,
|
|
||||||
ctrl_c,
|
|
||||||
shell_manager,
|
|
||||||
call_info,
|
|
||||||
input,
|
|
||||||
..
|
|
||||||
}: CommandArgs,
|
|
||||||
registry: &CommandRegistry,
|
|
||||||
) -> Result<OutputStream, ShellError> {
|
|
||||||
let registry = Arc::new(registry.clone());
|
|
||||||
let func = self.func;
|
|
||||||
|
|
||||||
Ok(input
|
|
||||||
.then(move |it| {
|
|
||||||
let host = host.clone();
|
|
||||||
let registry = registry.clone();
|
|
||||||
let ctrl_c = ctrl_c.clone();
|
|
||||||
let shell_manager = shell_manager.clone();
|
|
||||||
let call_info = call_info.clone();
|
|
||||||
async move {
|
|
||||||
let call_info = match call_info.evaluate_with_new_it(&*registry, &it).await {
|
|
||||||
Err(err) => {
|
|
||||||
return OutputStream::one(Err(err));
|
|
||||||
}
|
|
||||||
Ok(args) => args,
|
|
||||||
};
|
|
||||||
|
|
||||||
let args = EvaluatedFilterCommandArgs::new(
|
|
||||||
host.clone(),
|
|
||||||
ctrl_c.clone(),
|
|
||||||
shell_manager.clone(),
|
|
||||||
call_info,
|
|
||||||
);
|
|
||||||
|
|
||||||
match func(args) {
|
|
||||||
Err(err) => return OutputStream::one(Err(err)),
|
|
||||||
Ok(stream) => stream,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.flatten()
|
|
||||||
.to_output_stream())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn whole_stream_command(command: impl WholeStreamCommand + 'static) -> Command {
|
pub fn whole_stream_command(command: impl WholeStreamCommand + 'static) -> Command {
|
||||||
Command(Arc::new(command))
|
Command(Arc::new(command))
|
||||||
}
|
}
|
||||||
|
@ -37,22 +37,11 @@ impl WholeStreamCommand for Compact {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn examples(&self) -> Vec<Example> {
|
fn examples(&self) -> Vec<Example> {
|
||||||
vec![
|
vec![Example {
|
||||||
Example {
|
description: "Filter out all directory entries having no 'target'",
|
||||||
description: "Filter out all null entries in a list",
|
example: "ls -la | compact target",
|
||||||
example: "echo [1 2 $null 3 $null $null] | compact",
|
result: None,
|
||||||
result: Some(vec![
|
}]
|
||||||
UntaggedValue::int(1).into(),
|
|
||||||
UntaggedValue::int(2).into(),
|
|
||||||
UntaggedValue::int(3).into(),
|
|
||||||
]),
|
|
||||||
},
|
|
||||||
Example {
|
|
||||||
description: "Filter out all directory entries having no 'target'",
|
|
||||||
example: "ls -la | compact target",
|
|
||||||
result: None,
|
|
||||||
},
|
|
||||||
]
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -95,15 +95,7 @@ async fn do_(
|
|||||||
|
|
||||||
block.set_redirect(block_redirection);
|
block.set_redirect(block_redirection);
|
||||||
|
|
||||||
let result = run_block(
|
let result = run_block(&block, &mut context, input, scope).await;
|
||||||
&block,
|
|
||||||
&mut context,
|
|
||||||
input,
|
|
||||||
&scope.it,
|
|
||||||
&scope.vars,
|
|
||||||
&scope.env,
|
|
||||||
)
|
|
||||||
.await;
|
|
||||||
|
|
||||||
if ignore_errors {
|
if ignore_errors {
|
||||||
// To properly ignore errors we need to redirect stderr, consume it, and remove
|
// To properly ignore errors we need to redirect stderr, consume it, and remove
|
||||||
|
@ -97,9 +97,7 @@ pub async fn process_row(
|
|||||||
&block,
|
&block,
|
||||||
Arc::make_mut(&mut context),
|
Arc::make_mut(&mut context),
|
||||||
input_stream,
|
input_stream,
|
||||||
&input,
|
Scope::append_it(scope, input),
|
||||||
&scope.vars,
|
|
||||||
&scope.env,
|
|
||||||
)
|
)
|
||||||
.await?
|
.await?
|
||||||
.to_output_stream())
|
.to_output_stream())
|
||||||
@ -119,7 +117,7 @@ async fn each(
|
|||||||
) -> Result<OutputStream, ShellError> {
|
) -> Result<OutputStream, ShellError> {
|
||||||
let registry = registry.clone();
|
let registry = registry.clone();
|
||||||
let head = Arc::new(raw_args.call_info.args.head.clone());
|
let head = Arc::new(raw_args.call_info.args.head.clone());
|
||||||
let scope = Arc::new(raw_args.call_info.scope.clone());
|
let scope = raw_args.call_info.scope.clone();
|
||||||
let context = Arc::new(EvaluationContext::from_raw(&raw_args, ®istry));
|
let context = Arc::new(EvaluationContext::from_raw(&raw_args, ®istry));
|
||||||
let (each_args, input): (EachArgs, _) = raw_args.process(®istry).await?;
|
let (each_args, input): (EachArgs, _) = raw_args.process(®istry).await?;
|
||||||
let block = Arc::new(each_args.block);
|
let block = Arc::new(each_args.block);
|
||||||
|
@ -53,7 +53,7 @@ impl WholeStreamCommand for EachGroup {
|
|||||||
) -> Result<OutputStream, ShellError> {
|
) -> Result<OutputStream, ShellError> {
|
||||||
let registry = registry.clone();
|
let registry = registry.clone();
|
||||||
let head = Arc::new(raw_args.call_info.args.head.clone());
|
let head = Arc::new(raw_args.call_info.args.head.clone());
|
||||||
let scope = Arc::new(raw_args.call_info.scope.clone());
|
let scope = raw_args.call_info.scope.clone();
|
||||||
let context = Arc::new(EvaluationContext::from_raw(&raw_args, ®istry));
|
let context = Arc::new(EvaluationContext::from_raw(&raw_args, ®istry));
|
||||||
let (each_args, input): (EachGroupArgs, _) = raw_args.process(®istry).await?;
|
let (each_args, input): (EachGroupArgs, _) = raw_args.process(®istry).await?;
|
||||||
let block = Arc::new(each_args.block);
|
let block = Arc::new(each_args.block);
|
||||||
|
@ -57,7 +57,7 @@ impl WholeStreamCommand for EachWindow {
|
|||||||
) -> Result<OutputStream, ShellError> {
|
) -> Result<OutputStream, ShellError> {
|
||||||
let registry = registry.clone();
|
let registry = registry.clone();
|
||||||
let head = Arc::new(raw_args.call_info.args.head.clone());
|
let head = Arc::new(raw_args.call_info.args.head.clone());
|
||||||
let scope = Arc::new(raw_args.call_info.scope.clone());
|
let scope = raw_args.call_info.scope.clone();
|
||||||
let context = Arc::new(EvaluationContext::from_raw(&raw_args, ®istry));
|
let context = Arc::new(EvaluationContext::from_raw(&raw_args, ®istry));
|
||||||
let (each_args, mut input): (EachWindowArgs, _) = raw_args.process(®istry).await?;
|
let (each_args, mut input): (EachWindowArgs, _) = raw_args.process(®istry).await?;
|
||||||
let block = Arc::new(each_args.block);
|
let block = Arc::new(each_args.block);
|
||||||
|
@ -3,7 +3,7 @@ use crate::commands::WholeStreamCommand;
|
|||||||
use crate::evaluate::evaluate_baseline_expr;
|
use crate::evaluate::evaluate_baseline_expr;
|
||||||
use crate::prelude::*;
|
use crate::prelude::*;
|
||||||
use nu_errors::ShellError;
|
use nu_errors::ShellError;
|
||||||
use nu_protocol::{ReturnSuccess, Signature, SyntaxShape, UntaggedValue};
|
use nu_protocol::{ReturnSuccess, Scope, Signature, SyntaxShape, UntaggedValue};
|
||||||
use nu_source::Tagged;
|
use nu_source::Tagged;
|
||||||
use std::borrow::Borrow;
|
use std::borrow::Borrow;
|
||||||
|
|
||||||
@ -54,7 +54,7 @@ async fn format_command(
|
|||||||
registry: &CommandRegistry,
|
registry: &CommandRegistry,
|
||||||
) -> Result<OutputStream, ShellError> {
|
) -> Result<OutputStream, ShellError> {
|
||||||
let registry = Arc::new(registry.clone());
|
let registry = Arc::new(registry.clone());
|
||||||
let scope = Arc::new(args.call_info.scope.clone());
|
let scope = args.call_info.scope.clone();
|
||||||
let (FormatArgs { pattern }, input) = args.process(®istry).await?;
|
let (FormatArgs { pattern }, input) = args.process(®istry).await?;
|
||||||
|
|
||||||
let format_pattern = format(&pattern);
|
let format_pattern = format(&pattern);
|
||||||
@ -83,9 +83,7 @@ async fn format_command(
|
|||||||
let result = evaluate_baseline_expr(
|
let result = evaluate_baseline_expr(
|
||||||
&full_column_path.0,
|
&full_column_path.0,
|
||||||
®istry,
|
®istry,
|
||||||
&value,
|
Scope::append_it(scope.clone(), value.clone()),
|
||||||
&scope.vars,
|
|
||||||
&scope.env,
|
|
||||||
)
|
)
|
||||||
.await;
|
.await;
|
||||||
|
|
||||||
|
@ -96,7 +96,7 @@ pub async fn group_by(
|
|||||||
let name = args.call_info.name_tag.clone();
|
let name = args.call_info.name_tag.clone();
|
||||||
let registry = registry.clone();
|
let registry = registry.clone();
|
||||||
let head = Arc::new(args.call_info.args.head.clone());
|
let head = Arc::new(args.call_info.args.head.clone());
|
||||||
let scope = Arc::new(args.call_info.scope.clone());
|
let scope = args.call_info.scope.clone();
|
||||||
let context = Arc::new(EvaluationContext::from_raw(&args, ®istry));
|
let context = Arc::new(EvaluationContext::from_raw(&args, ®istry));
|
||||||
let (GroupByArgs { grouper }, input) = args.process(®istry).await?;
|
let (GroupByArgs { grouper }, input) = args.process(®istry).await?;
|
||||||
|
|
||||||
|
@ -4,7 +4,9 @@ use crate::commands::WholeStreamCommand;
|
|||||||
use crate::evaluate::evaluate_baseline_expr;
|
use crate::evaluate::evaluate_baseline_expr;
|
||||||
use crate::prelude::*;
|
use crate::prelude::*;
|
||||||
use nu_errors::ShellError;
|
use nu_errors::ShellError;
|
||||||
use nu_protocol::{hir::Block, hir::ClassifiedCommand, Signature, SyntaxShape, UntaggedValue};
|
use nu_protocol::{
|
||||||
|
hir::Block, hir::ClassifiedCommand, Scope, Signature, SyntaxShape, UntaggedValue,
|
||||||
|
};
|
||||||
|
|
||||||
pub struct If;
|
pub struct If;
|
||||||
|
|
||||||
@ -72,7 +74,7 @@ async fn if_command(
|
|||||||
registry: &CommandRegistry,
|
registry: &CommandRegistry,
|
||||||
) -> Result<OutputStream, ShellError> {
|
) -> Result<OutputStream, ShellError> {
|
||||||
let registry = Arc::new(registry.clone());
|
let registry = Arc::new(registry.clone());
|
||||||
let scope = Arc::new(raw_args.call_info.scope.clone());
|
let scope = raw_args.call_info.scope.clone();
|
||||||
let tag = raw_args.call_info.name_tag.clone();
|
let tag = raw_args.call_info.name_tag.clone();
|
||||||
let context = Arc::new(EvaluationContext::from_raw(&raw_args, ®istry));
|
let context = Arc::new(EvaluationContext::from_raw(&raw_args, ®istry));
|
||||||
|
|
||||||
@ -119,14 +121,12 @@ async fn if_command(
|
|||||||
let then_case = then_case.clone();
|
let then_case = then_case.clone();
|
||||||
let else_case = else_case.clone();
|
let else_case = else_case.clone();
|
||||||
let registry = registry.clone();
|
let registry = registry.clone();
|
||||||
let scope = scope.clone();
|
let scope = Scope::append_it(scope.clone(), input);
|
||||||
let mut context = context.clone();
|
let mut context = context.clone();
|
||||||
|
|
||||||
async move {
|
async move {
|
||||||
//FIXME: should we use the scope that's brought in as well?
|
//FIXME: should we use the scope that's brought in as well?
|
||||||
let condition =
|
let condition = evaluate_baseline_expr(&condition, &*registry, scope.clone()).await;
|
||||||
evaluate_baseline_expr(&condition, &*registry, &input, &scope.vars, &scope.env)
|
|
||||||
.await;
|
|
||||||
|
|
||||||
match condition {
|
match condition {
|
||||||
Ok(condition) => match condition.as_bool() {
|
Ok(condition) => match condition.as_bool() {
|
||||||
@ -136,9 +136,7 @@ async fn if_command(
|
|||||||
&then_case,
|
&then_case,
|
||||||
Arc::make_mut(&mut context),
|
Arc::make_mut(&mut context),
|
||||||
InputStream::empty(),
|
InputStream::empty(),
|
||||||
&input,
|
scope,
|
||||||
&scope.vars,
|
|
||||||
&scope.env,
|
|
||||||
)
|
)
|
||||||
.await
|
.await
|
||||||
{
|
{
|
||||||
@ -151,9 +149,7 @@ async fn if_command(
|
|||||||
&else_case,
|
&else_case,
|
||||||
Arc::make_mut(&mut context),
|
Arc::make_mut(&mut context),
|
||||||
InputStream::empty(),
|
InputStream::empty(),
|
||||||
&input,
|
scope,
|
||||||
&scope.vars,
|
|
||||||
&scope.env,
|
|
||||||
)
|
)
|
||||||
.await
|
.await
|
||||||
{
|
{
|
||||||
|
@ -63,15 +63,9 @@ async fn process_row(
|
|||||||
let for_block = input.clone();
|
let for_block = input.clone();
|
||||||
let input_stream = once(async { Ok(for_block) }).to_input_stream();
|
let input_stream = once(async { Ok(for_block) }).to_input_stream();
|
||||||
|
|
||||||
let result = run_block(
|
let scope = Scope::append_it(scope, input.clone());
|
||||||
&block,
|
|
||||||
Arc::make_mut(&mut context),
|
let result = run_block(&block, Arc::make_mut(&mut context), input_stream, scope).await;
|
||||||
input_stream,
|
|
||||||
&input,
|
|
||||||
&scope.vars,
|
|
||||||
&scope.env,
|
|
||||||
)
|
|
||||||
.await;
|
|
||||||
|
|
||||||
match result {
|
match result {
|
||||||
Ok(mut stream) => {
|
Ok(mut stream) => {
|
||||||
@ -118,7 +112,11 @@ async fn process_row(
|
|||||||
Value {
|
Value {
|
||||||
value: UntaggedValue::Primitive(Primitive::Nothing),
|
value: UntaggedValue::Primitive(Primitive::Nothing),
|
||||||
..
|
..
|
||||||
} => match scope.it.insert_data_at_column_path(&field, value.clone()) {
|
} => match scope
|
||||||
|
.it()
|
||||||
|
.unwrap_or_else(|| UntaggedValue::nothing().into_untagged_value())
|
||||||
|
.insert_data_at_column_path(&field, value.clone())
|
||||||
|
{
|
||||||
Ok(v) => OutputStream::one(ReturnSuccess::value(v)),
|
Ok(v) => OutputStream::one(ReturnSuccess::value(v)),
|
||||||
Err(e) => OutputStream::one(Err(e)),
|
Err(e) => OutputStream::one(Err(e)),
|
||||||
},
|
},
|
||||||
@ -135,7 +133,7 @@ async fn insert(
|
|||||||
registry: &CommandRegistry,
|
registry: &CommandRegistry,
|
||||||
) -> Result<OutputStream, ShellError> {
|
) -> Result<OutputStream, ShellError> {
|
||||||
let registry = registry.clone();
|
let registry = registry.clone();
|
||||||
let scope = Arc::new(raw_args.call_info.scope.clone());
|
let scope = raw_args.call_info.scope.clone();
|
||||||
let context = Arc::new(EvaluationContext::from_raw(&raw_args, ®istry));
|
let context = Arc::new(EvaluationContext::from_raw(&raw_args, ®istry));
|
||||||
let (InsertArgs { column, value }, input) = raw_args.process(®istry).await?;
|
let (InsertArgs { column, value }, input) = raw_args.process(®istry).await?;
|
||||||
let value = Arc::new(value);
|
let value = Arc::new(value);
|
||||||
|
@ -3,7 +3,7 @@ use crate::evaluate::evaluate_baseline_expr;
|
|||||||
use crate::prelude::*;
|
use crate::prelude::*;
|
||||||
use log::trace;
|
use log::trace;
|
||||||
use nu_errors::ShellError;
|
use nu_errors::ShellError;
|
||||||
use nu_protocol::{hir::ClassifiedCommand, Signature, SyntaxShape, UntaggedValue, Value};
|
use nu_protocol::{hir::ClassifiedCommand, Scope, Signature, SyntaxShape, UntaggedValue, Value};
|
||||||
|
|
||||||
pub struct SubCommand;
|
pub struct SubCommand;
|
||||||
|
|
||||||
@ -33,7 +33,7 @@ impl WholeStreamCommand for SubCommand {
|
|||||||
registry: &CommandRegistry,
|
registry: &CommandRegistry,
|
||||||
) -> Result<OutputStream, ShellError> {
|
) -> Result<OutputStream, ShellError> {
|
||||||
let registry = Arc::new(registry.clone());
|
let registry = Arc::new(registry.clone());
|
||||||
let scope = Arc::new(args.call_info.scope.clone());
|
let scope = args.call_info.scope.clone();
|
||||||
|
|
||||||
let call_info = args.evaluate_once(®istry).await?;
|
let call_info = args.evaluate_once(®istry).await?;
|
||||||
|
|
||||||
@ -85,19 +85,11 @@ impl WholeStreamCommand for SubCommand {
|
|||||||
.take_while(move |item| {
|
.take_while(move |item| {
|
||||||
let condition = condition.clone();
|
let condition = condition.clone();
|
||||||
let registry = registry.clone();
|
let registry = registry.clone();
|
||||||
let scope = scope.clone();
|
let scope = Scope::append_it(scope.clone(), item.clone());
|
||||||
let item = item.clone();
|
|
||||||
trace!("ITEM = {:?}", item);
|
trace!("ITEM = {:?}", item);
|
||||||
|
|
||||||
async move {
|
async move {
|
||||||
let result = evaluate_baseline_expr(
|
let result = evaluate_baseline_expr(&*condition, ®istry, scope).await;
|
||||||
&*condition,
|
|
||||||
®istry,
|
|
||||||
&item,
|
|
||||||
&scope.vars,
|
|
||||||
&scope.env,
|
|
||||||
)
|
|
||||||
.await;
|
|
||||||
trace!("RESULT = {:?}", result);
|
trace!("RESULT = {:?}", result);
|
||||||
|
|
||||||
!matches!(result, Ok(ref v) if v.is_true())
|
!matches!(result, Ok(ref v) if v.is_true())
|
||||||
|
@ -3,7 +3,7 @@ use crate::evaluate::evaluate_baseline_expr;
|
|||||||
use crate::prelude::*;
|
use crate::prelude::*;
|
||||||
use log::trace;
|
use log::trace;
|
||||||
use nu_errors::ShellError;
|
use nu_errors::ShellError;
|
||||||
use nu_protocol::{hir::ClassifiedCommand, Signature, SyntaxShape, UntaggedValue, Value};
|
use nu_protocol::{hir::ClassifiedCommand, Scope, Signature, SyntaxShape, UntaggedValue, Value};
|
||||||
|
|
||||||
pub struct SubCommand;
|
pub struct SubCommand;
|
||||||
|
|
||||||
@ -33,7 +33,7 @@ impl WholeStreamCommand for SubCommand {
|
|||||||
registry: &CommandRegistry,
|
registry: &CommandRegistry,
|
||||||
) -> Result<OutputStream, ShellError> {
|
) -> Result<OutputStream, ShellError> {
|
||||||
let registry = Arc::new(registry.clone());
|
let registry = Arc::new(registry.clone());
|
||||||
let scope = Arc::new(args.call_info.scope.clone());
|
let scope = args.call_info.scope.clone();
|
||||||
let call_info = args.evaluate_once(®istry).await?;
|
let call_info = args.evaluate_once(®istry).await?;
|
||||||
|
|
||||||
let block = call_info.args.expect_nth(0)?.clone();
|
let block = call_info.args.expect_nth(0)?.clone();
|
||||||
@ -84,20 +84,11 @@ impl WholeStreamCommand for SubCommand {
|
|||||||
.take_while(move |item| {
|
.take_while(move |item| {
|
||||||
let condition = condition.clone();
|
let condition = condition.clone();
|
||||||
let registry = registry.clone();
|
let registry = registry.clone();
|
||||||
let scope = scope.clone();
|
let scope = Scope::append_it(scope.clone(), item.clone());
|
||||||
let item = item.clone();
|
|
||||||
|
|
||||||
trace!("ITEM = {:?}", item);
|
trace!("ITEM = {:?}", item);
|
||||||
|
|
||||||
async move {
|
async move {
|
||||||
let result = evaluate_baseline_expr(
|
let result = evaluate_baseline_expr(&*condition, ®istry, scope).await;
|
||||||
&*condition,
|
|
||||||
®istry,
|
|
||||||
&item,
|
|
||||||
&scope.vars,
|
|
||||||
&scope.env,
|
|
||||||
)
|
|
||||||
.await;
|
|
||||||
trace!("RESULT = {:?}", result);
|
trace!("RESULT = {:?}", result);
|
||||||
|
|
||||||
matches!(result, Ok(ref v) if v.is_true())
|
matches!(result, Ok(ref v) if v.is_true())
|
||||||
|
@ -60,21 +60,13 @@ async fn merge(
|
|||||||
let (merge_args, input): (MergeArgs, _) = raw_args.process(®istry).await?;
|
let (merge_args, input): (MergeArgs, _) = raw_args.process(®istry).await?;
|
||||||
let block = merge_args.block;
|
let block = merge_args.block;
|
||||||
|
|
||||||
let table: Option<Vec<Value>> = match run_block(
|
let table: Option<Vec<Value>> =
|
||||||
&block,
|
match run_block(&block, &mut context, InputStream::empty(), scope).await {
|
||||||
&mut context,
|
Ok(mut stream) => Some(stream.drain_vec().await),
|
||||||
InputStream::empty(),
|
Err(err) => {
|
||||||
&scope.it,
|
return Err(err);
|
||||||
&scope.vars,
|
}
|
||||||
&scope.env,
|
};
|
||||||
)
|
|
||||||
.await
|
|
||||||
{
|
|
||||||
Ok(mut stream) => Some(stream.drain_vec().await),
|
|
||||||
Err(err) => {
|
|
||||||
return Err(err);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
let table = table.unwrap_or_else(|| {
|
let table = table.unwrap_or_else(|| {
|
||||||
vec![Value {
|
vec![Value {
|
||||||
|
@ -87,15 +87,9 @@ async fn process_row(
|
|||||||
let row_clone = row.clone();
|
let row_clone = row.clone();
|
||||||
let input_stream = once(async { Ok(row_clone) }).to_input_stream();
|
let input_stream = once(async { Ok(row_clone) }).to_input_stream();
|
||||||
|
|
||||||
Ok(run_block(
|
let scope = Scope::append_it(scope, row);
|
||||||
&block,
|
|
||||||
Arc::make_mut(&mut context),
|
Ok(run_block(&block, Arc::make_mut(&mut context), input_stream, scope).await?)
|
||||||
input_stream,
|
|
||||||
&row,
|
|
||||||
&scope.vars,
|
|
||||||
&scope.env,
|
|
||||||
)
|
|
||||||
.await?)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn reduce(
|
async fn reduce(
|
||||||
@ -133,7 +127,7 @@ async fn reduce(
|
|||||||
.enumerate()
|
.enumerate()
|
||||||
.fold(initial, move |acc, input| {
|
.fold(initial, move |acc, input| {
|
||||||
let block = Arc::clone(&block);
|
let block = Arc::clone(&block);
|
||||||
let mut scope = base_scope.clone();
|
let scope = base_scope.clone();
|
||||||
let context = Arc::clone(&context);
|
let context = Arc::clone(&context);
|
||||||
let row = each::make_indexed_item(input.0 + ioffset, input.1);
|
let row = each::make_indexed_item(input.0 + ioffset, input.1);
|
||||||
|
|
||||||
@ -151,8 +145,8 @@ async fn reduce(
|
|||||||
UntaggedValue::table(&values).into_untagged_value()
|
UntaggedValue::table(&values).into_untagged_value()
|
||||||
};
|
};
|
||||||
|
|
||||||
scope.vars.insert(String::from("$acc"), f);
|
let scope = Scope::append_var(scope, "$acc".into(), f);
|
||||||
process_row(block, Arc::new(scope), context, row).await
|
process_row(block, scope, context, row).await
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.await?
|
.await?
|
||||||
@ -162,7 +156,7 @@ async fn reduce(
|
|||||||
Ok(input
|
Ok(input
|
||||||
.fold(initial, move |acc, row| {
|
.fold(initial, move |acc, row| {
|
||||||
let block = Arc::clone(&block);
|
let block = Arc::clone(&block);
|
||||||
let mut scope = base_scope.clone();
|
let scope = base_scope.clone();
|
||||||
let context = Arc::clone(&context);
|
let context = Arc::clone(&context);
|
||||||
|
|
||||||
async {
|
async {
|
||||||
@ -179,8 +173,8 @@ async fn reduce(
|
|||||||
UntaggedValue::table(&values).into_untagged_value()
|
UntaggedValue::table(&values).into_untagged_value()
|
||||||
};
|
};
|
||||||
|
|
||||||
scope.vars.insert(String::from("$acc"), f);
|
let scope = Scope::append_var(scope, "$acc".into(), f);
|
||||||
process_row(block, Arc::new(scope), context, row).await
|
process_row(block, scope, context, row).await
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.await?
|
.await?
|
||||||
|
@ -4,7 +4,7 @@ use crate::prelude::*;
|
|||||||
|
|
||||||
use derive_new::new;
|
use derive_new::new;
|
||||||
use nu_errors::ShellError;
|
use nu_errors::ShellError;
|
||||||
use nu_protocol::{hir::Block, Signature, SyntaxShape};
|
use nu_protocol::{hir::Block, Scope, Signature, SyntaxShape};
|
||||||
|
|
||||||
#[derive(new, Clone)]
|
#[derive(new, Clone)]
|
||||||
pub struct AliasCommand {
|
pub struct AliasCommand {
|
||||||
@ -47,26 +47,21 @@ impl WholeStreamCommand for AliasCommand {
|
|||||||
let mut context = EvaluationContext::from_args(&args, ®istry);
|
let mut context = EvaluationContext::from_args(&args, ®istry);
|
||||||
let input = args.input;
|
let input = args.input;
|
||||||
|
|
||||||
let mut scope = call_info.scope.clone();
|
let scope = call_info.scope.clone();
|
||||||
let evaluated = call_info.evaluate(®istry).await?;
|
let evaluated = call_info.evaluate(®istry).await?;
|
||||||
|
|
||||||
|
let mut vars = IndexMap::new();
|
||||||
if let Some(positional) = &evaluated.args.positional {
|
if let Some(positional) = &evaluated.args.positional {
|
||||||
for (pos, arg) in positional.iter().enumerate() {
|
for (pos, arg) in positional.iter().enumerate() {
|
||||||
scope
|
vars.insert(alias_command.args[pos].0.to_string(), arg.clone());
|
||||||
.vars
|
|
||||||
.insert(alias_command.args[pos].0.to_string(), arg.clone());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let scope = Scope::append_vars(scope, vars);
|
||||||
|
|
||||||
// FIXME: we need to patch up the spans to point at the top-level error
|
// FIXME: we need to patch up the spans to point at the top-level error
|
||||||
Ok(run_block(
|
Ok(run_block(&block, &mut context, input, scope)
|
||||||
&block,
|
.await?
|
||||||
&mut context,
|
.to_output_stream())
|
||||||
input,
|
|
||||||
&scope.it,
|
|
||||||
&scope.vars,
|
|
||||||
&scope.env,
|
|
||||||
)
|
|
||||||
.await?
|
|
||||||
.to_output_stream())
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -133,7 +133,7 @@ impl WholeStreamCommand for RunExternalCommand {
|
|||||||
command,
|
command,
|
||||||
&mut external_context,
|
&mut external_context,
|
||||||
input,
|
input,
|
||||||
&scope,
|
scope,
|
||||||
external_redirection,
|
external_redirection,
|
||||||
)
|
)
|
||||||
.await;
|
.await;
|
||||||
|
@ -3,7 +3,7 @@ use crate::evaluate::evaluate_baseline_expr;
|
|||||||
use crate::prelude::*;
|
use crate::prelude::*;
|
||||||
use log::trace;
|
use log::trace;
|
||||||
use nu_errors::ShellError;
|
use nu_errors::ShellError;
|
||||||
use nu_protocol::{hir::ClassifiedCommand, Signature, SyntaxShape, UntaggedValue, Value};
|
use nu_protocol::{hir::ClassifiedCommand, Scope, Signature, SyntaxShape, UntaggedValue, Value};
|
||||||
|
|
||||||
pub struct SubCommand;
|
pub struct SubCommand;
|
||||||
|
|
||||||
@ -33,7 +33,7 @@ impl WholeStreamCommand for SubCommand {
|
|||||||
registry: &CommandRegistry,
|
registry: &CommandRegistry,
|
||||||
) -> Result<OutputStream, ShellError> {
|
) -> Result<OutputStream, ShellError> {
|
||||||
let registry = Arc::new(registry.clone());
|
let registry = Arc::new(registry.clone());
|
||||||
let scope = Arc::new(args.call_info.scope.clone());
|
let scope = args.call_info.scope.clone();
|
||||||
let call_info = args.evaluate_once(®istry).await?;
|
let call_info = args.evaluate_once(®istry).await?;
|
||||||
|
|
||||||
let block = call_info.args.expect_nth(0)?.clone();
|
let block = call_info.args.expect_nth(0)?.clone();
|
||||||
@ -84,19 +84,11 @@ impl WholeStreamCommand for SubCommand {
|
|||||||
.skip_while(move |item| {
|
.skip_while(move |item| {
|
||||||
let condition = condition.clone();
|
let condition = condition.clone();
|
||||||
let registry = registry.clone();
|
let registry = registry.clone();
|
||||||
let scope = scope.clone();
|
let scope = Scope::append_it(scope.clone(), item.clone());
|
||||||
let item = item.clone();
|
|
||||||
trace!("ITEM = {:?}", item);
|
trace!("ITEM = {:?}", item);
|
||||||
|
|
||||||
async move {
|
async move {
|
||||||
let result = evaluate_baseline_expr(
|
let result = evaluate_baseline_expr(&*condition, ®istry, scope).await;
|
||||||
&*condition,
|
|
||||||
®istry,
|
|
||||||
&item,
|
|
||||||
&scope.vars,
|
|
||||||
&scope.env,
|
|
||||||
)
|
|
||||||
.await;
|
|
||||||
trace!("RESULT = {:?}", result);
|
trace!("RESULT = {:?}", result);
|
||||||
|
|
||||||
!matches!(result, Ok(ref v) if v.is_true())
|
!matches!(result, Ok(ref v) if v.is_true())
|
||||||
|
@ -3,7 +3,7 @@ use crate::evaluate::evaluate_baseline_expr;
|
|||||||
use crate::prelude::*;
|
use crate::prelude::*;
|
||||||
use log::trace;
|
use log::trace;
|
||||||
use nu_errors::ShellError;
|
use nu_errors::ShellError;
|
||||||
use nu_protocol::{hir::ClassifiedCommand, Signature, SyntaxShape, UntaggedValue, Value};
|
use nu_protocol::{hir::ClassifiedCommand, Scope, Signature, SyntaxShape, UntaggedValue, Value};
|
||||||
|
|
||||||
pub struct SubCommand;
|
pub struct SubCommand;
|
||||||
|
|
||||||
@ -33,7 +33,7 @@ impl WholeStreamCommand for SubCommand {
|
|||||||
registry: &CommandRegistry,
|
registry: &CommandRegistry,
|
||||||
) -> Result<OutputStream, ShellError> {
|
) -> Result<OutputStream, ShellError> {
|
||||||
let registry = Arc::new(registry.clone());
|
let registry = Arc::new(registry.clone());
|
||||||
let scope = Arc::new(args.call_info.scope.clone());
|
let scope = args.call_info.scope.clone();
|
||||||
let call_info = args.evaluate_once(®istry).await?;
|
let call_info = args.evaluate_once(®istry).await?;
|
||||||
|
|
||||||
let block = call_info.args.expect_nth(0)?.clone();
|
let block = call_info.args.expect_nth(0)?.clone();
|
||||||
@ -85,18 +85,11 @@ impl WholeStreamCommand for SubCommand {
|
|||||||
let item = item.clone();
|
let item = item.clone();
|
||||||
let condition = condition.clone();
|
let condition = condition.clone();
|
||||||
let registry = registry.clone();
|
let registry = registry.clone();
|
||||||
let scope = scope.clone();
|
let scope = Scope::append_it(scope.clone(), item.clone());
|
||||||
trace!("ITEM = {:?}", item);
|
trace!("ITEM = {:?}", item);
|
||||||
|
|
||||||
async move {
|
async move {
|
||||||
let result = evaluate_baseline_expr(
|
let result = evaluate_baseline_expr(&*condition, ®istry, scope).await;
|
||||||
&*condition,
|
|
||||||
®istry,
|
|
||||||
&item,
|
|
||||||
&scope.vars,
|
|
||||||
&scope.env,
|
|
||||||
)
|
|
||||||
.await;
|
|
||||||
trace!("RESULT = {:?}", result);
|
trace!("RESULT = {:?}", result);
|
||||||
|
|
||||||
matches!(result, Ok(ref v) if v.is_true())
|
matches!(result, Ok(ref v) if v.is_true())
|
||||||
|
@ -70,15 +70,9 @@ async fn process_row(
|
|||||||
let for_block = input.clone();
|
let for_block = input.clone();
|
||||||
let input_stream = once(async { Ok(for_block) }).to_input_stream();
|
let input_stream = once(async { Ok(for_block) }).to_input_stream();
|
||||||
|
|
||||||
let result = run_block(
|
let scope = Scope::append_it(scope, input.clone());
|
||||||
&block,
|
|
||||||
Arc::make_mut(&mut context),
|
let result = run_block(&block, Arc::make_mut(&mut context), input_stream, scope).await;
|
||||||
input_stream,
|
|
||||||
&input,
|
|
||||||
&scope.vars,
|
|
||||||
&scope.env,
|
|
||||||
)
|
|
||||||
.await;
|
|
||||||
|
|
||||||
match result {
|
match result {
|
||||||
Ok(mut stream) => {
|
Ok(mut stream) => {
|
||||||
@ -130,7 +124,8 @@ async fn process_row(
|
|||||||
value: UntaggedValue::Primitive(Primitive::Nothing),
|
value: UntaggedValue::Primitive(Primitive::Nothing),
|
||||||
..
|
..
|
||||||
} => match scope
|
} => match scope
|
||||||
.it
|
.it()
|
||||||
|
.unwrap_or_else(|| UntaggedValue::nothing().into_untagged_value())
|
||||||
.replace_data_at_column_path(&field, replacement.clone())
|
.replace_data_at_column_path(&field, replacement.clone())
|
||||||
{
|
{
|
||||||
Some(v) => OutputStream::one(ReturnSuccess::value(v)),
|
Some(v) => OutputStream::one(ReturnSuccess::value(v)),
|
||||||
@ -160,7 +155,7 @@ async fn update(
|
|||||||
) -> Result<OutputStream, ShellError> {
|
) -> Result<OutputStream, ShellError> {
|
||||||
let registry = registry.clone();
|
let registry = registry.clone();
|
||||||
let name_tag = Arc::new(raw_args.call_info.name_tag.clone());
|
let name_tag = Arc::new(raw_args.call_info.name_tag.clone());
|
||||||
let scope = Arc::new(raw_args.call_info.scope.clone());
|
let scope = raw_args.call_info.scope.clone();
|
||||||
let context = Arc::new(EvaluationContext::from_raw(&raw_args, ®istry));
|
let context = Arc::new(EvaluationContext::from_raw(&raw_args, ®istry));
|
||||||
let (UpdateArgs { field, replacement }, input) = raw_args.process(®istry).await?;
|
let (UpdateArgs { field, replacement }, input) = raw_args.process(®istry).await?;
|
||||||
let replacement = Arc::new(replacement);
|
let replacement = Arc::new(replacement);
|
||||||
|
@ -3,7 +3,9 @@ use crate::commands::WholeStreamCommand;
|
|||||||
use crate::evaluate::evaluate_baseline_expr;
|
use crate::evaluate::evaluate_baseline_expr;
|
||||||
use crate::prelude::*;
|
use crate::prelude::*;
|
||||||
use nu_errors::ShellError;
|
use nu_errors::ShellError;
|
||||||
use nu_protocol::{hir::Block, hir::ClassifiedCommand, ReturnSuccess, Signature, SyntaxShape};
|
use nu_protocol::{
|
||||||
|
hir::Block, hir::ClassifiedCommand, ReturnSuccess, Scope, Signature, SyntaxShape,
|
||||||
|
};
|
||||||
|
|
||||||
pub struct Where;
|
pub struct Where;
|
||||||
|
|
||||||
@ -68,7 +70,7 @@ async fn where_command(
|
|||||||
registry: &CommandRegistry,
|
registry: &CommandRegistry,
|
||||||
) -> Result<OutputStream, ShellError> {
|
) -> Result<OutputStream, ShellError> {
|
||||||
let registry = Arc::new(registry.clone());
|
let registry = Arc::new(registry.clone());
|
||||||
let scope = Arc::new(raw_args.call_info.scope.clone());
|
let scope = raw_args.call_info.scope.clone();
|
||||||
let tag = raw_args.call_info.name_tag.clone();
|
let tag = raw_args.call_info.name_tag.clone();
|
||||||
let (WhereArgs { block }, input) = raw_args.process(®istry).await?;
|
let (WhereArgs { block }, input) = raw_args.process(®istry).await?;
|
||||||
let condition = {
|
let condition = {
|
||||||
@ -104,13 +106,11 @@ async fn where_command(
|
|||||||
.filter_map(move |input| {
|
.filter_map(move |input| {
|
||||||
let condition = condition.clone();
|
let condition = condition.clone();
|
||||||
let registry = registry.clone();
|
let registry = registry.clone();
|
||||||
let scope = scope.clone();
|
let scope = Scope::append_it(scope.clone(), input.clone());
|
||||||
|
|
||||||
async move {
|
async move {
|
||||||
//FIXME: should we use the scope that's brought in as well?
|
//FIXME: should we use the scope that's brought in as well?
|
||||||
let condition =
|
let condition = evaluate_baseline_expr(&condition, &*registry, scope).await;
|
||||||
evaluate_baseline_expr(&condition, &*registry, &input, &scope.vars, &scope.env)
|
|
||||||
.await;
|
|
||||||
|
|
||||||
match condition {
|
match condition {
|
||||||
Ok(condition) => match condition.as_bool() {
|
Ok(condition) => match condition.as_bool() {
|
||||||
|
@ -2,7 +2,9 @@ use crate::commands::classified::block::run_block;
|
|||||||
use crate::commands::WholeStreamCommand;
|
use crate::commands::WholeStreamCommand;
|
||||||
use crate::prelude::*;
|
use crate::prelude::*;
|
||||||
use nu_errors::ShellError;
|
use nu_errors::ShellError;
|
||||||
use nu_protocol::{hir::Block, Signature, SpannedTypeName, SyntaxShape, UntaggedValue, Value};
|
use nu_protocol::{
|
||||||
|
hir::Block, Scope, Signature, SpannedTypeName, SyntaxShape, UntaggedValue, Value,
|
||||||
|
};
|
||||||
|
|
||||||
pub struct WithEnv;
|
pub struct WithEnv;
|
||||||
|
|
||||||
@ -77,23 +79,23 @@ async fn with_env(
|
|||||||
let registry = registry.clone();
|
let registry = registry.clone();
|
||||||
|
|
||||||
let mut context = EvaluationContext::from_raw(&raw_args, ®istry);
|
let mut context = EvaluationContext::from_raw(&raw_args, ®istry);
|
||||||
let mut scope = raw_args.call_info.scope.clone();
|
let scope = raw_args.call_info.scope.clone();
|
||||||
let (WithEnvArgs { variable, block }, input) = raw_args.process(®istry).await?;
|
let (WithEnvArgs { variable, block }, input) = raw_args.process(®istry).await?;
|
||||||
|
|
||||||
|
let mut env = IndexMap::new();
|
||||||
|
|
||||||
match &variable.value {
|
match &variable.value {
|
||||||
UntaggedValue::Table(table) => {
|
UntaggedValue::Table(table) => {
|
||||||
if table.len() == 1 {
|
if table.len() == 1 {
|
||||||
// single row([[X W]; [Y Z]])
|
// single row([[X W]; [Y Z]])
|
||||||
for (k, v) in table[0].row_entries() {
|
for (k, v) in table[0].row_entries() {
|
||||||
scope.env.insert(k.clone(), v.convert_to_string());
|
env.insert(k.clone(), v.convert_to_string());
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// primitive values([X Y W Z])
|
// primitive values([X Y W Z])
|
||||||
for row in table.chunks(2) {
|
for row in table.chunks(2) {
|
||||||
if row.len() == 2 && row[0].is_primitive() && row[1].is_primitive() {
|
if row.len() == 2 && row[0].is_primitive() && row[1].is_primitive() {
|
||||||
scope
|
env.insert(row[0].convert_to_string(), row[1].convert_to_string());
|
||||||
.env
|
|
||||||
.insert(row[0].convert_to_string(), row[1].convert_to_string());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -101,7 +103,7 @@ async fn with_env(
|
|||||||
// when get object by `open x.json` or `from json`
|
// when get object by `open x.json` or `from json`
|
||||||
UntaggedValue::Row(row) => {
|
UntaggedValue::Row(row) => {
|
||||||
for (k, v) in &row.entries {
|
for (k, v) in &row.entries {
|
||||||
scope.env.insert(k.clone(), v.convert_to_string());
|
env.insert(k.clone(), v.convert_to_string());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
@ -112,15 +114,9 @@ async fn with_env(
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
let result = run_block(
|
let scope = Scope::append_env(scope, env);
|
||||||
&block,
|
|
||||||
&mut context,
|
let result = run_block(&block, &mut context, input, scope).await;
|
||||||
input,
|
|
||||||
&scope.it,
|
|
||||||
&scope.vars,
|
|
||||||
&scope.env,
|
|
||||||
)
|
|
||||||
.await;
|
|
||||||
|
|
||||||
result.map(|x| x.to_output_stream())
|
result.map(|x| x.to_output_stream())
|
||||||
}
|
}
|
||||||
|
@ -4,18 +4,18 @@ use crate::evaluate::evaluate_baseline_expr;
|
|||||||
use indexmap::IndexMap;
|
use indexmap::IndexMap;
|
||||||
use nu_errors::ShellError;
|
use nu_errors::ShellError;
|
||||||
use nu_protocol::{hir, EvaluatedArgs, Scope, UntaggedValue, Value};
|
use nu_protocol::{hir, EvaluatedArgs, Scope, UntaggedValue, Value};
|
||||||
|
use std::sync::Arc;
|
||||||
|
|
||||||
pub(crate) async fn evaluate_args(
|
pub(crate) async fn evaluate_args(
|
||||||
call: &hir::Call,
|
call: &hir::Call,
|
||||||
registry: &CommandRegistry,
|
registry: &CommandRegistry,
|
||||||
scope: &Scope,
|
scope: Arc<Scope>,
|
||||||
) -> Result<EvaluatedArgs, ShellError> {
|
) -> Result<EvaluatedArgs, ShellError> {
|
||||||
let mut positional_args: Vec<Value> = vec![];
|
let mut positional_args: Vec<Value> = vec![];
|
||||||
|
|
||||||
if let Some(positional) = &call.positional {
|
if let Some(positional) = &call.positional {
|
||||||
for pos in positional {
|
for pos in positional {
|
||||||
let result =
|
let result = evaluate_baseline_expr(pos, registry, scope.clone()).await?;
|
||||||
evaluate_baseline_expr(pos, registry, &scope.it, &scope.vars, &scope.env).await?;
|
|
||||||
positional_args.push(result);
|
positional_args.push(result);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -37,8 +37,7 @@ pub(crate) async fn evaluate_args(
|
|||||||
hir::NamedValue::Value(_, expr) => {
|
hir::NamedValue::Value(_, expr) => {
|
||||||
named_args.insert(
|
named_args.insert(
|
||||||
name.clone(),
|
name.clone(),
|
||||||
evaluate_baseline_expr(expr, registry, &scope.it, &scope.vars, &scope.env)
|
evaluate_baseline_expr(expr, registry, scope.clone()).await?,
|
||||||
.await?,
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
_ => {}
|
_ => {}
|
||||||
|
@ -7,16 +7,14 @@ use log::trace;
|
|||||||
use nu_errors::{ArgumentError, ShellError};
|
use nu_errors::{ArgumentError, ShellError};
|
||||||
use nu_protocol::hir::{self, Expression, ExternalRedirection, RangeOperator, SpannedExpression};
|
use nu_protocol::hir::{self, Expression, ExternalRedirection, RangeOperator, SpannedExpression};
|
||||||
use nu_protocol::{
|
use nu_protocol::{
|
||||||
ColumnPath, Primitive, RangeInclusion, UnspannedPathMember, UntaggedValue, Value,
|
ColumnPath, Primitive, RangeInclusion, Scope, UnspannedPathMember, UntaggedValue, Value,
|
||||||
};
|
};
|
||||||
|
|
||||||
#[async_recursion]
|
#[async_recursion]
|
||||||
pub(crate) async fn evaluate_baseline_expr(
|
pub(crate) async fn evaluate_baseline_expr(
|
||||||
expr: &SpannedExpression,
|
expr: &SpannedExpression,
|
||||||
registry: &CommandRegistry,
|
registry: &CommandRegistry,
|
||||||
it: &Value,
|
scope: Arc<Scope>,
|
||||||
vars: &IndexMap<String, Value>,
|
|
||||||
env: &IndexMap<String, String>,
|
|
||||||
) -> Result<Value, ShellError> {
|
) -> Result<Value, ShellError> {
|
||||||
let tag = Tag {
|
let tag = Tag {
|
||||||
span: expr.span,
|
span: expr.span,
|
||||||
@ -33,14 +31,14 @@ pub(crate) async fn evaluate_baseline_expr(
|
|||||||
Expression::Synthetic(hir::Synthetic::String(s)) => {
|
Expression::Synthetic(hir::Synthetic::String(s)) => {
|
||||||
Ok(UntaggedValue::string(s).into_untagged_value())
|
Ok(UntaggedValue::string(s).into_untagged_value())
|
||||||
}
|
}
|
||||||
Expression::Variable(var) => evaluate_reference(&var, it, vars, env, tag),
|
Expression::Variable(var) => evaluate_reference(&var, scope, tag),
|
||||||
Expression::Command => unimplemented!(),
|
Expression::Command => unimplemented!(),
|
||||||
Expression::Invocation(block) => evaluate_invocation(block, registry, it, vars, env).await,
|
Expression::Invocation(block) => evaluate_invocation(block, registry, scope).await,
|
||||||
Expression::ExternalCommand(_) => unimplemented!(),
|
Expression::ExternalCommand(_) => unimplemented!(),
|
||||||
Expression::Binary(binary) => {
|
Expression::Binary(binary) => {
|
||||||
// TODO: If we want to add short-circuiting, we'll need to move these down
|
// TODO: If we want to add short-circuiting, we'll need to move these down
|
||||||
let left = evaluate_baseline_expr(&binary.left, registry, it, vars, env).await?;
|
let left = evaluate_baseline_expr(&binary.left, registry, scope.clone()).await?;
|
||||||
let right = evaluate_baseline_expr(&binary.right, registry, it, vars, env).await?;
|
let right = evaluate_baseline_expr(&binary.right, registry, scope).await?;
|
||||||
|
|
||||||
trace!("left={:?} right={:?}", left.value, right.value);
|
trace!("left={:?} right={:?}", left.value, right.value);
|
||||||
|
|
||||||
@ -62,13 +60,13 @@ pub(crate) async fn evaluate_baseline_expr(
|
|||||||
}
|
}
|
||||||
Expression::Range(range) => {
|
Expression::Range(range) => {
|
||||||
let left = if let Some(left) = &range.left {
|
let left = if let Some(left) = &range.left {
|
||||||
evaluate_baseline_expr(&left, registry, it, vars, env).await?
|
evaluate_baseline_expr(&left, registry, scope.clone()).await?
|
||||||
} else {
|
} else {
|
||||||
Value::nothing()
|
Value::nothing()
|
||||||
};
|
};
|
||||||
|
|
||||||
let right = if let Some(right) = &range.right {
|
let right = if let Some(right) = &range.right {
|
||||||
evaluate_baseline_expr(&right, registry, it, vars, env).await?
|
evaluate_baseline_expr(&right, registry, scope).await?
|
||||||
} else {
|
} else {
|
||||||
Value::nothing()
|
Value::nothing()
|
||||||
};
|
};
|
||||||
@ -94,7 +92,7 @@ pub(crate) async fn evaluate_baseline_expr(
|
|||||||
let mut output_headers = vec![];
|
let mut output_headers = vec![];
|
||||||
|
|
||||||
for expr in headers {
|
for expr in headers {
|
||||||
let val = evaluate_baseline_expr(&expr, registry, it, vars, env).await?;
|
let val = evaluate_baseline_expr(&expr, registry, scope.clone()).await?;
|
||||||
|
|
||||||
let header = val.as_string()?;
|
let header = val.as_string()?;
|
||||||
output_headers.push(header);
|
output_headers.push(header);
|
||||||
@ -122,7 +120,7 @@ pub(crate) async fn evaluate_baseline_expr(
|
|||||||
|
|
||||||
let mut row_output = IndexMap::new();
|
let mut row_output = IndexMap::new();
|
||||||
for cell in output_headers.iter().zip(row.iter()) {
|
for cell in output_headers.iter().zip(row.iter()) {
|
||||||
let val = evaluate_baseline_expr(&cell.1, registry, it, vars, env).await?;
|
let val = evaluate_baseline_expr(&cell.1, registry, scope.clone()).await?;
|
||||||
row_output.insert(cell.0.clone(), val);
|
row_output.insert(cell.0.clone(), val);
|
||||||
}
|
}
|
||||||
output_table.push(UntaggedValue::row(row_output).into_value(tag.clone()));
|
output_table.push(UntaggedValue::row(row_output).into_value(tag.clone()));
|
||||||
@ -134,7 +132,7 @@ pub(crate) async fn evaluate_baseline_expr(
|
|||||||
let mut exprs = vec![];
|
let mut exprs = vec![];
|
||||||
|
|
||||||
for expr in list {
|
for expr in list {
|
||||||
let expr = evaluate_baseline_expr(&expr, registry, it, vars, env).await?;
|
let expr = evaluate_baseline_expr(&expr, registry, scope.clone()).await?;
|
||||||
exprs.push(expr);
|
exprs.push(expr);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -142,7 +140,7 @@ pub(crate) async fn evaluate_baseline_expr(
|
|||||||
}
|
}
|
||||||
Expression::Block(block) => Ok(UntaggedValue::Block(block.clone()).into_value(&tag)),
|
Expression::Block(block) => Ok(UntaggedValue::Block(block.clone()).into_value(&tag)),
|
||||||
Expression::Path(path) => {
|
Expression::Path(path) => {
|
||||||
let value = evaluate_baseline_expr(&path.head, registry, it, vars, env).await?;
|
let value = evaluate_baseline_expr(&path.head, registry, scope).await?;
|
||||||
let mut item = value;
|
let mut item = value;
|
||||||
|
|
||||||
for member in &path.tail {
|
for member in &path.tail {
|
||||||
@ -208,15 +206,20 @@ fn evaluate_literal(literal: &hir::Literal, span: Span) -> Value {
|
|||||||
|
|
||||||
fn evaluate_reference(
|
fn evaluate_reference(
|
||||||
name: &hir::Variable,
|
name: &hir::Variable,
|
||||||
it: &Value,
|
scope: Arc<Scope>,
|
||||||
vars: &IndexMap<String, Value>,
|
|
||||||
env: &IndexMap<String, String>,
|
|
||||||
tag: Tag,
|
tag: Tag,
|
||||||
) -> Result<Value, ShellError> {
|
) -> Result<Value, ShellError> {
|
||||||
match name {
|
match name {
|
||||||
hir::Variable::It(_) => Ok(it.clone()),
|
hir::Variable::It(_) => match scope.it() {
|
||||||
|
Some(v) => Ok(v),
|
||||||
|
None => Err(ShellError::labeled_error(
|
||||||
|
"$it variable not in scope",
|
||||||
|
"not in scope (are you missing an 'each'?)",
|
||||||
|
tag.span,
|
||||||
|
)),
|
||||||
|
},
|
||||||
hir::Variable::Other(name, _) => match name {
|
hir::Variable::Other(name, _) => match name {
|
||||||
x if x == "$nu" => crate::evaluate::variables::nu(env, tag),
|
x if x == "$nu" => crate::evaluate::variables::nu(&scope.env(), tag),
|
||||||
x if x == "$true" => Ok(Value {
|
x if x == "$true" => Ok(Value {
|
||||||
value: UntaggedValue::boolean(true),
|
value: UntaggedValue::boolean(true),
|
||||||
tag,
|
tag,
|
||||||
@ -225,10 +228,14 @@ fn evaluate_reference(
|
|||||||
value: UntaggedValue::boolean(false),
|
value: UntaggedValue::boolean(false),
|
||||||
tag,
|
tag,
|
||||||
}),
|
}),
|
||||||
x => Ok(vars
|
x => match scope.var(x) {
|
||||||
.get(x)
|
Some(v) => Ok(v),
|
||||||
.cloned()
|
None => Err(ShellError::labeled_error(
|
||||||
.unwrap_or_else(|| UntaggedValue::nothing().into_value(tag))),
|
"Variable not in scope",
|
||||||
|
"unknown variable",
|
||||||
|
tag.span,
|
||||||
|
)),
|
||||||
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -236,20 +243,21 @@ fn evaluate_reference(
|
|||||||
async fn evaluate_invocation(
|
async fn evaluate_invocation(
|
||||||
block: &hir::Block,
|
block: &hir::Block,
|
||||||
registry: &CommandRegistry,
|
registry: &CommandRegistry,
|
||||||
it: &Value,
|
scope: Arc<Scope>,
|
||||||
vars: &IndexMap<String, Value>,
|
|
||||||
env: &IndexMap<String, String>,
|
|
||||||
) -> Result<Value, ShellError> {
|
) -> Result<Value, ShellError> {
|
||||||
// FIXME: we should use a real context here
|
// FIXME: we should use a real context here
|
||||||
let mut context = EvaluationContext::basic()?;
|
let mut context = EvaluationContext::basic()?;
|
||||||
context.registry = registry.clone();
|
context.registry = registry.clone();
|
||||||
|
|
||||||
let input = InputStream::one(it.clone());
|
let input = match scope.it() {
|
||||||
|
Some(it) => InputStream::one(it),
|
||||||
|
None => InputStream::empty(),
|
||||||
|
};
|
||||||
|
|
||||||
let mut block = block.clone();
|
let mut block = block.clone();
|
||||||
block.set_redirect(ExternalRedirection::Stdout);
|
block.set_redirect(ExternalRedirection::Stdout);
|
||||||
|
|
||||||
let result = run_block(&block, &mut context, input, it, vars, env).await?;
|
let result = run_block(&block, &mut context, input, scope).await?;
|
||||||
|
|
||||||
let output = result.into_vec().await;
|
let output = result.into_vec().await;
|
||||||
|
|
||||||
|
@ -152,18 +152,18 @@ impl EvaluationContext {
|
|||||||
command: Command,
|
command: Command,
|
||||||
name_tag: Tag,
|
name_tag: Tag,
|
||||||
args: hir::Call,
|
args: hir::Call,
|
||||||
scope: &Scope,
|
scope: Arc<Scope>,
|
||||||
input: InputStream,
|
input: InputStream,
|
||||||
) -> Result<OutputStream, ShellError> {
|
) -> Result<OutputStream, ShellError> {
|
||||||
let command_args = self.command_args(args, input, name_tag, scope);
|
let command_args = self.command_args(args, input, name_tag, scope);
|
||||||
command.run(command_args, self.registry()).await
|
command.run(command_args, self.registry()).await
|
||||||
}
|
}
|
||||||
|
|
||||||
fn call_info(&self, args: hir::Call, name_tag: Tag, scope: &Scope) -> UnevaluatedCallInfo {
|
fn call_info(&self, args: hir::Call, name_tag: Tag, scope: Arc<Scope>) -> UnevaluatedCallInfo {
|
||||||
UnevaluatedCallInfo {
|
UnevaluatedCallInfo {
|
||||||
args,
|
args,
|
||||||
name_tag,
|
name_tag,
|
||||||
scope: scope.clone(),
|
scope,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -172,7 +172,7 @@ impl EvaluationContext {
|
|||||||
args: hir::Call,
|
args: hir::Call,
|
||||||
input: InputStream,
|
input: InputStream,
|
||||||
name_tag: Tag,
|
name_tag: Tag,
|
||||||
scope: &Scope,
|
scope: Arc<Scope>,
|
||||||
) -> CommandArgs {
|
) -> CommandArgs {
|
||||||
CommandArgs {
|
CommandArgs {
|
||||||
host: self.host.clone(),
|
host: self.host.clone(),
|
||||||
|
@ -1,9 +1,8 @@
|
|||||||
use futures::executor::block_on;
|
use futures::executor::block_on;
|
||||||
|
|
||||||
use crate::prelude::*;
|
|
||||||
use nu_errors::ShellError;
|
use nu_errors::ShellError;
|
||||||
use nu_protocol::hir::ClassifiedBlock;
|
use nu_protocol::hir::ClassifiedBlock;
|
||||||
use nu_protocol::{ShellTypeName, Value};
|
use nu_protocol::{Scope, ShellTypeName, Value};
|
||||||
|
|
||||||
use crate::commands::classified::block::run_block;
|
use crate::commands::classified::block::run_block;
|
||||||
use crate::commands::{whole_stream_command, BuildString, Each, Echo, StrCollect};
|
use crate::commands::{whole_stream_command, BuildString, Each, Echo, StrCollect};
|
||||||
@ -83,17 +82,12 @@ async fn evaluate_block(
|
|||||||
let input_stream = InputStream::empty();
|
let input_stream = InputStream::empty();
|
||||||
let env = ctx.get_env();
|
let env = ctx.get_env();
|
||||||
|
|
||||||
Ok(run_block(
|
let scope = Scope::from_env(env);
|
||||||
&block.block,
|
|
||||||
ctx,
|
Ok(run_block(&block.block, ctx, input_stream, scope)
|
||||||
input_stream,
|
.await?
|
||||||
&Value::nothing(),
|
.into_vec()
|
||||||
&IndexMap::new(),
|
.await)
|
||||||
&env,
|
|
||||||
)
|
|
||||||
.await?
|
|
||||||
.into_vec()
|
|
||||||
.await)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO probably something already available to do this
|
// TODO probably something already available to do this
|
||||||
|
@ -2,30 +2,121 @@ use crate::value::Value;
|
|||||||
use indexmap::IndexMap;
|
use indexmap::IndexMap;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use std::fmt::Debug;
|
use std::fmt::Debug;
|
||||||
|
use std::sync::Arc;
|
||||||
|
|
||||||
/// An evaluation scope. Scopes map variable names to Values and aid in evaluating blocks and expressions.
|
/// An evaluation scope. Scopes map variable names to Values and aid in evaluating blocks and expressions.
|
||||||
/// Additionally, holds the value for the special $it variable, a variable used to refer to the value passing
|
/// Additionally, holds the value for the special $it variable, a variable used to refer to the value passing
|
||||||
/// through the pipeline at that moment
|
/// through the pipeline at that moment
|
||||||
#[derive(Deserialize, Serialize, Debug, Clone)]
|
#[derive(Deserialize, Serialize, Debug, Clone)]
|
||||||
pub struct Scope {
|
pub struct Scope {
|
||||||
pub it: Value,
|
vars: IndexMap<String, Value>,
|
||||||
pub vars: IndexMap<String, Value>,
|
env: IndexMap<String, String>,
|
||||||
pub env: IndexMap<String, String>,
|
parent: Option<Arc<Scope>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Scope {
|
impl Scope {
|
||||||
/// Create an empty scope
|
pub fn vars(&self) -> IndexMap<String, Value> {
|
||||||
pub fn new() -> Scope {
|
//FIXME: should this be an interator?
|
||||||
Scope {
|
|
||||||
it: Value::nothing(),
|
let mut output = IndexMap::new();
|
||||||
vars: IndexMap::new(),
|
|
||||||
env: IndexMap::new(),
|
for v in &self.vars {
|
||||||
|
output.insert(v.0.clone(), v.1.clone());
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some(parent) = &self.parent {
|
||||||
|
for v in parent.vars() {
|
||||||
|
if !output.contains_key(&v.0) {
|
||||||
|
output.insert(v.0.clone(), v.1.clone());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
output
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn env(&self) -> IndexMap<String, String> {
|
||||||
|
//FIXME: should this be an interator?
|
||||||
|
|
||||||
|
let mut output = IndexMap::new();
|
||||||
|
|
||||||
|
for v in &self.env {
|
||||||
|
output.insert(v.0.clone(), v.1.clone());
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some(parent) = &self.parent {
|
||||||
|
for v in parent.env() {
|
||||||
|
if !output.contains_key(&v.0) {
|
||||||
|
output.insert(v.0.clone(), v.1.clone());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
output
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn var(&self, name: &str) -> Option<Value> {
|
||||||
|
if let Some(value) = self.vars().get(name) {
|
||||||
|
Some(value.clone())
|
||||||
|
} else {
|
||||||
|
None
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
impl Default for Scope {
|
pub fn it(&self) -> Option<Value> {
|
||||||
fn default() -> Scope {
|
self.var("$it")
|
||||||
Scope::new()
|
}
|
||||||
|
|
||||||
|
pub fn from_env(env: IndexMap<String, String>) -> Arc<Scope> {
|
||||||
|
Arc::new(Scope {
|
||||||
|
vars: IndexMap::new(),
|
||||||
|
env,
|
||||||
|
parent: None,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn append_it(this: Arc<Self>, it: Value) -> Arc<Scope> {
|
||||||
|
let mut vars = IndexMap::new();
|
||||||
|
vars.insert("$it".into(), it);
|
||||||
|
Arc::new(Scope {
|
||||||
|
vars,
|
||||||
|
env: IndexMap::new(),
|
||||||
|
parent: Some(this),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn append_var(this: Arc<Self>, name: String, value: Value) -> Arc<Scope> {
|
||||||
|
let mut vars = IndexMap::new();
|
||||||
|
vars.insert(name, value);
|
||||||
|
Arc::new(Scope {
|
||||||
|
vars,
|
||||||
|
env: IndexMap::new(),
|
||||||
|
parent: Some(this),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn append_vars(this: Arc<Self>, vars: IndexMap<String, Value>) -> Arc<Scope> {
|
||||||
|
Arc::new(Scope {
|
||||||
|
vars,
|
||||||
|
env: IndexMap::new(),
|
||||||
|
parent: Some(this),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn append_env(this: Arc<Self>, env: IndexMap<String, String>) -> Arc<Scope> {
|
||||||
|
Arc::new(Scope {
|
||||||
|
vars: IndexMap::new(),
|
||||||
|
env,
|
||||||
|
parent: Some(this),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Create an empty scope
|
||||||
|
pub fn create() -> Arc<Scope> {
|
||||||
|
Arc::new(Scope {
|
||||||
|
vars: IndexMap::new(),
|
||||||
|
env: IndexMap::new(),
|
||||||
|
parent: None,
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user