Improve the simplified parse form. (#1875)

This commit is contained in:
Jason Gedge 2020-05-25 14:19:49 -04:00 committed by GitHub
parent 07996ea93d
commit cb6ccc3c5a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 71 additions and 28 deletions

View File

@ -2,31 +2,67 @@ use nu_test_support::fs::Stub;
use nu_test_support::playground::Playground; use nu_test_support::playground::Playground;
use nu_test_support::{nu, pipeline}; use nu_test_support::{nu, pipeline};
#[test] mod simple {
fn extracts_fields_from_the_given_the_pattern() { use super::*;
Playground::setup("parse_test_1", |dirs, sandbox| {
sandbox.with_files(vec![Stub::FileWithContentToBeTrimmed(
"key_value_separated_arepa_ingredients.txt",
r#"
VAR1=Cheese
VAR2=JonathanParsed
VAR3=NushellSecretIngredient
"#,
)]);
let actual = nu!( #[test]
cwd: dirs.test(), pipeline( fn extracts_fields_from_the_given_the_pattern() {
r#" Playground::setup("parse_test_1", |dirs, sandbox| {
open key_value_separated_arepa_ingredients.txt sandbox.with_files(vec![Stub::FileWithContentToBeTrimmed(
| parse "{Name}={Value}" "key_value_separated_arepa_ingredients.txt",
| nth 1 r#"
| get Value VAR1=Cheese
| echo $it VAR2=JonathanParsed
VAR3=NushellSecretIngredient
"#,
)]);
let actual = nu!(
cwd: dirs.test(), pipeline(
r#"
open key_value_separated_arepa_ingredients.txt
| lines
| each { echo $it | parse "{Name}={Value}" }
| nth 1
| echo $it.Value
"#
));
assert_eq!(actual.out, "JonathanParsed");
})
}
#[test]
fn double_open_curly_evalutes_to_a_single_curly() {
Playground::setup("parse_test_regex_2", |dirs, _sandbox| {
let actual = nu!(
cwd: dirs.test(), pipeline(
r#"
echo "{abc}123"
| parse "{{abc}{name}"
| echo $it.name
"# "#
)); ));
assert_eq!(actual.out, "JonathanParsed"); assert_eq!(actual.out, "123");
}) })
}
#[test]
fn properly_escapes_text() {
Playground::setup("parse_test_regex_3", |dirs, _sandbox| {
let actual = nu!(
cwd: dirs.test(), pipeline(
r#"
echo "(abc)123"
| parse "(abc){name}"
| echo $it.name
"#
));
assert_eq!(actual.out, "123");
})
}
} }
mod regex { mod regex {

View File

@ -6,7 +6,7 @@ use nu_protocol::{
}; };
use crate::{ColumnNames, Parse}; use crate::{ColumnNames, Parse};
use regex::Regex; use regex::{self, Regex};
impl Plugin for Parse { impl Plugin for Parse {
fn config(&mut self) -> Result<Signature, ShellError> { fn config(&mut self) -> Result<Signature, ShellError> {
@ -125,13 +125,18 @@ fn parse(input: &str) -> Vec<ParseCommand> {
let mut output = vec![]; let mut output = vec![];
//let mut loop_input = input; //let mut loop_input = input;
let mut loop_input = input.chars(); let mut loop_input = input.chars().peekable();
loop { loop {
let mut before = String::new(); let mut before = String::new();
while let Some(c) = loop_input.next() { while let Some(c) = loop_input.next() {
if c == '{' { if c == '{' {
break; // If '{{', still creating a plaintext parse command, but just for a single '{' char
if loop_input.peek() == Some(&'{') {
let _ = loop_input.next();
} else {
break;
}
} }
before.push(c); before.push(c);
} }
@ -188,19 +193,21 @@ impl From<&Regex> for ColumnNames {
} }
fn build_regex(commands: &[ParseCommand]) -> String { fn build_regex(commands: &[ParseCommand]) -> String {
let mut output = String::new(); let mut output = "(?s)\\A".to_string();
for command in commands { for command in commands {
match command { match command {
ParseCommand::Text(s) => { ParseCommand::Text(s) => {
output.push_str(&s.replace("(", "\\(")); output.push_str(&regex::escape(&s));
} }
ParseCommand::Column(_) => { ParseCommand::Column(_) => {
output.push_str("(.*)"); output.push_str("(.*?)");
} }
} }
} }
output.push_str("\\z");
output output
} }