mirror of
https://github.com/nushell/nushell
synced 2024-12-27 21:43:09 +00:00
Improve external output in subexprs (#294)
This commit is contained in:
parent
c7d159a0f3
commit
02b8027749
50 changed files with 320 additions and 136 deletions
|
@ -72,8 +72,12 @@ impl Completer for NuCompleter {
|
||||||
parse(&mut working_set, None, custom_completion.as_bytes(), false);
|
parse(&mut working_set, None, custom_completion.as_bytes(), false);
|
||||||
|
|
||||||
let mut stack = Stack::default();
|
let mut stack = Stack::default();
|
||||||
let result =
|
let result = eval_block(
|
||||||
eval_block(&self.engine_state, &mut stack, &block, PipelineData::new());
|
&self.engine_state,
|
||||||
|
&mut stack,
|
||||||
|
&block,
|
||||||
|
PipelineData::new(flat.0),
|
||||||
|
);
|
||||||
|
|
||||||
let v: Vec<_> = match result {
|
let v: Vec<_> = match result {
|
||||||
Ok(pd) => pd
|
Ok(pd) => pd
|
||||||
|
|
|
@ -131,7 +131,7 @@ pub fn action(input: &Value, span: Span) -> Value {
|
||||||
fn int_from_string(a_string: &str, span: Span) -> Result<i64, ShellError> {
|
fn int_from_string(a_string: &str, span: Span) -> Result<i64, ShellError> {
|
||||||
match a_string.parse::<bytesize::ByteSize>() {
|
match a_string.parse::<bytesize::ByteSize>() {
|
||||||
Ok(n) => Ok(n.0 as i64),
|
Ok(n) => Ok(n.0 as i64),
|
||||||
Err(_) => Err(ShellError::CantConvert("int".into(), span)),
|
Err(_) => Err(ShellError::CantConvert("int".into(), "string".into(), span)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -137,7 +137,11 @@ fn int_from_string(a_string: &str, span: Span) -> Result<i64, ShellError> {
|
||||||
Ok(n) => Ok(n),
|
Ok(n) => Ok(n),
|
||||||
Err(_) => match a_string.parse::<f64>() {
|
Err(_) => match a_string.parse::<f64>() {
|
||||||
Ok(f) => Ok(f as i64),
|
Ok(f) => Ok(f as i64),
|
||||||
_ => Err(ShellError::CantConvert("into int".into(), span)),
|
_ => Err(ShellError::CantConvert(
|
||||||
|
"into int".into(),
|
||||||
|
"string".into(),
|
||||||
|
span,
|
||||||
|
)),
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -229,11 +229,8 @@ pub fn action(
|
||||||
span,
|
span,
|
||||||
),
|
),
|
||||||
},
|
},
|
||||||
_ => Value::Error {
|
x => Value::Error {
|
||||||
error: ShellError::CantConvert(
|
error: ShellError::CantConvert(String::from("string"), x.get_type().to_string(), span),
|
||||||
String::from(" into string. Probably this type is not supported yet"),
|
|
||||||
span,
|
|
||||||
),
|
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -28,9 +28,9 @@ impl Command for Alias {
|
||||||
&self,
|
&self,
|
||||||
_engine_state: &EngineState,
|
_engine_state: &EngineState,
|
||||||
_stack: &mut Stack,
|
_stack: &mut Stack,
|
||||||
_call: &Call,
|
call: &Call,
|
||||||
_input: PipelineData,
|
_input: PipelineData,
|
||||||
) -> Result<nu_protocol::PipelineData, nu_protocol::ShellError> {
|
) -> Result<nu_protocol::PipelineData, nu_protocol::ShellError> {
|
||||||
Ok(PipelineData::new())
|
Ok(PipelineData::new(call.head))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -29,9 +29,9 @@ impl Command for Def {
|
||||||
&self,
|
&self,
|
||||||
_engine_state: &EngineState,
|
_engine_state: &EngineState,
|
||||||
_stack: &mut Stack,
|
_stack: &mut Stack,
|
||||||
_call: &Call,
|
call: &Call,
|
||||||
_input: PipelineData,
|
_input: PipelineData,
|
||||||
) -> Result<nu_protocol::PipelineData, nu_protocol::ShellError> {
|
) -> Result<nu_protocol::PipelineData, nu_protocol::ShellError> {
|
||||||
Ok(PipelineData::new())
|
Ok(PipelineData::new(call.head))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,9 +1,7 @@
|
||||||
use nu_engine::CallExt;
|
use nu_engine::CallExt;
|
||||||
use nu_protocol::ast::Call;
|
use nu_protocol::ast::Call;
|
||||||
use nu_protocol::engine::{Command, EngineState, Stack};
|
use nu_protocol::engine::{Command, EngineState, Stack};
|
||||||
use nu_protocol::{
|
use nu_protocol::{Example, PipelineData, ShellError, Signature, SyntaxShape, Value, ValueStream};
|
||||||
Example, PipelineData, ShellError, Signature, Span, SyntaxShape, Value, ValueStream,
|
|
||||||
};
|
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct Echo;
|
pub struct Echo;
|
||||||
|
@ -43,7 +41,7 @@ impl Command for Echo {
|
||||||
// When there are no elements, we echo the empty string
|
// When there are no elements, we echo the empty string
|
||||||
std::cmp::Ordering::Less => PipelineData::Value(Value::String {
|
std::cmp::Ordering::Less => PipelineData::Value(Value::String {
|
||||||
val: "".to_string(),
|
val: "".to_string(),
|
||||||
span: Span::unknown(),
|
span: call.head,
|
||||||
}),
|
}),
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
|
@ -29,9 +29,9 @@ impl Command for ExportDef {
|
||||||
&self,
|
&self,
|
||||||
_engine_state: &EngineState,
|
_engine_state: &EngineState,
|
||||||
_stack: &mut Stack,
|
_stack: &mut Stack,
|
||||||
_call: &Call,
|
call: &Call,
|
||||||
_input: PipelineData,
|
_input: PipelineData,
|
||||||
) -> Result<nu_protocol::PipelineData, nu_protocol::ShellError> {
|
) -> Result<nu_protocol::PipelineData, nu_protocol::ShellError> {
|
||||||
Ok(PipelineData::new())
|
Ok(PipelineData::new(call.head))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -44,6 +44,7 @@ impl Command for For {
|
||||||
call: &Call,
|
call: &Call,
|
||||||
_input: PipelineData,
|
_input: PipelineData,
|
||||||
) -> Result<nu_protocol::PipelineData, nu_protocol::ShellError> {
|
) -> Result<nu_protocol::PipelineData, nu_protocol::ShellError> {
|
||||||
|
let head = call.head;
|
||||||
let var_id = call.positional[0]
|
let var_id = call.positional[0]
|
||||||
.as_var()
|
.as_var()
|
||||||
.expect("internal error: missing variable");
|
.expect("internal error: missing variable");
|
||||||
|
@ -69,8 +70,8 @@ impl Command for For {
|
||||||
stack.add_var(var_id, x);
|
stack.add_var(var_id, x);
|
||||||
|
|
||||||
//let block = engine_state.get_block(block_id);
|
//let block = engine_state.get_block(block_id);
|
||||||
match eval_block(&engine_state, &mut stack, &block, PipelineData::new()) {
|
match eval_block(&engine_state, &mut stack, &block, PipelineData::new(head)) {
|
||||||
Ok(pipeline_data) => pipeline_data.into_value(),
|
Ok(pipeline_data) => pipeline_data.into_value(head),
|
||||||
Err(error) => Value::Error { error },
|
Err(error) => Value::Error { error },
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
@ -81,8 +82,8 @@ impl Command for For {
|
||||||
stack.add_var(var_id, x);
|
stack.add_var(var_id, x);
|
||||||
|
|
||||||
//let block = engine_state.get_block(block_id);
|
//let block = engine_state.get_block(block_id);
|
||||||
match eval_block(&engine_state, &mut stack, &block, PipelineData::new()) {
|
match eval_block(&engine_state, &mut stack, &block, PipelineData::new(head)) {
|
||||||
Ok(pipeline_data) => pipeline_data.into_value(),
|
Ok(pipeline_data) => pipeline_data.into_value(head),
|
||||||
Err(error) => Value::Error { error },
|
Err(error) => Value::Error { error },
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
@ -90,7 +91,7 @@ impl Command for For {
|
||||||
x => {
|
x => {
|
||||||
stack.add_var(var_id, x);
|
stack.add_var(var_id, x);
|
||||||
|
|
||||||
eval_block(&engine_state, &mut stack, &block, PipelineData::new())
|
eval_block(&engine_state, &mut stack, &block, PipelineData::new(head))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,9 +22,9 @@ impl Command for Hide {
|
||||||
&self,
|
&self,
|
||||||
_engine_state: &EngineState,
|
_engine_state: &EngineState,
|
||||||
_stack: &mut Stack,
|
_stack: &mut Stack,
|
||||||
_call: &Call,
|
call: &Call,
|
||||||
_input: PipelineData,
|
_input: PipelineData,
|
||||||
) -> Result<nu_protocol::PipelineData, nu_protocol::ShellError> {
|
) -> Result<nu_protocol::PipelineData, nu_protocol::ShellError> {
|
||||||
Ok(PipelineData::new())
|
Ok(PipelineData::new(call.head))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -40,9 +40,9 @@ impl Command for If {
|
||||||
let else_case = call.positional.get(2);
|
let else_case = call.positional.get(2);
|
||||||
|
|
||||||
let result = eval_expression(engine_state, stack, cond)?;
|
let result = eval_expression(engine_state, stack, cond)?;
|
||||||
match result {
|
match &result {
|
||||||
Value::Bool { val, .. } => {
|
Value::Bool { val, .. } => {
|
||||||
if val {
|
if *val {
|
||||||
let block = engine_state.get_block(then_block);
|
let block = engine_state.get_block(then_block);
|
||||||
let mut stack = stack.collect_captures(&block.captures);
|
let mut stack = stack.collect_captures(&block.captures);
|
||||||
eval_block(engine_state, &mut stack, block, input)
|
eval_block(engine_state, &mut stack, block, input)
|
||||||
|
@ -61,10 +61,14 @@ impl Command for If {
|
||||||
.map(|x| x.into_pipeline_data())
|
.map(|x| x.into_pipeline_data())
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
Ok(PipelineData::new())
|
Ok(PipelineData::new(call.head))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_ => Err(ShellError::CantConvert("bool".into(), result.span()?)),
|
x => Err(ShellError::CantConvert(
|
||||||
|
"bool".into(),
|
||||||
|
x.get_type().to_string(),
|
||||||
|
result.span()?,
|
||||||
|
)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -45,6 +45,6 @@ impl Command for Let {
|
||||||
//println!("Adding: {:?} to {}", rhs, var_id);
|
//println!("Adding: {:?} to {}", rhs, var_id);
|
||||||
|
|
||||||
stack.add_var(var_id, rhs);
|
stack.add_var(var_id, rhs);
|
||||||
Ok(PipelineData::new())
|
Ok(PipelineData::new(call.head))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -28,9 +28,9 @@ impl Command for Module {
|
||||||
&self,
|
&self,
|
||||||
_engine_state: &EngineState,
|
_engine_state: &EngineState,
|
||||||
_stack: &mut Stack,
|
_stack: &mut Stack,
|
||||||
_call: &Call,
|
call: &Call,
|
||||||
_input: PipelineData,
|
_input: PipelineData,
|
||||||
) -> Result<nu_protocol::PipelineData, nu_protocol::ShellError> {
|
) -> Result<nu_protocol::PipelineData, nu_protocol::ShellError> {
|
||||||
Ok(PipelineData::new())
|
Ok(PipelineData::new(call.head))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -26,9 +26,9 @@ impl Command for Register {
|
||||||
&self,
|
&self,
|
||||||
_engine_state: &EngineState,
|
_engine_state: &EngineState,
|
||||||
_stack: &mut Stack,
|
_stack: &mut Stack,
|
||||||
_call: &Call,
|
call: &Call,
|
||||||
_input: PipelineData,
|
_input: PipelineData,
|
||||||
) -> Result<nu_protocol::PipelineData, nu_protocol::ShellError> {
|
) -> Result<nu_protocol::PipelineData, nu_protocol::ShellError> {
|
||||||
Ok(PipelineData::new())
|
Ok(PipelineData::new(call.head))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,9 +22,9 @@ impl Command for Use {
|
||||||
&self,
|
&self,
|
||||||
_engine_state: &EngineState,
|
_engine_state: &EngineState,
|
||||||
_stack: &mut Stack,
|
_stack: &mut Stack,
|
||||||
_call: &Call,
|
call: &Call,
|
||||||
_input: PipelineData,
|
_input: PipelineData,
|
||||||
) -> Result<nu_protocol::PipelineData, nu_protocol::ShellError> {
|
) -> Result<nu_protocol::PipelineData, nu_protocol::ShellError> {
|
||||||
Ok(PipelineData::new())
|
Ok(PipelineData::new(call.head))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -111,7 +111,7 @@ fn _to_timezone(dt: DateTime<FixedOffset>, timezone: &Spanned<String>, span: Spa
|
||||||
match datetime_in_timezone(&dt, timezone.item.as_str()) {
|
match datetime_in_timezone(&dt, timezone.item.as_str()) {
|
||||||
Ok(dt) => Value::Date { val: dt, span },
|
Ok(dt) => Value::Date { val: dt, span },
|
||||||
Err(_) => Value::Error {
|
Err(_) => Value::Error {
|
||||||
error: ShellError::UnsupportedInput(String::from("invalid time zone"), Span::unknown()),
|
error: ShellError::UnsupportedInput(String::from("invalid time zone"), span),
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
2
crates/nu-command/src/env/let_env.rs
vendored
2
crates/nu-command/src/env/let_env.rs
vendored
|
@ -46,6 +46,6 @@ impl Command for LetEnv {
|
||||||
//println!("Adding: {:?} to {}", rhs, var_id);
|
//println!("Adding: {:?} to {}", rhs, var_id);
|
||||||
|
|
||||||
stack.add_env_var(env_var, rhs);
|
stack.add_env_var(env_var, rhs);
|
||||||
Ok(PipelineData::new())
|
Ok(PipelineData::new(call.head))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
12
crates/nu-command/src/env/with_env.rs
vendored
12
crates/nu-command/src/env/with_env.rs
vendored
|
@ -91,7 +91,11 @@ impl TryFrom<&Value> for EnvVar {
|
||||||
Ok(EnvVar::Proper(s))
|
Ok(EnvVar::Proper(s))
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
Err(ShellError::CantConvert("string".into(), value.span()?))
|
Err(ShellError::CantConvert(
|
||||||
|
"string".into(),
|
||||||
|
value.get_type().to_string(),
|
||||||
|
value.span()?,
|
||||||
|
))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -123,9 +127,10 @@ fn with_env(
|
||||||
env.insert(k.to_string(), v.try_into()?);
|
env.insert(k.to_string(), v.try_into()?);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_ => {
|
x => {
|
||||||
return Err(ShellError::CantConvert(
|
return Err(ShellError::CantConvert(
|
||||||
"string list or single row".into(),
|
"string list or single row".into(),
|
||||||
|
x.get_type().to_string(),
|
||||||
call.positional[1].span,
|
call.positional[1].span,
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
@ -145,9 +150,10 @@ fn with_env(
|
||||||
env.insert(k.clone(), v.try_into()?);
|
env.insert(k.clone(), v.try_into()?);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_ => {
|
x => {
|
||||||
return Err(ShellError::CantConvert(
|
return Err(ShellError::CantConvert(
|
||||||
"string list or single row".into(),
|
"string list or single row".into(),
|
||||||
|
x.get_type().to_string(),
|
||||||
call.positional[1].span,
|
call.positional[1].span,
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,7 +2,7 @@ use nu_engine::eval_block;
|
||||||
use nu_parser::parse;
|
use nu_parser::parse;
|
||||||
use nu_protocol::{
|
use nu_protocol::{
|
||||||
engine::{Command, EngineState, Stack, StateWorkingSet},
|
engine::{Command, EngineState, Stack, StateWorkingSet},
|
||||||
PipelineData,
|
PipelineData, Span,
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::To;
|
use crate::To;
|
||||||
|
@ -56,10 +56,15 @@ pub fn test_examples(cmd: impl Command + 'static) {
|
||||||
|
|
||||||
let mut stack = Stack::new();
|
let mut stack = Stack::new();
|
||||||
|
|
||||||
match eval_block(&engine_state, &mut stack, &block, PipelineData::new()) {
|
match eval_block(
|
||||||
|
&engine_state,
|
||||||
|
&mut stack,
|
||||||
|
&block,
|
||||||
|
PipelineData::new(Span::unknown()),
|
||||||
|
) {
|
||||||
Err(err) => panic!("test eval error in `{}`: {:?}", example.example, err),
|
Err(err) => panic!("test eval error in `{}`: {:?}", example.example, err),
|
||||||
Ok(result) => {
|
Ok(result) => {
|
||||||
let result = result.into_value();
|
let result = result.into_value(Span::unknown());
|
||||||
println!("input: {}", example.example);
|
println!("input: {}", example.example);
|
||||||
println!("result: {:?}", result);
|
println!("result: {:?}", result);
|
||||||
println!("done: {:?}", start.elapsed());
|
println!("done: {:?}", start.elapsed());
|
||||||
|
|
|
@ -44,13 +44,13 @@ impl Command for Git {
|
||||||
}
|
}
|
||||||
Err(_err) => {
|
Err(_err) => {
|
||||||
// FIXME: Move this to an external signature and add better error handling
|
// FIXME: Move this to an external signature and add better error handling
|
||||||
Ok(PipelineData::new())
|
Ok(PipelineData::new(call.head))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Err(_err) => {
|
Err(_err) => {
|
||||||
// FIXME: Move this to an external signature and add better error handling
|
// FIXME: Move this to an external signature and add better error handling
|
||||||
Ok(PipelineData::new())
|
Ok(PipelineData::new(call.head))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -59,13 +59,13 @@ impl Command for GitCheckout {
|
||||||
}
|
}
|
||||||
Err(_err) => {
|
Err(_err) => {
|
||||||
// FIXME: Move this to an external signature and add better error handling
|
// FIXME: Move this to an external signature and add better error handling
|
||||||
Ok(PipelineData::new())
|
Ok(PipelineData::new(call.head))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Err(_err) => {
|
Err(_err) => {
|
||||||
// FIXME: Move this to an external signature and add better error handling
|
// FIXME: Move this to an external signature and add better error handling
|
||||||
Ok(PipelineData::new())
|
Ok(PipelineData::new(call.head))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -66,10 +66,10 @@ impl Command for ListGitBranches {
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.into_pipeline_data(engine_state.ctrlc.clone()))
|
.into_pipeline_data(engine_state.ctrlc.clone()))
|
||||||
} else {
|
} else {
|
||||||
Ok(PipelineData::new())
|
Ok(PipelineData::new(call.head))
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
Ok(PipelineData::new())
|
Ok(PipelineData::new(call.head))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -43,6 +43,6 @@ impl Command for Cd {
|
||||||
//FIXME: this only changes the current scope, but instead this environment variable
|
//FIXME: this only changes the current scope, but instead this environment variable
|
||||||
//should probably be a block that loads the information from the state in the overlay
|
//should probably be a block that loads the information from the state in the overlay
|
||||||
stack.add_env_var("PWD".into(), path);
|
stack.add_env_var("PWD".into(), path);
|
||||||
Ok(PipelineData::new())
|
Ok(PipelineData::new(call.head))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -204,6 +204,6 @@ impl Command for Cp {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(PipelineData::new())
|
Ok(PipelineData::new(call.head))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -130,7 +130,7 @@ impl Command for Mv {
|
||||||
move_file(call, &entry, &destination)?
|
move_file(call, &entry, &destination)?
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(PipelineData::new())
|
Ok(PipelineData::new(call.head))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -49,6 +49,6 @@ impl Command for Touch {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(PipelineData::new())
|
Ok(PipelineData::new(call.head))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -102,8 +102,8 @@ impl Command for Each {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
match eval_block(&engine_state, &mut stack, &block, PipelineData::new()) {
|
match eval_block(&engine_state, &mut stack, &block, PipelineData::new(span)) {
|
||||||
Ok(v) => v.into_value(),
|
Ok(v) => v.into_value(span),
|
||||||
Err(error) => Value::Error { error },
|
Err(error) => Value::Error { error },
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
@ -136,7 +136,7 @@ impl Command for Each {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
match eval_block(&engine_state, &mut stack, block, PipelineData::new())? {
|
match eval_block(&engine_state, &mut stack, block, PipelineData::new(span))? {
|
||||||
PipelineData::Value(Value::Record {
|
PipelineData::Value(Value::Record {
|
||||||
mut cols, mut vals, ..
|
mut cols, mut vals, ..
|
||||||
}) => {
|
}) => {
|
||||||
|
@ -146,7 +146,7 @@ impl Command for Each {
|
||||||
}
|
}
|
||||||
x => {
|
x => {
|
||||||
output_cols.push(col);
|
output_cols.push(col);
|
||||||
output_vals.push(x.into_value());
|
output_vals.push(x.into_value(span));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -167,7 +167,7 @@ impl Command for Each {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
eval_block(&engine_state, &mut stack, block, PipelineData::new())
|
eval_block(&engine_state, &mut stack, block, PipelineData::new(span))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -88,7 +88,7 @@ impl Command for ParEach {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
match eval_block(&engine_state, &mut stack, block, PipelineData::new()) {
|
match eval_block(&engine_state, &mut stack, block, PipelineData::new(span)) {
|
||||||
Ok(v) => v,
|
Ok(v) => v,
|
||||||
Err(error) => Value::Error { error }.into_pipeline_data(),
|
Err(error) => Value::Error { error }.into_pipeline_data(),
|
||||||
}
|
}
|
||||||
|
@ -129,7 +129,7 @@ impl Command for ParEach {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
match eval_block(&engine_state, &mut stack, block, PipelineData::new()) {
|
match eval_block(&engine_state, &mut stack, block, PipelineData::new(span)) {
|
||||||
Ok(v) => v,
|
Ok(v) => v,
|
||||||
Err(error) => Value::Error { error }.into_pipeline_data(),
|
Err(error) => Value::Error { error }.into_pipeline_data(),
|
||||||
}
|
}
|
||||||
|
@ -169,7 +169,7 @@ impl Command for ParEach {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
match eval_block(&engine_state, &mut stack, block, PipelineData::new()) {
|
match eval_block(&engine_state, &mut stack, block, PipelineData::new(span)) {
|
||||||
Ok(v) => v,
|
Ok(v) => v,
|
||||||
Err(error) => Value::Error { error }.into_pipeline_data(),
|
Err(error) => Value::Error { error }.into_pipeline_data(),
|
||||||
}
|
}
|
||||||
|
@ -206,7 +206,7 @@ impl Command for ParEach {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
match eval_block(&engine_state, &mut stack, block, PipelineData::new())? {
|
match eval_block(&engine_state, &mut stack, block, PipelineData::new(span))? {
|
||||||
PipelineData::Value(Value::Record {
|
PipelineData::Value(Value::Record {
|
||||||
mut cols, mut vals, ..
|
mut cols, mut vals, ..
|
||||||
}) => {
|
}) => {
|
||||||
|
@ -216,7 +216,7 @@ impl Command for ParEach {
|
||||||
}
|
}
|
||||||
x => {
|
x => {
|
||||||
output_cols.push(col);
|
output_cols.push(col);
|
||||||
output_vals.push(x.into_value());
|
output_vals.push(x.into_value(span));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -237,7 +237,7 @@ impl Command for ParEach {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
eval_block(&engine_state, &mut stack, block, PipelineData::new())
|
eval_block(&engine_state, &mut stack, block, PipelineData::new(span))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -29,6 +29,7 @@ impl Command for Where {
|
||||||
call: &Call,
|
call: &Call,
|
||||||
input: PipelineData,
|
input: PipelineData,
|
||||||
) -> Result<nu_protocol::PipelineData, nu_protocol::ShellError> {
|
) -> Result<nu_protocol::PipelineData, nu_protocol::ShellError> {
|
||||||
|
let head = call.head;
|
||||||
let cond = call.positional[0].clone();
|
let cond = call.positional[0].clone();
|
||||||
|
|
||||||
let ctrlc = engine_state.ctrlc.clone();
|
let ctrlc = engine_state.ctrlc.clone();
|
||||||
|
@ -79,7 +80,7 @@ impl Command for Where {
|
||||||
if result.is_true() {
|
if result.is_true() {
|
||||||
Ok(x.into_pipeline_data())
|
Ok(x.into_pipeline_data())
|
||||||
} else {
|
} else {
|
||||||
Ok(PipelineData::new())
|
Ok(PipelineData::new(head))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,9 +22,9 @@ impl Command for From {
|
||||||
&self,
|
&self,
|
||||||
_engine_state: &EngineState,
|
_engine_state: &EngineState,
|
||||||
_stack: &mut Stack,
|
_stack: &mut Stack,
|
||||||
_call: &Call,
|
call: &Call,
|
||||||
_input: PipelineData,
|
_input: PipelineData,
|
||||||
) -> Result<nu_protocol::PipelineData, ShellError> {
|
) -> Result<nu_protocol::PipelineData, ShellError> {
|
||||||
Ok(PipelineData::new())
|
Ok(PipelineData::new(call.head))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -128,7 +128,11 @@ fn convert_nujson_to_value(value: &nu_json::Value, span: Span) -> Value {
|
||||||
nu_json::Value::U64(u) => {
|
nu_json::Value::U64(u) => {
|
||||||
if *u > i64::MAX as u64 {
|
if *u > i64::MAX as u64 {
|
||||||
Value::Error {
|
Value::Error {
|
||||||
error: ShellError::CantConvert("i64 sized integer".into(), span),
|
error: ShellError::CantConvert(
|
||||||
|
"i64 sized integer".into(),
|
||||||
|
"larger than i64".into(),
|
||||||
|
span,
|
||||||
|
),
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
Value::Int {
|
Value::Int {
|
||||||
|
@ -151,6 +155,7 @@ fn convert_string_to_value(string_input: String, span: Span) -> Result<Value, Sh
|
||||||
|
|
||||||
Err(_x) => Err(ShellError::CantConvert(
|
Err(_x) => Err(ShellError::CantConvert(
|
||||||
"structured data from json".into(),
|
"structured data from json".into(),
|
||||||
|
"string".into(),
|
||||||
span,
|
span,
|
||||||
)),
|
)),
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,9 +22,9 @@ impl Command for To {
|
||||||
&self,
|
&self,
|
||||||
_engine_state: &EngineState,
|
_engine_state: &EngineState,
|
||||||
_stack: &mut Stack,
|
_stack: &mut Stack,
|
||||||
_call: &Call,
|
call: &Call,
|
||||||
_input: PipelineData,
|
_input: PipelineData,
|
||||||
) -> Result<nu_protocol::PipelineData, ShellError> {
|
) -> Result<nu_protocol::PipelineData, ShellError> {
|
||||||
Ok(PipelineData::new())
|
Ok(PipelineData::new(call.head))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -127,7 +127,11 @@ fn to_json(
|
||||||
}
|
}
|
||||||
.into_pipeline_data()),
|
.into_pipeline_data()),
|
||||||
_ => Ok(Value::Error {
|
_ => Ok(Value::Error {
|
||||||
error: ShellError::CantConvert("JSON".into(), name_span),
|
error: ShellError::CantConvert(
|
||||||
|
"JSON".into(),
|
||||||
|
value.get_type().to_string(),
|
||||||
|
name_span,
|
||||||
|
),
|
||||||
}
|
}
|
||||||
.into_pipeline_data()),
|
.into_pipeline_data()),
|
||||||
}
|
}
|
||||||
|
@ -141,12 +145,20 @@ fn to_json(
|
||||||
span: name_span,
|
span: name_span,
|
||||||
},
|
},
|
||||||
_ => Value::Error {
|
_ => Value::Error {
|
||||||
error: ShellError::CantConvert("JSON".into(), name_span),
|
error: ShellError::CantConvert(
|
||||||
|
"JSON".into(),
|
||||||
|
value.get_type().to_string(),
|
||||||
|
name_span,
|
||||||
|
),
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
Value::Error {
|
Value::Error {
|
||||||
error: ShellError::CantConvert("JSON".into(), name_span),
|
error: ShellError::CantConvert(
|
||||||
|
"JSON".into(),
|
||||||
|
value.get_type().to_string(),
|
||||||
|
name_span,
|
||||||
|
),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
|
@ -41,7 +41,7 @@ impl Command for SubCommand {
|
||||||
|
|
||||||
pub fn maximum(values: &[Value], head: &Span) -> Result<Value, ShellError> {
|
pub fn maximum(values: &[Value], head: &Span) -> Result<Value, ShellError> {
|
||||||
let max_func = reducer_for(Reduce::Maximum);
|
let max_func = reducer_for(Reduce::Maximum);
|
||||||
max_func(Value::nothing(), values.to_vec(), *head)
|
max_func(Value::nothing(*head), values.to_vec(), *head)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
|
|
|
@ -41,7 +41,7 @@ impl Command for SubCommand {
|
||||||
|
|
||||||
pub fn minimum(values: &[Value], head: &Span) -> Result<Value, ShellError> {
|
pub fn minimum(values: &[Value], head: &Span) -> Result<Value, ShellError> {
|
||||||
let min_func = reducer_for(Reduce::Minimum);
|
let min_func = reducer_for(Reduce::Minimum);
|
||||||
min_func(Value::nothing(), values.to_vec(), *head)
|
min_func(Value::nothing(*head), values.to_vec(), *head)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
|
|
|
@ -42,7 +42,7 @@ impl Command for SubCommand {
|
||||||
/// Calculate product of given values
|
/// Calculate product of given values
|
||||||
pub fn product(values: &[Value], head: &Span) -> Result<Value, ShellError> {
|
pub fn product(values: &[Value], head: &Span) -> Result<Value, ShellError> {
|
||||||
let product_func = reducer_for(Reduce::Product);
|
let product_func = reducer_for(Reduce::Product);
|
||||||
product_func(Value::nothing(), values.to_vec(), *head)
|
product_func(Value::nothing(*head), values.to_vec(), *head)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
|
|
|
@ -24,7 +24,7 @@ pub fn reducer_for(command: Reduce) -> ReducerFunction {
|
||||||
pub fn max(data: Vec<Value>, head: Span) -> Result<Value, ShellError> {
|
pub fn max(data: Vec<Value>, head: Span) -> Result<Value, ShellError> {
|
||||||
let mut biggest = data
|
let mut biggest = data
|
||||||
.first()
|
.first()
|
||||||
.ok_or_else(|| ShellError::UnsupportedInput("Empty input".to_string(), Span::unknown()))?
|
.ok_or_else(|| ShellError::UnsupportedInput("Empty input".to_string(), head))?
|
||||||
.clone();
|
.clone();
|
||||||
|
|
||||||
for value in &data {
|
for value in &data {
|
||||||
|
@ -48,7 +48,7 @@ pub fn max(data: Vec<Value>, head: Span) -> Result<Value, ShellError> {
|
||||||
pub fn min(data: Vec<Value>, head: Span) -> Result<Value, ShellError> {
|
pub fn min(data: Vec<Value>, head: Span) -> Result<Value, ShellError> {
|
||||||
let mut smallest = data
|
let mut smallest = data
|
||||||
.first()
|
.first()
|
||||||
.ok_or_else(|| ShellError::UnsupportedInput("Empty input".to_string(), Span::unknown()))?
|
.ok_or_else(|| ShellError::UnsupportedInput("Empty input".to_string(), head))?
|
||||||
.clone();
|
.clone();
|
||||||
|
|
||||||
for value in &data {
|
for value in &data {
|
||||||
|
@ -87,9 +87,9 @@ pub fn sum(data: Vec<Value>, head: Span) -> Result<Value, ShellError> {
|
||||||
}),
|
}),
|
||||||
None => Err(ShellError::UnsupportedInput(
|
None => Err(ShellError::UnsupportedInput(
|
||||||
"Empty input".to_string(),
|
"Empty input".to_string(),
|
||||||
Span::unknown(),
|
head,
|
||||||
)),
|
)),
|
||||||
_ => Ok(Value::nothing()),
|
_ => Ok(Value::nothing(head)),
|
||||||
}?;
|
}?;
|
||||||
|
|
||||||
for value in &data {
|
for value in &data {
|
||||||
|
@ -127,7 +127,7 @@ pub fn product(data: Vec<Value>, head: Span) -> Result<Value, ShellError> {
|
||||||
"Empty input".to_string(),
|
"Empty input".to_string(),
|
||||||
Span::unknown(),
|
Span::unknown(),
|
||||||
)),
|
)),
|
||||||
_ => Ok(Value::nothing()),
|
_ => Ok(Value::nothing(head)),
|
||||||
}?;
|
}?;
|
||||||
|
|
||||||
for value in &data {
|
for value in &data {
|
||||||
|
|
|
@ -48,7 +48,7 @@ impl Command for SubCommand {
|
||||||
|
|
||||||
pub fn summation(values: &[Value], head: &Span) -> Result<Value, ShellError> {
|
pub fn summation(values: &[Value], head: &Span) -> Result<Value, ShellError> {
|
||||||
let sum_func = reducer_for(Reduce::Summation);
|
let sum_func = reducer_for(Reduce::Summation);
|
||||||
sum_func(Value::nothing(), values.to_vec(), *head)
|
sum_func(Value::nothing(*head), values.to_vec(), *head)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
|
|
|
@ -38,7 +38,7 @@ impl Command for Format {
|
||||||
Ok(pattern) => {
|
Ok(pattern) => {
|
||||||
let string_pattern = pattern.as_string().unwrap();
|
let string_pattern = pattern.as_string().unwrap();
|
||||||
let ops = extract_formatting_operations(string_pattern);
|
let ops = extract_formatting_operations(string_pattern);
|
||||||
format(input, &ops)
|
format(input, &ops, call.head)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -116,8 +116,9 @@ fn extract_formatting_operations(input: String) -> Vec<FormatOperation> {
|
||||||
fn format(
|
fn format(
|
||||||
input_data: PipelineData,
|
input_data: PipelineData,
|
||||||
format_operations: &[FormatOperation],
|
format_operations: &[FormatOperation],
|
||||||
|
span: Span,
|
||||||
) -> Result<PipelineData, ShellError> {
|
) -> Result<PipelineData, ShellError> {
|
||||||
let data_as_value = input_data.into_value();
|
let data_as_value = input_data.into_value(span);
|
||||||
|
|
||||||
// We can only handle a Record or a List of Record's
|
// We can only handle a Record or a List of Record's
|
||||||
match data_as_value {
|
match data_as_value {
|
||||||
|
|
|
@ -39,7 +39,13 @@ impl Command for Benchmark {
|
||||||
|
|
||||||
let mut stack = stack.collect_captures(&block.captures);
|
let mut stack = stack.collect_captures(&block.captures);
|
||||||
let start_time = Instant::now();
|
let start_time = Instant::now();
|
||||||
eval_block(engine_state, &mut stack, block, PipelineData::new())?.into_value();
|
eval_block(
|
||||||
|
engine_state,
|
||||||
|
&mut stack,
|
||||||
|
block,
|
||||||
|
PipelineData::new(call.head),
|
||||||
|
)?
|
||||||
|
.into_value(call.head);
|
||||||
|
|
||||||
let end_time = Instant::now();
|
let end_time = Instant::now();
|
||||||
|
|
||||||
|
|
|
@ -161,9 +161,9 @@ impl ExternalCommand {
|
||||||
});
|
});
|
||||||
|
|
||||||
// The ValueStream is consumed by the next expression in the pipeline
|
// The ValueStream is consumed by the next expression in the pipeline
|
||||||
ChannelReceiver::new(rx).into_pipeline_data(ctrlc)
|
ChannelReceiver::new(rx, self.name.span).into_pipeline_data(ctrlc)
|
||||||
} else {
|
} else {
|
||||||
PipelineData::new()
|
PipelineData::new(self.name.span)
|
||||||
};
|
};
|
||||||
|
|
||||||
match child.wait() {
|
match child.wait() {
|
||||||
|
@ -214,11 +214,12 @@ enum Data {
|
||||||
// It implements iterator so it can be used as a ValueStream
|
// It implements iterator so it can be used as a ValueStream
|
||||||
struct ChannelReceiver {
|
struct ChannelReceiver {
|
||||||
rx: mpsc::Receiver<Data>,
|
rx: mpsc::Receiver<Data>,
|
||||||
|
span: Span,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ChannelReceiver {
|
impl ChannelReceiver {
|
||||||
pub fn new(rx: mpsc::Receiver<Data>) -> Self {
|
pub fn new(rx: mpsc::Receiver<Data>, span: Span) -> Self {
|
||||||
Self { rx }
|
Self { rx, span }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -230,11 +231,11 @@ impl Iterator for ChannelReceiver {
|
||||||
Ok(v) => match v {
|
Ok(v) => match v {
|
||||||
Data::String(s) => Some(Value::String {
|
Data::String(s) => Some(Value::String {
|
||||||
val: s,
|
val: s,
|
||||||
span: Span::unknown(),
|
span: self.span,
|
||||||
}),
|
}),
|
||||||
Data::Bytes(b) => Some(Value::Binary {
|
Data::Bytes(b) => Some(Value::Binary {
|
||||||
val: b,
|
val: b,
|
||||||
span: Span::unknown(),
|
span: self.span,
|
||||||
}),
|
}),
|
||||||
},
|
},
|
||||||
Err(_) => None,
|
Err(_) => None,
|
||||||
|
|
|
@ -70,7 +70,7 @@ prints out the list properly."#
|
||||||
separator_param,
|
separator_param,
|
||||||
))
|
))
|
||||||
} else {
|
} else {
|
||||||
Ok(PipelineData::new())
|
Ok(PipelineData::new(call.head))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
PipelineData::Stream(stream) => {
|
PipelineData::Stream(stream) => {
|
||||||
|
@ -86,7 +86,7 @@ prints out the list properly."#
|
||||||
))
|
))
|
||||||
} else {
|
} else {
|
||||||
// dbg!(data);
|
// dbg!(data);
|
||||||
Ok(PipelineData::new())
|
Ok(PipelineData::new(call.head))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
PipelineData::Value(Value::Record { cols, vals, .. }) => {
|
PipelineData::Value(Value::Record { cols, vals, .. }) => {
|
||||||
|
|
|
@ -48,7 +48,7 @@ impl Command for Table {
|
||||||
}
|
}
|
||||||
.into_pipeline_data())
|
.into_pipeline_data())
|
||||||
} else {
|
} else {
|
||||||
Ok(PipelineData::new())
|
Ok(PipelineData::new(call.head))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
PipelineData::Stream(stream) => {
|
PipelineData::Stream(stream) => {
|
||||||
|
@ -63,7 +63,7 @@ impl Command for Table {
|
||||||
}
|
}
|
||||||
.into_pipeline_data())
|
.into_pipeline_data())
|
||||||
} else {
|
} else {
|
||||||
Ok(PipelineData::new())
|
Ok(PipelineData::new(call.head))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
PipelineData::Value(Value::Record { cols, vals, .. }) => {
|
PipelineData::Value(Value::Record { cols, vals, .. }) => {
|
||||||
|
|
|
@ -178,7 +178,11 @@ pub fn eval_expression(
|
||||||
}),
|
}),
|
||||||
Expr::ValueWithUnit(e, unit) => match eval_expression(engine_state, stack, e)? {
|
Expr::ValueWithUnit(e, unit) => match eval_expression(engine_state, stack, e)? {
|
||||||
Value::Int { val, .. } => Ok(compute(val, unit.item, unit.span)),
|
Value::Int { val, .. } => Ok(compute(val, unit.item, unit.span)),
|
||||||
_ => Err(ShellError::CantConvert("unit value".into(), e.span)),
|
x => Err(ShellError::CantConvert(
|
||||||
|
"unit value".into(),
|
||||||
|
x.get_type().to_string(),
|
||||||
|
e.span,
|
||||||
|
)),
|
||||||
},
|
},
|
||||||
Expr::Range(from, next, to, operator) => {
|
Expr::Range(from, next, to, operator) => {
|
||||||
let from = if let Some(f) = from {
|
let from = if let Some(f) = from {
|
||||||
|
@ -224,7 +228,10 @@ pub fn eval_expression(
|
||||||
Expr::RowCondition(_, expr) => eval_expression(engine_state, stack, expr),
|
Expr::RowCondition(_, expr) => eval_expression(engine_state, stack, expr),
|
||||||
Expr::Call(call) => {
|
Expr::Call(call) => {
|
||||||
// FIXME: protect this collect with ctrl-c
|
// FIXME: protect this collect with ctrl-c
|
||||||
Ok(eval_call(engine_state, stack, call, PipelineData::new())?.into_value())
|
Ok(
|
||||||
|
eval_call(engine_state, stack, call, PipelineData::new(call.head))?
|
||||||
|
.into_value(call.head),
|
||||||
|
)
|
||||||
}
|
}
|
||||||
Expr::ExternalCall(name, span, args) => {
|
Expr::ExternalCall(name, span, args) => {
|
||||||
// FIXME: protect this collect with ctrl-c
|
// FIXME: protect this collect with ctrl-c
|
||||||
|
@ -234,10 +241,10 @@ pub fn eval_expression(
|
||||||
name,
|
name,
|
||||||
span,
|
span,
|
||||||
args,
|
args,
|
||||||
PipelineData::new(),
|
PipelineData::new(*span),
|
||||||
true,
|
true,
|
||||||
)?
|
)?
|
||||||
.into_value())
|
.into_value(*span))
|
||||||
}
|
}
|
||||||
Expr::Operator(_) => Ok(Value::Nothing { span: expr.span }),
|
Expr::Operator(_) => Ok(Value::Nothing { span: expr.span }),
|
||||||
Expr::BinaryOp(lhs, op, rhs) => {
|
Expr::BinaryOp(lhs, op, rhs) => {
|
||||||
|
@ -271,7 +278,10 @@ pub fn eval_expression(
|
||||||
let block = engine_state.get_block(*block_id);
|
let block = engine_state.get_block(*block_id);
|
||||||
|
|
||||||
// FIXME: protect this collect with ctrl-c
|
// FIXME: protect this collect with ctrl-c
|
||||||
Ok(eval_block(engine_state, stack, block, PipelineData::new())?.into_value())
|
Ok(
|
||||||
|
eval_subexpression(engine_state, stack, block, PipelineData::new(expr.span))?
|
||||||
|
.into_value(expr.span),
|
||||||
|
)
|
||||||
}
|
}
|
||||||
Expr::Block(block_id) => Ok(Value::Block {
|
Expr::Block(block_id) => Ok(Value::Block {
|
||||||
val: *block_id,
|
val: *block_id,
|
||||||
|
@ -370,6 +380,64 @@ pub fn eval_block(
|
||||||
Ok(input)
|
Ok(input)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn eval_subexpression(
|
||||||
|
engine_state: &EngineState,
|
||||||
|
stack: &mut Stack,
|
||||||
|
block: &Block,
|
||||||
|
mut input: PipelineData,
|
||||||
|
) -> Result<PipelineData, ShellError> {
|
||||||
|
for stmt in block.stmts.iter() {
|
||||||
|
if let Statement::Pipeline(pipeline) = stmt {
|
||||||
|
for (i, elem) in pipeline.expressions.iter().enumerate() {
|
||||||
|
match elem {
|
||||||
|
Expression {
|
||||||
|
expr: Expr::Call(call),
|
||||||
|
..
|
||||||
|
} => {
|
||||||
|
input = eval_call(engine_state, stack, call, input)?;
|
||||||
|
}
|
||||||
|
Expression {
|
||||||
|
expr: Expr::ExternalCall(name, name_span, args),
|
||||||
|
..
|
||||||
|
} => {
|
||||||
|
input = eval_external(
|
||||||
|
engine_state,
|
||||||
|
stack,
|
||||||
|
name,
|
||||||
|
name_span,
|
||||||
|
args,
|
||||||
|
input,
|
||||||
|
false,
|
||||||
|
)?;
|
||||||
|
|
||||||
|
if i == pipeline.expressions.len() - 1 {
|
||||||
|
// We're at the end, so drain as a string for the value
|
||||||
|
// to be used later
|
||||||
|
// FIXME: the trimming of the end probably needs to live in a better place
|
||||||
|
|
||||||
|
let mut s = input.collect_string();
|
||||||
|
if s.ends_with('\n') {
|
||||||
|
s.pop();
|
||||||
|
}
|
||||||
|
input = Value::String {
|
||||||
|
val: s.to_string(),
|
||||||
|
span: *name_span,
|
||||||
|
}
|
||||||
|
.into_pipeline_data()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
elem => {
|
||||||
|
input = eval_expression(engine_state, stack, elem)?.into_pipeline_data();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(input)
|
||||||
|
}
|
||||||
|
|
||||||
pub fn eval_variable(
|
pub fn eval_variable(
|
||||||
engine_state: &EngineState,
|
engine_state: &EngineState,
|
||||||
stack: &Stack,
|
stack: &Stack,
|
||||||
|
|
|
@ -32,7 +32,11 @@ impl FromValue for Spanned<i64> {
|
||||||
span: *span,
|
span: *span,
|
||||||
}),
|
}),
|
||||||
|
|
||||||
v => Err(ShellError::CantConvert("integer".into(), v.span()?)),
|
v => Err(ShellError::CantConvert(
|
||||||
|
"integer".into(),
|
||||||
|
v.get_type().to_string(),
|
||||||
|
v.span()?,
|
||||||
|
)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -44,7 +48,11 @@ impl FromValue for i64 {
|
||||||
Value::Filesize { val, .. } => Ok(*val as i64),
|
Value::Filesize { val, .. } => Ok(*val as i64),
|
||||||
Value::Duration { val, .. } => Ok(*val as i64),
|
Value::Duration { val, .. } => Ok(*val as i64),
|
||||||
|
|
||||||
v => Err(ShellError::CantConvert("integer".into(), v.span()?)),
|
v => Err(ShellError::CantConvert(
|
||||||
|
"integer".into(),
|
||||||
|
v.get_type().to_string(),
|
||||||
|
v.span()?,
|
||||||
|
)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -61,7 +69,11 @@ impl FromValue for Spanned<f64> {
|
||||||
span: *span,
|
span: *span,
|
||||||
}),
|
}),
|
||||||
|
|
||||||
v => Err(ShellError::CantConvert("float".into(), v.span()?)),
|
v => Err(ShellError::CantConvert(
|
||||||
|
"float".into(),
|
||||||
|
v.get_type().to_string(),
|
||||||
|
v.span()?,
|
||||||
|
)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -71,7 +83,11 @@ impl FromValue for f64 {
|
||||||
match v {
|
match v {
|
||||||
Value::Float { val, .. } => Ok(*val),
|
Value::Float { val, .. } => Ok(*val),
|
||||||
Value::Int { val, .. } => Ok(*val as f64),
|
Value::Int { val, .. } => Ok(*val as f64),
|
||||||
v => Err(ShellError::CantConvert("float".into(), v.span()?)),
|
v => Err(ShellError::CantConvert(
|
||||||
|
"float".into(),
|
||||||
|
v.get_type().to_string(),
|
||||||
|
v.span()?,
|
||||||
|
)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -109,7 +125,11 @@ impl FromValue for CellPath {
|
||||||
span,
|
span,
|
||||||
}],
|
}],
|
||||||
}),
|
}),
|
||||||
_ => Err(ShellError::CantConvert("cell path".into(), span)),
|
x => Err(ShellError::CantConvert(
|
||||||
|
"cell path".into(),
|
||||||
|
x.get_type().to_string(),
|
||||||
|
span,
|
||||||
|
)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -118,7 +138,11 @@ impl FromValue for bool {
|
||||||
fn from_value(v: &Value) -> Result<Self, ShellError> {
|
fn from_value(v: &Value) -> Result<Self, ShellError> {
|
||||||
match v {
|
match v {
|
||||||
Value::Bool { val, .. } => Ok(*val),
|
Value::Bool { val, .. } => Ok(*val),
|
||||||
v => Err(ShellError::CantConvert("bool".into(), v.span()?)),
|
v => Err(ShellError::CantConvert(
|
||||||
|
"bool".into(),
|
||||||
|
v.get_type().to_string(),
|
||||||
|
v.span()?,
|
||||||
|
)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -130,7 +154,11 @@ impl FromValue for Spanned<bool> {
|
||||||
item: *val,
|
item: *val,
|
||||||
span: *span,
|
span: *span,
|
||||||
}),
|
}),
|
||||||
v => Err(ShellError::CantConvert("bool".into(), v.span()?)),
|
v => Err(ShellError::CantConvert(
|
||||||
|
"bool".into(),
|
||||||
|
v.get_type().to_string(),
|
||||||
|
v.span()?,
|
||||||
|
)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -139,7 +167,11 @@ impl FromValue for DateTime<FixedOffset> {
|
||||||
fn from_value(v: &Value) -> Result<Self, ShellError> {
|
fn from_value(v: &Value) -> Result<Self, ShellError> {
|
||||||
match v {
|
match v {
|
||||||
Value::Date { val, .. } => Ok(*val),
|
Value::Date { val, .. } => Ok(*val),
|
||||||
v => Err(ShellError::CantConvert("date".into(), v.span()?)),
|
v => Err(ShellError::CantConvert(
|
||||||
|
"date".into(),
|
||||||
|
v.get_type().to_string(),
|
||||||
|
v.span()?,
|
||||||
|
)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -151,7 +183,11 @@ impl FromValue for Spanned<DateTime<FixedOffset>> {
|
||||||
item: *val,
|
item: *val,
|
||||||
span: *span,
|
span: *span,
|
||||||
}),
|
}),
|
||||||
v => Err(ShellError::CantConvert("date".into(), v.span()?)),
|
v => Err(ShellError::CantConvert(
|
||||||
|
"date".into(),
|
||||||
|
v.get_type().to_string(),
|
||||||
|
v.span()?,
|
||||||
|
)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -160,7 +196,11 @@ impl FromValue for Range {
|
||||||
fn from_value(v: &Value) -> Result<Self, ShellError> {
|
fn from_value(v: &Value) -> Result<Self, ShellError> {
|
||||||
match v {
|
match v {
|
||||||
Value::Range { val, .. } => Ok((**val).clone()),
|
Value::Range { val, .. } => Ok((**val).clone()),
|
||||||
v => Err(ShellError::CantConvert("range".into(), v.span()?)),
|
v => Err(ShellError::CantConvert(
|
||||||
|
"range".into(),
|
||||||
|
v.get_type().to_string(),
|
||||||
|
v.span()?,
|
||||||
|
)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -172,7 +212,11 @@ impl FromValue for Spanned<Range> {
|
||||||
item: (**val).clone(),
|
item: (**val).clone(),
|
||||||
span: *span,
|
span: *span,
|
||||||
}),
|
}),
|
||||||
v => Err(ShellError::CantConvert("range".into(), v.span()?)),
|
v => Err(ShellError::CantConvert(
|
||||||
|
"range".into(),
|
||||||
|
v.get_type().to_string(),
|
||||||
|
v.span()?,
|
||||||
|
)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -182,7 +226,11 @@ impl FromValue for Vec<u8> {
|
||||||
match v {
|
match v {
|
||||||
Value::Binary { val, .. } => Ok(val.clone()),
|
Value::Binary { val, .. } => Ok(val.clone()),
|
||||||
Value::String { val, .. } => Ok(val.bytes().collect()),
|
Value::String { val, .. } => Ok(val.bytes().collect()),
|
||||||
v => Err(ShellError::CantConvert("binary data".into(), v.span()?)),
|
v => Err(ShellError::CantConvert(
|
||||||
|
"binary data".into(),
|
||||||
|
v.get_type().to_string(),
|
||||||
|
v.span()?,
|
||||||
|
)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1292,6 +1292,7 @@ pub fn parse_full_cell_path(
|
||||||
if let Some(head) = tokens.peek() {
|
if let Some(head) = tokens.peek() {
|
||||||
let bytes = working_set.get_span_contents(head.span);
|
let bytes = working_set.get_span_contents(head.span);
|
||||||
let (head, expect_dot) = if bytes.starts_with(b"(") {
|
let (head, expect_dot) = if bytes.starts_with(b"(") {
|
||||||
|
let head_span = head.span;
|
||||||
let mut start = head.span.start;
|
let mut start = head.span.start;
|
||||||
let mut end = head.span.end;
|
let mut end = head.span.end;
|
||||||
|
|
||||||
|
@ -1331,7 +1332,7 @@ pub fn parse_full_cell_path(
|
||||||
(
|
(
|
||||||
Expression {
|
Expression {
|
||||||
expr: Expr::Subexpression(block_id),
|
expr: Expr::Subexpression(block_id),
|
||||||
span,
|
span: head_span,
|
||||||
ty: Type::Unknown, // FIXME
|
ty: Type::Unknown, // FIXME
|
||||||
custom_completion: None,
|
custom_completion: None,
|
||||||
},
|
},
|
||||||
|
|
|
@ -37,16 +37,16 @@ pub enum PipelineData {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl PipelineData {
|
impl PipelineData {
|
||||||
pub fn new() -> PipelineData {
|
pub fn new(span: Span) -> PipelineData {
|
||||||
PipelineData::Value(Value::nothing())
|
PipelineData::Value(Value::Nothing { span })
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn into_value(self) -> Value {
|
pub fn into_value(self, span: Span) -> Value {
|
||||||
match self {
|
match self {
|
||||||
PipelineData::Value(v) => v,
|
PipelineData::Value(v) => v,
|
||||||
PipelineData::Stream(s) => Value::List {
|
PipelineData::Stream(s) => Value::List {
|
||||||
vals: s.collect(),
|
vals: s.collect(),
|
||||||
span: Span::unknown(), // FIXME?
|
span, // FIXME?
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -140,11 +140,11 @@ impl PipelineData {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for PipelineData {
|
// impl Default for PipelineData {
|
||||||
fn default() -> Self {
|
// fn default() -> Self {
|
||||||
PipelineData::new()
|
// PipelineData::new()
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
|
||||||
pub struct PipelineIterator(PipelineData);
|
pub struct PipelineIterator(PipelineData);
|
||||||
|
|
||||||
|
|
|
@ -82,7 +82,7 @@ pub enum ShellError {
|
||||||
|
|
||||||
#[error("Can't convert to {0}.")]
|
#[error("Can't convert to {0}.")]
|
||||||
#[diagnostic(code(nu::shell::cant_convert), url(docsrs))]
|
#[diagnostic(code(nu::shell::cant_convert), url(docsrs))]
|
||||||
CantConvert(String, #[label("can't convert to {0}")] Span),
|
CantConvert(String, String, #[label("can't convert {1} to {0}")] Span),
|
||||||
|
|
||||||
#[error("Division by zero.")]
|
#[error("Division by zero.")]
|
||||||
#[diagnostic(code(nu::shell::division_by_zero), url(docsrs))]
|
#[diagnostic(code(nu::shell::division_by_zero), url(docsrs))]
|
||||||
|
|
|
@ -87,7 +87,14 @@ impl Value {
|
||||||
pub fn as_string(&self) -> Result<String, ShellError> {
|
pub fn as_string(&self) -> Result<String, ShellError> {
|
||||||
match self {
|
match self {
|
||||||
Value::String { val, .. } => Ok(val.to_string()),
|
Value::String { val, .. } => Ok(val.to_string()),
|
||||||
_ => Err(ShellError::CantConvert("string".into(), self.span()?)),
|
x => {
|
||||||
|
println!("{:?}", x);
|
||||||
|
Err(ShellError::CantConvert(
|
||||||
|
"string".into(),
|
||||||
|
x.get_type().to_string(),
|
||||||
|
self.span()?,
|
||||||
|
))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -225,10 +232,8 @@ impl Value {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Create a new `Nothing` value
|
/// Create a new `Nothing` value
|
||||||
pub fn nothing() -> Value {
|
pub fn nothing(span: Span) -> Value {
|
||||||
Value::Nothing {
|
Value::Nothing { span }
|
||||||
span: Span::unknown(),
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Follow a given column path into the value: for example accessing nth elements in a stream or list
|
/// Follow a given column path into the value: for example accessing nth elements in a stream or list
|
||||||
|
@ -425,7 +430,9 @@ impl Value {
|
||||||
|
|
||||||
impl Default for Value {
|
impl Default for Value {
|
||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
Value::nothing()
|
Value::Nothing {
|
||||||
|
span: Span::unknown(),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
25
src/main.rs
25
src/main.rs
|
@ -19,7 +19,7 @@ use nu_parser::parse;
|
||||||
use nu_protocol::{
|
use nu_protocol::{
|
||||||
ast::Call,
|
ast::Call,
|
||||||
engine::{EngineState, Stack, StateWorkingSet},
|
engine::{EngineState, Stack, StateWorkingSet},
|
||||||
IntoPipelineData, PipelineData, ShellError, Value,
|
IntoPipelineData, PipelineData, ShellError, Span, Value,
|
||||||
};
|
};
|
||||||
use reedline::{Completer, CompletionActionHandler, DefaultPrompt, LineBuffer, Prompt};
|
use reedline::{Completer, CompletionActionHandler, DefaultPrompt, LineBuffer, Prompt};
|
||||||
|
|
||||||
|
@ -126,7 +126,12 @@ fn main() -> Result<()> {
|
||||||
stack.env_vars.insert(k, v);
|
stack.env_vars.insert(k, v);
|
||||||
}
|
}
|
||||||
|
|
||||||
match eval_block(&engine_state, &mut stack, &block, PipelineData::new()) {
|
match eval_block(
|
||||||
|
&engine_state,
|
||||||
|
&mut stack,
|
||||||
|
&block,
|
||||||
|
PipelineData::new(Span::unknown()),
|
||||||
|
) {
|
||||||
Ok(pipeline_data) => {
|
Ok(pipeline_data) => {
|
||||||
println!("{}", pipeline_data.collect_string());
|
println!("{}", pipeline_data.collect_string());
|
||||||
}
|
}
|
||||||
|
@ -312,7 +317,12 @@ fn update_prompt<'prompt>(
|
||||||
|
|
||||||
let mut stack = stack.clone();
|
let mut stack = stack.clone();
|
||||||
|
|
||||||
let evaluated_prompt = match eval_block(engine_state, &mut stack, &block, PipelineData::new()) {
|
let evaluated_prompt = match eval_block(
|
||||||
|
engine_state,
|
||||||
|
&mut stack,
|
||||||
|
&block,
|
||||||
|
PipelineData::new(Span::unknown()),
|
||||||
|
) {
|
||||||
Ok(pipeline_data) => pipeline_data.collect_string(),
|
Ok(pipeline_data) => pipeline_data.collect_string(),
|
||||||
Err(err) => {
|
Err(err) => {
|
||||||
let working_set = StateWorkingSet::new(engine_state);
|
let working_set = StateWorkingSet::new(engine_state);
|
||||||
|
@ -349,9 +359,14 @@ fn eval_source(
|
||||||
|
|
||||||
engine_state.merge_delta(delta);
|
engine_state.merge_delta(delta);
|
||||||
|
|
||||||
match eval_block(engine_state, stack, &block, PipelineData::new()) {
|
match eval_block(
|
||||||
|
engine_state,
|
||||||
|
stack,
|
||||||
|
&block,
|
||||||
|
PipelineData::new(Span::unknown()),
|
||||||
|
) {
|
||||||
Ok(pipeline_data) => {
|
Ok(pipeline_data) => {
|
||||||
if let Err(err) = print_value(pipeline_data.into_value(), engine_state) {
|
if let Err(err) = print_value(pipeline_data.into_value(Span::unknown()), engine_state) {
|
||||||
let working_set = StateWorkingSet::new(engine_state);
|
let working_set = StateWorkingSet::new(engine_state);
|
||||||
|
|
||||||
report_error(&working_set, &err);
|
report_error(&working_set, &err);
|
||||||
|
|
Loading…
Reference in a new issue