mirror of
https://github.com/nushell/nushell.git
synced 2025-02-09 23:19:22 +01:00
Merge pull request #879 from andrasio/tilde-pattern
Expand tilde in patterns.
This commit is contained in:
commit
1eaaf368ee
@ -367,6 +367,10 @@ impl ShellError {
|
|||||||
// pub fn string(title: impl Into<String>) -> ShellError {
|
// pub fn string(title: impl Into<String>) -> ShellError {
|
||||||
// ProximateShellError::String(StringError::new(title.into(), String::new())).start()
|
// ProximateShellError::String(StringError::new(title.into(), String::new())).start()
|
||||||
// }
|
// }
|
||||||
|
//
|
||||||
|
// pub(crate) fn unreachable(title: impl Into<String>) -> ShellError {
|
||||||
|
// ShellError::untagged_runtime_error(&format!("BUG: Unreachable: {}", title.into()))
|
||||||
|
// }
|
||||||
|
|
||||||
pub(crate) fn unimplemented(title: impl Into<String>) -> ShellError {
|
pub(crate) fn unimplemented(title: impl Into<String>) -> ShellError {
|
||||||
ShellError::untagged_runtime_error(&format!("Unimplemented: {}", title.into()))
|
ShellError::untagged_runtime_error(&format!("Unimplemented: {}", title.into()))
|
||||||
@ -375,10 +379,6 @@ impl ShellError {
|
|||||||
pub(crate) fn unexpected(title: impl Into<String>) -> ShellError {
|
pub(crate) fn unexpected(title: impl Into<String>) -> ShellError {
|
||||||
ShellError::untagged_runtime_error(&format!("Unexpected: {}", title.into()))
|
ShellError::untagged_runtime_error(&format!("Unexpected: {}", title.into()))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn unreachable(title: impl Into<String>) -> ShellError {
|
|
||||||
ShellError::untagged_runtime_error(&format!("BUG: Unreachable: {}", title.into()))
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Eq, PartialEq, Clone, Ord, PartialOrd, Serialize, Deserialize)]
|
#[derive(Debug, Eq, PartialEq, Clone, Ord, PartialOrd, Serialize, Deserialize)]
|
||||||
|
@ -148,7 +148,7 @@ fn evaluate_literal(literal: Tagged<&hir::Literal>, source: &Text) -> Tagged<Val
|
|||||||
hir::Literal::Number(int) => int.into(),
|
hir::Literal::Number(int) => int.into(),
|
||||||
hir::Literal::Size(int, unit) => unit.compute(int),
|
hir::Literal::Size(int, unit) => unit.compute(int),
|
||||||
hir::Literal::String(tag) => Value::string(tag.slice(source)),
|
hir::Literal::String(tag) => Value::string(tag.slice(source)),
|
||||||
hir::Literal::GlobPattern => Value::pattern(literal.tag().slice(source)),
|
hir::Literal::GlobPattern(pattern) => Value::pattern(pattern),
|
||||||
hir::Literal::Bare => Value::string(literal.tag().slice(source)),
|
hir::Literal::Bare => Value::string(literal.tag().slice(source)),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -227,8 +227,8 @@ impl Expression {
|
|||||||
RawExpression::Literal(Literal::Bare).spanned(span)
|
RawExpression::Literal(Literal::Bare).spanned(span)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn pattern(span: impl Into<Span>) -> Expression {
|
pub(crate) fn pattern(inner: impl Into<String>, outer: impl Into<Span>) -> Expression {
|
||||||
RawExpression::Literal(Literal::GlobPattern).spanned(span.into())
|
RawExpression::Literal(Literal::GlobPattern(inner.into())).spanned(outer.into())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn variable(inner: impl Into<Span>, outer: impl Into<Span>) -> Expression {
|
pub(crate) fn variable(inner: impl Into<Span>, outer: impl Into<Span>) -> Expression {
|
||||||
@ -297,7 +297,7 @@ pub enum Literal {
|
|||||||
Number(Number),
|
Number(Number),
|
||||||
Size(Number, Unit),
|
Size(Number, Unit),
|
||||||
String(Span),
|
String(Span),
|
||||||
GlobPattern,
|
GlobPattern(String),
|
||||||
Bare,
|
Bare,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -315,7 +315,7 @@ impl std::fmt::Display for Tagged<&Literal> {
|
|||||||
Literal::Number(number) => write!(f, "{}", number),
|
Literal::Number(number) => write!(f, "{}", number),
|
||||||
Literal::Size(number, unit) => write!(f, "{}{}", number, unit.as_str()),
|
Literal::Size(number, unit) => write!(f, "{}{}", number, unit.as_str()),
|
||||||
Literal::String(_) => write!(f, "String{{ {}..{} }}", span.start(), span.end()),
|
Literal::String(_) => write!(f, "String{{ {}..{} }}", span.start(), span.end()),
|
||||||
Literal::GlobPattern => write!(f, "Glob{{ {}..{} }}", span.start(), span.end()),
|
Literal::GlobPattern(_) => write!(f, "Glob{{ {}..{} }}", span.start(), span.end()),
|
||||||
Literal::Bare => write!(f, "Bare{{ {}..{} }}", span.start(), span.end()),
|
Literal::Bare => write!(f, "Bare{{ {}..{} }}", span.start(), span.end()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -327,7 +327,7 @@ impl ToDebug for Spanned<&Literal> {
|
|||||||
Literal::Number(number) => write!(f, "{:?}", number),
|
Literal::Number(number) => write!(f, "{:?}", number),
|
||||||
Literal::Size(number, unit) => write!(f, "{:?}{:?}", *number, unit),
|
Literal::Size(number, unit) => write!(f, "{:?}{:?}", *number, unit),
|
||||||
Literal::String(tag) => write!(f, "{}", tag.slice(source)),
|
Literal::String(tag) => write!(f, "{}", tag.slice(source)),
|
||||||
Literal::GlobPattern => write!(f, "{}", self.span.slice(source)),
|
Literal::GlobPattern(_) => write!(f, "{}", self.span.slice(source)),
|
||||||
Literal::Bare => write!(f, "{}", self.span.slice(source)),
|
Literal::Bare => write!(f, "{}", self.span.slice(source)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -340,7 +340,7 @@ impl Literal {
|
|||||||
Literal::Size(..) => "size",
|
Literal::Size(..) => "size",
|
||||||
Literal::String(..) => "string",
|
Literal::String(..) => "string",
|
||||||
Literal::Bare => "string",
|
Literal::Bare => "string",
|
||||||
Literal::GlobPattern => "pattern",
|
Literal::GlobPattern(_) => "pattern",
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -6,7 +6,7 @@ use crate::parser::hir::syntax_shape::*;
|
|||||||
use crate::parser::hir::TokensIterator;
|
use crate::parser::hir::TokensIterator;
|
||||||
use crate::parser::parse::token_tree_builder::{CurriedToken, TokenTreeBuilder as b};
|
use crate::parser::parse::token_tree_builder::{CurriedToken, TokenTreeBuilder as b};
|
||||||
use crate::parser::TokenNode;
|
use crate::parser::TokenNode;
|
||||||
use crate::{Span, SpannedItem, Tag, Tagged, Text};
|
use crate::{Span, SpannedItem, Tag, Text};
|
||||||
use pretty_assertions::assert_eq;
|
use pretty_assertions::assert_eq;
|
||||||
use std::fmt::Debug;
|
use std::fmt::Debug;
|
||||||
|
|
||||||
@ -63,7 +63,7 @@ fn test_parse_command() {
|
|||||||
vec![b::bare("ls"), b::sp(), b::pattern("*.txt")],
|
vec![b::bare("ls"), b::sp(), b::pattern("*.txt")],
|
||||||
|tokens| {
|
|tokens| {
|
||||||
let bare = tokens[0].expect_bare();
|
let bare = tokens[0].expect_bare();
|
||||||
let pat = tokens[2].span();
|
let pattern = tokens[2].expect_pattern();
|
||||||
|
|
||||||
ClassifiedCommand::Internal(InternalCommand::new(
|
ClassifiedCommand::Internal(InternalCommand::new(
|
||||||
"ls".to_string(),
|
"ls".to_string(),
|
||||||
@ -73,7 +73,7 @@ fn test_parse_command() {
|
|||||||
},
|
},
|
||||||
hir::Call {
|
hir::Call {
|
||||||
head: Box::new(hir::RawExpression::Command(bare).spanned(bare)),
|
head: Box::new(hir::RawExpression::Command(bare).spanned(bare)),
|
||||||
positional: Some(vec![hir::Expression::pattern(pat)]),
|
positional: Some(vec![hir::Expression::pattern("*.txt", pattern)]),
|
||||||
named: None,
|
named: None,
|
||||||
},
|
},
|
||||||
))
|
))
|
||||||
@ -84,41 +84,19 @@ fn test_parse_command() {
|
|||||||
// )
|
// )
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
parse_tokens(
|
|
||||||
VariablePathShape,
|
|
||||||
vec![
|
|
||||||
b::var("cpu"),
|
|
||||||
b::op("."),
|
|
||||||
b::bare("amount"),
|
|
||||||
b::op("."),
|
|
||||||
b::string("max ghz"),
|
|
||||||
],
|
|
||||||
|tokens| {
|
|
||||||
let (outer_var, inner_var) = tokens[0].expect_var();
|
|
||||||
let amount = tokens[2].expect_bare();
|
|
||||||
let (outer_max_ghz, _) = tokens[4].expect_string();
|
|
||||||
|
|
||||||
hir::Expression::path(
|
|
||||||
hir::Expression::variable(inner_var, outer_var),
|
|
||||||
vec!["amount".spanned(amount), "max ghz".spanned(outer_max_ghz)],
|
|
||||||
outer_var.until(outer_max_ghz),
|
|
||||||
)
|
|
||||||
},
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parse_tokens<T: Eq + Debug>(
|
fn parse_tokens<T: Eq + Debug>(
|
||||||
shape: impl ExpandSyntax<Output = T>,
|
shape: impl ExpandSyntax<Output = T>,
|
||||||
tokens: Vec<CurriedToken>,
|
tokens: Vec<CurriedToken>,
|
||||||
expected: impl FnOnce(Tagged<&[TokenNode]>) -> T,
|
expected: impl FnOnce(&[TokenNode]) -> T,
|
||||||
) {
|
) {
|
||||||
let tokens = b::token_list(tokens);
|
let tokens = b::token_list(tokens);
|
||||||
let (tokens, source) = b::build(tokens);
|
let (tokens, source) = b::build(tokens);
|
||||||
|
|
||||||
ExpandContext::with_empty(&Text::from(source), |context| {
|
ExpandContext::with_empty(&Text::from(source), |context| {
|
||||||
let tokens = tokens.expect_list();
|
let tokens = tokens.expect_list();
|
||||||
let mut iterator = TokensIterator::all(tokens.item, *context.span());
|
let mut iterator = TokensIterator::all(tokens, *context.span());
|
||||||
|
|
||||||
let expr = expand_syntax(&shape, &mut iterator, &context);
|
let expr = expand_syntax(&shape, &mut iterator, &context);
|
||||||
|
|
||||||
|
@ -497,18 +497,18 @@ pub(crate) fn expand_expr<'a, 'b, T: ExpandExpression>(
|
|||||||
token_nodes: &'b mut TokensIterator<'a>,
|
token_nodes: &'b mut TokensIterator<'a>,
|
||||||
context: &ExpandContext,
|
context: &ExpandContext,
|
||||||
) -> Result<hir::Expression, ShellError> {
|
) -> Result<hir::Expression, ShellError> {
|
||||||
trace!(target: "nu::expand_syntax", "before {} :: {:?}", std::any::type_name::<T>(), debug_tokens(token_nodes.state(), context.source));
|
trace!(target: "nu::expand_expression", "before {} :: {:?}", std::any::type_name::<T>(), debug_tokens(token_nodes.state(), context.source));
|
||||||
|
|
||||||
let result = shape.expand_syntax(token_nodes, context);
|
let result = shape.expand_expr(token_nodes, context);
|
||||||
|
|
||||||
match result {
|
match result {
|
||||||
Err(err) => {
|
Err(err) => {
|
||||||
trace!(target: "nu::expand_syntax", "error :: {} :: {:?}", err, debug_tokens(token_nodes.state(), context.source));
|
trace!(target: "nu::expand_expression", "error :: {} :: {:?}", err, debug_tokens(token_nodes.state(), context.source));
|
||||||
Err(err)
|
Err(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(result) => {
|
Ok(result) => {
|
||||||
trace!(target: "nu::expand_syntax", "ok :: {:?} :: {:?}", result, debug_tokens(token_nodes.state(), context.source));
|
trace!(target: "nu::expand_expression", "ok :: {:?} :: {:?}", result, debug_tokens(token_nodes.state(), context.source));
|
||||||
Ok(result)
|
Ok(result)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -719,11 +719,7 @@ impl TestSyntax for BareShape {
|
|||||||
let peeked = token_nodes.peek_any();
|
let peeked = token_nodes.peek_any();
|
||||||
|
|
||||||
match peeked.node {
|
match peeked.node {
|
||||||
Some(TokenNode::Token(token)) => match token.item {
|
Some(token) if token.is_bare() => Some(peeked),
|
||||||
RawToken::Bare => Some(peeked),
|
|
||||||
_ => None,
|
|
||||||
},
|
|
||||||
|
|
||||||
_ => None,
|
_ => None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -142,7 +142,10 @@ impl<'tokens> SpannedAtomicToken<'tokens> {
|
|||||||
Expression::external_command(*command, self.span)
|
Expression::external_command(*command, self.span)
|
||||||
}
|
}
|
||||||
AtomicToken::ExternalWord { text } => Expression::string(*text, self.span),
|
AtomicToken::ExternalWord { text } => Expression::string(*text, self.span),
|
||||||
AtomicToken::GlobPattern { pattern } => Expression::pattern(*pattern),
|
AtomicToken::GlobPattern { pattern } => Expression::pattern(
|
||||||
|
expand_file_path(pattern.slice(context.source), context).to_string_lossy(),
|
||||||
|
self.span,
|
||||||
|
),
|
||||||
AtomicToken::Word { text } => Expression::string(*text, *text),
|
AtomicToken::Word { text } => Expression::string(*text, *text),
|
||||||
AtomicToken::SquareDelimited { .. } => unimplemented!("into_hir"),
|
AtomicToken::SquareDelimited { .. } => unimplemented!("into_hir"),
|
||||||
AtomicToken::ParenDelimited { .. } => unimplemented!("into_hir"),
|
AtomicToken::ParenDelimited { .. } => unimplemented!("into_hir"),
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
use crate::parser::hir::syntax_shape::{
|
use crate::parser::hir::syntax_shape::{
|
||||||
expand_atom, expand_bare, expand_syntax, expression::expand_file_path, parse_single_node,
|
expand_atom, expand_bare, expression::expand_file_path, AtomicToken, ExpandContext,
|
||||||
AtomicToken, ExpandContext, ExpandExpression, ExpandSyntax, ExpansionRule, FallibleColorSyntax,
|
ExpandExpression, ExpandSyntax, ExpansionRule, FallibleColorSyntax, FlatShape,
|
||||||
FlatShape,
|
|
||||||
};
|
};
|
||||||
use crate::parser::{hir, hir::TokensIterator, Operator, RawToken, TokenNode};
|
use crate::parser::{hir, hir::TokensIterator, Operator, RawToken, TokenNode};
|
||||||
use crate::prelude::*;
|
use crate::prelude::*;
|
||||||
@ -72,43 +71,17 @@ impl ExpandExpression for PatternShape {
|
|||||||
token_nodes: &mut TokensIterator<'_>,
|
token_nodes: &mut TokensIterator<'_>,
|
||||||
context: &ExpandContext,
|
context: &ExpandContext,
|
||||||
) -> Result<hir::Expression, ShellError> {
|
) -> Result<hir::Expression, ShellError> {
|
||||||
let pattern = expand_syntax(&BarePatternShape, token_nodes, context);
|
let atom = expand_atom(token_nodes, "pattern", context, ExpansionRule::new())?;
|
||||||
|
|
||||||
match pattern {
|
match atom.item {
|
||||||
Ok(tag) => {
|
AtomicToken::Word { text: body }
|
||||||
return Ok(hir::Expression::pattern(tag));
|
| AtomicToken::String { body }
|
||||||
|
| AtomicToken::GlobPattern { pattern: body } => {
|
||||||
|
let path = expand_file_path(body.slice(context.source), context);
|
||||||
|
return Ok(hir::Expression::pattern(path.to_string_lossy(), atom.span));
|
||||||
}
|
}
|
||||||
Err(_) => {}
|
_ => return atom.into_hir(context, "pattern"),
|
||||||
}
|
}
|
||||||
|
|
||||||
parse_single_node(token_nodes, "Pattern", |token, token_tag, _| {
|
|
||||||
Ok(match token {
|
|
||||||
RawToken::GlobPattern => {
|
|
||||||
return Err(ShellError::unreachable(
|
|
||||||
"glob pattern after glob already returned",
|
|
||||||
))
|
|
||||||
}
|
|
||||||
RawToken::Operator(..) => {
|
|
||||||
return Err(ShellError::unreachable("dot after glob already returned"))
|
|
||||||
}
|
|
||||||
RawToken::Bare => {
|
|
||||||
return Err(ShellError::unreachable("bare after glob already returned"))
|
|
||||||
}
|
|
||||||
|
|
||||||
RawToken::Variable(tag) if tag.slice(context.source) == "it" => {
|
|
||||||
hir::Expression::it_variable(tag, token_tag)
|
|
||||||
}
|
|
||||||
RawToken::Variable(tag) => hir::Expression::variable(tag, token_tag),
|
|
||||||
RawToken::ExternalCommand(tag) => hir::Expression::external_command(tag, token_tag),
|
|
||||||
RawToken::ExternalWord => return Err(ShellError::invalid_external_word(token_tag)),
|
|
||||||
RawToken::Number(_) => hir::Expression::bare(token_tag),
|
|
||||||
|
|
||||||
RawToken::String(tag) => hir::Expression::file_path(
|
|
||||||
expand_file_path(tag.slice(context.source), context),
|
|
||||||
token_tag,
|
|
||||||
),
|
|
||||||
})
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3,7 +3,7 @@ use crate::parser::hir::syntax_shape::{
|
|||||||
ExpansionRule, FallibleColorSyntax, FlatShape, TestSyntax,
|
ExpansionRule, FallibleColorSyntax, FlatShape, TestSyntax,
|
||||||
};
|
};
|
||||||
use crate::parser::hir::tokens_iterator::Peeked;
|
use crate::parser::hir::tokens_iterator::Peeked;
|
||||||
use crate::parser::{hir, hir::TokensIterator, RawToken, TokenNode};
|
use crate::parser::{hir, hir::TokensIterator, RawToken};
|
||||||
use crate::prelude::*;
|
use crate::prelude::*;
|
||||||
|
|
||||||
#[derive(Debug, Copy, Clone)]
|
#[derive(Debug, Copy, Clone)]
|
||||||
@ -118,11 +118,7 @@ impl TestSyntax for StringShape {
|
|||||||
let peeked = token_nodes.peek_any();
|
let peeked = token_nodes.peek_any();
|
||||||
|
|
||||||
match peeked.node {
|
match peeked.node {
|
||||||
Some(TokenNode::Token(token)) => match token.item {
|
Some(token) if token.is_string() => Some(peeked),
|
||||||
RawToken::String(_) => Some(peeked),
|
|
||||||
_ => None,
|
|
||||||
},
|
|
||||||
|
|
||||||
_ => None,
|
_ => None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -821,7 +821,7 @@ impl ExpandSyntax for MemberShape {
|
|||||||
|
|
||||||
if let Some(peeked) = string {
|
if let Some(peeked) = string {
|
||||||
let node = peeked.not_eof("column")?.commit();
|
let node = peeked.not_eof("column")?.commit();
|
||||||
let (outer, inner) = node.expect_string();
|
let (outer, inner) = node.as_string().unwrap();
|
||||||
|
|
||||||
return Ok(Member::String(outer, inner));
|
return Ok(Member::String(outer, inner));
|
||||||
}
|
}
|
||||||
|
@ -566,7 +566,7 @@ impl<'content> TokensIterator<'content> {
|
|||||||
impl<'content> Iterator for TokensIterator<'content> {
|
impl<'content> Iterator for TokensIterator<'content> {
|
||||||
type Item = &'content TokenNode;
|
type Item = &'content TokenNode;
|
||||||
|
|
||||||
fn next(&mut self) -> Option<&'content TokenNode> {
|
fn next(&mut self) -> Option<Self::Item> {
|
||||||
next(self, self.state.skip_ws)
|
next(self, self.state.skip_ws)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -666,7 +666,7 @@ fn is_glob_specific_char(c: char) -> bool {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn is_start_glob_char(c: char) -> bool {
|
fn is_start_glob_char(c: char) -> bool {
|
||||||
is_start_bare_char(c) || is_glob_specific_char(c)
|
is_start_bare_char(c) || is_glob_specific_char(c) || c == '.'
|
||||||
}
|
}
|
||||||
|
|
||||||
fn is_glob_char(c: char) -> bool {
|
fn is_glob_char(c: char) -> bool {
|
||||||
@ -1147,7 +1147,7 @@ mod tests {
|
|||||||
fn test_patterns() {
|
fn test_patterns() {
|
||||||
equal_tokens! {
|
equal_tokens! {
|
||||||
<pipeline>
|
<pipeline>
|
||||||
"cp ../formats/*" -> b::pipeline(vec![vec![b::bare("cp"), b::sp(), b::op("."), b::op("."), b::pattern("/formats/*")]])
|
"cp ../formats/*" -> b::pipeline(vec![vec![b::bare("cp"), b::sp(), b::pattern("../formats/*")]])
|
||||||
}
|
}
|
||||||
|
|
||||||
equal_tokens! {
|
equal_tokens! {
|
||||||
|
@ -155,6 +155,26 @@ impl TokenNode {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn is_string(&self) -> bool {
|
||||||
|
match self {
|
||||||
|
TokenNode::Token(Spanned {
|
||||||
|
item: RawToken::String(_),
|
||||||
|
..
|
||||||
|
}) => true,
|
||||||
|
_ => false,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn as_string(&self) -> Option<(Span, Span)> {
|
||||||
|
match self {
|
||||||
|
TokenNode::Token(Spanned {
|
||||||
|
item: RawToken::String(inner_span),
|
||||||
|
span: outer_span,
|
||||||
|
}) => Some((*outer_span, *inner_span)),
|
||||||
|
_ => None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn is_pattern(&self) -> bool {
|
pub fn is_pattern(&self) -> bool {
|
||||||
match self {
|
match self {
|
||||||
TokenNode::Token(Spanned {
|
TokenNode::Token(Spanned {
|
||||||
@ -200,16 +220,6 @@ impl TokenNode {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn expect_external(&self) -> Span {
|
|
||||||
match self {
|
|
||||||
TokenNode::Token(Spanned {
|
|
||||||
item: RawToken::ExternalCommand(span),
|
|
||||||
..
|
|
||||||
}) => *span,
|
|
||||||
_ => panic!("Only call expect_external if you checked is_external first"),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub(crate) fn as_flag(&self, value: &str, source: &Text) -> Option<Spanned<Flag>> {
|
pub(crate) fn as_flag(&self, value: &str, source: &Text) -> Option<Spanned<Flag>> {
|
||||||
match self {
|
match self {
|
||||||
TokenNode::Flag(
|
TokenNode::Flag(
|
||||||
@ -224,7 +234,7 @@ impl TokenNode {
|
|||||||
pub fn as_pipeline(&self) -> Result<Pipeline, ShellError> {
|
pub fn as_pipeline(&self) -> Result<Pipeline, ShellError> {
|
||||||
match self {
|
match self {
|
||||||
TokenNode::Pipeline(Spanned { item, .. }) => Ok(item.clone()),
|
TokenNode::Pipeline(Spanned { item, .. }) => Ok(item.clone()),
|
||||||
_ => Err(ShellError::unimplemented("unimplemented")),
|
_ => Err(ShellError::type_error("pipeline", self.tagged_type_name())),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -234,49 +244,6 @@ impl TokenNode {
|
|||||||
_ => false,
|
_ => false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn expect_string(&self) -> (Span, Span) {
|
|
||||||
match self {
|
|
||||||
TokenNode::Token(Spanned {
|
|
||||||
item: RawToken::String(inner_span),
|
|
||||||
span: outer_span,
|
|
||||||
}) => (*outer_span, *inner_span),
|
|
||||||
other => panic!("Expected string, found {:?}", other),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(test)]
|
|
||||||
impl TokenNode {
|
|
||||||
pub fn expect_list(&self) -> Tagged<&[TokenNode]> {
|
|
||||||
match self {
|
|
||||||
TokenNode::Nodes(Spanned { item, span }) => (&item[..]).tagged(Tag {
|
|
||||||
span: *span,
|
|
||||||
anchor: None,
|
|
||||||
}),
|
|
||||||
other => panic!("Expected list, found {:?}", other),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn expect_var(&self) -> (Span, Span) {
|
|
||||||
match self {
|
|
||||||
TokenNode::Token(Spanned {
|
|
||||||
item: RawToken::Variable(inner_span),
|
|
||||||
span: outer_span,
|
|
||||||
}) => (*outer_span, *inner_span),
|
|
||||||
other => panic!("Expected var, found {:?}", other),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn expect_bare(&self) -> Span {
|
|
||||||
match self {
|
|
||||||
TokenNode::Token(Spanned {
|
|
||||||
item: RawToken::Bare,
|
|
||||||
span,
|
|
||||||
}) => *span,
|
|
||||||
other => panic!("Expected bare, found {:?}", other),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, Eq, PartialEq, Ord, PartialOrd, Getters, new)]
|
#[derive(Debug, Clone, Eq, PartialEq, Ord, PartialOrd, Getters, new)]
|
||||||
@ -328,3 +295,76 @@ pub struct PathNode {
|
|||||||
head: Box<TokenNode>,
|
head: Box<TokenNode>,
|
||||||
tail: Vec<TokenNode>,
|
tail: Vec<TokenNode>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
impl TokenNode {
|
||||||
|
pub fn expect_external(&self) -> Span {
|
||||||
|
match self {
|
||||||
|
TokenNode::Token(Spanned {
|
||||||
|
item: RawToken::ExternalCommand(span),
|
||||||
|
..
|
||||||
|
}) => *span,
|
||||||
|
other => panic!(
|
||||||
|
"Only call expect_external if you checked is_external first, found {:?}",
|
||||||
|
other
|
||||||
|
),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn expect_string(&self) -> (Span, Span) {
|
||||||
|
match self {
|
||||||
|
TokenNode::Token(Spanned {
|
||||||
|
item: RawToken::String(inner_span),
|
||||||
|
span: outer_span,
|
||||||
|
}) => (*outer_span, *inner_span),
|
||||||
|
other => panic!("Expected string, found {:?}", other),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn expect_list(&self) -> &[TokenNode] {
|
||||||
|
match self {
|
||||||
|
TokenNode::Nodes(token_nodes) => &token_nodes[..],
|
||||||
|
other => panic!("Expected list, found {:?}", other),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn expect_pattern(&self) -> Span {
|
||||||
|
match self {
|
||||||
|
TokenNode::Token(Spanned {
|
||||||
|
item: RawToken::GlobPattern,
|
||||||
|
span: outer_span,
|
||||||
|
}) => *outer_span,
|
||||||
|
other => panic!("Expected pattern, found {:?}", other),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn expect_var(&self) -> (Span, Span) {
|
||||||
|
match self {
|
||||||
|
TokenNode::Token(Spanned {
|
||||||
|
item: RawToken::Variable(inner_span),
|
||||||
|
span: outer_span,
|
||||||
|
}) => (*outer_span, *inner_span),
|
||||||
|
other => panic!("Expected var, found {:?}", other),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn expect_dot(&self) -> Span {
|
||||||
|
match self {
|
||||||
|
TokenNode::Token(Spanned {
|
||||||
|
item: RawToken::Operator(Operator::Dot),
|
||||||
|
span,
|
||||||
|
}) => *span,
|
||||||
|
other => panic!("Expected dot, found {:?}", other),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn expect_bare(&self) -> Span {
|
||||||
|
match self {
|
||||||
|
TokenNode::Token(Spanned {
|
||||||
|
item: RawToken::Bare,
|
||||||
|
span,
|
||||||
|
}) => *span,
|
||||||
|
other => panic!("Expected bare, found {:?}", other),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user