mirror of
https://github.com/nushell/nushell.git
synced 2025-01-20 13:19:18 +01:00
Add user autoload directory (#14669)
# Description Adds a user-level (non-vendor) autoload directory: ``` ($nu.default-config-dir)/autoload ``` Currently this is the only directory. We can consider adding others if needed. Related: As a separate PR, I'm going to try to restore the ability to set `$env.NU_AUTOLOAD_DIRS` during startup. # User-Facing Changes Files in `$nu.default-config-dir/autoload` will be autoload at startup. These files will be loaded after any vendor autoloads, so that a user can override the vendor settings. # Tests + Formatting - 🟢 `toolkit fmt` - 🟢 `toolkit clippy` - 🟢 `toolkit test` - 🟢 `toolkit test stdlib` # After Submitting TODO; add a `$nu.user-autoload-dirs` constant. Doc updates
This commit is contained in:
parent
df3892f323
commit
461eb43d9d
@ -1357,7 +1357,7 @@ fn variables_completions() {
|
|||||||
// Test completions for $nu
|
// Test completions for $nu
|
||||||
let suggestions = completer.complete("$nu.", 4);
|
let suggestions = completer.complete("$nu.", 4);
|
||||||
|
|
||||||
assert_eq!(18, suggestions.len());
|
assert_eq!(19, suggestions.len());
|
||||||
|
|
||||||
let expected: Vec<String> = vec![
|
let expected: Vec<String> = vec![
|
||||||
"cache-dir".into(),
|
"cache-dir".into(),
|
||||||
@ -1377,6 +1377,7 @@ fn variables_completions() {
|
|||||||
"plugin-path".into(),
|
"plugin-path".into(),
|
||||||
"startup-time".into(),
|
"startup-time".into(),
|
||||||
"temp-path".into(),
|
"temp-path".into(),
|
||||||
|
"user-autoload-dirs".into(),
|
||||||
"vendor-autoload-dirs".into(),
|
"vendor-autoload-dirs".into(),
|
||||||
];
|
];
|
||||||
|
|
||||||
|
@ -194,6 +194,17 @@ pub(crate) fn create_nu_constant(engine_state: &EngineState, span: Span) -> Valu
|
|||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
record.push(
|
||||||
|
"user-autoload-dirs",
|
||||||
|
Value::list(
|
||||||
|
get_user_autoload_dirs(engine_state)
|
||||||
|
.iter()
|
||||||
|
.map(|path| Value::string(path.to_string_lossy(), span))
|
||||||
|
.collect(),
|
||||||
|
span,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
record.push("temp-path", {
|
record.push("temp-path", {
|
||||||
let canon_temp_path = canonicalize_path(engine_state, &std::env::temp_dir());
|
let canon_temp_path = canonicalize_path(engine_state, &std::env::temp_dir());
|
||||||
Value::string(canon_temp_path.to_string_lossy(), span)
|
Value::string(canon_temp_path.to_string_lossy(), span)
|
||||||
@ -306,10 +317,9 @@ pub fn get_vendor_autoload_dirs(_engine_state: &EngineState) -> Vec<PathBuf> {
|
|||||||
.map(into_autoload_path_fn)
|
.map(into_autoload_path_fn)
|
||||||
.for_each(&mut append_fn);
|
.for_each(&mut append_fn);
|
||||||
|
|
||||||
option_env!("NU_VENDOR_AUTOLOAD_DIR")
|
if let Some(path) = option_env!("NU_VENDOR_AUTOLOAD_DIR") {
|
||||||
.into_iter()
|
append_fn(PathBuf::from(path));
|
||||||
.map(PathBuf::from)
|
}
|
||||||
.for_each(&mut append_fn);
|
|
||||||
|
|
||||||
#[cfg(target_os = "macos")]
|
#[cfg(target_os = "macos")]
|
||||||
std::env::var("XDG_DATA_HOME")
|
std::env::var("XDG_DATA_HOME")
|
||||||
@ -326,15 +336,37 @@ pub fn get_vendor_autoload_dirs(_engine_state: &EngineState) -> Vec<PathBuf> {
|
|||||||
.into_iter()
|
.into_iter()
|
||||||
.for_each(&mut append_fn);
|
.for_each(&mut append_fn);
|
||||||
|
|
||||||
dirs::data_dir()
|
if let Some(data_dir) = dirs::data_dir() {
|
||||||
.into_iter()
|
append_fn(into_autoload_path_fn(data_dir));
|
||||||
.map(into_autoload_path_fn)
|
}
|
||||||
.for_each(&mut append_fn);
|
|
||||||
|
|
||||||
std::env::var_os("NU_VENDOR_AUTOLOAD_DIR")
|
if let Some(path) = std::env::var_os("NU_VENDOR_AUTOLOAD_DIR") {
|
||||||
.into_iter()
|
append_fn(PathBuf::from(path));
|
||||||
.map(PathBuf::from)
|
}
|
||||||
.for_each(&mut append_fn);
|
|
||||||
|
dirs
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_user_autoload_dirs(_engine_state: &EngineState) -> Vec<PathBuf> {
|
||||||
|
// User autoload directories - Currently just `autoload` in the default
|
||||||
|
// configuration directory
|
||||||
|
let into_autoload_path_fn = |mut path: PathBuf| {
|
||||||
|
path.push("nushell");
|
||||||
|
path.push("autoload");
|
||||||
|
path
|
||||||
|
};
|
||||||
|
|
||||||
|
let mut dirs = Vec::new();
|
||||||
|
|
||||||
|
let mut append_fn = |path: PathBuf| {
|
||||||
|
if !dirs.contains(&path) {
|
||||||
|
dirs.push(path)
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
if let Some(config_dir) = dirs::config_dir() {
|
||||||
|
append_fn(into_autoload_path_fn(config_dir));
|
||||||
|
}
|
||||||
|
|
||||||
dirs
|
dirs
|
||||||
}
|
}
|
||||||
|
@ -6,6 +6,7 @@ use nu_engine::convert_env_values;
|
|||||||
use nu_path::canonicalize_with;
|
use nu_path::canonicalize_with;
|
||||||
use nu_protocol::{
|
use nu_protocol::{
|
||||||
engine::{EngineState, Stack, StateWorkingSet},
|
engine::{EngineState, Stack, StateWorkingSet},
|
||||||
|
eval_const::{get_user_autoload_dirs, get_vendor_autoload_dirs},
|
||||||
report_parse_error, report_shell_error, Config, ParseError, PipelineData, Spanned,
|
report_parse_error, report_shell_error, Config, ParseError, PipelineData, Spanned,
|
||||||
};
|
};
|
||||||
use nu_utils::{get_default_config, get_default_env, get_scaffold_config, get_scaffold_env, perf};
|
use nu_utils::{get_default_config, get_default_env, get_scaffold_config, get_scaffold_env, perf};
|
||||||
@ -197,24 +198,29 @@ pub(crate) fn read_vendor_autoload_files(engine_state: &mut EngineState, stack:
|
|||||||
|
|
||||||
// The evaluation order is first determined by the semantics of `get_vendor_autoload_dirs`
|
// The evaluation order is first determined by the semantics of `get_vendor_autoload_dirs`
|
||||||
// to determine the order of directories to evaluate
|
// to determine the order of directories to evaluate
|
||||||
for autoload_dir in nu_protocol::eval_const::get_vendor_autoload_dirs(engine_state) {
|
get_vendor_autoload_dirs(engine_state)
|
||||||
warn!("read_vendor_autoload_files: {}", autoload_dir.display());
|
.iter()
|
||||||
|
// User autoload directories are evaluated after vendor, which means that
|
||||||
|
// the user can override vendor autoload files
|
||||||
|
.chain(get_user_autoload_dirs(engine_state).iter())
|
||||||
|
.for_each(|autoload_dir| {
|
||||||
|
warn!("read_vendor_autoload_files: {}", autoload_dir.display());
|
||||||
|
|
||||||
if autoload_dir.exists() {
|
if autoload_dir.exists() {
|
||||||
// on a second levels files are lexicographically sorted by the string of the filename
|
// on a second levels files are lexicographically sorted by the string of the filename
|
||||||
let entries = read_and_sort_directory(&autoload_dir);
|
let entries = read_and_sort_directory(autoload_dir);
|
||||||
if let Ok(entries) = entries {
|
if let Ok(entries) = entries {
|
||||||
for entry in entries {
|
for entry in entries {
|
||||||
if !entry.ends_with(".nu") {
|
if !entry.ends_with(".nu") {
|
||||||
continue;
|
continue;
|
||||||
|
}
|
||||||
|
let path = autoload_dir.join(entry);
|
||||||
|
warn!("AutoLoading: {:?}", path);
|
||||||
|
eval_config_contents(path, engine_state, stack);
|
||||||
}
|
}
|
||||||
let path = autoload_dir.join(entry);
|
|
||||||
warn!("AutoLoading: {:?}", path);
|
|
||||||
eval_config_contents(path, engine_state, stack);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
});
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn eval_default_config(
|
fn eval_default_config(
|
||||||
|
Loading…
Reference in New Issue
Block a user