Files
nushell/crates/nu-parser/src/parse/source.rs
JT f562a4526c Fix clippy lints (#4262)
* Fix clippy lints

* Fix clippy lints

* Fix clippy lints
2022-01-18 23:33:28 +11:00

101 lines
3.0 KiB
Rust

use crate::{lex::tokens::LiteCommand, ParserScope};
use nu_errors::{ArgumentError, ParseError};
use nu_path::{canonicalize, canonicalize_with};
use nu_protocol::hir::{Expression, InternalCommand};
use std::path::Path;
use nu_source::SpannedItem;
pub fn parse_source_internal(
lite_cmd: &LiteCommand,
command: &InternalCommand,
scope: &dyn ParserScope,
) -> Result<(), ParseError> {
if lite_cmd.parts.len() != 2 {
return Err(ParseError::argument_error(
lite_cmd.parts[0].clone(),
ArgumentError::MissingMandatoryPositional("a path for sourcing".into()),
));
}
if lite_cmd.parts[1].item.starts_with('$') {
return Err(ParseError::mismatch(
"a filepath constant",
lite_cmd.parts[1].clone(),
));
}
// look for source files in lib dirs first
// if not files are found, try the current path
// first file found wins.
find_source_file(lite_cmd, command, scope)
}
fn find_source_file(
lite_cmd: &LiteCommand,
command: &InternalCommand,
scope: &dyn ParserScope,
) -> Result<(), ParseError> {
let (file, file_span) = if let Some(ref positional_args) = command.args.positional {
if let Expression::FilePath(ref p) = positional_args[0].expr {
(p.as_path(), &positional_args[0].span)
} else {
(Path::new(&lite_cmd.parts[1].item), &lite_cmd.parts[1].span)
}
} else {
(Path::new(&lite_cmd.parts[1].item), &lite_cmd.parts[1].span)
};
let lib_dirs = nu_data::config::config(nu_source::Tag::unknown())
.ok()
.as_ref()
.map(|configuration| match configuration.get("lib_dirs") {
Some(paths) => paths
.table_entries()
.cloned()
.map(|path| path.as_string())
.collect(),
None => vec![],
});
if let Some(dir) = lib_dirs {
for lib_path in dir.into_iter().flatten() {
let path = if let Ok(p) = canonicalize_with(&file, lib_path) {
p
} else {
continue;
};
if let Ok(contents) = std::fs::read_to_string(&path) {
return parse(&contents, 0, scope);
}
}
}
let path = canonicalize(&file).map_err(|e| {
ParseError::general_error(
format!("Can't load source file. Reason: {}", e),
"Can't load this file".spanned(file_span),
)
})?;
let contents = std::fs::read_to_string(&path);
match contents {
Ok(contents) => parse(&contents, 0, scope),
Err(e) => Err(ParseError::general_error(
format!("Can't load source file. Reason: {}", e),
"Can't load this file".spanned(file_span),
)),
}
}
pub fn parse(input: &str, span_offset: usize, scope: &dyn ParserScope) -> Result<(), ParseError> {
if let (_, Some(parse_error)) = super::parse(input, span_offset, scope) {
Err(parse_error)
} else {
Ok(())
}
}