mirror of
https://github.com/nushell/nushell
synced 2024-11-13 08:27:06 +00:00
Introduce new command - nu check (#5864)
* nu check command - 1 * Support stream * Polish code and fix corner case
This commit is contained in:
parent
32f0f94b46
commit
dc9d939c83
5 changed files with 858 additions and 0 deletions
|
@ -158,6 +158,7 @@ pub fn create_default_context(cwd: impl AsRef<Path>) -> EngineState {
|
|||
Complete,
|
||||
Exec,
|
||||
External,
|
||||
NuCheck,
|
||||
Ps,
|
||||
Sys,
|
||||
};
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
mod benchmark;
|
||||
mod complete;
|
||||
mod exec;
|
||||
mod nu_check;
|
||||
mod ps;
|
||||
mod run_external;
|
||||
mod sys;
|
||||
|
@ -9,6 +10,7 @@ mod which_;
|
|||
pub use benchmark::Benchmark;
|
||||
pub use complete::Complete;
|
||||
pub use exec::Exec;
|
||||
pub use nu_check::NuCheck;
|
||||
pub use ps::Ps;
|
||||
pub use run_external::{External, ExternalCommand};
|
||||
pub use sys::Sys;
|
||||
|
|
302
crates/nu-command/src/system/nu_check.rs
Normal file
302
crates/nu-command/src/system/nu_check.rs
Normal file
|
@ -0,0 +1,302 @@
|
|||
use nu_engine::{current_dir, CallExt};
|
||||
use nu_parser::{parse, parse_module_block, unescape_unquote_string};
|
||||
use nu_protocol::ast::Call;
|
||||
use nu_protocol::engine::{Command, EngineState, Stack, StateWorkingSet};
|
||||
use nu_protocol::{
|
||||
Category, Example, PipelineData, ShellError, Signature, Span, Spanned, SyntaxShape, Value,
|
||||
};
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct NuCheck;
|
||||
|
||||
impl Command for NuCheck {
|
||||
fn name(&self) -> &str {
|
||||
"nu-check"
|
||||
}
|
||||
|
||||
fn signature(&self) -> Signature {
|
||||
Signature::build("nu-check")
|
||||
.optional("path", SyntaxShape::Filepath, "File path to parse")
|
||||
.switch("as-module", "Parse content as module", Some('m'))
|
||||
.switch("debug", "Show error messages", Some('d'))
|
||||
.category(Category::Strings)
|
||||
}
|
||||
|
||||
fn usage(&self) -> &str {
|
||||
"Validate and parse input content"
|
||||
}
|
||||
|
||||
fn search_terms(&self) -> Vec<&str> {
|
||||
vec!["syntax", "parse", "debug"]
|
||||
}
|
||||
|
||||
fn run(
|
||||
&self,
|
||||
engine_state: &EngineState,
|
||||
stack: &mut Stack,
|
||||
call: &Call,
|
||||
input: PipelineData,
|
||||
) -> Result<PipelineData, ShellError> {
|
||||
let path: Option<Spanned<String>> = call.opt(engine_state, stack, 0)?;
|
||||
let is_module = call.has_flag("as-module");
|
||||
let is_debug = call.has_flag("debug");
|
||||
let config = engine_state.get_config();
|
||||
let mut contents = vec![];
|
||||
|
||||
// DO NOT ever try to merge the working_set in this command
|
||||
let mut working_set = StateWorkingSet::new(engine_state);
|
||||
|
||||
match input {
|
||||
PipelineData::Value(Value::String { val, span }, ..) => {
|
||||
let contents = Vec::from(val);
|
||||
if is_module {
|
||||
parse_module(&mut working_set, None, contents, is_debug, span)
|
||||
} else {
|
||||
parse_script(&mut working_set, None, contents, is_debug, span)
|
||||
}
|
||||
}
|
||||
PipelineData::ListStream(stream, ..) => {
|
||||
let list_stream = stream.into_string("\n", config);
|
||||
let contents = Vec::from(list_stream);
|
||||
|
||||
if is_module {
|
||||
parse_module(&mut working_set, None, contents, is_debug, call.head)
|
||||
} else {
|
||||
parse_script(&mut working_set, None, contents, is_debug, call.head)
|
||||
}
|
||||
}
|
||||
PipelineData::ExternalStream {
|
||||
stdout: Some(stream),
|
||||
..
|
||||
} => {
|
||||
let raw_stream: Vec<_> = stream.stream.into_iter().collect();
|
||||
for r in raw_stream {
|
||||
match r {
|
||||
Ok(v) => contents.extend(v),
|
||||
Err(error) => return Err(error),
|
||||
};
|
||||
}
|
||||
|
||||
if is_module {
|
||||
parse_module(&mut working_set, None, contents, is_debug, call.head)
|
||||
} else {
|
||||
parse_script(&mut working_set, None, contents, is_debug, call.head)
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
if path.is_some() {
|
||||
let path = match find_path(path, engine_state, stack, call.head) {
|
||||
Ok(path) => path,
|
||||
Err(error) => return Err(error),
|
||||
};
|
||||
|
||||
let ext: Vec<_> = path.rsplitn(2, '.').collect();
|
||||
if ext[0] != "nu" {
|
||||
return Err(ShellError::GenericError(
|
||||
"Cannot parse input".to_string(),
|
||||
"File extension must be the type of .nu".to_string(),
|
||||
Some(call.head),
|
||||
None,
|
||||
Vec::new(),
|
||||
));
|
||||
}
|
||||
|
||||
if is_module {
|
||||
parse_file_module(path, &mut working_set, call, is_debug)
|
||||
} else {
|
||||
parse_file_script(path, &mut working_set, call, is_debug)
|
||||
}
|
||||
} else {
|
||||
Err(ShellError::GenericError(
|
||||
"Failed to execute command".to_string(),
|
||||
"Please run 'nu-check --help' for more details".to_string(),
|
||||
Some(call.head),
|
||||
None,
|
||||
Vec::new(),
|
||||
))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn examples(&self) -> Vec<Example> {
|
||||
vec![
|
||||
Example {
|
||||
description: "Parse a input file as script(Default)",
|
||||
example: "nu-check script.nu",
|
||||
result: None,
|
||||
},
|
||||
Example {
|
||||
description: "Parse a input file as module",
|
||||
example: "nu-check --as-module module.nu",
|
||||
result: None,
|
||||
},
|
||||
Example {
|
||||
description: "Parse a input file by showing error message",
|
||||
example: "nu-check -d script.nu",
|
||||
result: None,
|
||||
},
|
||||
Example {
|
||||
description: "Parse an external stream as script by showing error message",
|
||||
example: "open foo.nu | nu-check -d script.nu",
|
||||
result: None,
|
||||
},
|
||||
Example {
|
||||
description: "Parse an internal stream as module by showing error message",
|
||||
example: "open module.nu | lines | nu-check -d --as-module module.nu",
|
||||
result: None,
|
||||
},
|
||||
Example {
|
||||
description: "Parse a string as script",
|
||||
example: "echo $'two(char nl)lines' | nu-check ",
|
||||
result: None,
|
||||
},
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
fn find_path(
|
||||
path: Option<Spanned<String>>,
|
||||
engine_state: &EngineState,
|
||||
stack: &mut Stack,
|
||||
span: Span,
|
||||
) -> Result<String, ShellError> {
|
||||
let cwd = current_dir(engine_state, stack)?;
|
||||
|
||||
let path = match path {
|
||||
Some(s) => {
|
||||
let path_no_whitespace = &s.item.trim_end_matches(|x| matches!(x, '\x09'..='\x0d'));
|
||||
|
||||
let path = match nu_path::canonicalize_with(path_no_whitespace, &cwd) {
|
||||
Ok(p) => {
|
||||
if !p.is_file() {
|
||||
return Err(ShellError::GenericError(
|
||||
"Cannot parse input".to_string(),
|
||||
"Path is not a file".to_string(),
|
||||
Some(s.span),
|
||||
None,
|
||||
Vec::new(),
|
||||
));
|
||||
} else {
|
||||
p
|
||||
}
|
||||
}
|
||||
|
||||
Err(_) => {
|
||||
return Err(ShellError::FileNotFound(s.span));
|
||||
}
|
||||
};
|
||||
path.to_string_lossy().to_string()
|
||||
}
|
||||
None => {
|
||||
return Err(ShellError::NotFound(span));
|
||||
}
|
||||
};
|
||||
Ok(path)
|
||||
}
|
||||
|
||||
fn parse_module(
|
||||
working_set: &mut StateWorkingSet,
|
||||
filename: Option<String>,
|
||||
contents: Vec<u8>,
|
||||
is_debug: bool,
|
||||
span: Span,
|
||||
) -> Result<PipelineData, ShellError> {
|
||||
let start = working_set.next_span_start();
|
||||
working_set.add_file(
|
||||
filename.unwrap_or_else(|| "empty".to_string()),
|
||||
contents.as_ref(),
|
||||
);
|
||||
let end = working_set.next_span_start();
|
||||
|
||||
let new_span = Span::new(start, end);
|
||||
let (_, _, err) = parse_module_block(working_set, new_span, &[]);
|
||||
|
||||
if err.is_some() {
|
||||
if is_debug {
|
||||
let msg = format!(
|
||||
r#"Found : {}"#,
|
||||
err.expect("Unable to parse content as module")
|
||||
);
|
||||
Err(ShellError::GenericError(
|
||||
"Failed to parse content".to_string(),
|
||||
msg,
|
||||
Some(span),
|
||||
Some("If the content is intended to be a script, please try to remove `--as-module` flag ".to_string()),
|
||||
Vec::new(),
|
||||
))
|
||||
} else {
|
||||
Ok(PipelineData::Value(Value::boolean(false, new_span), None))
|
||||
}
|
||||
} else {
|
||||
Ok(PipelineData::Value(Value::boolean(true, new_span), None))
|
||||
}
|
||||
}
|
||||
|
||||
fn parse_script(
|
||||
working_set: &mut StateWorkingSet,
|
||||
filename: Option<&str>,
|
||||
contents: Vec<u8>,
|
||||
is_debug: bool,
|
||||
span: Span,
|
||||
) -> Result<PipelineData, ShellError> {
|
||||
let (_, err) = parse(working_set, filename, &contents, false, &[]);
|
||||
if err.is_some() {
|
||||
let msg = format!(r#"Found : {}"#, err.expect("Unable to parse content"));
|
||||
if is_debug {
|
||||
Err(ShellError::GenericError(
|
||||
"Failed to parse content".to_string(),
|
||||
msg,
|
||||
Some(span),
|
||||
Some("If the content is intended to be a module, please consider flag of `--as-module` ".to_string()),
|
||||
Vec::new(),
|
||||
))
|
||||
} else {
|
||||
Ok(PipelineData::Value(Value::boolean(false, span), None))
|
||||
}
|
||||
} else {
|
||||
Ok(PipelineData::Value(Value::boolean(true, span), None))
|
||||
}
|
||||
}
|
||||
|
||||
fn parse_file_script(
|
||||
path: String,
|
||||
working_set: &mut StateWorkingSet,
|
||||
call: &Call,
|
||||
is_debug: bool,
|
||||
) -> Result<PipelineData, ShellError> {
|
||||
let (filename, err) = unescape_unquote_string(path.as_bytes(), call.head);
|
||||
if err.is_none() {
|
||||
if let Ok(contents) = std::fs::read(&path) {
|
||||
parse_script(
|
||||
working_set,
|
||||
Some(filename.as_str()),
|
||||
contents,
|
||||
is_debug,
|
||||
call.head,
|
||||
)
|
||||
} else {
|
||||
Err(ShellError::IOError("Can not read path".to_string()))
|
||||
}
|
||||
} else {
|
||||
Err(ShellError::NotFound(call.head))
|
||||
}
|
||||
}
|
||||
|
||||
fn parse_file_module(
|
||||
path: String,
|
||||
working_set: &mut StateWorkingSet,
|
||||
call: &Call,
|
||||
is_debug: bool,
|
||||
) -> Result<PipelineData, ShellError> {
|
||||
let (filename, err) = unescape_unquote_string(path.as_bytes(), call.head);
|
||||
if err.is_none() {
|
||||
if let Ok(contents) = std::fs::read(path) {
|
||||
parse_module(working_set, Some(filename), contents, is_debug, call.head)
|
||||
} else {
|
||||
Err(ShellError::IOError("Can not read path".to_string()))
|
||||
}
|
||||
} else {
|
||||
Err(ShellError::NotFound(call.head))
|
||||
}
|
||||
}
|
|
@ -38,6 +38,7 @@ mod merge;
|
|||
mod mkdir;
|
||||
mod move_;
|
||||
mod network;
|
||||
mod nu_check;
|
||||
mod open;
|
||||
mod parse;
|
||||
mod path;
|
||||
|
|
552
crates/nu-command/tests/commands/nu_check.rs
Normal file
552
crates/nu-command/tests/commands/nu_check.rs
Normal file
|
@ -0,0 +1,552 @@
|
|||
use nu_test_support::fs::Stub::FileWithContentToBeTrimmed;
|
||||
use nu_test_support::playground::Playground;
|
||||
use nu_test_support::{nu, pipeline};
|
||||
|
||||
#[test]
|
||||
fn parse_script_success() {
|
||||
Playground::setup("nu_check_test_1", |dirs, sandbox| {
|
||||
sandbox.with_files(vec![FileWithContentToBeTrimmed(
|
||||
"script.nu",
|
||||
r#"
|
||||
greet "world"
|
||||
|
||||
def greet [name] {
|
||||
echo "hello" $name
|
||||
}
|
||||
"#,
|
||||
)]);
|
||||
|
||||
let actual = nu!(
|
||||
cwd: dirs.test(), pipeline(
|
||||
r#"
|
||||
nu-check script.nu
|
||||
"#
|
||||
));
|
||||
|
||||
assert!(actual.err.is_empty());
|
||||
})
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn parse_script_with_wrong_type() {
|
||||
Playground::setup("nu_check_test_2", |dirs, sandbox| {
|
||||
sandbox.with_files(vec![FileWithContentToBeTrimmed(
|
||||
"script.nu",
|
||||
r#"
|
||||
greet "world"
|
||||
|
||||
def greet [name] {
|
||||
echo "hello" $name
|
||||
}
|
||||
"#,
|
||||
)]);
|
||||
|
||||
let actual = nu!(
|
||||
cwd: dirs.test(), pipeline(
|
||||
r#"
|
||||
nu-check -d --as-module script.nu
|
||||
"#
|
||||
));
|
||||
|
||||
assert!(actual.err.contains("Failed to parse content"));
|
||||
})
|
||||
}
|
||||
#[test]
|
||||
fn parse_script_failure() {
|
||||
Playground::setup("nu_check_test_3", |dirs, sandbox| {
|
||||
sandbox.with_files(vec![FileWithContentToBeTrimmed(
|
||||
"script.nu",
|
||||
r#"
|
||||
greet "world"
|
||||
|
||||
def greet [name {
|
||||
echo "hello" $name
|
||||
}
|
||||
"#,
|
||||
)]);
|
||||
|
||||
let actual = nu!(
|
||||
cwd: dirs.test(), pipeline(
|
||||
r#"
|
||||
nu-check -d script.nu
|
||||
"#
|
||||
));
|
||||
|
||||
assert!(actual.err.contains("Unexpected end of code"));
|
||||
})
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn parse_module_success() {
|
||||
Playground::setup("nu_check_test_4", |dirs, sandbox| {
|
||||
sandbox.with_files(vec![FileWithContentToBeTrimmed(
|
||||
"foo.nu",
|
||||
r#"
|
||||
# foo.nu
|
||||
|
||||
export def hello [name: string] {
|
||||
$"hello ($name)!"
|
||||
}
|
||||
|
||||
export def hi [where: string] {
|
||||
$"hi ($where)!"
|
||||
}
|
||||
"#,
|
||||
)]);
|
||||
|
||||
let actual = nu!(
|
||||
cwd: dirs.test(), pipeline(
|
||||
r#"
|
||||
nu-check --as-module foo.nu
|
||||
"#
|
||||
));
|
||||
|
||||
assert!(actual.err.is_empty());
|
||||
})
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn parse_module_with_wrong_type() {
|
||||
Playground::setup("nu_check_test_5", |dirs, sandbox| {
|
||||
sandbox.with_files(vec![FileWithContentToBeTrimmed(
|
||||
"foo.nu",
|
||||
r#"
|
||||
# foo.nu
|
||||
|
||||
export def hello [name: string {
|
||||
$"hello ($name)!"
|
||||
}
|
||||
|
||||
export def hi [where: string] {
|
||||
$"hi ($where)!"
|
||||
}
|
||||
"#,
|
||||
)]);
|
||||
|
||||
let actual = nu!(
|
||||
cwd: dirs.test(), pipeline(
|
||||
r#"
|
||||
nu-check -d foo.nu
|
||||
"#
|
||||
));
|
||||
|
||||
assert!(actual.err.contains("Failed to parse content"));
|
||||
})
|
||||
}
|
||||
#[test]
|
||||
fn parse_module_failure() {
|
||||
Playground::setup("nu_check_test_6", |dirs, sandbox| {
|
||||
sandbox.with_files(vec![FileWithContentToBeTrimmed(
|
||||
"foo.nu",
|
||||
r#"
|
||||
# foo.nu
|
||||
|
||||
export def hello [name: string {
|
||||
$"hello ($name)!"
|
||||
}
|
||||
|
||||
export def hi [where: string] {
|
||||
$"hi ($where)!"
|
||||
}
|
||||
"#,
|
||||
)]);
|
||||
|
||||
let actual = nu!(
|
||||
cwd: dirs.test(), pipeline(
|
||||
r#"
|
||||
nu-check -d --as-module foo.nu
|
||||
"#
|
||||
));
|
||||
|
||||
assert!(actual.err.contains("Unexpected end of code"));
|
||||
})
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn file_not_exist() {
|
||||
Playground::setup("nu_check_test_7", |dirs, _sandbox| {
|
||||
let actual = nu!(
|
||||
cwd: dirs.test(), pipeline(
|
||||
r#"
|
||||
nu-check --as-module foo.nu
|
||||
"#
|
||||
));
|
||||
|
||||
assert!(actual.err.contains("file not found"));
|
||||
})
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn parse_unsupported_file() {
|
||||
Playground::setup("nu_check_test_8", |dirs, sandbox| {
|
||||
sandbox.with_files(vec![FileWithContentToBeTrimmed(
|
||||
"foo.txt",
|
||||
r#"
|
||||
# foo.nu
|
||||
|
||||
export def hello [name: string {
|
||||
$"hello ($name)!"
|
||||
}
|
||||
|
||||
export def hi [where: string] {
|
||||
$"hi ($where)!"
|
||||
}
|
||||
"#,
|
||||
)]);
|
||||
|
||||
let actual = nu!(
|
||||
cwd: dirs.test(), pipeline(
|
||||
r#"
|
||||
nu-check --as-module foo.txt
|
||||
"#
|
||||
));
|
||||
|
||||
assert!(actual
|
||||
.err
|
||||
.contains("File extension must be the type of .nu"));
|
||||
})
|
||||
}
|
||||
#[test]
|
||||
fn parse_dir_failure() {
|
||||
Playground::setup("nu_check_test_9", |dirs, _sandbox| {
|
||||
let actual = nu!(
|
||||
cwd: dirs.test(), pipeline(
|
||||
r#"
|
||||
nu-check --as-module ~
|
||||
"#
|
||||
));
|
||||
|
||||
assert!(actual.err.contains("Path is not a file"));
|
||||
})
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn parse_module_success_2() {
|
||||
Playground::setup("nu_check_test_10", |dirs, sandbox| {
|
||||
sandbox.with_files(vec![FileWithContentToBeTrimmed(
|
||||
"foo.nu",
|
||||
r#"
|
||||
# foo.nu
|
||||
|
||||
export env MYNAME { "Arthur, King of the Britons" }
|
||||
"#,
|
||||
)]);
|
||||
|
||||
let actual = nu!(
|
||||
cwd: dirs.test(), pipeline(
|
||||
r#"
|
||||
nu-check --as-module foo.nu
|
||||
"#
|
||||
));
|
||||
|
||||
assert!(actual.err.is_empty());
|
||||
})
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn parse_script_success_with_raw_stream() {
|
||||
Playground::setup("nu_check_test_11", |dirs, sandbox| {
|
||||
sandbox.with_files(vec![FileWithContentToBeTrimmed(
|
||||
"script.nu",
|
||||
r#"
|
||||
greet "world"
|
||||
|
||||
def greet [name] {
|
||||
echo "hello" $name
|
||||
}
|
||||
"#,
|
||||
)]);
|
||||
|
||||
let actual = nu!(
|
||||
cwd: dirs.test(), pipeline(
|
||||
r#"
|
||||
open script.nu | nu-check
|
||||
"#
|
||||
));
|
||||
|
||||
assert!(actual.err.is_empty());
|
||||
})
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn parse_module_success_with_raw_stream() {
|
||||
Playground::setup("nu_check_test_12", |dirs, sandbox| {
|
||||
sandbox.with_files(vec![FileWithContentToBeTrimmed(
|
||||
"foo.nu",
|
||||
r#"
|
||||
# foo.nu
|
||||
|
||||
export def hello [name: string] {
|
||||
$"hello ($name)!"
|
||||
}
|
||||
|
||||
export def hi [where: string] {
|
||||
$"hi ($where)!"
|
||||
}
|
||||
"#,
|
||||
)]);
|
||||
|
||||
let actual = nu!(
|
||||
cwd: dirs.test(), pipeline(
|
||||
r#"
|
||||
open foo.nu | nu-check --as-module
|
||||
"#
|
||||
));
|
||||
|
||||
assert!(actual.err.is_empty());
|
||||
})
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn parse_string_as_script_success() {
|
||||
Playground::setup("nu_check_test_13", |dirs, _sandbox| {
|
||||
let actual = nu!(
|
||||
cwd: dirs.test(), pipeline(
|
||||
r#"
|
||||
echo $'two(char nl)lines' | nu-check
|
||||
"#
|
||||
));
|
||||
|
||||
assert!(actual.err.is_empty());
|
||||
})
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn parse_string_as_script() {
|
||||
Playground::setup("nu_check_test_14", |dirs, _sandbox| {
|
||||
let actual = nu!(
|
||||
cwd: dirs.test(), pipeline(
|
||||
r#"
|
||||
echo $'two(char nl)lines' | nu-check -d --as-module
|
||||
"#
|
||||
));
|
||||
|
||||
println!("the out put is {}", actual.err);
|
||||
assert!(actual.err.contains("Failed to parse content"));
|
||||
})
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn parse_module_success_with_internal_stream() {
|
||||
Playground::setup("nu_check_test_15", |dirs, sandbox| {
|
||||
sandbox.with_files(vec![FileWithContentToBeTrimmed(
|
||||
"foo.nu",
|
||||
r#"
|
||||
# foo.nu
|
||||
|
||||
export def hello [name: string] {
|
||||
$"hello ($name)!"
|
||||
}
|
||||
|
||||
export def hi [where: string] {
|
||||
$"hi ($where)!"
|
||||
}
|
||||
"#,
|
||||
)]);
|
||||
|
||||
let actual = nu!(
|
||||
cwd: dirs.test(), pipeline(
|
||||
r#"
|
||||
open foo.nu | lines | nu-check --as-module
|
||||
"#
|
||||
));
|
||||
|
||||
assert!(actual.err.is_empty());
|
||||
})
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn parse_script_success_with_complex_internal_stream() {
|
||||
Playground::setup("nu_check_test_16", |dirs, sandbox| {
|
||||
sandbox.with_files(vec![FileWithContentToBeTrimmed(
|
||||
"grep.nu",
|
||||
r#"
|
||||
#grep for nu
|
||||
def grep-nu [
|
||||
search #search term
|
||||
entrada? #file or pipe
|
||||
#
|
||||
#Examples
|
||||
#grep-nu search file.txt
|
||||
#ls **/* | some_filter | grep-nu search
|
||||
#open file.txt | grep-nu search
|
||||
] {
|
||||
if ($entrada | empty?) {
|
||||
if ($in | column? name) {
|
||||
grep -ihHn $search ($in | get name)
|
||||
} else {
|
||||
($in | into string) | grep -ihHn $search
|
||||
}
|
||||
} else {
|
||||
grep -ihHn $search $entrada
|
||||
}
|
||||
| lines
|
||||
| parse "{file}:{line}:{match}"
|
||||
| str trim
|
||||
| update match {|f|
|
||||
$f.match
|
||||
| nu-highlight
|
||||
}
|
||||
| rename "source file" "line number"
|
||||
}
|
||||
|
||||
"#,
|
||||
)]);
|
||||
|
||||
let actual = nu!(
|
||||
cwd: dirs.test(), pipeline(
|
||||
r#"
|
||||
open grep.nu | lines | nu-check
|
||||
"#
|
||||
));
|
||||
|
||||
assert!(actual.err.is_empty());
|
||||
})
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn parse_script_failure_with_complex_internal_stream() {
|
||||
Playground::setup("nu_check_test_17", |dirs, sandbox| {
|
||||
sandbox.with_files(vec![FileWithContentToBeTrimmed(
|
||||
"grep.nu",
|
||||
r#"
|
||||
#grep for nu
|
||||
def grep-nu [
|
||||
search #search term
|
||||
entrada? #file or pipe
|
||||
#
|
||||
#Examples
|
||||
#grep-nu search file.txt
|
||||
#ls **/* | some_filter | grep-nu search
|
||||
#open file.txt | grep-nu search
|
||||
]
|
||||
if ($entrada | empty?) {
|
||||
if ($in | column? name) {
|
||||
grep -ihHn $search ($in | get name)
|
||||
} else {
|
||||
($in | into string) | grep -ihHn $search
|
||||
}
|
||||
} else {
|
||||
grep -ihHn $search $entrada
|
||||
}
|
||||
| lines
|
||||
| parse "{file}:{line}:{match}"
|
||||
| str trim
|
||||
| update match {|f|
|
||||
$f.match
|
||||
| nu-highlight
|
||||
}
|
||||
| rename "source file" "line number"
|
||||
}
|
||||
|
||||
"#,
|
||||
)]);
|
||||
|
||||
let actual = nu!(
|
||||
cwd: dirs.test(), pipeline(
|
||||
r#"
|
||||
open grep.nu | lines | nu-check
|
||||
"#
|
||||
));
|
||||
|
||||
assert_eq!(actual.out, "false".to_string());
|
||||
})
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn parse_script_success_with_complex_external_stream() {
|
||||
Playground::setup("nu_check_test_18", |dirs, sandbox| {
|
||||
sandbox.with_files(vec![FileWithContentToBeTrimmed(
|
||||
"grep.nu",
|
||||
r#"
|
||||
#grep for nu
|
||||
def grep-nu [
|
||||
search #search term
|
||||
entrada? #file or pipe
|
||||
#
|
||||
#Examples
|
||||
#grep-nu search file.txt
|
||||
#ls **/* | some_filter | grep-nu search
|
||||
#open file.txt | grep-nu search
|
||||
] {
|
||||
if ($entrada | empty?) {
|
||||
if ($in | column? name) {
|
||||
grep -ihHn $search ($in | get name)
|
||||
} else {
|
||||
($in | into string) | grep -ihHn $search
|
||||
}
|
||||
} else {
|
||||
grep -ihHn $search $entrada
|
||||
}
|
||||
| lines
|
||||
| parse "{file}:{line}:{match}"
|
||||
| str trim
|
||||
| update match {|f|
|
||||
$f.match
|
||||
| nu-highlight
|
||||
}
|
||||
| rename "source file" "line number"
|
||||
}
|
||||
|
||||
"#,
|
||||
)]);
|
||||
|
||||
let actual = nu!(
|
||||
cwd: dirs.test(), pipeline(
|
||||
r#"
|
||||
open grep.nu | nu-check
|
||||
"#
|
||||
));
|
||||
|
||||
assert!(actual.err.is_empty());
|
||||
})
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn parse_module_success_with_complex_external_stream() {
|
||||
Playground::setup("nu_check_test_19", |dirs, sandbox| {
|
||||
sandbox.with_files(vec![FileWithContentToBeTrimmed(
|
||||
"grep.nu",
|
||||
r#"
|
||||
#grep for nu
|
||||
def grep-nu [
|
||||
search #search term
|
||||
entrada? #file or pipe
|
||||
#
|
||||
#Examples
|
||||
#grep-nu search file.txt
|
||||
#ls **/* | some_filter | grep-nu search
|
||||
#open file.txt | grep-nu search
|
||||
] {
|
||||
if ($entrada | empty?) {
|
||||
if ($in | column? name) {
|
||||
grep -ihHn $search ($in | get name)
|
||||
} else {
|
||||
($in | into string) | grep -ihHn $search
|
||||
}
|
||||
} else {
|
||||
grep -ihHn $search $entrada
|
||||
}
|
||||
| lines
|
||||
| parse "{file}:{line}:{match}"
|
||||
| str trim
|
||||
| update match {|f|
|
||||
$f.match
|
||||
| nu-highlight
|
||||
}
|
||||
| rename "source file" "line number"
|
||||
}
|
||||
|
||||
"#,
|
||||
)]);
|
||||
|
||||
let actual = nu!(
|
||||
cwd: dirs.test(), pipeline(
|
||||
r#"
|
||||
open grep.nu | nu-check -d --as-module
|
||||
"#
|
||||
));
|
||||
|
||||
assert!(actual.err.is_empty());
|
||||
})
|
||||
}
|
Loading…
Reference in a new issue