mirror of
https://github.com/nushell/nushell.git
synced 2025-08-09 21:07:58 +02:00
Fixing captures (#723)
* WIP fixing captures * small fix * WIP * Rewrite to proof-of-concept better parse_def * Add missing file * Finish capture refactor * Fix tests * Add more tests
This commit is contained in:
@ -112,6 +112,10 @@ impl Expression {
|
||||
Expr::Block(block_id) => {
|
||||
let block = working_set.get_block(*block_id);
|
||||
|
||||
if block.captures.contains(&IN_VARIABLE_ID) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if let Some(Statement::Pipeline(pipeline)) = block.stmts.get(0) {
|
||||
match pipeline.expressions.get(0) {
|
||||
Some(expr) => expr.has_in_variable(working_set),
|
||||
|
9
crates/nu-protocol/src/engine/capture_block.rs
Normal file
9
crates/nu-protocol/src/engine/capture_block.rs
Normal file
@ -0,0 +1,9 @@
|
||||
use std::collections::HashMap;
|
||||
|
||||
use crate::{BlockId, Value, VarId};
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct CaptureBlock {
|
||||
pub block_id: BlockId,
|
||||
pub captures: HashMap<VarId, Value>,
|
||||
}
|
@ -154,6 +154,7 @@ pub const SCOPE_VARIABLE_ID: usize = 1;
|
||||
pub const IN_VARIABLE_ID: usize = 2;
|
||||
pub const CONFIG_VARIABLE_ID: usize = 3;
|
||||
pub const ENV_VARIABLE_ID: usize = 4;
|
||||
// NOTE: If you add more to this list, make sure to update the > checks based on the last in the list
|
||||
|
||||
impl EngineState {
|
||||
pub fn new() -> Self {
|
||||
|
@ -1,9 +1,11 @@
|
||||
mod call_info;
|
||||
mod capture_block;
|
||||
mod command;
|
||||
mod engine_state;
|
||||
mod stack;
|
||||
|
||||
pub use call_info::*;
|
||||
pub use capture_block::*;
|
||||
pub use command::*;
|
||||
pub use engine_state::*;
|
||||
pub use stack::*;
|
||||
|
@ -62,7 +62,10 @@ impl Stack {
|
||||
return Ok(v.clone());
|
||||
}
|
||||
|
||||
Err(ShellError::NushellFailed("variable not found".into()))
|
||||
Err(ShellError::NushellFailed(format!(
|
||||
"variable (var_id: {}) not found",
|
||||
var_id
|
||||
)))
|
||||
}
|
||||
|
||||
pub fn add_var(&mut self, var_id: VarId, value: Value) {
|
||||
@ -80,7 +83,24 @@ impl Stack {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn collect_captures(&self, captures: &[VarId]) -> Stack {
|
||||
pub fn captures_to_stack(&self, captures: &HashMap<VarId, Value>) -> Stack {
|
||||
let mut output = Stack::new();
|
||||
|
||||
output.vars = captures.clone();
|
||||
|
||||
// FIXME: this is probably slow
|
||||
output.env_vars = self.env_vars.clone();
|
||||
output.env_vars.push(HashMap::new());
|
||||
|
||||
let config = self
|
||||
.get_var(CONFIG_VARIABLE_ID)
|
||||
.expect("internal error: config is missing");
|
||||
output.vars.insert(CONFIG_VARIABLE_ID, config);
|
||||
|
||||
output
|
||||
}
|
||||
|
||||
pub fn gather_captures(&self, captures: &[VarId]) -> Stack {
|
||||
let mut output = Stack::new();
|
||||
|
||||
for capture in captures {
|
||||
|
@ -6,6 +6,7 @@ use std::str::FromStr;
|
||||
use chrono::{DateTime, FixedOffset};
|
||||
// use nu_path::expand_path;
|
||||
use crate::ast::{CellPath, PathMember};
|
||||
use crate::engine::CaptureBlock;
|
||||
use crate::ShellError;
|
||||
use crate::{Range, Spanned, Value};
|
||||
|
||||
@ -351,3 +352,42 @@ impl FromValue for Vec<Value> {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl FromValue for CaptureBlock {
|
||||
fn from_value(v: &Value) -> Result<Self, ShellError> {
|
||||
match v {
|
||||
Value::Block { val, captures, .. } => Ok(CaptureBlock {
|
||||
block_id: *val,
|
||||
captures: captures.clone(),
|
||||
}),
|
||||
v => Err(ShellError::CantConvert(
|
||||
"Block".into(),
|
||||
v.get_type().to_string(),
|
||||
v.span()?,
|
||||
)),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl FromValue for Spanned<CaptureBlock> {
|
||||
fn from_value(v: &Value) -> Result<Self, ShellError> {
|
||||
match v {
|
||||
Value::Block {
|
||||
val,
|
||||
captures,
|
||||
span,
|
||||
} => Ok(Spanned {
|
||||
item: CaptureBlock {
|
||||
block_id: *val,
|
||||
captures: captures.clone(),
|
||||
},
|
||||
span: *span,
|
||||
}),
|
||||
v => Err(ShellError::CantConvert(
|
||||
"Block".into(),
|
||||
v.get_type().to_string(),
|
||||
v.span()?,
|
||||
)),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -22,7 +22,7 @@ use std::path::PathBuf;
|
||||
use std::{cmp::Ordering, fmt::Debug};
|
||||
|
||||
use crate::ast::{CellPath, PathMember};
|
||||
use crate::{did_you_mean, span, BlockId, Config, Span, Spanned, Type};
|
||||
use crate::{did_you_mean, span, BlockId, Config, Span, Spanned, Type, VarId};
|
||||
|
||||
use crate::ast::Operator;
|
||||
pub use custom_value::CustomValue;
|
||||
@ -75,6 +75,7 @@ pub enum Value {
|
||||
},
|
||||
Block {
|
||||
val: BlockId,
|
||||
captures: HashMap<VarId, Value>,
|
||||
span: Span,
|
||||
},
|
||||
Nothing {
|
||||
@ -141,8 +142,13 @@ impl Clone for Value {
|
||||
vals: vals.clone(),
|
||||
span: *span,
|
||||
},
|
||||
Value::Block { val, span } => Value::Block {
|
||||
Value::Block {
|
||||
val,
|
||||
captures,
|
||||
span,
|
||||
} => Value::Block {
|
||||
val: *val,
|
||||
captures: captures.clone(),
|
||||
span: *span,
|
||||
},
|
||||
Value::Nothing { span } => Value::Nothing { span: *span },
|
||||
|
Reference in New Issue
Block a user