mirror of
https://github.com/nushell/nushell
synced 2024-12-27 05:23:11 +00:00
Add FILE_PWD environment variable when running 'nu script.nu' (#7424)
# Description When running `nu script.nu`, the `$env.FILE_PWD` will be set to the directory where the script is. Also makes the error message a bit nicer: ``` > target/debug/nu asdihga Error: nu:🐚:file_not_found (link) × File not found ╭─[source:1:1] 1 │ nu · ▲ · ╰── Could not access file 'asdihga': "No such file or directory (os error 2)" ╰──── ``` # User-Facing Changes `FILE_PWD` environment variable is available when running a script as `nu script.nu`. # Tests + Formatting Don't forget to add tests that cover your changes. Make sure you've run and fixed any issues with these commands: - `cargo fmt --all -- --check` to check standard code formatting (`cargo fmt --all` applies these changes) - `cargo clippy --workspace -- -D warnings -D clippy::unwrap_used -A clippy::needless_collect` to check that you're using the standard code style - `cargo test --workspace` to check that all tests pass # After Submitting If your PR had any user-facing changes, update [the documentation](https://github.com/nushell/nushell.github.io) after the PR is merged, if necessary. This will help us keep the docs up to date.
This commit is contained in:
parent
f43edbccdc
commit
f1000a17b4
3 changed files with 97 additions and 10 deletions
|
@ -2,13 +2,13 @@ use crate::util::{eval_source, report_error};
|
||||||
use log::info;
|
use log::info;
|
||||||
use log::trace;
|
use log::trace;
|
||||||
use miette::{IntoDiagnostic, Result};
|
use miette::{IntoDiagnostic, Result};
|
||||||
use nu_engine::convert_env_values;
|
use nu_engine::{convert_env_values, current_dir};
|
||||||
use nu_parser::parse;
|
use nu_parser::parse;
|
||||||
use nu_protocol::Type;
|
use nu_path::canonicalize_with;
|
||||||
use nu_protocol::{
|
use nu_protocol::{
|
||||||
ast::Call,
|
ast::Call,
|
||||||
engine::{EngineState, Stack, StateWorkingSet},
|
engine::{EngineState, Stack, StateWorkingSet},
|
||||||
Config, PipelineData, Span, Value,
|
Config, PipelineData, ShellError, Span, Type, Value,
|
||||||
};
|
};
|
||||||
use nu_utils::stdout_write_all_and_flush;
|
use nu_utils::stdout_write_all_and_flush;
|
||||||
|
|
||||||
|
@ -27,25 +27,92 @@ pub fn evaluate_file(
|
||||||
std::process::exit(1);
|
std::process::exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
let file = std::fs::read(&path).into_diagnostic()?;
|
let cwd = current_dir(engine_state, stack)?;
|
||||||
|
|
||||||
engine_state.start_in_file(Some(&path));
|
let file_path = {
|
||||||
|
match canonicalize_with(&path, &cwd) {
|
||||||
|
Ok(p) => p,
|
||||||
|
Err(e) => {
|
||||||
|
let working_set = StateWorkingSet::new(engine_state);
|
||||||
|
report_error(
|
||||||
|
&working_set,
|
||||||
|
&ShellError::FileNotFoundCustom(
|
||||||
|
format!("Could not access file '{}': {:?}", path, e.to_string()),
|
||||||
|
Span::unknown(),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
std::process::exit(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
let file_path_str = match file_path.to_str() {
|
||||||
|
Some(s) => s,
|
||||||
|
None => {
|
||||||
|
let working_set = StateWorkingSet::new(engine_state);
|
||||||
|
report_error(
|
||||||
|
&working_set,
|
||||||
|
&ShellError::NonUtf8Custom(
|
||||||
|
format!(
|
||||||
|
"Input file name '{}' is not valid UTF8",
|
||||||
|
file_path.to_string_lossy()
|
||||||
|
),
|
||||||
|
Span::unknown(),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
std::process::exit(1);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
let file = match std::fs::read(&file_path).into_diagnostic() {
|
||||||
|
Ok(p) => p,
|
||||||
|
Err(e) => {
|
||||||
|
let working_set = StateWorkingSet::new(engine_state);
|
||||||
|
report_error(
|
||||||
|
&working_set,
|
||||||
|
&ShellError::FileNotFoundCustom(
|
||||||
|
format!(
|
||||||
|
"Could not read file '{}': {:?}",
|
||||||
|
file_path_str,
|
||||||
|
e.to_string()
|
||||||
|
),
|
||||||
|
Span::unknown(),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
std::process::exit(1);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
engine_state.start_in_file(Some(file_path_str));
|
||||||
|
|
||||||
|
let mut parent = file_path.clone();
|
||||||
|
parent.pop();
|
||||||
|
|
||||||
|
stack.add_env_var(
|
||||||
|
"FILE_PWD".to_string(),
|
||||||
|
Value::string(parent.to_string_lossy(), Span::unknown()),
|
||||||
|
);
|
||||||
|
|
||||||
let mut working_set = StateWorkingSet::new(engine_state);
|
let mut working_set = StateWorkingSet::new(engine_state);
|
||||||
trace!("parsing file: {}", path);
|
trace!("parsing file: {}", file_path_str);
|
||||||
|
let _ = parse(&mut working_set, Some(file_path_str), &file, false, &[]);
|
||||||
let _ = parse(&mut working_set, Some(&path), &file, false, &[]);
|
|
||||||
|
|
||||||
if working_set.find_decl(b"main", &Type::Any).is_some() {
|
if working_set.find_decl(b"main", &Type::Any).is_some() {
|
||||||
let args = format!("main {}", args.join(" "));
|
let args = format!("main {}", args.join(" "));
|
||||||
|
|
||||||
if !eval_source(engine_state, stack, &file, &path, PipelineData::empty()) {
|
if !eval_source(
|
||||||
|
engine_state,
|
||||||
|
stack,
|
||||||
|
&file,
|
||||||
|
file_path_str,
|
||||||
|
PipelineData::empty(),
|
||||||
|
) {
|
||||||
std::process::exit(1);
|
std::process::exit(1);
|
||||||
}
|
}
|
||||||
if !eval_source(engine_state, stack, args.as_bytes(), "<commandline>", input) {
|
if !eval_source(engine_state, stack, args.as_bytes(), "<commandline>", input) {
|
||||||
std::process::exit(1);
|
std::process::exit(1);
|
||||||
}
|
}
|
||||||
} else if !eval_source(engine_state, stack, &file, &path, input) {
|
} else if !eval_source(engine_state, stack, &file, file_path_str, input) {
|
||||||
std::process::exit(1);
|
std::process::exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -749,6 +749,15 @@ Either make sure {0} is a string, or add a 'to_string' entry for it in ENV_CONVE
|
||||||
#[diagnostic(code(nu::parser::non_utf8), url(docsrs))]
|
#[diagnostic(code(nu::parser::non_utf8), url(docsrs))]
|
||||||
NonUtf8(#[label = "non-UTF8 string"] Span),
|
NonUtf8(#[label = "non-UTF8 string"] Span),
|
||||||
|
|
||||||
|
/// The given input must be valid UTF-8 for further processing.
|
||||||
|
///
|
||||||
|
/// ## Resolution
|
||||||
|
///
|
||||||
|
/// Check your input's encoding. Are there any funny characters/bytes?
|
||||||
|
#[error("Non-UTF8 string")]
|
||||||
|
#[diagnostic(code(nu::parser::non_utf8_custom), url(docsrs))]
|
||||||
|
NonUtf8Custom(String, #[label = "{0}"] Span),
|
||||||
|
|
||||||
/// A custom value could not be converted to a Dataframe.
|
/// A custom value could not be converted to a Dataframe.
|
||||||
///
|
///
|
||||||
/// ## Resolution
|
/// ## Resolution
|
||||||
|
|
|
@ -118,6 +118,17 @@ fn passes_with_env_env_var_to_external_process() {
|
||||||
assert_eq!(actual.out, "foo");
|
assert_eq!(actual.out, "foo");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn has_file_pwd() {
|
||||||
|
Playground::setup("has_file_pwd", |dirs, sandbox| {
|
||||||
|
sandbox.with_files(vec![FileWithContent("spam.nu", "$env.FILE_PWD")]);
|
||||||
|
|
||||||
|
let actual = nu!(cwd: dirs.test(), "nu spam.nu");
|
||||||
|
|
||||||
|
assert!(actual.out.ends_with("has_file_pwd"));
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
// FIXME: autoenv not currently implemented
|
// FIXME: autoenv not currently implemented
|
||||||
#[ignore]
|
#[ignore]
|
||||||
#[test]
|
#[test]
|
||||||
|
|
Loading…
Reference in a new issue