mirror of
https://github.com/nushell/nushell.git
synced 2025-06-18 16:07:02 +02:00
implement autoloading (#13217)
# Description This PR implements script or module autoloading. It does this by finding the `$nu.vendor-autoload-dir`, lists the contents and sorts them by file name. These files are evaluated in that order. To see what's going on, you can use `--log-level warn` ``` ❯ cargo r -- --log-level warn Finished dev [unoptimized + debuginfo] target(s) in 0.58s Running `target\debug\nu.exe --log-level warn` 2024-06-24 09:23:20.494 PM [WARN ] nu::config_files: set_config_path() cwd: "C:\\Users\\fdncred\\source\\repos\\nushell", default_config: config.nu, key: config-path, config_file_specified: None 2024-06-24 09:23:20.495 PM [WARN ] nu::config_files: set_config_path() cwd: "C:\\Users\\fdncred\\source\\repos\\nushell", default_config: env.nu, key: env-path, config_file_specified: None 2024-06-24 09:23:20.629 PM [WARN ] nu::config_files: setup_config() config_file_specified: None, env_file_specified: None, login: false 2024-06-24 09:23:20.660 PM [WARN ] nu::config_files: read_config_file() config_file_specified: None, is_env_config: true Hello, from env.nu 2024-06-24 09:23:20.679 PM [WARN ] nu::config_files: read_config_file() config_file_specified: None, is_env_config: false Hello, from config.nu Hello, from defs.nu Activating Microsoft Visual Studio environment. 2024-06-24 09:23:21.398 PM [WARN ] nu::config_files: read_vendor_autoload_files() src\config_files.rs:234:9 2024-06-24 09:23:21.399 PM [WARN ] nu::config_files: read_vendor_autoload_files: C:\ProgramData\nushell\vendor\autoload 2024-06-24 09:23:21.399 PM [WARN ] nu::config_files: AutoLoading: "C:\\ProgramData\\nushell\\vendor\\autoload\\01_get-weather.nu" 2024-06-24 09:23:21.675 PM [WARN ] nu::config_files: AutoLoading: "C:\\ProgramData\\nushell\\vendor\\autoload\\02_temp.nu" 2024-06-24 09:23:21.817 PM [WARN ] nu_cli::repl: Terminal doesn't support use_kitty_protocol config ``` # User-Facing Changes <!-- List of all changes that impact the user experience here. This helps us keep track of breaking changes. --> # 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` to check that you're using the standard code style - `cargo test --workspace` to check that all tests pass (on Windows make sure to [enable developer mode](https://learn.microsoft.com/en-us/windows/apps/get-started/developer-mode-features-and-debugging)) - `cargo run -- -c "use toolkit.nu; toolkit test stdlib"` to run the tests for the standard library > **Note** > from `nushell` you can also use the `toolkit` as follows > ```bash > use toolkit.nu # or use an `env_change` hook to activate it automatically > toolkit check pr > ``` --> # 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
0dd35cddcd
commit
f241110005
@ -194,31 +194,11 @@ pub(crate) fn create_nu_constant(engine_state: &EngineState, span: Span) -> Valu
|
|||||||
// if not, use the default /usr/share/nushell/vendor/autoload
|
// if not, use the default /usr/share/nushell/vendor/autoload
|
||||||
|
|
||||||
// check to see if NU_VENDOR_AUTOLOAD_DIR env var is set, if not, use the default
|
// check to see if NU_VENDOR_AUTOLOAD_DIR env var is set, if not, use the default
|
||||||
Value::string(
|
if let Some(path) = get_vendor_autoload_dir(engine_state) {
|
||||||
option_env!("NU_VENDOR_AUTOLOAD_DIR")
|
Value::string(path.to_string_lossy(), span)
|
||||||
.map(String::from)
|
|
||||||
.unwrap_or_else(|| {
|
|
||||||
if cfg!(windows) {
|
|
||||||
let all_user_profile = match engine_state.get_env_var("ALLUSERPROFILE") {
|
|
||||||
Some(v) => format!(
|
|
||||||
"{}\\nushell\\vendor\\autoload",
|
|
||||||
v.coerce_string().unwrap_or("C:\\ProgramData".into())
|
|
||||||
),
|
|
||||||
None => "C:\\ProgramData\\nushell\\vendor\\autoload".into(),
|
|
||||||
};
|
|
||||||
all_user_profile
|
|
||||||
} else {
|
} else {
|
||||||
// In non-Windows environments, if NU_VENDOR_AUTOLOAD_DIR is not set
|
Value::error(ShellError::ConfigDirNotFound { span: Some(span) }, span)
|
||||||
// check to see if PREFIX env var is set, and use it as PREFIX/nushell/vendor/autoload
|
},
|
||||||
// otherwise default to /usr/share/nushell/vendor/autoload
|
|
||||||
option_env!("PREFIX").map(String::from).map_or_else(
|
|
||||||
|| "/usr/local/share/nushell/vendor/autoload".into(),
|
|
||||||
|prefix| format!("{}/share/nushell/vendor/autoload", prefix),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}),
|
|
||||||
span,
|
|
||||||
),
|
|
||||||
);
|
);
|
||||||
|
|
||||||
record.push("temp-path", {
|
record.push("temp-path", {
|
||||||
@ -275,6 +255,41 @@ pub(crate) fn create_nu_constant(engine_state: &EngineState, span: Span) -> Valu
|
|||||||
Value::record(record, span)
|
Value::record(record, span)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn get_vendor_autoload_dir(engine_state: &EngineState) -> Option<PathBuf> {
|
||||||
|
// pseudo code
|
||||||
|
// if env var NU_VENDOR_AUTOLOAD_DIR is set, in any platform, use it
|
||||||
|
// if not, if windows, use ALLUSERPROFILE\nushell\vendor\autoload
|
||||||
|
// if not, if non-windows, if env var PREFIX is set, use PREFIX/share/nushell/vendor/autoload
|
||||||
|
// if not, use the default /usr/share/nushell/vendor/autoload
|
||||||
|
|
||||||
|
// check to see if NU_VENDOR_AUTOLOAD_DIR env var is set, if not, use the default
|
||||||
|
Some(
|
||||||
|
option_env!("NU_VENDOR_AUTOLOAD_DIR")
|
||||||
|
.map(String::from)
|
||||||
|
.unwrap_or_else(|| {
|
||||||
|
if cfg!(windows) {
|
||||||
|
let all_user_profile = match engine_state.get_env_var("ALLUSERPROFILE") {
|
||||||
|
Some(v) => format!(
|
||||||
|
"{}\\nushell\\vendor\\autoload",
|
||||||
|
v.coerce_string().unwrap_or("C:\\ProgramData".into())
|
||||||
|
),
|
||||||
|
None => "C:\\ProgramData\\nushell\\vendor\\autoload".into(),
|
||||||
|
};
|
||||||
|
all_user_profile
|
||||||
|
} else {
|
||||||
|
// In non-Windows environments, if NU_VENDOR_AUTOLOAD_DIR is not set
|
||||||
|
// check to see if PREFIX env var is set, and use it as PREFIX/nushell/vendor/autoload
|
||||||
|
// otherwise default to /usr/share/nushell/vendor/autoload
|
||||||
|
option_env!("PREFIX").map(String::from).map_or_else(
|
||||||
|
|| "/usr/local/share/nushell/vendor/autoload".into(),
|
||||||
|
|prefix| format!("{}/share/nushell/vendor/autoload", prefix),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.into(),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
fn eval_const_call(
|
fn eval_const_call(
|
||||||
working_set: &StateWorkingSet,
|
working_set: &StateWorkingSet,
|
||||||
call: &Call,
|
call: &Call,
|
||||||
|
@ -9,8 +9,9 @@ use nu_protocol::{
|
|||||||
};
|
};
|
||||||
use nu_utils::{get_default_config, get_default_env};
|
use nu_utils::{get_default_config, get_default_env};
|
||||||
use std::{
|
use std::{
|
||||||
|
fs,
|
||||||
fs::File,
|
fs::File,
|
||||||
io::Write,
|
io::{Result, Write},
|
||||||
panic::{catch_unwind, AssertUnwindSafe},
|
panic::{catch_unwind, AssertUnwindSafe},
|
||||||
path::Path,
|
path::Path,
|
||||||
sync::Arc,
|
sync::Arc,
|
||||||
@ -176,6 +177,46 @@ pub(crate) fn read_default_env_file(engine_state: &mut EngineState, stack: &mut
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn read_and_sort_directory(path: &Path) -> Result<Vec<String>> {
|
||||||
|
let mut entries = Vec::new();
|
||||||
|
|
||||||
|
for entry in fs::read_dir(path)? {
|
||||||
|
let entry = entry?;
|
||||||
|
let file_name = entry.file_name();
|
||||||
|
let file_name_str = file_name.into_string().unwrap_or_default();
|
||||||
|
entries.push(file_name_str);
|
||||||
|
}
|
||||||
|
|
||||||
|
entries.sort();
|
||||||
|
|
||||||
|
Ok(entries)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) fn read_vendor_autoload_files(engine_state: &mut EngineState, stack: &mut Stack) {
|
||||||
|
warn!(
|
||||||
|
"read_vendor_autoload_files() {}:{}:{}",
|
||||||
|
file!(),
|
||||||
|
line!(),
|
||||||
|
column!()
|
||||||
|
);
|
||||||
|
|
||||||
|
// read and source vendor_autoload_files file if exists
|
||||||
|
if let Some(autoload_dir) = nu_protocol::eval_const::get_vendor_autoload_dir(engine_state) {
|
||||||
|
warn!("read_vendor_autoload_files: {}", autoload_dir.display());
|
||||||
|
|
||||||
|
if autoload_dir.exists() {
|
||||||
|
let entries = read_and_sort_directory(&autoload_dir);
|
||||||
|
if let Ok(entries) = entries {
|
||||||
|
for entry in entries {
|
||||||
|
let path = autoload_dir.join(entry);
|
||||||
|
warn!("AutoLoading: {:?}", path);
|
||||||
|
eval_config_contents(path, engine_state, stack);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn eval_default_config(
|
fn eval_default_config(
|
||||||
engine_state: &mut EngineState,
|
engine_state: &mut EngineState,
|
||||||
stack: &mut Stack,
|
stack: &mut Stack,
|
||||||
@ -236,6 +277,8 @@ pub(crate) fn setup_config(
|
|||||||
if is_login_shell {
|
if is_login_shell {
|
||||||
read_loginshell_file(engine_state, stack);
|
read_loginshell_file(engine_state, stack);
|
||||||
}
|
}
|
||||||
|
// read and auto load vendor autoload files
|
||||||
|
read_vendor_autoload_files(engine_state, stack);
|
||||||
}));
|
}));
|
||||||
if result.is_err() {
|
if result.is_err() {
|
||||||
eprintln!(
|
eprintln!(
|
||||||
|
Loading…
x
Reference in New Issue
Block a user