mirror of
https://github.com/nushell/nushell
synced 2024-12-26 13:03:07 +00:00
Revert "Allow NU_LIBS_DIR and friends to be const" (#8501)
Reverts nushell/nushell#8310 In anticipation that we may want to revert this PR. I'm starting the process because of this issue. This stopped working ``` let-env NU_LIB_DIRS = [ ($nu.config-path | path dirname | path join 'scripts') 'C:\Users\username\source\repos\forks\nu_scripts' ($nu.config-path | path dirname) ] ``` You have to do this now instead. ``` const NU_LIB_DIRS = [ 'C:\Users\username\AppData\Roaming\nushell\scripts' 'C:\Users\username\source\repos\forks\nu_scripts' 'C:\Users\username\AppData\Roaming\nushell' ] ``` In talking with @kubouch, he was saying that the `let-env` version should keep working. Hopefully it's a small change.
This commit is contained in:
parent
eb2e2e6370
commit
ef7fbf4bf9
13 changed files with 116 additions and 264 deletions
|
@ -6,7 +6,7 @@ use nu_protocol::{
|
||||||
PipelineData, Span, Type, Value,
|
PipelineData, Span, Type, Value,
|
||||||
};
|
};
|
||||||
use reedline::Suggestion;
|
use reedline::Suggestion;
|
||||||
use std::{collections::HashMap, sync::Arc};
|
use std::sync::Arc;
|
||||||
|
|
||||||
use super::completer::map_value_completions;
|
use super::completer::map_value_completions;
|
||||||
|
|
||||||
|
@ -66,7 +66,7 @@ impl Completer for CustomCompletion {
|
||||||
],
|
],
|
||||||
redirect_stdout: true,
|
redirect_stdout: true,
|
||||||
redirect_stderr: true,
|
redirect_stderr: true,
|
||||||
parser_info: HashMap::new(),
|
parser_info: vec![],
|
||||||
},
|
},
|
||||||
PipelineData::empty(),
|
PipelineData::empty(),
|
||||||
);
|
);
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
use nu_engine::{eval_block, find_in_dirs_env, get_dirs_var_from_call, redirect_env, CallExt};
|
use nu_engine::{eval_block, find_in_dirs_env, redirect_env, CallExt};
|
||||||
use nu_parser::trim_quotes_str;
|
use nu_parser::trim_quotes_str;
|
||||||
use nu_protocol::ast::{Call, Expr};
|
use nu_protocol::ast::{Call, Expr};
|
||||||
use nu_protocol::engine::{Command, EngineState, Stack};
|
use nu_protocol::engine::{Command, EngineState, Stack};
|
||||||
|
@ -66,24 +66,23 @@ impl Command for OverlayUse {
|
||||||
let mut name_arg: Spanned<String> = call.req(engine_state, caller_stack, 0)?;
|
let mut name_arg: Spanned<String> = call.req(engine_state, caller_stack, 0)?;
|
||||||
name_arg.item = trim_quotes_str(&name_arg.item).to_string();
|
name_arg.item = trim_quotes_str(&name_arg.item).to_string();
|
||||||
|
|
||||||
let maybe_origin_module_id =
|
let maybe_origin_module_id = if let Some(overlay_expr) = call.parser_info_nth(0) {
|
||||||
if let Some(overlay_expr) = call.get_parser_info("overlay_expr") {
|
if let Expr::Overlay(module_id) = overlay_expr.expr {
|
||||||
if let Expr::Overlay(module_id) = overlay_expr.expr {
|
module_id
|
||||||
module_id
|
|
||||||
} else {
|
|
||||||
return Err(ShellError::NushellFailedSpanned {
|
|
||||||
msg: "Not an overlay".to_string(),
|
|
||||||
label: "requires an overlay (path or a string)".to_string(),
|
|
||||||
span: overlay_expr.span,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
return Err(ShellError::NushellFailedSpanned {
|
return Err(ShellError::NushellFailedSpanned {
|
||||||
msg: "Missing positional".to_string(),
|
msg: "Not an overlay".to_string(),
|
||||||
label: "missing required overlay".to_string(),
|
label: "requires an overlay (path or a string)".to_string(),
|
||||||
span: call.head,
|
span: overlay_expr.span,
|
||||||
});
|
});
|
||||||
};
|
}
|
||||||
|
} else {
|
||||||
|
return Err(ShellError::NushellFailedSpanned {
|
||||||
|
msg: "Missing positional".to_string(),
|
||||||
|
label: "missing required overlay".to_string(),
|
||||||
|
span: call.head,
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
let overlay_name = if let Some(name) = call.opt(engine_state, caller_stack, 1)? {
|
let overlay_name = if let Some(name) = call.opt(engine_state, caller_stack, 1)? {
|
||||||
name
|
name
|
||||||
|
@ -114,12 +113,7 @@ impl Command for OverlayUse {
|
||||||
|
|
||||||
// Evaluate the export-env block (if any) and keep its environment
|
// Evaluate the export-env block (if any) and keep its environment
|
||||||
if let Some(block_id) = module.env_block {
|
if let Some(block_id) = module.env_block {
|
||||||
let maybe_path = find_in_dirs_env(
|
let maybe_path = find_in_dirs_env(&name_arg.item, engine_state, caller_stack)?;
|
||||||
&name_arg.item,
|
|
||||||
engine_state,
|
|
||||||
caller_stack,
|
|
||||||
get_dirs_var_from_call(call),
|
|
||||||
)?;
|
|
||||||
|
|
||||||
let block = engine_state.get_block(block_id);
|
let block = engine_state.get_block(block_id);
|
||||||
let mut callee_stack = caller_stack.gather_captures(&block.captures);
|
let mut callee_stack = caller_stack.gather_captures(&block.captures);
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
use nu_engine::{eval_block, find_in_dirs_env, get_dirs_var_from_call, redirect_env};
|
use nu_engine::{eval_block, find_in_dirs_env, redirect_env};
|
||||||
use nu_protocol::ast::{Call, Expr, Expression};
|
use nu_protocol::ast::{Call, Expr, Expression};
|
||||||
use nu_protocol::engine::{Command, EngineState, Stack};
|
use nu_protocol::engine::{Command, EngineState, Stack};
|
||||||
use nu_protocol::{
|
use nu_protocol::{
|
||||||
|
@ -48,7 +48,7 @@ impl Command for Use {
|
||||||
let import_pattern = if let Some(Expression {
|
let import_pattern = if let Some(Expression {
|
||||||
expr: Expr::ImportPattern(pat),
|
expr: Expr::ImportPattern(pat),
|
||||||
..
|
..
|
||||||
}) = call.get_parser_info("import_pattern")
|
}) = call.parser_info_nth(0)
|
||||||
{
|
{
|
||||||
pat
|
pat
|
||||||
} else {
|
} else {
|
||||||
|
@ -72,12 +72,9 @@ impl Command for Use {
|
||||||
let module_arg_str = String::from_utf8_lossy(
|
let module_arg_str = String::from_utf8_lossy(
|
||||||
engine_state.get_span_contents(&import_pattern.head.span),
|
engine_state.get_span_contents(&import_pattern.head.span),
|
||||||
);
|
);
|
||||||
let maybe_parent = if let Some(path) = find_in_dirs_env(
|
let maybe_parent = if let Some(path) =
|
||||||
&module_arg_str,
|
find_in_dirs_env(&module_arg_str, engine_state, caller_stack)?
|
||||||
engine_state,
|
{
|
||||||
caller_stack,
|
|
||||||
get_dirs_var_from_call(call),
|
|
||||||
)? {
|
|
||||||
path.parent().map(|p| p.to_path_buf()).or(None)
|
path.parent().map(|p| p.to_path_buf()).or(None)
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
|
|
|
@ -45,7 +45,7 @@ impl Command for Source {
|
||||||
) -> Result<PipelineData, ShellError> {
|
) -> Result<PipelineData, ShellError> {
|
||||||
// Note: this hidden positional is the block_id that corresponded to the 0th position
|
// Note: this hidden positional is the block_id that corresponded to the 0th position
|
||||||
// it is put here by the parser
|
// it is put here by the parser
|
||||||
let block_id: i64 = call.req_parser_info(engine_state, stack, "block_id")?;
|
let block_id: i64 = call.req_parser_info(engine_state, stack, 0)?;
|
||||||
|
|
||||||
let block = engine_state.get_block(block_id as usize).clone();
|
let block = engine_state.get_block(block_id as usize).clone();
|
||||||
eval_block_with_early_return(
|
eval_block_with_early_return(
|
||||||
|
|
15
crates/nu-command/src/env/source_env.rs
vendored
15
crates/nu-command/src/env/source_env.rs
vendored
|
@ -1,8 +1,6 @@
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
|
|
||||||
use nu_engine::{
|
use nu_engine::{eval_block_with_early_return, find_in_dirs_env, redirect_env, CallExt};
|
||||||
eval_block_with_early_return, find_in_dirs_env, get_dirs_var_from_call, redirect_env, CallExt,
|
|
||||||
};
|
|
||||||
use nu_protocol::ast::Call;
|
use nu_protocol::ast::Call;
|
||||||
use nu_protocol::engine::{Command, EngineState, Stack};
|
use nu_protocol::engine::{Command, EngineState, Stack};
|
||||||
use nu_protocol::{
|
use nu_protocol::{
|
||||||
|
@ -44,15 +42,12 @@ impl Command for SourceEnv {
|
||||||
|
|
||||||
// Note: this hidden positional is the block_id that corresponded to the 0th position
|
// Note: this hidden positional is the block_id that corresponded to the 0th position
|
||||||
// it is put here by the parser
|
// it is put here by the parser
|
||||||
let block_id: i64 = call.req_parser_info(engine_state, caller_stack, "block_id")?;
|
let block_id: i64 = call.req_parser_info(engine_state, caller_stack, 0)?;
|
||||||
|
|
||||||
// Set the currently evaluated directory (file-relative PWD)
|
// Set the currently evaluated directory (file-relative PWD)
|
||||||
let mut parent = if let Some(path) = find_in_dirs_env(
|
let mut parent = if let Some(path) =
|
||||||
&source_filename.item,
|
find_in_dirs_env(&source_filename.item, engine_state, caller_stack)?
|
||||||
engine_state,
|
{
|
||||||
caller_stack,
|
|
||||||
get_dirs_var_from_call(call),
|
|
||||||
)? {
|
|
||||||
PathBuf::from(&path)
|
PathBuf::from(&path)
|
||||||
} else {
|
} else {
|
||||||
return Err(ShellError::FileNotFound(source_filename.span));
|
return Err(ShellError::FileNotFound(source_filename.span));
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
use nu_engine::{find_in_dirs_env, get_dirs_var_from_call, CallExt};
|
use nu_engine::{find_in_dirs_env, CallExt};
|
||||||
use nu_parser::{parse, parse_module_block, unescape_unquote_string};
|
use nu_parser::{parse, parse_module_block, unescape_unquote_string};
|
||||||
use nu_protocol::ast::Call;
|
use nu_protocol::ast::Call;
|
||||||
use nu_protocol::engine::{Command, EngineState, Stack, StateWorkingSet};
|
use nu_protocol::engine::{Command, EngineState, Stack, StateWorkingSet};
|
||||||
|
@ -106,12 +106,7 @@ impl Command for NuCheck {
|
||||||
_ => {
|
_ => {
|
||||||
if let Some(path_str) = path {
|
if let Some(path_str) = path {
|
||||||
// look up the path as relative to FILE_PWD or inside NU_LIB_DIRS (same process as source-env)
|
// look up the path as relative to FILE_PWD or inside NU_LIB_DIRS (same process as source-env)
|
||||||
let path = match find_in_dirs_env(
|
let path = match find_in_dirs_env(&path_str.item, engine_state, stack) {
|
||||||
&path_str.item,
|
|
||||||
engine_state,
|
|
||||||
stack,
|
|
||||||
get_dirs_var_from_call(call),
|
|
||||||
) {
|
|
||||||
Ok(path) => {
|
Ok(path) => {
|
||||||
if let Some(path) = path {
|
if let Some(path) = path {
|
||||||
path
|
path
|
||||||
|
|
|
@ -39,7 +39,7 @@ pub trait CallExt {
|
||||||
&self,
|
&self,
|
||||||
engine_state: &EngineState,
|
engine_state: &EngineState,
|
||||||
stack: &mut Stack,
|
stack: &mut Stack,
|
||||||
name: &str,
|
pos: usize,
|
||||||
) -> Result<T, ShellError>;
|
) -> Result<T, ShellError>;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -111,9 +111,9 @@ impl CallExt for Call {
|
||||||
&self,
|
&self,
|
||||||
engine_state: &EngineState,
|
engine_state: &EngineState,
|
||||||
stack: &mut Stack,
|
stack: &mut Stack,
|
||||||
name: &str,
|
pos: usize,
|
||||||
) -> Result<T, ShellError> {
|
) -> Result<T, ShellError> {
|
||||||
if let Some(expr) = self.get_parser_info(name) {
|
if let Some(expr) = self.parser_info_nth(pos) {
|
||||||
let result = eval_expression(engine_state, stack, expr)?;
|
let result = eval_expression(engine_state, stack, expr)?;
|
||||||
FromValue::from_value(&result)
|
FromValue::from_value(&result)
|
||||||
} else if self.parser_info.is_empty() {
|
} else if self.parser_info.is_empty() {
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use std::path::{Path, PathBuf};
|
use std::path::{Path, PathBuf};
|
||||||
|
|
||||||
use nu_protocol::ast::{Call, Expr, PathMember};
|
use nu_protocol::ast::PathMember;
|
||||||
use nu_protocol::engine::{EngineState, Stack};
|
use nu_protocol::engine::{EngineState, Stack};
|
||||||
use nu_protocol::{PipelineData, ShellError, Span, Value, VarId};
|
use nu_protocol::{PipelineData, ShellError, Span, Value};
|
||||||
|
|
||||||
use nu_path::canonicalize_with;
|
use nu_path::canonicalize_with;
|
||||||
|
|
||||||
|
@ -18,6 +18,8 @@ const ENV_PATH_NAME: &str = "PATH";
|
||||||
|
|
||||||
const ENV_CONVERSIONS: &str = "ENV_CONVERSIONS";
|
const ENV_CONVERSIONS: &str = "ENV_CONVERSIONS";
|
||||||
|
|
||||||
|
static LIB_DIRS_ENV: &str = "NU_LIB_DIRS";
|
||||||
|
|
||||||
enum ConversionResult {
|
enum ConversionResult {
|
||||||
Ok(Value),
|
Ok(Value),
|
||||||
ConversionError(ShellError), // Failure during the conversion itself
|
ConversionError(ShellError), // Failure during the conversion itself
|
||||||
|
@ -222,17 +224,6 @@ pub fn path_str(
|
||||||
env_to_string(pathname, &pathval, engine_state, stack)
|
env_to_string(pathname, &pathval, engine_state, stack)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub const DIR_VAR_PARSER_INFO: &str = "dirs_var";
|
|
||||||
pub fn get_dirs_var_from_call(call: &Call) -> Option<VarId> {
|
|
||||||
call.get_parser_info(DIR_VAR_PARSER_INFO).and_then(|x| {
|
|
||||||
if let Expr::Var(id) = x.expr {
|
|
||||||
Some(id)
|
|
||||||
} else {
|
|
||||||
None
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
/// This helper function is used to find files during eval
|
/// This helper function is used to find files during eval
|
||||||
///
|
///
|
||||||
/// First, the actual current working directory is selected as
|
/// First, the actual current working directory is selected as
|
||||||
|
@ -248,7 +239,6 @@ pub fn find_in_dirs_env(
|
||||||
filename: &str,
|
filename: &str,
|
||||||
engine_state: &EngineState,
|
engine_state: &EngineState,
|
||||||
stack: &Stack,
|
stack: &Stack,
|
||||||
dirs_var: Option<VarId>,
|
|
||||||
) -> Result<Option<PathBuf>, ShellError> {
|
) -> Result<Option<PathBuf>, ShellError> {
|
||||||
// Choose whether to use file-relative or PWD-relative path
|
// Choose whether to use file-relative or PWD-relative path
|
||||||
let cwd = if let Some(pwd) = stack.get_env_var(engine_state, "FILE_PWD") {
|
let cwd = if let Some(pwd) = stack.get_env_var(engine_state, "FILE_PWD") {
|
||||||
|
@ -272,32 +262,36 @@ pub fn find_in_dirs_env(
|
||||||
current_dir_str(engine_state, stack)?
|
current_dir_str(engine_state, stack)?
|
||||||
};
|
};
|
||||||
|
|
||||||
Ok((|| -> Option<PathBuf> {
|
if let Ok(p) = canonicalize_with(filename, &cwd) {
|
||||||
if let Ok(p) = canonicalize_with(filename, &cwd) {
|
Ok(Some(p))
|
||||||
return Some(p);
|
} else {
|
||||||
}
|
|
||||||
let path = Path::new(filename);
|
let path = Path::new(filename);
|
||||||
if !path.is_relative() {
|
|
||||||
return None;
|
if path.is_relative() {
|
||||||
|
if let Some(lib_dirs) = stack.get_env_var(engine_state, LIB_DIRS_ENV) {
|
||||||
|
if let Ok(dirs) = lib_dirs.as_list() {
|
||||||
|
for lib_dir in dirs {
|
||||||
|
if let Ok(dir) = lib_dir.as_path() {
|
||||||
|
// make sure the dir is absolute path
|
||||||
|
if let Ok(dir_abs) = canonicalize_with(dir, &cwd) {
|
||||||
|
if let Ok(path) = canonicalize_with(filename, dir_abs) {
|
||||||
|
return Ok(Some(path));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(None)
|
||||||
|
} else {
|
||||||
|
Ok(None)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
Ok(None)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
Ok(None)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
let lib_dirs = dirs_var.and_then(|dirs_var| engine_state.find_constant(dirs_var, &[]));
|
|
||||||
// TODO: remove (see #8310)
|
|
||||||
let lib_dirs_fallback = stack.get_env_var(engine_state, "NU_LIB_DIRS");
|
|
||||||
let lib_dirs = lib_dirs.or(lib_dirs_fallback.as_ref())?;
|
|
||||||
|
|
||||||
lib_dirs
|
|
||||||
.as_list()
|
|
||||||
.ok()?
|
|
||||||
.iter()
|
|
||||||
.map(|lib_dir| -> Option<PathBuf> {
|
|
||||||
let dir = lib_dir.as_path().ok()?;
|
|
||||||
let dir_abs = canonicalize_with(dir, &cwd).ok()?;
|
|
||||||
canonicalize_with(filename, dir_abs).ok()
|
|
||||||
})
|
|
||||||
.find(Option::is_some)
|
|
||||||
.flatten()
|
|
||||||
})())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_converted_value(
|
fn get_converted_value(
|
||||||
|
|
|
@ -828,7 +828,7 @@ pub fn eval_element_with_input(
|
||||||
],
|
],
|
||||||
redirect_stdout: false,
|
redirect_stdout: false,
|
||||||
redirect_stderr: false,
|
redirect_stderr: false,
|
||||||
parser_info: HashMap::new(),
|
parser_info: vec![],
|
||||||
},
|
},
|
||||||
input,
|
input,
|
||||||
)
|
)
|
||||||
|
@ -899,7 +899,7 @@ pub fn eval_element_with_input(
|
||||||
],
|
],
|
||||||
redirect_stdout: false,
|
redirect_stdout: false,
|
||||||
redirect_stderr: false,
|
redirect_stderr: false,
|
||||||
parser_info: HashMap::new(),
|
parser_info: vec![],
|
||||||
},
|
},
|
||||||
input,
|
input,
|
||||||
)
|
)
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
use log::trace;
|
use log::trace;
|
||||||
use nu_engine::get_dirs_var_from_call;
|
|
||||||
use nu_path::canonicalize_with;
|
use nu_path::canonicalize_with;
|
||||||
use nu_protocol::{
|
use nu_protocol::{
|
||||||
ast::{
|
ast::{
|
||||||
|
@ -8,14 +7,13 @@ use nu_protocol::{
|
||||||
},
|
},
|
||||||
engine::{StateWorkingSet, DEFAULT_OVERLAY_NAME},
|
engine::{StateWorkingSet, DEFAULT_OVERLAY_NAME},
|
||||||
span, Alias, BlockId, Exportable, Module, PositionalArg, Span, Spanned, SyntaxShape, Type,
|
span, Alias, BlockId, Exportable, Module, PositionalArg, Span, Spanned, SyntaxShape, Type,
|
||||||
VarId,
|
|
||||||
};
|
};
|
||||||
use std::collections::{HashMap, HashSet};
|
use std::collections::HashSet;
|
||||||
use std::path::{Path, PathBuf};
|
use std::path::{Path, PathBuf};
|
||||||
|
|
||||||
pub const LIB_DIRS_VAR: &str = "NU_LIB_DIRS";
|
static LIB_DIRS_ENV: &str = "NU_LIB_DIRS";
|
||||||
#[cfg(feature = "plugin")]
|
#[cfg(feature = "plugin")]
|
||||||
pub const PLUGIN_DIRS_VAR: &str = "NU_PLUGIN_DIRS";
|
static PLUGIN_DIRS_ENV: &str = "NU_PLUGIN_DIRS";
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
eval::{eval_constant, value_as_string},
|
eval::{eval_constant, value_as_string},
|
||||||
|
@ -964,7 +962,7 @@ pub fn parse_old_alias(
|
||||||
decl_id,
|
decl_id,
|
||||||
redirect_stdout: true,
|
redirect_stdout: true,
|
||||||
redirect_stderr: false,
|
redirect_stderr: false,
|
||||||
parser_info: HashMap::new(),
|
parser_info: vec![],
|
||||||
}));
|
}));
|
||||||
return (
|
return (
|
||||||
Pipeline::from_vec(vec![Expression {
|
Pipeline::from_vec(vec![Expression {
|
||||||
|
@ -1265,7 +1263,7 @@ pub fn parse_export_in_module(
|
||||||
arguments: vec![],
|
arguments: vec![],
|
||||||
redirect_stdout: true,
|
redirect_stdout: true,
|
||||||
redirect_stderr: false,
|
redirect_stderr: false,
|
||||||
parser_info: HashMap::new(),
|
parser_info: vec![],
|
||||||
});
|
});
|
||||||
|
|
||||||
let exportables = if let Some(kw_span) = spans.get(1) {
|
let exportables = if let Some(kw_span) = spans.get(1) {
|
||||||
|
@ -2089,7 +2087,7 @@ pub fn parse_module(
|
||||||
],
|
],
|
||||||
redirect_stdout: true,
|
redirect_stdout: true,
|
||||||
redirect_stderr: false,
|
redirect_stderr: false,
|
||||||
parser_info: HashMap::new(),
|
parser_info: vec![],
|
||||||
});
|
});
|
||||||
|
|
||||||
(
|
(
|
||||||
|
@ -2231,12 +2229,9 @@ pub fn parse_use(
|
||||||
unescape_unquote_string(&import_pattern.head.name, import_pattern.head.span);
|
unescape_unquote_string(&import_pattern.head.name, import_pattern.head.span);
|
||||||
|
|
||||||
if err.is_none() {
|
if err.is_none() {
|
||||||
if let Some(module_path) = find_in_dirs_with_id(
|
if let Some(module_path) =
|
||||||
&module_filename,
|
find_in_dirs(&module_filename, working_set, &cwd, LIB_DIRS_ENV)
|
||||||
working_set,
|
{
|
||||||
&cwd,
|
|
||||||
get_dirs_var_from_call(&call),
|
|
||||||
) {
|
|
||||||
if let Some(i) = working_set
|
if let Some(i) = working_set
|
||||||
.parsed_module_files
|
.parsed_module_files
|
||||||
.iter()
|
.iter()
|
||||||
|
@ -2449,7 +2444,7 @@ pub fn parse_use(
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut call = call;
|
let mut call = call;
|
||||||
call.set_parser_info("import_pattern".to_string(), import_pattern_expr);
|
call.add_parser_info(import_pattern_expr);
|
||||||
|
|
||||||
(
|
(
|
||||||
Pipeline::from_vec(vec![Expression {
|
Pipeline::from_vec(vec![Expression {
|
||||||
|
@ -2670,7 +2665,7 @@ pub fn parse_hide(
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut call = call;
|
let mut call = call;
|
||||||
call.set_parser_info("import_pattern".to_string(), import_pattern_expr);
|
call.add_parser_info(import_pattern_expr);
|
||||||
|
|
||||||
(
|
(
|
||||||
Pipeline::from_vec(vec![Expression {
|
Pipeline::from_vec(vec![Expression {
|
||||||
|
@ -2894,12 +2889,9 @@ pub fn parse_overlay_use(
|
||||||
if let Ok(module_filename) =
|
if let Ok(module_filename) =
|
||||||
String::from_utf8(trim_quotes(overlay_name.as_bytes()).to_vec())
|
String::from_utf8(trim_quotes(overlay_name.as_bytes()).to_vec())
|
||||||
{
|
{
|
||||||
if let Some(module_path) = find_in_dirs_with_id(
|
if let Some(module_path) =
|
||||||
&module_filename,
|
find_in_dirs(&module_filename, working_set, &cwd, LIB_DIRS_ENV)
|
||||||
working_set,
|
{
|
||||||
&cwd,
|
|
||||||
get_dirs_var_from_call(&call),
|
|
||||||
) {
|
|
||||||
let overlay_name = if let Some(stem) = module_path.file_stem() {
|
let overlay_name = if let Some(stem) = module_path.file_stem() {
|
||||||
stem.to_string_lossy().to_string()
|
stem.to_string_lossy().to_string()
|
||||||
} else {
|
} else {
|
||||||
|
@ -2990,19 +2982,16 @@ pub fn parse_overlay_use(
|
||||||
|
|
||||||
// Change the call argument to include the Overlay expression with the module ID
|
// Change the call argument to include the Overlay expression with the module ID
|
||||||
let mut call = call;
|
let mut call = call;
|
||||||
call.set_parser_info(
|
call.add_parser_info(Expression {
|
||||||
"overlay_expr".to_string(),
|
expr: Expr::Overlay(if is_module_updated {
|
||||||
Expression {
|
Some(origin_module_id)
|
||||||
expr: Expr::Overlay(if is_module_updated {
|
} else {
|
||||||
Some(origin_module_id)
|
None
|
||||||
} else {
|
}),
|
||||||
None
|
span: overlay_name_span,
|
||||||
}),
|
ty: Type::Any,
|
||||||
span: overlay_name_span,
|
custom_completion: None,
|
||||||
ty: Type::Any,
|
});
|
||||||
custom_completion: None,
|
|
||||||
},
|
|
||||||
);
|
|
||||||
|
|
||||||
let pipeline = Pipeline::from_vec(vec![Expression {
|
let pipeline = Pipeline::from_vec(vec![Expression {
|
||||||
expr: Expr::Call(call),
|
expr: Expr::Call(call),
|
||||||
|
@ -3171,7 +3160,7 @@ pub fn parse_let_or_const(
|
||||||
],
|
],
|
||||||
redirect_stdout: true,
|
redirect_stdout: true,
|
||||||
redirect_stderr: false,
|
redirect_stderr: false,
|
||||||
parser_info: HashMap::new(),
|
parser_info: vec![],
|
||||||
});
|
});
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
@ -3293,7 +3282,7 @@ pub fn parse_mut(
|
||||||
],
|
],
|
||||||
redirect_stdout: true,
|
redirect_stdout: true,
|
||||||
redirect_stderr: false,
|
redirect_stderr: false,
|
||||||
parser_info: HashMap::new(),
|
parser_info: vec![],
|
||||||
});
|
});
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
@ -3422,7 +3411,7 @@ pub fn parse_source(
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
if let Some(path) = find_in_dirs(&filename, working_set, &cwd, LIB_DIRS_VAR) {
|
if let Some(path) = find_in_dirs(&filename, working_set, &cwd, LIB_DIRS_ENV) {
|
||||||
if let Ok(contents) = std::fs::read(&path) {
|
if let Ok(contents) = std::fs::read(&path) {
|
||||||
// Change currently parsed directory
|
// Change currently parsed directory
|
||||||
let prev_currently_parsed_cwd = if let Some(parent) = path.parent() {
|
let prev_currently_parsed_cwd = if let Some(parent) = path.parent() {
|
||||||
|
@ -3468,15 +3457,12 @@ pub fn parse_source(
|
||||||
|
|
||||||
// FIXME: Adding this expression to the positional creates a syntax highlighting error
|
// FIXME: Adding this expression to the positional creates a syntax highlighting error
|
||||||
// after writing `source example.nu`
|
// after writing `source example.nu`
|
||||||
call_with_block.set_parser_info(
|
call_with_block.add_parser_info(Expression {
|
||||||
"block_id".to_string(),
|
expr: Expr::Int(block_id as i64),
|
||||||
Expression {
|
span: spans[1],
|
||||||
expr: Expr::Int(block_id as i64),
|
ty: Type::Any,
|
||||||
span: spans[1],
|
custom_completion: None,
|
||||||
ty: Type::Any,
|
});
|
||||||
custom_completion: None,
|
|
||||||
},
|
|
||||||
);
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
Pipeline::from_vec(vec![Expression {
|
Pipeline::from_vec(vec![Expression {
|
||||||
|
@ -3686,7 +3672,7 @@ pub fn parse_register(
|
||||||
if let Some(err) = err {
|
if let Some(err) = err {
|
||||||
Err(err)
|
Err(err)
|
||||||
} else {
|
} else {
|
||||||
let path = if let Some(p) = find_in_dirs(&name, working_set, &cwd, PLUGIN_DIRS_VAR)
|
let path = if let Some(p) = find_in_dirs(&name, working_set, &cwd, PLUGIN_DIRS_ENV)
|
||||||
{
|
{
|
||||||
p
|
p
|
||||||
} else {
|
} else {
|
||||||
|
@ -3831,67 +3817,12 @@ pub fn parse_register(
|
||||||
/// a) the directory of a file currently being parsed
|
/// a) the directory of a file currently being parsed
|
||||||
/// b) current working directory (PWD)
|
/// b) current working directory (PWD)
|
||||||
///
|
///
|
||||||
/// Then, if the file is not found in the actual cwd, dirs_var is checked.
|
/// Then, if the file is not found in the actual cwd, NU_LIB_DIRS is checked.
|
||||||
/// If dirs_var is an Expr::Var, then we look for a const with that VarId,
|
/// If there is a relative path in NU_LIB_DIRS, it is assumed to be relative to the actual cwd
|
||||||
/// and if dirs_var is an Expr::String, then we look for an environment with that name.
|
|
||||||
/// If there is a relative path in dirs_var, it is assumed to be relative to the actual cwd
|
|
||||||
/// determined in the first step.
|
/// determined in the first step.
|
||||||
///
|
///
|
||||||
/// Always returns an absolute path
|
/// Always returns an absolute path
|
||||||
pub fn find_in_dirs_with_id(
|
|
||||||
filename: &str,
|
|
||||||
working_set: &StateWorkingSet,
|
|
||||||
cwd: &str,
|
|
||||||
dirs_var_id: Option<VarId>,
|
|
||||||
) -> Option<PathBuf> {
|
|
||||||
// Choose whether to use file-relative or PWD-relative path
|
|
||||||
let actual_cwd = if let Some(currently_parsed_cwd) = &working_set.currently_parsed_cwd {
|
|
||||||
currently_parsed_cwd.as_path()
|
|
||||||
} else {
|
|
||||||
Path::new(cwd)
|
|
||||||
};
|
|
||||||
if let Ok(p) = canonicalize_with(filename, actual_cwd) {
|
|
||||||
return Some(p);
|
|
||||||
}
|
|
||||||
|
|
||||||
let path = Path::new(filename);
|
|
||||||
if !path.is_relative() {
|
|
||||||
return None;
|
|
||||||
}
|
|
||||||
|
|
||||||
working_set
|
|
||||||
.find_constant(dirs_var_id?)?
|
|
||||||
.as_list()
|
|
||||||
.ok()?
|
|
||||||
.iter()
|
|
||||||
.map(|lib_dir| -> Option<PathBuf> {
|
|
||||||
let dir = lib_dir.as_path().ok()?;
|
|
||||||
let dir_abs = canonicalize_with(dir, actual_cwd).ok()?;
|
|
||||||
canonicalize_with(filename, dir_abs).ok()
|
|
||||||
})
|
|
||||||
.find(Option::is_some)
|
|
||||||
.flatten()
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn find_dirs_var(working_set: &StateWorkingSet, var_name: &str) -> Option<VarId> {
|
|
||||||
working_set
|
|
||||||
.find_variable(format!("${}", var_name).as_bytes())
|
|
||||||
.filter(|var_id| working_set.find_constant(*var_id).is_some())
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn find_in_dirs(
|
pub fn find_in_dirs(
|
||||||
filename: &str,
|
|
||||||
working_set: &StateWorkingSet,
|
|
||||||
cwd: &str,
|
|
||||||
dirs_var_name: &str,
|
|
||||||
) -> Option<PathBuf> {
|
|
||||||
find_dirs_var(working_set, dirs_var_name)
|
|
||||||
.and_then(|var_id| find_in_dirs_with_id(filename, working_set, cwd, Some(var_id)))
|
|
||||||
.or_else(|| find_in_dirs_old(filename, working_set, cwd, dirs_var_name))
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: remove (see #8310)
|
|
||||||
pub fn find_in_dirs_old(
|
|
||||||
filename: &str,
|
filename: &str,
|
||||||
working_set: &StateWorkingSet,
|
working_set: &StateWorkingSet,
|
||||||
cwd: &str,
|
cwd: &str,
|
||||||
|
|
|
@ -7,7 +7,6 @@ use crate::{
|
||||||
ParseError, Token, TokenContents,
|
ParseError, Token, TokenContents,
|
||||||
};
|
};
|
||||||
|
|
||||||
use nu_engine::DIR_VAR_PARSER_INFO;
|
|
||||||
use nu_protocol::{
|
use nu_protocol::{
|
||||||
ast::{
|
ast::{
|
||||||
Argument, Assignment, Bits, Block, Boolean, Call, CellPath, Comparison, Expr, Expression,
|
Argument, Assignment, Bits, Block, Boolean, Call, CellPath, Comparison, Expr, Expression,
|
||||||
|
@ -20,10 +19,10 @@ use nu_protocol::{
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::parse_keywords::{
|
use crate::parse_keywords::{
|
||||||
find_dirs_var, is_unaliasable_parser_keyword, parse_alias, parse_def, parse_def_predecl,
|
is_unaliasable_parser_keyword, parse_alias, parse_def, parse_def_predecl,
|
||||||
parse_export_in_block, parse_extern, parse_for, parse_hide, parse_keyword, parse_let_or_const,
|
parse_export_in_block, parse_extern, parse_for, parse_hide, parse_keyword, parse_let_or_const,
|
||||||
parse_module, parse_old_alias, parse_overlay_hide, parse_overlay_new, parse_overlay_use,
|
parse_module, parse_old_alias, parse_overlay_hide, parse_overlay_new, parse_overlay_use,
|
||||||
parse_source, parse_use, parse_where, parse_where_expr, LIB_DIRS_VAR,
|
parse_source, parse_use, parse_where, parse_where_expr,
|
||||||
};
|
};
|
||||||
|
|
||||||
use itertools::Itertools;
|
use itertools::Itertools;
|
||||||
|
@ -803,25 +802,6 @@ pub struct ParsedInternalCall {
|
||||||
pub error: Option<ParseError>,
|
pub error: Option<ParseError>,
|
||||||
}
|
}
|
||||||
|
|
||||||
fn attach_parser_info_builtin(working_set: &StateWorkingSet, name: &str, call: &mut Call) {
|
|
||||||
match name {
|
|
||||||
"use" | "overlay use" | "source-env" | "nu-check" => {
|
|
||||||
if let Some(var_id) = find_dirs_var(working_set, LIB_DIRS_VAR) {
|
|
||||||
call.set_parser_info(
|
|
||||||
DIR_VAR_PARSER_INFO.to_owned(),
|
|
||||||
Expression {
|
|
||||||
expr: Expr::Var(var_id),
|
|
||||||
span: call.head,
|
|
||||||
ty: Type::Any,
|
|
||||||
custom_completion: None,
|
|
||||||
},
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
_ => {}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn parse_internal_call(
|
pub fn parse_internal_call(
|
||||||
working_set: &mut StateWorkingSet,
|
working_set: &mut StateWorkingSet,
|
||||||
command_span: Span,
|
command_span: Span,
|
||||||
|
@ -841,10 +821,6 @@ pub fn parse_internal_call(
|
||||||
let signature = decl.signature();
|
let signature = decl.signature();
|
||||||
let output = signature.output_type.clone();
|
let output = signature.output_type.clone();
|
||||||
|
|
||||||
if decl.is_builtin() {
|
|
||||||
attach_parser_info_builtin(working_set, decl.name(), &mut call);
|
|
||||||
}
|
|
||||||
|
|
||||||
// The index into the positional parameter in the definition
|
// The index into the positional parameter in the definition
|
||||||
let mut positional_idx = 0;
|
let mut positional_idx = 0;
|
||||||
|
|
||||||
|
@ -5370,7 +5346,7 @@ pub fn parse_expression(
|
||||||
arguments,
|
arguments,
|
||||||
redirect_stdout: true,
|
redirect_stdout: true,
|
||||||
redirect_stderr: false,
|
redirect_stderr: false,
|
||||||
parser_info: HashMap::new(),
|
parser_info: vec![],
|
||||||
}));
|
}));
|
||||||
|
|
||||||
(
|
(
|
||||||
|
@ -6216,7 +6192,7 @@ fn wrap_expr_with_collect(working_set: &mut StateWorkingSet, expr: &Expression)
|
||||||
decl_id,
|
decl_id,
|
||||||
redirect_stdout: true,
|
redirect_stdout: true,
|
||||||
redirect_stderr: false,
|
redirect_stderr: false,
|
||||||
parser_info: HashMap::new(),
|
parser_info: vec![],
|
||||||
})),
|
})),
|
||||||
span,
|
span,
|
||||||
ty: Type::String,
|
ty: Type::String,
|
||||||
|
|
|
@ -1,5 +1,3 @@
|
||||||
use std::collections::HashMap;
|
|
||||||
|
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
use super::Expression;
|
use super::Expression;
|
||||||
|
@ -21,7 +19,7 @@ pub struct Call {
|
||||||
pub redirect_stdout: bool,
|
pub redirect_stdout: bool,
|
||||||
pub redirect_stderr: bool,
|
pub redirect_stderr: bool,
|
||||||
/// this field is used by the parser to pass additional command-specific information
|
/// this field is used by the parser to pass additional command-specific information
|
||||||
pub parser_info: HashMap<String, Expression>,
|
pub parser_info: Vec<Expression>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Call {
|
impl Call {
|
||||||
|
@ -32,7 +30,7 @@ impl Call {
|
||||||
arguments: vec![],
|
arguments: vec![],
|
||||||
redirect_stdout: true,
|
redirect_stdout: true,
|
||||||
redirect_stderr: false,
|
redirect_stderr: false,
|
||||||
parser_info: HashMap::new(),
|
parser_info: vec![],
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -72,6 +70,10 @@ impl Call {
|
||||||
self.arguments.push(Argument::Positional(positional));
|
self.arguments.push(Argument::Positional(positional));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn add_parser_info(&mut self, info: Expression) {
|
||||||
|
self.parser_info.push(info);
|
||||||
|
}
|
||||||
|
|
||||||
pub fn add_unknown(&mut self, unknown: Expression) {
|
pub fn add_unknown(&mut self, unknown: Expression) {
|
||||||
self.arguments.push(Argument::Unknown(unknown));
|
self.arguments.push(Argument::Unknown(unknown));
|
||||||
}
|
}
|
||||||
|
@ -104,12 +106,8 @@ impl Call {
|
||||||
self.positional_iter().count()
|
self.positional_iter().count()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_parser_info(&self, name: &str) -> Option<&Expression> {
|
pub fn parser_info_nth(&self, i: usize) -> Option<&Expression> {
|
||||||
self.parser_info.get(name)
|
self.parser_info.get(i)
|
||||||
}
|
|
||||||
|
|
||||||
pub fn set_parser_info(&mut self, name: String, val: Expression) -> Option<Expression> {
|
|
||||||
self.parser_info.insert(name, val)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn has_flag(&self, flag_name: &str) -> bool {
|
pub fn has_flag(&self, flag_name: &str) -> bool {
|
||||||
|
|
|
@ -140,34 +140,6 @@ fn nu_lib_dirs_relative_repl() {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: add absolute path tests after we expand const capabilities (see #8310)
|
|
||||||
#[test]
|
|
||||||
fn const_nu_lib_dirs_relative() {
|
|
||||||
Playground::setup("const_nu_lib_dirs_relative", |dirs, sandbox| {
|
|
||||||
sandbox
|
|
||||||
.mkdir("scripts")
|
|
||||||
.with_files(vec![FileWithContentToBeTrimmed(
|
|
||||||
"scripts/foo.nu",
|
|
||||||
r#"
|
|
||||||
let-env FOO = "foo"
|
|
||||||
"#,
|
|
||||||
)])
|
|
||||||
.with_files(vec![FileWithContentToBeTrimmed(
|
|
||||||
"main.nu",
|
|
||||||
r#"
|
|
||||||
const NU_LIB_DIRS = [ 'scripts' ]
|
|
||||||
source-env foo.nu
|
|
||||||
$env.FOO
|
|
||||||
"#,
|
|
||||||
)]);
|
|
||||||
|
|
||||||
let outcome = nu!(cwd: dirs.test(), "source main.nu");
|
|
||||||
|
|
||||||
assert!(outcome.err.is_empty());
|
|
||||||
assert_eq!(outcome.out, "foo");
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn nu_lib_dirs_relative_script() {
|
fn nu_lib_dirs_relative_script() {
|
||||||
Playground::setup("nu_lib_dirs_relative_script", |dirs, sandbox| {
|
Playground::setup("nu_lib_dirs_relative_script", |dirs, sandbox| {
|
||||||
|
|
Loading…
Reference in a new issue