mirror of
https://github.com/nushell/nushell.git
synced 2025-03-30 01:28:11 +01:00
Fix warnings and split Scope (#1902)
This commit is contained in:
parent
9567c1f564
commit
fa812849b8
@ -13,7 +13,7 @@ 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, Scope, Signature, UntaggedValue, Value};
|
use nu_protocol::{Primitive, ReturnSuccess, Signature, UntaggedValue, Value};
|
||||||
|
|
||||||
use log::{debug, trace};
|
use log::{debug, trace};
|
||||||
use rustyline::error::ReadlineError;
|
use rustyline::error::ReadlineError;
|
||||||
@ -870,7 +870,16 @@ async fn process_line(
|
|||||||
|
|
||||||
trace!("{:#?}", classified_block);
|
trace!("{:#?}", classified_block);
|
||||||
let env = ctx.get_env();
|
let env = ctx.get_env();
|
||||||
match run_block(&classified_block.block, ctx, input_stream, &Scope::env(env)).await {
|
match run_block(
|
||||||
|
&classified_block.block,
|
||||||
|
ctx,
|
||||||
|
input_stream,
|
||||||
|
&Value::nothing(),
|
||||||
|
&IndexMap::new(),
|
||||||
|
&env,
|
||||||
|
)
|
||||||
|
.await
|
||||||
|
{
|
||||||
Ok(input) => {
|
Ok(input) => {
|
||||||
// Running a pipeline gives us back a stream that we can then
|
// Running a pipeline gives us back a stream that we can then
|
||||||
// work through. At the top level, we just want to pull on the
|
// work through. At the top level, we just want to pull on the
|
||||||
|
@ -368,7 +368,7 @@ fn create_default_command_args(context: &RunnableContextWithoutInput) -> RawComm
|
|||||||
is_last: true,
|
is_last: true,
|
||||||
},
|
},
|
||||||
name_tag: context.name.clone(),
|
name_tag: context.name.clone(),
|
||||||
scope: Scope::empty(),
|
scope: Scope::new(),
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -6,14 +6,16 @@ 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, Scope, UntaggedValue, Value};
|
use nu_protocol::{ReturnSuccess, 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 Context,
|
ctx: &mut Context,
|
||||||
mut input: InputStream,
|
mut input: InputStream,
|
||||||
scope: &Scope,
|
it: &Value,
|
||||||
|
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 {
|
||||||
@ -52,7 +54,7 @@ pub(crate) async fn run_block(
|
|||||||
return Err(e);
|
return Err(e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
output = run_pipeline(pipeline, ctx, input, scope).await;
|
output = run_pipeline(pipeline, ctx, input, it, vars, env).await;
|
||||||
|
|
||||||
input = InputStream::empty();
|
input = InputStream::empty();
|
||||||
}
|
}
|
||||||
@ -64,10 +66,11 @@ async fn run_pipeline(
|
|||||||
commands: &Commands,
|
commands: &Commands,
|
||||||
ctx: &mut Context,
|
ctx: &mut Context,
|
||||||
mut input: InputStream,
|
mut input: InputStream,
|
||||||
scope: &Scope,
|
it: &Value,
|
||||||
|
vars: &IndexMap<String, Value>,
|
||||||
|
env: &IndexMap<String, String>,
|
||||||
) -> Result<InputStream, ShellError> {
|
) -> Result<InputStream, ShellError> {
|
||||||
let mut iter = commands.list.clone().into_iter().peekable();
|
let mut iter = commands.list.clone().into_iter().peekable();
|
||||||
|
|
||||||
loop {
|
loop {
|
||||||
let item: Option<ClassifiedCommand> = iter.next();
|
let item: Option<ClassifiedCommand> = iter.next();
|
||||||
let next: Option<&ClassifiedCommand> = iter.peek();
|
let next: Option<&ClassifiedCommand> = iter.peek();
|
||||||
@ -78,13 +81,13 @@ async fn run_pipeline(
|
|||||||
}
|
}
|
||||||
|
|
||||||
(Some(ClassifiedCommand::Expr(expr)), _) => {
|
(Some(ClassifiedCommand::Expr(expr)), _) => {
|
||||||
run_expression_block(*expr, ctx, input, scope).await?
|
run_expression_block(*expr, ctx, it, vars, env).await?
|
||||||
}
|
}
|
||||||
(Some(ClassifiedCommand::Error(err)), _) => return Err(err.into()),
|
(Some(ClassifiedCommand::Error(err)), _) => return Err(err.into()),
|
||||||
(_, Some(ClassifiedCommand::Error(err))) => return Err(err.clone().into()),
|
(_, Some(ClassifiedCommand::Error(err))) => return Err(err.clone().into()),
|
||||||
|
|
||||||
(Some(ClassifiedCommand::Internal(left)), _) => {
|
(Some(ClassifiedCommand::Internal(left)), _) => {
|
||||||
run_internal_command(left, ctx, input, scope)?
|
run_internal_command(left, ctx, input, it, vars, env)?
|
||||||
}
|
}
|
||||||
|
|
||||||
(None, _) => break,
|
(None, _) => break,
|
||||||
|
@ -6,22 +6,22 @@ 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::Scope;
|
use nu_protocol::Value;
|
||||||
|
|
||||||
pub(crate) async fn run_expression_block(
|
pub(crate) async fn run_expression_block(
|
||||||
expr: SpannedExpression,
|
expr: SpannedExpression,
|
||||||
context: &mut Context,
|
context: &mut Context,
|
||||||
_input: InputStream,
|
it: &Value,
|
||||||
scope: &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", "->");
|
||||||
trace!(target: "nu::run::expr", "{:?}", expr);
|
trace!(target: "nu::run::expr", "{:?}", expr);
|
||||||
}
|
}
|
||||||
|
|
||||||
let scope = scope.clone();
|
|
||||||
let registry = context.registry().clone();
|
let registry = context.registry().clone();
|
||||||
let output = evaluate_baseline_expr(&expr, ®istry, &scope).await?;
|
let output = evaluate_baseline_expr(&expr, ®istry, it, vars, env).await?;
|
||||||
|
|
||||||
Ok(once(async { Ok(output) }).to_input_stream())
|
Ok(once(async { Ok(output) }).to_input_stream())
|
||||||
}
|
}
|
||||||
|
@ -115,7 +115,9 @@ 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 = evaluate_baseline_expr(arg, &context.registry, scope).await?;
|
let value =
|
||||||
|
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
|
||||||
// what value we would put in its place.
|
// what value we would put in its place.
|
||||||
@ -509,7 +511,7 @@ mod tests {
|
|||||||
let mut ctx = Context::basic().expect("There was a problem creating a basic context.");
|
let mut ctx = Context::basic().expect("There was a problem creating a basic context.");
|
||||||
|
|
||||||
assert!(
|
assert!(
|
||||||
run_external_command(cmd, &mut ctx, input, &Scope::empty(), false)
|
run_external_command(cmd, &mut ctx, input, &Scope::new(), false)
|
||||||
.await
|
.await
|
||||||
.is_err()
|
.is_err()
|
||||||
);
|
);
|
||||||
|
@ -11,13 +11,20 @@ pub(crate) fn run_internal_command(
|
|||||||
command: InternalCommand,
|
command: InternalCommand,
|
||||||
context: &mut Context,
|
context: &mut Context,
|
||||||
input: InputStream,
|
input: InputStream,
|
||||||
scope: &Scope,
|
it: &Value,
|
||||||
|
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);
|
||||||
|
|
||||||
@ -26,14 +33,14 @@ pub(crate) 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,
|
||||||
objects,
|
objects,
|
||||||
)
|
)
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut result = trace_out_stream!(target: "nu::trace_stream::internal", "output" = result);
|
let mut result = trace_out_stream!(target: "nu::trace_stream::internal", "output" = result);
|
||||||
let mut context = context.clone();
|
let mut context = context.clone();
|
||||||
let scope = scope.clone();
|
// let scope = scope.clone();
|
||||||
|
|
||||||
let stream = async_stream! {
|
let stream = async_stream! {
|
||||||
let mut soft_errs: Vec<ShellError> = vec![];
|
let mut soft_errs: Vec<ShellError> = vec![];
|
||||||
|
@ -35,7 +35,7 @@ impl UnevaluatedCallInfo {
|
|||||||
it: &Value,
|
it: &Value,
|
||||||
) -> Result<CallInfo, ShellError> {
|
) -> Result<CallInfo, ShellError> {
|
||||||
let mut scope = self.scope.clone();
|
let mut scope = self.scope.clone();
|
||||||
scope = scope.set_it(it.clone());
|
scope.it = it.clone();
|
||||||
let args = evaluate_args(&self.args, registry, &scope).await?;
|
let args = evaluate_args(&self.args, registry, &scope).await?;
|
||||||
|
|
||||||
Ok(CallInfo {
|
Ok(CallInfo {
|
||||||
|
@ -84,19 +84,20 @@ fn each(raw_args: CommandArgs, registry: &CommandRegistry) -> Result<OutputStrea
|
|||||||
let (each_args, mut input): (EachArgs, _) = raw_args.process(®istry).await?;
|
let (each_args, mut input): (EachArgs, _) = raw_args.process(®istry).await?;
|
||||||
let block = each_args.block;
|
let block = each_args.block;
|
||||||
while let Some(input) = input.next().await {
|
while let Some(input) = input.next().await {
|
||||||
|
|
||||||
let input_clone = input.clone();
|
let input_clone = input.clone();
|
||||||
let input_stream = if is_expanded_it_usage(&head) {
|
let input_stream = if is_expanded_it_usage(&head) {
|
||||||
InputStream::empty()
|
InputStream::empty()
|
||||||
} else {
|
} else {
|
||||||
once(async { Ok(input) }).to_input_stream()
|
once(async { Ok(input_clone) }).to_input_stream()
|
||||||
};
|
};
|
||||||
|
|
||||||
let result = run_block(
|
let result = run_block(
|
||||||
&block,
|
&block,
|
||||||
&mut context,
|
&mut context,
|
||||||
input_stream,
|
input_stream,
|
||||||
&scope.clone().set_it(input_clone),
|
&input,
|
||||||
|
&scope.vars,
|
||||||
|
&scope.env
|
||||||
).await;
|
).await;
|
||||||
|
|
||||||
match result {
|
match result {
|
||||||
|
@ -62,7 +62,6 @@ fn format_command(
|
|||||||
let commands = format_pattern;
|
let commands = format_pattern;
|
||||||
|
|
||||||
while let Some(value) = input.next().await {
|
while let Some(value) = input.next().await {
|
||||||
let scope = scope.clone().set_it(value);
|
|
||||||
let mut output = String::new();
|
let mut output = String::new();
|
||||||
|
|
||||||
for command in &commands {
|
for command in &commands {
|
||||||
@ -74,7 +73,7 @@ fn format_command(
|
|||||||
// FIXME: use the correct spans
|
// FIXME: use the correct spans
|
||||||
let full_column_path = nu_parser::parse_full_column_path(&(c.to_string()).spanned(Span::unknown()), ®istry);
|
let full_column_path = nu_parser::parse_full_column_path(&(c.to_string()).spanned(Span::unknown()), ®istry);
|
||||||
|
|
||||||
let result = evaluate_baseline_expr(&full_column_path.0, ®istry, &scope).await;
|
let result = evaluate_baseline_expr(&full_column_path.0, ®istry, &value, &scope.vars, &scope.env).await;
|
||||||
|
|
||||||
if let Ok(c) = result {
|
if let Ok(c) = result {
|
||||||
output
|
output
|
||||||
|
@ -89,7 +89,7 @@ impl WholeStreamCommand for KeepUntil {
|
|||||||
let condition = condition.clone();
|
let condition = condition.clone();
|
||||||
trace!("ITEM = {:?}", item);
|
trace!("ITEM = {:?}", item);
|
||||||
let result =
|
let result =
|
||||||
evaluate_baseline_expr(&*condition, ®istry, &scope.clone().set_it(item.clone()))
|
evaluate_baseline_expr(&*condition, ®istry, &item, &scope.vars, &scope.env)
|
||||||
.await;
|
.await;
|
||||||
trace!("RESULT = {:?}", result);
|
trace!("RESULT = {:?}", result);
|
||||||
|
|
||||||
|
@ -89,7 +89,7 @@ impl WholeStreamCommand for KeepWhile {
|
|||||||
let condition = condition.clone();
|
let condition = condition.clone();
|
||||||
trace!("ITEM = {:?}", item);
|
trace!("ITEM = {:?}", item);
|
||||||
let result =
|
let result =
|
||||||
evaluate_baseline_expr(&*condition, ®istry, &scope.clone().set_it(item.clone()))
|
evaluate_baseline_expr(&*condition, ®istry, &item, &scope.vars, &scope.env)
|
||||||
.await;
|
.await;
|
||||||
trace!("RESULT = {:?}", result);
|
trace!("RESULT = {:?}", result);
|
||||||
|
|
||||||
|
@ -50,17 +50,19 @@ impl WholeStreamCommand for Merge {
|
|||||||
|
|
||||||
fn merge(raw_args: CommandArgs, registry: &CommandRegistry) -> Result<OutputStream, ShellError> {
|
fn merge(raw_args: CommandArgs, registry: &CommandRegistry) -> Result<OutputStream, ShellError> {
|
||||||
let registry = registry.clone();
|
let registry = registry.clone();
|
||||||
|
let scope = raw_args.call_info.scope.clone();
|
||||||
let stream = async_stream! {
|
let stream = async_stream! {
|
||||||
let mut context = Context::from_raw(&raw_args, ®istry);
|
let mut context = Context::from_raw(&raw_args, ®istry);
|
||||||
let name_tag = raw_args.call_info.name_tag.clone();
|
let name_tag = raw_args.call_info.name_tag.clone();
|
||||||
let scope = raw_args.call_info.scope.clone();
|
|
||||||
let (merge_args, mut input): (MergeArgs, _) = raw_args.process(®istry).await?;
|
let (merge_args, mut 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(&block,
|
let table: Option<Vec<Value>> = match run_block(&block,
|
||||||
&mut context,
|
&mut context,
|
||||||
InputStream::empty(),
|
InputStream::empty(),
|
||||||
&scope).await {
|
&scope.it,
|
||||||
|
&scope.vars,
|
||||||
|
&scope.env).await {
|
||||||
Ok(mut stream) => Some(stream.drain_vec().await),
|
Ok(mut stream) => Some(stream.drain_vec().await),
|
||||||
Err(err) => {
|
Err(err) => {
|
||||||
yield Err(err);
|
yield Err(err);
|
||||||
|
@ -50,7 +50,7 @@ impl WholeStreamCommand for AliasCommand {
|
|||||||
let evaluated = call_info.evaluate(®istry).await?;
|
let evaluated = call_info.evaluate(®istry).await?;
|
||||||
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 = scope.set_var(alias_command.args[pos].to_string(), arg.clone());
|
scope.vars.insert(alias_command.args[pos].to_string(), arg.clone());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -58,7 +58,9 @@ impl WholeStreamCommand for AliasCommand {
|
|||||||
&block,
|
&block,
|
||||||
&mut context,
|
&mut context,
|
||||||
input,
|
input,
|
||||||
&scope,
|
&scope.it,
|
||||||
|
&scope.vars,
|
||||||
|
&scope.env,
|
||||||
).await;
|
).await;
|
||||||
|
|
||||||
match result {
|
match result {
|
||||||
|
@ -90,7 +90,7 @@ impl WholeStreamCommand for SkipUntil {
|
|||||||
let condition = condition.clone();
|
let condition = condition.clone();
|
||||||
trace!("ITEM = {:?}", item);
|
trace!("ITEM = {:?}", item);
|
||||||
let result =
|
let result =
|
||||||
evaluate_baseline_expr(&*condition, ®istry, &scope.clone().set_it(item.clone()))
|
evaluate_baseline_expr(&*condition, ®istry, &item, &scope.vars, &scope.env)
|
||||||
.await;
|
.await;
|
||||||
trace!("RESULT = {:?}", result);
|
trace!("RESULT = {:?}", result);
|
||||||
|
|
||||||
|
@ -90,7 +90,7 @@ impl WholeStreamCommand for SkipWhile {
|
|||||||
let condition = condition.clone();
|
let condition = condition.clone();
|
||||||
trace!("ITEM = {:?}", item);
|
trace!("ITEM = {:?}", item);
|
||||||
let result =
|
let result =
|
||||||
evaluate_baseline_expr(&*condition, ®istry, &scope.clone().set_it(item.clone()))
|
evaluate_baseline_expr(&*condition, ®istry, &item, &scope.vars, &scope.env)
|
||||||
.await;
|
.await;
|
||||||
trace!("RESULT = {:?}", result);
|
trace!("RESULT = {:?}", result);
|
||||||
|
|
||||||
|
@ -62,14 +62,15 @@ fn update(raw_args: CommandArgs, registry: &CommandRegistry) -> Result<OutputStr
|
|||||||
tag,
|
tag,
|
||||||
} => {
|
} => {
|
||||||
let for_block = input.clone();
|
let for_block = input.clone();
|
||||||
let input_clone = 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 result = run_block(
|
||||||
&block,
|
&block,
|
||||||
&mut context,
|
&mut context,
|
||||||
input_stream,
|
input_stream,
|
||||||
&scope.clone().set_it(input_clone),
|
&input,
|
||||||
|
&scope.vars,
|
||||||
|
&scope.env
|
||||||
).await;
|
).await;
|
||||||
|
|
||||||
match result {
|
match result {
|
||||||
|
@ -67,10 +67,9 @@ fn where_command(
|
|||||||
registry: &CommandRegistry,
|
registry: &CommandRegistry,
|
||||||
) -> Result<OutputStream, ShellError> {
|
) -> Result<OutputStream, ShellError> {
|
||||||
let registry = registry.clone();
|
let registry = registry.clone();
|
||||||
|
let scope = raw_args.call_info.scope.clone();
|
||||||
|
let tag = raw_args.call_info.name_tag.clone();
|
||||||
let stream = async_stream! {
|
let stream = async_stream! {
|
||||||
let tag = raw_args.call_info.name_tag.clone();
|
|
||||||
let scope = raw_args.call_info.scope.clone();
|
|
||||||
|
|
||||||
let (WhereArgs { block }, mut input) = raw_args.process(®istry).await?;
|
let (WhereArgs { block }, mut input) = raw_args.process(®istry).await?;
|
||||||
let condition = {
|
let condition = {
|
||||||
if block.block.len() != 1 {
|
if block.block.len() != 1 {
|
||||||
@ -108,7 +107,7 @@ fn where_command(
|
|||||||
while let Some(input) = input.next().await {
|
while let Some(input) = input.next().await {
|
||||||
|
|
||||||
//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 = evaluate_baseline_expr(&condition, ®istry, &scope.clone().set_it(input.clone())).await?;
|
let condition = evaluate_baseline_expr(&condition, ®istry, &input, &scope.vars, &scope.env).await?;
|
||||||
|
|
||||||
match condition.as_bool() {
|
match condition.as_bool() {
|
||||||
Ok(b) => {
|
Ok(b) => {
|
||||||
|
@ -57,18 +57,21 @@ fn with_env(raw_args: CommandArgs, registry: &CommandRegistry) -> Result<OutputS
|
|||||||
|
|
||||||
let stream = async_stream! {
|
let stream = async_stream! {
|
||||||
let mut context = Context::from_raw(&raw_args, ®istry);
|
let mut context = Context::from_raw(&raw_args, ®istry);
|
||||||
let scope = raw_args
|
let mut scope = raw_args
|
||||||
.call_info
|
.call_info
|
||||||
.scope
|
.scope
|
||||||
.clone();
|
.clone();
|
||||||
let (WithEnvArgs { variable, block }, mut input) = raw_args.process(®istry).await?;
|
let (WithEnvArgs { variable, block }, mut input) = raw_args.process(®istry).await?;
|
||||||
let scope = scope.set_env_var(variable.0.item, variable.1.item);
|
|
||||||
|
scope.env.insert(variable.0.item, variable.1.item);
|
||||||
|
|
||||||
let result = run_block(
|
let result = run_block(
|
||||||
&block,
|
&block,
|
||||||
&mut context,
|
&mut context,
|
||||||
input,
|
input,
|
||||||
&scope.clone(),
|
&scope.it,
|
||||||
|
&scope.vars,
|
||||||
|
&scope.env,
|
||||||
).await;
|
).await;
|
||||||
|
|
||||||
match result {
|
match result {
|
||||||
|
@ -14,7 +14,8 @@ pub(crate) async fn evaluate_args(
|
|||||||
|
|
||||||
if let Some(positional) = &call.positional {
|
if let Some(positional) = &call.positional {
|
||||||
for pos in positional {
|
for pos in positional {
|
||||||
let result = evaluate_baseline_expr(pos, registry, scope).await?;
|
let result =
|
||||||
|
evaluate_baseline_expr(pos, registry, &scope.it, &scope.vars, &scope.env).await?;
|
||||||
positional_args.push(result);
|
positional_args.push(result);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -36,7 +37,8 @@ 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).await?,
|
evaluate_baseline_expr(expr, registry, &scope.it, &scope.vars, &scope.env)
|
||||||
|
.await?,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -7,14 +7,16 @@ use log::trace;
|
|||||||
use nu_errors::{ArgumentError, ShellError};
|
use nu_errors::{ArgumentError, ShellError};
|
||||||
use nu_protocol::hir::{self, Expression, SpannedExpression};
|
use nu_protocol::hir::{self, Expression, SpannedExpression};
|
||||||
use nu_protocol::{
|
use nu_protocol::{
|
||||||
ColumnPath, Primitive, RangeInclusion, Scope, UnspannedPathMember, UntaggedValue, Value,
|
ColumnPath, Primitive, RangeInclusion, 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,
|
||||||
scope: &Scope,
|
it: &Value,
|
||||||
|
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,
|
||||||
@ -31,14 +33,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, &scope, tag),
|
Expression::Variable(var) => evaluate_reference(&var, it, vars, env, tag),
|
||||||
Expression::Command(_) => evaluate_command(tag, &scope),
|
Expression::Command(_) => unimplemented!(),
|
||||||
Expression::Invocation(block) => evaluate_invocation(block, registry, scope).await,
|
Expression::Invocation(block) => evaluate_invocation(block, registry, it, vars, env).await,
|
||||||
Expression::ExternalCommand(external) => evaluate_external(&external, &scope),
|
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, scope).await?;
|
let left = evaluate_baseline_expr(&binary.left, registry, it, vars, env).await?;
|
||||||
let right = evaluate_baseline_expr(&binary.right, registry, scope).await?;
|
let right = evaluate_baseline_expr(&binary.right, registry, it, vars, env).await?;
|
||||||
|
|
||||||
trace!("left={:?} right={:?}", left.value, right.value);
|
trace!("left={:?} right={:?}", left.value, right.value);
|
||||||
|
|
||||||
@ -59,8 +61,8 @@ pub(crate) async fn evaluate_baseline_expr(
|
|||||||
let left = &range.left;
|
let left = &range.left;
|
||||||
let right = &range.right;
|
let right = &range.right;
|
||||||
|
|
||||||
let left = evaluate_baseline_expr(&left, registry, scope).await?;
|
let left = evaluate_baseline_expr(&left, registry, it, vars, env).await?;
|
||||||
let right = evaluate_baseline_expr(&right, registry, scope).await?;
|
let right = evaluate_baseline_expr(&right, registry, it, vars, env).await?;
|
||||||
let left_span = left.tag.span;
|
let left_span = left.tag.span;
|
||||||
let right_span = right.tag.span;
|
let right_span = right.tag.span;
|
||||||
|
|
||||||
@ -79,7 +81,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, scope).await?;
|
let expr = evaluate_baseline_expr(&expr, registry, it, vars, env).await?;
|
||||||
exprs.push(expr);
|
exprs.push(expr);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -87,7 +89,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, scope).await?;
|
let value = evaluate_baseline_expr(&path.head, registry, it, vars, env).await?;
|
||||||
let mut item = value;
|
let mut item = value;
|
||||||
|
|
||||||
for member in &path.tail {
|
for member in &path.tail {
|
||||||
@ -151,12 +153,17 @@ fn evaluate_literal(literal: &hir::Literal, span: Span) -> Value {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn evaluate_reference(name: &hir::Variable, scope: &Scope, tag: Tag) -> Result<Value, ShellError> {
|
fn evaluate_reference(
|
||||||
trace!("Evaluating {:?} with Scope {:?}", name, scope);
|
name: &hir::Variable,
|
||||||
|
it: &Value,
|
||||||
|
vars: &IndexMap<String, Value>,
|
||||||
|
env: &IndexMap<String, String>,
|
||||||
|
tag: Tag,
|
||||||
|
) -> Result<Value, ShellError> {
|
||||||
match name {
|
match name {
|
||||||
hir::Variable::It(_) => Ok(scope.it.value.clone().into_value(tag)),
|
hir::Variable::It(_) => Ok(it.clone()),
|
||||||
hir::Variable::Other(name, _) => match name {
|
hir::Variable::Other(name, _) => match name {
|
||||||
x if x == "$nu" => crate::evaluate::variables::nu(scope, tag),
|
x if x == "$nu" => crate::evaluate::variables::nu(env, tag),
|
||||||
x if x == "$true" => Ok(Value {
|
x if x == "$true" => Ok(Value {
|
||||||
value: UntaggedValue::boolean(true),
|
value: UntaggedValue::boolean(true),
|
||||||
tag,
|
tag,
|
||||||
@ -165,8 +172,7 @@ fn evaluate_reference(name: &hir::Variable, scope: &Scope, tag: Tag) -> Result<V
|
|||||||
value: UntaggedValue::boolean(false),
|
value: UntaggedValue::boolean(false),
|
||||||
tag,
|
tag,
|
||||||
}),
|
}),
|
||||||
x => Ok(scope
|
x => Ok(vars
|
||||||
.vars
|
|
||||||
.get(x)
|
.get(x)
|
||||||
.cloned()
|
.cloned()
|
||||||
.unwrap_or_else(|| UntaggedValue::nothing().into_value(tag))),
|
.unwrap_or_else(|| UntaggedValue::nothing().into_value(tag))),
|
||||||
@ -174,19 +180,12 @@ fn evaluate_reference(name: &hir::Variable, scope: &Scope, tag: Tag) -> Result<V
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn evaluate_external(
|
|
||||||
external: &hir::ExternalStringCommand,
|
|
||||||
_scope: &Scope,
|
|
||||||
) -> Result<Value, ShellError> {
|
|
||||||
Err(ShellError::syntax_error(
|
|
||||||
"Unexpected external command".spanned(external.name.span),
|
|
||||||
))
|
|
||||||
}
|
|
||||||
|
|
||||||
async fn evaluate_invocation(
|
async fn evaluate_invocation(
|
||||||
block: &hir::Block,
|
block: &hir::Block,
|
||||||
registry: &CommandRegistry,
|
registry: &CommandRegistry,
|
||||||
scope: &Scope,
|
it: &Value,
|
||||||
|
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 = Context::basic()?;
|
let mut context = Context::basic()?;
|
||||||
@ -194,7 +193,7 @@ async fn evaluate_invocation(
|
|||||||
|
|
||||||
let input = InputStream::empty();
|
let input = InputStream::empty();
|
||||||
|
|
||||||
let result = run_block(&block, &mut context, input, &scope.clone()).await?;
|
let result = run_block(&block, &mut context, input, it, vars, env).await?;
|
||||||
|
|
||||||
let output = result.into_vec().await;
|
let output = result.into_vec().await;
|
||||||
|
|
||||||
@ -208,9 +207,3 @@ async fn evaluate_invocation(
|
|||||||
_ => Ok(UntaggedValue::nothing().into_value(Tag::unknown())),
|
_ => Ok(UntaggedValue::nothing().into_value(Tag::unknown())),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn evaluate_command(tag: Tag, _scope: &Scope) -> Result<Value, ShellError> {
|
|
||||||
Err(ShellError::syntax_error(
|
|
||||||
"Unexpected command".spanned(tag.span),
|
|
||||||
))
|
|
||||||
}
|
|
||||||
|
@ -1,15 +1,16 @@
|
|||||||
use crate::cli::History;
|
use crate::cli::History;
|
||||||
|
use crate::prelude::*;
|
||||||
use nu_errors::ShellError;
|
use nu_errors::ShellError;
|
||||||
use nu_protocol::{Scope, TaggedDictBuilder, UntaggedValue, Value};
|
use nu_protocol::{TaggedDictBuilder, UntaggedValue, Value};
|
||||||
use nu_source::Tag;
|
use nu_source::Tag;
|
||||||
|
|
||||||
pub fn nu(scope: &Scope, tag: impl Into<Tag>) -> Result<Value, ShellError> {
|
pub fn nu(env: &IndexMap<String, String>, tag: impl Into<Tag>) -> Result<Value, ShellError> {
|
||||||
let tag = tag.into();
|
let tag = tag.into();
|
||||||
|
|
||||||
let mut nu_dict = TaggedDictBuilder::new(&tag);
|
let mut nu_dict = TaggedDictBuilder::new(&tag);
|
||||||
|
|
||||||
let mut dict = TaggedDictBuilder::new(&tag);
|
let mut dict = TaggedDictBuilder::new(&tag);
|
||||||
for v in scope.env.iter() {
|
for v in env.iter() {
|
||||||
if v.0 != "PATH" && v.0 != "Path" {
|
if v.0 != "PATH" && v.0 != "Path" {
|
||||||
dict.insert_untagged(v.0, UntaggedValue::string(v.1));
|
dict.insert_untagged(v.0, UntaggedValue::string(v.1));
|
||||||
}
|
}
|
||||||
|
@ -1,8 +1,9 @@
|
|||||||
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::{Scope, ShellTypeName, Value};
|
use nu_protocol::{ShellTypeName, Value};
|
||||||
|
|
||||||
use crate::commands::classified::block::run_block;
|
use crate::commands::classified::block::run_block;
|
||||||
use crate::commands::{whole_stream_command, Echo};
|
use crate::commands::{whole_stream_command, Echo};
|
||||||
@ -58,10 +59,17 @@ 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(&block.block, ctx, input_stream, &Scope::env(env))
|
Ok(run_block(
|
||||||
.await?
|
&block.block,
|
||||||
.into_vec()
|
ctx,
|
||||||
.await)
|
input_stream,
|
||||||
|
&Value::nothing(),
|
||||||
|
&IndexMap::new(),
|
||||||
|
&env,
|
||||||
|
)
|
||||||
|
.await?
|
||||||
|
.into_vec()
|
||||||
|
.await)
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO probably something already available to do this
|
// TODO probably something already available to do this
|
||||||
|
@ -102,6 +102,7 @@ pub(crate) use std::future::Future;
|
|||||||
pub(crate) use std::sync::atomic::AtomicBool;
|
pub(crate) use std::sync::atomic::AtomicBool;
|
||||||
pub(crate) use std::sync::Arc;
|
pub(crate) use std::sync::Arc;
|
||||||
|
|
||||||
|
pub(crate) use indexmap::IndexMap;
|
||||||
pub(crate) use itertools::Itertools;
|
pub(crate) use itertools::Itertools;
|
||||||
|
|
||||||
pub trait FromInputStream {
|
pub trait FromInputStream {
|
||||||
|
@ -24,6 +24,6 @@ fn to_row() {
|
|||||||
"#
|
"#
|
||||||
));
|
));
|
||||||
|
|
||||||
assert!(actual.out.contains("5"));
|
assert!(actual.out.contains('5'));
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -63,6 +63,8 @@ fn outputs_zero_with_no_input() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
#[allow(clippy::unreadable_literal)]
|
||||||
|
#[allow(clippy::float_cmp)]
|
||||||
fn compute_sum_of_individual_row() -> Result<(), String> {
|
fn compute_sum_of_individual_row() -> Result<(), String> {
|
||||||
let answers_for_columns = [
|
let answers_for_columns = [
|
||||||
("cpu", 88.257434),
|
("cpu", 88.257434),
|
||||||
@ -82,6 +84,8 @@ fn compute_sum_of_individual_row() -> Result<(), String> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
#[allow(clippy::unreadable_literal)]
|
||||||
|
#[allow(clippy::float_cmp)]
|
||||||
fn compute_sum_of_table() -> Result<(), String> {
|
fn compute_sum_of_table() -> Result<(), String> {
|
||||||
let answers_for_columns = [
|
let answers_for_columns = [
|
||||||
("cpu", 88.257434),
|
("cpu", 88.257434),
|
||||||
|
@ -387,6 +387,10 @@ impl Value {
|
|||||||
_ => false,
|
_ => false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn nothing() -> Value {
|
||||||
|
UntaggedValue::nothing().into_untagged_value()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<String> for Value {
|
impl From<String> for Value {
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
use crate::value::{Primitive, UntaggedValue, Value};
|
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;
|
||||||
@ -13,69 +13,19 @@ pub struct Scope {
|
|||||||
pub env: IndexMap<String, String>,
|
pub env: IndexMap<String, String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Scope {
|
|
||||||
/// Create a new scope
|
|
||||||
pub fn new(it: Value) -> Scope {
|
|
||||||
Scope {
|
|
||||||
it,
|
|
||||||
vars: IndexMap::new(),
|
|
||||||
env: IndexMap::new(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Scope {
|
impl Scope {
|
||||||
/// Create an empty scope
|
/// Create an empty scope
|
||||||
pub fn empty() -> Scope {
|
pub fn new() -> Scope {
|
||||||
Scope {
|
Scope {
|
||||||
it: UntaggedValue::Primitive(Primitive::Nothing).into_untagged_value(),
|
it: Value::nothing(),
|
||||||
vars: IndexMap::new(),
|
vars: IndexMap::new(),
|
||||||
env: IndexMap::new(),
|
env: IndexMap::new(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
/// Create an empty scope, setting $it to a known Value
|
|
||||||
pub fn it_value(value: Value) -> Scope {
|
impl Default for Scope {
|
||||||
Scope {
|
fn default() -> Scope {
|
||||||
it: value,
|
Scope::new()
|
||||||
vars: IndexMap::new(),
|
}
|
||||||
env: IndexMap::new(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn env(env: IndexMap<String, String>) -> Scope {
|
|
||||||
Scope {
|
|
||||||
it: UntaggedValue::Primitive(Primitive::Nothing).into_untagged_value(),
|
|
||||||
vars: IndexMap::new(),
|
|
||||||
env,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn set_it(self, value: Value) -> Scope {
|
|
||||||
Scope {
|
|
||||||
it: value,
|
|
||||||
vars: self.vars,
|
|
||||||
env: self.env,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn set_var(self, name: String, value: Value) -> Scope {
|
|
||||||
let mut new_vars = self.vars.clone();
|
|
||||||
new_vars.insert(name, value);
|
|
||||||
Scope {
|
|
||||||
it: self.it,
|
|
||||||
vars: new_vars,
|
|
||||||
env: self.env,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn set_env_var(self, variable: String, value: String) -> Scope {
|
|
||||||
let mut new_env_vars = self.env.clone();
|
|
||||||
new_env_vars.insert(variable, value);
|
|
||||||
Scope {
|
|
||||||
it: self.it,
|
|
||||||
vars: self.vars,
|
|
||||||
env: new_env_vars,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -267,6 +267,7 @@ mod integration {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
#[test]
|
#[test]
|
||||||
|
#[allow(clippy::approx_constant)]
|
||||||
fn converts_the_input_to_float_using_the_field_passed_as_parameter() -> Result<(), ShellError> {
|
fn converts_the_input_to_float_using_the_field_passed_as_parameter() -> Result<(), ShellError> {
|
||||||
let run = plugin(&mut Str::new())
|
let run = plugin(&mut Str::new())
|
||||||
.args(
|
.args(
|
||||||
|
@ -294,6 +294,7 @@ pub mod tests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
#[allow(clippy::approx_constant)]
|
||||||
fn converts_to_float() -> Result<(), Box<dyn std::error::Error>> {
|
fn converts_to_float() -> Result<(), Box<dyn std::error::Error>> {
|
||||||
let mut strutils = Str::new();
|
let mut strutils = Str::new();
|
||||||
strutils.for_to_float();
|
strutils.for_to_float();
|
||||||
|
Loading…
Reference in New Issue
Block a user