forked from extern/nushell
@ -29,11 +29,16 @@ impl LiteCommand {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct LitePipeline {
|
||||
pub commands: Vec<LiteCommand>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct LiteBlock {
|
||||
pub block: Vec<LitePipeline>,
|
||||
}
|
||||
|
||||
fn skip_whitespace(src: &mut Input) {
|
||||
while let Some((_, x)) = src.peek() {
|
||||
if x.is_whitespace() {
|
||||
@ -58,7 +63,8 @@ fn bare(src: &mut Input, span_offset: usize) -> Result<Spanned<String>, ParseErr
|
||||
let mut inside_quote = false;
|
||||
let mut block_level = vec![];
|
||||
|
||||
for (_, c) in src {
|
||||
while let Some((_, c)) = src.peek() {
|
||||
let c = *c;
|
||||
if inside_quote {
|
||||
if c == delimiter {
|
||||
inside_quote = false;
|
||||
@ -84,10 +90,11 @@ fn bare(src: &mut Input, span_offset: usize) -> Result<Spanned<String>, ParseErr
|
||||
if let Some('(') = block_level.last() {
|
||||
let _ = block_level.pop();
|
||||
}
|
||||
} else if block_level.is_empty() && c.is_whitespace() {
|
||||
} else if block_level.is_empty() && (c.is_whitespace() || c == '|' || c == ';') {
|
||||
break;
|
||||
}
|
||||
bare.push(c);
|
||||
let _ = src.next();
|
||||
}
|
||||
|
||||
let span = Span::new(
|
||||
@ -139,16 +146,14 @@ fn quoted(
|
||||
fn command(src: &mut Input, span_offset: usize) -> Result<LiteCommand, ParseError> {
|
||||
let command = bare(src, span_offset)?;
|
||||
if command.item.is_empty() {
|
||||
Err(ParseError::unexpected_eof(
|
||||
"unexpected end of input",
|
||||
command.span,
|
||||
))
|
||||
Err(ParseError::unexpected_eof("command", command.span))
|
||||
} else {
|
||||
Ok(LiteCommand::new(command))
|
||||
}
|
||||
}
|
||||
|
||||
fn pipeline(src: &mut Input, span_offset: usize) -> Result<LitePipeline, ParseError> {
|
||||
fn pipeline(src: &mut Input, span_offset: usize) -> Result<LiteBlock, ParseError> {
|
||||
let mut block = vec![];
|
||||
let mut commands = vec![];
|
||||
|
||||
skip_whitespace(src);
|
||||
@ -167,6 +172,10 @@ fn pipeline(src: &mut Input, span_offset: usize) -> Result<LitePipeline, ParseEr
|
||||
if let Some((_, c)) = src.peek() {
|
||||
// The first character tells us a lot about each argument
|
||||
match c {
|
||||
';' => {
|
||||
// this is the end of the command and the end of the pipeline
|
||||
break;
|
||||
}
|
||||
'|' => {
|
||||
let _ = src.next();
|
||||
if let Some((pos, next_c)) = src.peek() {
|
||||
@ -202,21 +211,35 @@ fn pipeline(src: &mut Input, span_offset: usize) -> Result<LitePipeline, ParseEr
|
||||
}
|
||||
commands.push(cmd);
|
||||
skip_whitespace(src);
|
||||
|
||||
if let Some((_, ';')) = src.peek() {
|
||||
let _ = src.next();
|
||||
|
||||
if !commands.is_empty() {
|
||||
block.push(LitePipeline { commands });
|
||||
commands = vec![];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Ok(LitePipeline { commands })
|
||||
if !commands.is_empty() {
|
||||
block.push(LitePipeline { commands });
|
||||
}
|
||||
|
||||
Ok(LiteBlock { block })
|
||||
}
|
||||
|
||||
pub fn lite_parse(src: &str, span_offset: usize) -> Result<LitePipeline, ParseError> {
|
||||
pub fn lite_parse(src: &str, span_offset: usize) -> Result<LiteBlock, ParseError> {
|
||||
pipeline(&mut src.char_indices().peekable(), span_offset)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn lite_simple_1() -> Result<(), ParseError> {
|
||||
let result = lite_parse("foo", 0)?;
|
||||
assert_eq!(result.commands.len(), 1);
|
||||
assert_eq!(result.commands[0].name.span.start(), 0);
|
||||
assert_eq!(result.commands[0].name.span.end(), 3);
|
||||
assert_eq!(result.block.len(), 1);
|
||||
assert_eq!(result.block[0].commands.len(), 1);
|
||||
assert_eq!(result.block[0].commands[0].name.span.start(), 0);
|
||||
assert_eq!(result.block[0].commands[0].name.span.end(), 3);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
@ -224,9 +247,10 @@ fn lite_simple_1() -> Result<(), ParseError> {
|
||||
#[test]
|
||||
fn lite_simple_offset() -> Result<(), ParseError> {
|
||||
let result = lite_parse("foo", 10)?;
|
||||
assert_eq!(result.commands.len(), 1);
|
||||
assert_eq!(result.commands[0].name.span.start(), 10);
|
||||
assert_eq!(result.commands[0].name.span.end(), 13);
|
||||
assert_eq!(result.block.len(), 1);
|
||||
assert_eq!(result.block[0].commands.len(), 1);
|
||||
assert_eq!(result.block[0].commands[0].name.span.start(), 10);
|
||||
assert_eq!(result.block[0].commands[0].name.span.end(), 13);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
Reference in New Issue
Block a user