mirror of
https://github.com/nushell/nushell
synced 2025-01-14 22:24:54 +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,
|
Complete,
|
||||||
Exec,
|
Exec,
|
||||||
External,
|
External,
|
||||||
|
NuCheck,
|
||||||
Ps,
|
Ps,
|
||||||
Sys,
|
Sys,
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
mod benchmark;
|
mod benchmark;
|
||||||
mod complete;
|
mod complete;
|
||||||
mod exec;
|
mod exec;
|
||||||
|
mod nu_check;
|
||||||
mod ps;
|
mod ps;
|
||||||
mod run_external;
|
mod run_external;
|
||||||
mod sys;
|
mod sys;
|
||||||
|
@ -9,6 +10,7 @@ mod which_;
|
||||||
pub use benchmark::Benchmark;
|
pub use benchmark::Benchmark;
|
||||||
pub use complete::Complete;
|
pub use complete::Complete;
|
||||||
pub use exec::Exec;
|
pub use exec::Exec;
|
||||||
|
pub use nu_check::NuCheck;
|
||||||
pub use ps::Ps;
|
pub use ps::Ps;
|
||||||
pub use run_external::{External, ExternalCommand};
|
pub use run_external::{External, ExternalCommand};
|
||||||
pub use sys::Sys;
|
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 mkdir;
|
||||||
mod move_;
|
mod move_;
|
||||||
mod network;
|
mod network;
|
||||||
|
mod nu_check;
|
||||||
mod open;
|
mod open;
|
||||||
mod parse;
|
mod parse;
|
||||||
mod path;
|
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