mirror of
https://github.com/nushell/nushell.git
synced 2025-07-08 18:37:07 +02:00
101 lines
3.0 KiB
Rust
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(())
|
|
}
|
|
}
|