mirror of
https://github.com/nushell/nushell.git
synced 2025-05-25 09:01:17 +00:00
This PR sets the current working directory to the location of the Nushell executable at startup, using `std::env::set_current_dir()`. This is desirable because after PR https://github.com/nushell/nushell/pull/12922, we no longer change our current working directory even after `cd` is executed, and some OS might lock the directory where Nushell started. The location of the Nushell executable is chosen because it cannot be removed while Nushell is running anyways, so we don't have to worry about OS locking it. This PR has the side effect that it breaks buggy command even harder. I'll keep this PR as a draft until these commands are fixed, but it might be helpful to pull this PR if you're working on fixing one of those bugs. --------- Co-authored-by: Devyn Cairns <devyn.cairns@gmail.com> Co-authored-by: Darren Schroeder <343840+fdncred@users.noreply.github.com>
106 lines
3.4 KiB
Rust
106 lines
3.4 KiB
Rust
#![doc = include_str!("../README.md")]
|
|
use log::trace;
|
|
use nu_engine::eval_block;
|
|
use nu_parser::parse;
|
|
use nu_protocol::{
|
|
debugger::WithoutDebug,
|
|
engine::{FileStack, Stack, StateWorkingSet, VirtualPath},
|
|
report_parse_error, PipelineData,
|
|
};
|
|
use std::path::PathBuf;
|
|
|
|
// Virtual std directory unlikely to appear in user's file system
|
|
const NU_STDLIB_VIRTUAL_DIR: &str = "NU_STDLIB_VIRTUAL_DIR";
|
|
|
|
pub fn load_standard_library(
|
|
engine_state: &mut nu_protocol::engine::EngineState,
|
|
) -> Result<(), miette::ErrReport> {
|
|
trace!("load_standard_library");
|
|
let (block, delta) = {
|
|
// Using full virtual path to avoid potential conflicts with user having 'std' directory
|
|
// in their working directory.
|
|
let std_dir = PathBuf::from(NU_STDLIB_VIRTUAL_DIR).join("std");
|
|
|
|
let mut std_files = vec![
|
|
("mod.nu", include_str!("../std/mod.nu")),
|
|
("dirs.nu", include_str!("../std/dirs.nu")),
|
|
("dt.nu", include_str!("../std/dt.nu")),
|
|
("help.nu", include_str!("../std/help.nu")),
|
|
("iter.nu", include_str!("../std/iter.nu")),
|
|
("log.nu", include_str!("../std/log.nu")),
|
|
("assert.nu", include_str!("../std/assert.nu")),
|
|
("xml.nu", include_str!("../std/xml.nu")),
|
|
("input.nu", include_str!("../std/input.nu")),
|
|
("math.nu", include_str!("../std/math.nu")),
|
|
("formats.nu", include_str!("../std/formats.nu")),
|
|
];
|
|
|
|
let mut working_set = StateWorkingSet::new(engine_state);
|
|
let mut std_virt_paths = vec![];
|
|
|
|
for (name, content) in std_files.drain(..) {
|
|
let name = std_dir.join(name);
|
|
|
|
let file_id =
|
|
working_set.add_file(name.to_string_lossy().to_string(), content.as_bytes());
|
|
let virtual_file_id = working_set.add_virtual_path(
|
|
name.to_string_lossy().to_string(),
|
|
VirtualPath::File(file_id),
|
|
);
|
|
std_virt_paths.push(virtual_file_id);
|
|
}
|
|
|
|
let std_dir = std_dir.to_string_lossy().to_string();
|
|
let source = r#"
|
|
# Define the `std` module
|
|
module std
|
|
|
|
# Prelude
|
|
use std dirs [
|
|
enter
|
|
shells
|
|
g
|
|
n
|
|
p
|
|
dexit
|
|
]
|
|
use std pwd
|
|
"#;
|
|
|
|
let _ = working_set.add_virtual_path(std_dir, VirtualPath::Dir(std_virt_paths));
|
|
|
|
// Add a placeholder file to the stack of files being evaluated.
|
|
// The name of this file doesn't matter; it's only there to set the current working directory to NU_STDLIB_VIRTUAL_DIR.
|
|
let placeholder = PathBuf::from(NU_STDLIB_VIRTUAL_DIR).join("loading stdlib");
|
|
working_set.files = FileStack::with_file(placeholder);
|
|
|
|
let block = parse(
|
|
&mut working_set,
|
|
Some("loading stdlib"),
|
|
source.as_bytes(),
|
|
false,
|
|
);
|
|
|
|
// Remove the placeholder file from the stack of files being evaluated.
|
|
working_set.files.pop();
|
|
|
|
if let Some(err) = working_set.parse_errors.first() {
|
|
report_parse_error(&working_set, err);
|
|
}
|
|
|
|
(block, working_set.render())
|
|
};
|
|
|
|
engine_state.merge_delta(delta)?;
|
|
|
|
// We need to evaluate the module in order to run the `export-env` blocks.
|
|
let mut stack = Stack::new();
|
|
let pipeline_data = PipelineData::Empty;
|
|
|
|
eval_block::<WithoutDebug>(engine_state, &mut stack, &block, pipeline_data)?;
|
|
|
|
engine_state.merge_env(&mut stack)?;
|
|
|
|
Ok(())
|
|
}
|