mirror of
https://github.com/nushell/nushell.git
synced 2025-01-03 13:00:08 +01:00
Improve parsing of pipelines, require pipes
At the moment the pipeline parser does not enforce that there must be a pipe between each part of the pipeline, which can lead to confusing behaviour or misleading errors.
This commit is contained in:
parent
c6c4d4ddb1
commit
6034de641a
@ -552,11 +552,11 @@ pub fn node(input: NomSpan) -> IResult<NomSpan, TokenNode> {
|
|||||||
pub fn pipeline(input: NomSpan) -> IResult<NomSpan, TokenNode> {
|
pub fn pipeline(input: NomSpan) -> IResult<NomSpan, TokenNode> {
|
||||||
trace_step(input, "pipeline", |input| {
|
trace_step(input, "pipeline", |input| {
|
||||||
let start = input.offset;
|
let start = input.offset;
|
||||||
let (input, head) = opt(tuple((raw_call, opt(space1), opt(tag("|")))))(input)?;
|
let (input, head) = opt(tuple((raw_call, opt(space1))))(input)?;
|
||||||
let (input, items) = trace_step(
|
let (input, items) = trace_step(
|
||||||
input,
|
input,
|
||||||
"many0",
|
"many0",
|
||||||
many0(tuple((opt(space1), raw_call, opt(space1), opt(tag("|"))))),
|
many0(tuple((tag("|"), opt(space1), raw_call, opt(space1)))),
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
let (input, tail) = opt(space1)(input)?;
|
let (input, tail) = opt(space1)(input)?;
|
||||||
@ -582,28 +582,28 @@ pub fn pipeline(input: NomSpan) -> IResult<NomSpan, TokenNode> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn make_call_list(
|
fn make_call_list(
|
||||||
head: Option<(Tagged<CallNode>, Option<NomSpan>, Option<NomSpan>)>,
|
head: Option<(Tagged<CallNode>, Option<NomSpan>)>,
|
||||||
items: Vec<(
|
items: Vec<(
|
||||||
|
NomSpan,
|
||||||
Option<NomSpan>,
|
Option<NomSpan>,
|
||||||
Tagged<CallNode>,
|
Tagged<CallNode>,
|
||||||
Option<NomSpan>,
|
Option<NomSpan>,
|
||||||
Option<NomSpan>,
|
|
||||||
)>,
|
)>,
|
||||||
) -> Vec<PipelineElement> {
|
) -> Vec<PipelineElement> {
|
||||||
let mut out = vec![];
|
let mut out = vec![];
|
||||||
|
|
||||||
if let Some(head) = head {
|
if let Some(head) = head {
|
||||||
let el = PipelineElement::new(None, head.0, head.1.map(Span::from), head.2.map(Span::from));
|
let el = PipelineElement::new(None, None, head.0, head.1.map(Span::from));
|
||||||
out.push(el);
|
out.push(el);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (ws1, call, ws2, pipe) in items {
|
for (pipe, ws1, call, ws2) in items {
|
||||||
let el = PipelineElement::new(
|
let el = PipelineElement::new(
|
||||||
|
Some(pipe).map(Span::from),
|
||||||
ws1.map(Span::from),
|
ws1.map(Span::from),
|
||||||
call,
|
call,
|
||||||
ws2.map(Span::from),
|
ws2.map(Span::from));
|
||||||
pipe.map(Span::from),
|
|
||||||
);
|
|
||||||
out.push(el);
|
out.push(el);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -11,9 +11,9 @@ pub struct Pipeline {
|
|||||||
|
|
||||||
#[derive(Debug, Clone, Eq, PartialEq, Ord, PartialOrd, Getters, new)]
|
#[derive(Debug, Clone, Eq, PartialEq, Ord, PartialOrd, Getters, new)]
|
||||||
pub struct PipelineElement {
|
pub struct PipelineElement {
|
||||||
|
pub pipe: Option<Span>,
|
||||||
pub pre_ws: Option<Span>,
|
pub pre_ws: Option<Span>,
|
||||||
#[get = "pub(crate)"]
|
#[get = "pub(crate)"]
|
||||||
call: Tagged<CallNode>,
|
call: Tagged<CallNode>,
|
||||||
pub post_ws: Option<Span>,
|
pub post_ws: Option<Span>,
|
||||||
pub post_pipe: Option<Span>,
|
|
||||||
}
|
}
|
||||||
|
@ -47,32 +47,31 @@ impl TokenTreeBuilder {
|
|||||||
.next()
|
.next()
|
||||||
.expect("A pipeline must contain at least one element");
|
.expect("A pipeline must contain at least one element");
|
||||||
|
|
||||||
|
let pipe = None;
|
||||||
let pre_span = pre.map(|pre| b.consume(&pre));
|
let pre_span = pre.map(|pre| b.consume(&pre));
|
||||||
let call = call(b);
|
let call = call(b);
|
||||||
let post_span = post.map(|post| b.consume(&post));
|
let post_span = post.map(|post| b.consume(&post));
|
||||||
let pipe = input.peek().map(|_| Span::from(b.consume("|")));
|
|
||||||
out.push(PipelineElement::new(
|
out.push(PipelineElement::new(
|
||||||
|
pipe,
|
||||||
pre_span.map(Span::from),
|
pre_span.map(Span::from),
|
||||||
call,
|
call,
|
||||||
post_span.map(Span::from),
|
post_span.map(Span::from)));
|
||||||
pipe,
|
|
||||||
));
|
|
||||||
|
|
||||||
loop {
|
loop {
|
||||||
match input.next() {
|
match input.next() {
|
||||||
None => break,
|
None => break,
|
||||||
Some((pre, call, post)) => {
|
Some((pre, call, post)) => {
|
||||||
|
let pipe = Some(Span::from(b.consume("|")));
|
||||||
let pre_span = pre.map(|pre| b.consume(&pre));
|
let pre_span = pre.map(|pre| b.consume(&pre));
|
||||||
let call = call(b);
|
let call = call(b);
|
||||||
let post_span = post.map(|post| b.consume(&post));
|
let post_span = post.map(|post| b.consume(&post));
|
||||||
|
|
||||||
let pipe = input.peek().map(|_| Span::from(b.consume("|")));
|
|
||||||
|
|
||||||
out.push(PipelineElement::new(
|
out.push(PipelineElement::new(
|
||||||
|
pipe,
|
||||||
pre_span.map(Span::from),
|
pre_span.map(Span::from),
|
||||||
call,
|
call,
|
||||||
post_span.map(Span::from),
|
post_span.map(Span::from),
|
||||||
pipe,
|
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -147,6 +147,10 @@ fn paint_token_node(token_node: &TokenNode, line: &str) -> String {
|
|||||||
fn paint_pipeline_element(pipeline_element: &PipelineElement, line: &str) -> String {
|
fn paint_pipeline_element(pipeline_element: &PipelineElement, line: &str) -> String {
|
||||||
let mut styled = String::new();
|
let mut styled = String::new();
|
||||||
|
|
||||||
|
if let Some(_) = pipeline_element.pipe {
|
||||||
|
styled.push_str(&Color::Purple.paint("|"));
|
||||||
|
}
|
||||||
|
|
||||||
if let Some(ws) = pipeline_element.pre_ws {
|
if let Some(ws) = pipeline_element.pre_ws {
|
||||||
styled.push_str(&Color::White.normal().paint(ws.slice(line)));
|
styled.push_str(&Color::White.normal().paint(ws.slice(line)));
|
||||||
}
|
}
|
||||||
@ -168,10 +172,6 @@ fn paint_pipeline_element(pipeline_element: &PipelineElement, line: &str) -> Str
|
|||||||
styled.push_str(&Color::White.normal().paint(ws.slice(line)));
|
styled.push_str(&Color::White.normal().paint(ws.slice(line)));
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(_) = pipeline_element.post_pipe {
|
|
||||||
styled.push_str(&Color::Purple.paint("|"));
|
|
||||||
}
|
|
||||||
|
|
||||||
styled.to_string()
|
styled.to_string()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user