mirror of
https://github.com/nushell/nushell
synced 2025-01-15 14:44:14 +00:00
Remove external name exceptions (#5115)
This commit is contained in:
parent
591fb4bd36
commit
ef1934a7ee
6 changed files with 45 additions and 147 deletions
|
@ -56,10 +56,6 @@ pub fn evaluate_commands(
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// Make a note of the exceptions we see for externals that look like math expressions
|
|
||||||
let exceptions = crate::util::external_exceptions(engine_state, stack);
|
|
||||||
engine_state.external_exceptions = exceptions;
|
|
||||||
|
|
||||||
// Merge the delta in case env vars changed in the config
|
// Merge the delta in case env vars changed in the config
|
||||||
match nu_engine::env::current_dir(engine_state, stack) {
|
match nu_engine::env::current_dir(engine_state, stack) {
|
||||||
Ok(cwd) => {
|
Ok(cwd) => {
|
||||||
|
|
|
@ -27,10 +27,6 @@ pub fn evaluate_file(
|
||||||
std::process::exit(1);
|
std::process::exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Make a note of the exceptions we see for externals that look like math expressions
|
|
||||||
let exceptions = crate::util::external_exceptions(engine_state, stack);
|
|
||||||
engine_state.external_exceptions = exceptions;
|
|
||||||
|
|
||||||
let file = std::fs::read(&path).into_diagnostic()?;
|
let file = std::fs::read(&path).into_diagnostic()?;
|
||||||
|
|
||||||
let mut working_set = StateWorkingSet::new(engine_state);
|
let mut working_set = StateWorkingSet::new(engine_state);
|
||||||
|
|
|
@ -83,10 +83,6 @@ pub fn evaluate_repl(
|
||||||
report_error(&working_set, &e);
|
report_error(&working_set, &e);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Make a note of the exceptions we see for externals that look like math expressions
|
|
||||||
let exceptions = crate::util::external_exceptions(engine_state, stack);
|
|
||||||
engine_state.external_exceptions = exceptions;
|
|
||||||
|
|
||||||
// seed env vars
|
// seed env vars
|
||||||
stack.add_env_var(
|
stack.add_env_var(
|
||||||
"CMD_DURATION_MS".into(),
|
"CMD_DURATION_MS".into(),
|
||||||
|
@ -356,10 +352,6 @@ pub fn evaluate_repl(
|
||||||
let _ = std::env::set_current_dir(path);
|
let _ = std::env::set_current_dir(path);
|
||||||
engine_state.env_vars.insert("PWD".into(), cwd);
|
engine_state.env_vars.insert("PWD".into(), cwd);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Make a note of the exceptions we see for externals that look like math expressions
|
|
||||||
let exceptions = crate::util::external_exceptions(engine_state, stack);
|
|
||||||
engine_state.external_exceptions = exceptions;
|
|
||||||
}
|
}
|
||||||
Ok(Signal::CtrlC) => {
|
Ok(Signal::CtrlC) => {
|
||||||
// `Reedline` clears the line content. New prompt is shown
|
// `Reedline` clears the line content. New prompt is shown
|
||||||
|
|
|
@ -326,98 +326,6 @@ fn set_last_exit_code(stack: &mut Stack, exit_code: i64) {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn seems_like_number(bytes: &[u8]) -> bool {
|
|
||||||
if bytes.is_empty() {
|
|
||||||
false
|
|
||||||
} else {
|
|
||||||
let b = bytes[0];
|
|
||||||
|
|
||||||
b == b'0'
|
|
||||||
|| b == b'1'
|
|
||||||
|| b == b'2'
|
|
||||||
|| b == b'3'
|
|
||||||
|| b == b'4'
|
|
||||||
|| b == b'5'
|
|
||||||
|| b == b'6'
|
|
||||||
|| b == b'7'
|
|
||||||
|| b == b'8'
|
|
||||||
|| b == b'9'
|
|
||||||
|| b == b'('
|
|
||||||
|| b == b'{'
|
|
||||||
|| b == b'['
|
|
||||||
|| b == b'$'
|
|
||||||
|| b == b'"'
|
|
||||||
|| b == b'\''
|
|
||||||
|| b == b'-'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Finds externals that have names that look like math expressions
|
|
||||||
pub fn external_exceptions(engine_state: &EngineState, stack: &Stack) -> Vec<Vec<u8>> {
|
|
||||||
let mut executables = vec![];
|
|
||||||
|
|
||||||
if let Some(path) = stack.get_env_var(engine_state, "PATH") {
|
|
||||||
match path {
|
|
||||||
Value::List { vals, .. } => {
|
|
||||||
for val in vals {
|
|
||||||
let path = val.as_string();
|
|
||||||
|
|
||||||
if let Ok(path) = path {
|
|
||||||
if let Ok(mut contents) = std::fs::read_dir(path) {
|
|
||||||
while let Some(Ok(item)) = contents.next() {
|
|
||||||
if is_executable::is_executable(&item.path()) {
|
|
||||||
if let Ok(name) = item.file_name().into_string() {
|
|
||||||
if seems_like_number(name.as_bytes()) {
|
|
||||||
let name = name.as_bytes().to_vec();
|
|
||||||
executables.push(name);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if let Some(name) = item.path().file_stem() {
|
|
||||||
let name = name.to_string_lossy();
|
|
||||||
if seems_like_number(name.as_bytes()) {
|
|
||||||
let name = name.as_bytes().to_vec();
|
|
||||||
executables.push(name);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Value::String { val, .. } => {
|
|
||||||
for path in std::env::split_paths(&val) {
|
|
||||||
let path = path.to_string_lossy().to_string();
|
|
||||||
|
|
||||||
if let Ok(mut contents) = std::fs::read_dir(path) {
|
|
||||||
while let Some(Ok(item)) = contents.next() {
|
|
||||||
if is_executable::is_executable(&item.path()) {
|
|
||||||
if let Ok(name) = item.file_name().into_string() {
|
|
||||||
if seems_like_number(name.as_bytes()) {
|
|
||||||
let name = name.as_bytes().to_vec();
|
|
||||||
executables.push(name);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if let Some(name) = item.path().file_stem() {
|
|
||||||
let name = name.to_string_lossy();
|
|
||||||
if seems_like_number(name.as_bytes()) {
|
|
||||||
let name = name.as_bytes().to_vec();
|
|
||||||
executables.push(name);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
_ => {}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
executables
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn report_error(
|
pub fn report_error(
|
||||||
working_set: &StateWorkingSet,
|
working_set: &StateWorkingSet,
|
||||||
error: &(dyn miette::Diagnostic + Send + Sync + 'static),
|
error: &(dyn miette::Diagnostic + Send + Sync + 'static),
|
||||||
|
|
|
@ -44,7 +44,12 @@ fn is_identifier_byte(b: u8) -> bool {
|
||||||
b != b'.' && b != b'[' && b != b'(' && b != b'{'
|
b != b'.' && b != b'[' && b != b'(' && b != b'{'
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn is_math_expression_like(bytes: &[u8]) -> bool {
|
pub fn is_math_expression_like(
|
||||||
|
working_set: &mut StateWorkingSet,
|
||||||
|
span: Span,
|
||||||
|
expand_aliases_denylist: &[usize],
|
||||||
|
) -> bool {
|
||||||
|
let bytes = working_set.get_span_contents(span);
|
||||||
if bytes.is_empty() {
|
if bytes.is_empty() {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -55,17 +60,7 @@ pub fn is_math_expression_like(bytes: &[u8]) -> bool {
|
||||||
|
|
||||||
let b = bytes[0];
|
let b = bytes[0];
|
||||||
|
|
||||||
b == b'0'
|
if b == b'('
|
||||||
|| b == b'1'
|
|
||||||
|| b == b'2'
|
|
||||||
|| b == b'3'
|
|
||||||
|| b == b'4'
|
|
||||||
|| b == b'5'
|
|
||||||
|| b == b'6'
|
|
||||||
|| b == b'7'
|
|
||||||
|| b == b'8'
|
|
||||||
|| b == b'9'
|
|
||||||
|| b == b'('
|
|
||||||
|| b == b'{'
|
|| b == b'{'
|
||||||
|| b == b'['
|
|| b == b'['
|
||||||
|| b == b'$'
|
|| b == b'$'
|
||||||
|
@ -73,6 +68,34 @@ pub fn is_math_expression_like(bytes: &[u8]) -> bool {
|
||||||
|| b == b'\''
|
|| b == b'\''
|
||||||
|| b == b'`'
|
|| b == b'`'
|
||||||
|| b == b'-'
|
|| b == b'-'
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if parse_number(bytes, span).1.is_none() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if parse_filesize(working_set, span).1.is_none() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if parse_duration(working_set, span).1.is_none() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if parse_binary(working_set, span).1.is_none() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if parse_range(working_set, span, expand_aliases_denylist)
|
||||||
|
.1
|
||||||
|
.is_none()
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
false
|
||||||
}
|
}
|
||||||
|
|
||||||
fn is_identifier(bytes: &[u8]) -> bool {
|
fn is_identifier(bytes: &[u8]) -> bool {
|
||||||
|
@ -869,20 +892,12 @@ pub fn parse_call(
|
||||||
|
|
||||||
for word_span in spans[cmd_start..].iter() {
|
for word_span in spans[cmd_start..].iter() {
|
||||||
// Find the longest group of words that could form a command
|
// Find the longest group of words that could form a command
|
||||||
let bytes = working_set.get_span_contents(*word_span);
|
|
||||||
|
|
||||||
if is_math_expression_like(bytes)
|
if is_math_expression_like(working_set, *word_span, expand_aliases_denylist) {
|
||||||
&& bytes != b"true"
|
let bytes = working_set.get_span_contents(*word_span);
|
||||||
&& bytes != b"false"
|
if bytes != b"true" && bytes != b"false" && bytes != b"null" && bytes != b"not" {
|
||||||
&& bytes != b"null"
|
break;
|
||||||
&& bytes != b"not"
|
}
|
||||||
&& !working_set
|
|
||||||
.permanent_state
|
|
||||||
.external_exceptions
|
|
||||||
.iter()
|
|
||||||
.any(|x| x == bytes)
|
|
||||||
{
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
name_spans.push(*word_span);
|
name_spans.push(*word_span);
|
||||||
|
@ -1951,7 +1966,7 @@ pub fn parse_datetime(
|
||||||
|
|
||||||
/// Parse a duration type, eg '10day'
|
/// Parse a duration type, eg '10day'
|
||||||
pub fn parse_duration(
|
pub fn parse_duration(
|
||||||
working_set: &mut StateWorkingSet,
|
working_set: &StateWorkingSet,
|
||||||
span: Span,
|
span: Span,
|
||||||
) -> (Expression, Option<ParseError>) {
|
) -> (Expression, Option<ParseError>) {
|
||||||
trace!("parsing: duration");
|
trace!("parsing: duration");
|
||||||
|
@ -2055,7 +2070,7 @@ pub fn parse_duration_bytes(bytes: &[u8], span: Span) -> Option<Expression> {
|
||||||
|
|
||||||
/// Parse a unit type, eg '10kb'
|
/// Parse a unit type, eg '10kb'
|
||||||
pub fn parse_filesize(
|
pub fn parse_filesize(
|
||||||
working_set: &mut StateWorkingSet,
|
working_set: &StateWorkingSet,
|
||||||
span: Span,
|
span: Span,
|
||||||
) -> (Expression, Option<ParseError>) {
|
) -> (Expression, Option<ParseError>) {
|
||||||
trace!("parsing: duration");
|
trace!("parsing: duration");
|
||||||
|
@ -4228,17 +4243,12 @@ pub fn parse_expression(
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
let bytes = working_set.get_span_contents(spans[pos]);
|
let (output, err) = if is_math_expression_like(working_set, spans[pos], expand_aliases_denylist)
|
||||||
|
|
||||||
let (output, err) = if is_math_expression_like(bytes)
|
|
||||||
&& !working_set
|
|
||||||
.permanent_state
|
|
||||||
.external_exceptions
|
|
||||||
.iter()
|
|
||||||
.any(|x| x == bytes)
|
|
||||||
{
|
{
|
||||||
parse_math_expression(working_set, &spans[pos..], None, expand_aliases_denylist)
|
parse_math_expression(working_set, &spans[pos..], None, expand_aliases_denylist)
|
||||||
} else {
|
} else {
|
||||||
|
let bytes = working_set.get_span_contents(spans[pos]);
|
||||||
|
|
||||||
// For now, check for special parses of certain keywords
|
// For now, check for special parses of certain keywords
|
||||||
match bytes {
|
match bytes {
|
||||||
b"def" => (
|
b"def" => (
|
||||||
|
|
|
@ -178,9 +178,6 @@ pub struct EngineState {
|
||||||
pub env_vars: im::HashMap<String, Value>,
|
pub env_vars: im::HashMap<String, Value>,
|
||||||
#[cfg(feature = "plugin")]
|
#[cfg(feature = "plugin")]
|
||||||
pub plugin_signatures: Option<PathBuf>,
|
pub plugin_signatures: Option<PathBuf>,
|
||||||
|
|
||||||
// A list of external commands that look like math expressions
|
|
||||||
pub external_exceptions: Vec<Vec<u8>>,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub const NU_VARIABLE_ID: usize = 0;
|
pub const NU_VARIABLE_ID: usize = 0;
|
||||||
|
@ -210,7 +207,6 @@ impl EngineState {
|
||||||
env_vars: im::HashMap::new(),
|
env_vars: im::HashMap::new(),
|
||||||
#[cfg(feature = "plugin")]
|
#[cfg(feature = "plugin")]
|
||||||
plugin_signatures: None,
|
plugin_signatures: None,
|
||||||
external_exceptions: vec![],
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue