mirror of
https://github.com/nushell/nushell
synced 2025-01-13 13:49:21 +00:00
Add support for math-like externals (#4606)
This commit is contained in:
parent
d054a724d1
commit
25712760ba
7 changed files with 63 additions and 4 deletions
1
Cargo.lock
generated
1
Cargo.lock
generated
|
@ -2100,6 +2100,7 @@ dependencies = [
|
||||||
"crossterm_winapi",
|
"crossterm_winapi",
|
||||||
"ctrlc",
|
"ctrlc",
|
||||||
"hamcrest2",
|
"hamcrest2",
|
||||||
|
"is_executable",
|
||||||
"itertools",
|
"itertools",
|
||||||
"log",
|
"log",
|
||||||
"miette",
|
"miette",
|
||||||
|
|
|
@ -54,6 +54,8 @@ nu-term-grid = { path = "./crates/nu-term-grid", version = "0.59.0" }
|
||||||
pretty_env_logger = "0.4.0"
|
pretty_env_logger = "0.4.0"
|
||||||
rayon = "1.5.1"
|
rayon = "1.5.1"
|
||||||
reedline = { git = "https://github.com/nushell/reedline", branch = "main" }
|
reedline = { git = "https://github.com/nushell/reedline", branch = "main" }
|
||||||
|
is_executable = "1.0.1"
|
||||||
|
|
||||||
# mimalloc = { version = "*", default-features = false }
|
# mimalloc = { version = "*", default-features = false }
|
||||||
|
|
||||||
# Plugins
|
# Plugins
|
||||||
|
|
|
@ -13,7 +13,9 @@ pub use known_external::KnownExternal;
|
||||||
pub use lex::{lex, Token, TokenContents};
|
pub use lex::{lex, Token, TokenContents};
|
||||||
pub use lite_parse::{lite_parse, LiteBlock};
|
pub use lite_parse::{lite_parse, LiteBlock};
|
||||||
|
|
||||||
pub use parser::{parse, parse_block, parse_external_call, trim_quotes, Import};
|
pub use parser::{
|
||||||
|
is_math_expression_like, parse, parse_block, parse_external_call, trim_quotes, Import,
|
||||||
|
};
|
||||||
|
|
||||||
#[cfg(feature = "plugin")]
|
#[cfg(feature = "plugin")]
|
||||||
pub use parse_keywords::parse_register;
|
pub use parse_keywords::parse_register;
|
||||||
|
|
|
@ -41,7 +41,13 @@ fn is_identifier_byte(b: u8) -> bool {
|
||||||
b != b'.' && b != b'[' && b != b'(' && b != b'{'
|
b != b'.' && b != b'[' && b != b'(' && b != b'{'
|
||||||
}
|
}
|
||||||
|
|
||||||
fn is_math_expression_byte(b: u8) -> bool {
|
pub fn is_math_expression_like(bytes: &[u8]) -> bool {
|
||||||
|
if bytes.is_empty() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
let b = bytes[0];
|
||||||
|
|
||||||
b == b'0'
|
b == b'0'
|
||||||
|| b == b'1'
|
|| b == b'1'
|
||||||
|| b == b'2'
|
|| b == b'2'
|
||||||
|
@ -826,7 +832,13 @@ pub fn parse_call(
|
||||||
// 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);
|
let bytes = working_set.get_span_contents(*word_span);
|
||||||
|
|
||||||
if is_math_expression_byte(bytes[0]) {
|
if is_math_expression_like(bytes)
|
||||||
|
&& !working_set
|
||||||
|
.permanent_state
|
||||||
|
.external_exceptions
|
||||||
|
.iter()
|
||||||
|
.any(|x| x == bytes)
|
||||||
|
{
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3446,7 +3458,13 @@ pub fn parse_expression(
|
||||||
|
|
||||||
let bytes = working_set.get_span_contents(spans[pos]);
|
let bytes = working_set.get_span_contents(spans[pos]);
|
||||||
|
|
||||||
let (output, err) = if is_math_expression_byte(bytes[0]) {
|
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)
|
parse_math_expression(working_set, &spans[pos..], None)
|
||||||
} else {
|
} else {
|
||||||
// For now, check for special parses of certain keywords
|
// For now, check for special parses of certain keywords
|
||||||
|
|
|
@ -169,6 +169,9 @@ 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;
|
||||||
|
@ -199,6 +202,7 @@ 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![],
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -633,6 +637,7 @@ impl Default for EngineState {
|
||||||
pub struct StateWorkingSet<'a> {
|
pub struct StateWorkingSet<'a> {
|
||||||
pub permanent_state: &'a EngineState,
|
pub permanent_state: &'a EngineState,
|
||||||
pub delta: StateDelta,
|
pub delta: StateDelta,
|
||||||
|
pub external_commands: Vec<Vec<u8>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A delta (or change set) between the current global state and a possible future global state. Deltas
|
/// A delta (or change set) between the current global state and a possible future global state. Deltas
|
||||||
|
@ -707,6 +712,7 @@ impl<'a> StateWorkingSet<'a> {
|
||||||
Self {
|
Self {
|
||||||
delta: StateDelta::new(),
|
delta: StateDelta::new(),
|
||||||
permanent_state,
|
permanent_state,
|
||||||
|
external_commands: vec![],
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -57,6 +57,10 @@ fn main() -> Result<()> {
|
||||||
};
|
};
|
||||||
let _ = engine_state.merge_delta(delta, None, &init_cwd);
|
let _ = engine_state.merge_delta(delta, None, &init_cwd);
|
||||||
|
|
||||||
|
// Make a note of the exceptions we see for externals that look like math expressions
|
||||||
|
let exceptions = crate::utils::external_exceptions();
|
||||||
|
engine_state.external_exceptions = exceptions;
|
||||||
|
|
||||||
// TODO: make this conditional in the future
|
// TODO: make this conditional in the future
|
||||||
// Ctrl-c protection section
|
// Ctrl-c protection section
|
||||||
let ctrlc = Arc::new(AtomicBool::new(false));
|
let ctrlc = Arc::new(AtomicBool::new(false));
|
||||||
|
|
26
src/utils.rs
26
src/utils.rs
|
@ -254,6 +254,32 @@ pub(crate) fn eval_source(
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Finds externals that have names that look like math expressions
|
||||||
|
pub fn external_exceptions() -> Vec<Vec<u8>> {
|
||||||
|
let mut executables = vec![];
|
||||||
|
|
||||||
|
if let Ok(path) = std::env::var("PATH") {
|
||||||
|
for path in std::env::split_paths(&path) {
|
||||||
|
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() {
|
||||||
|
let name = name.as_bytes().to_vec();
|
||||||
|
if nu_parser::is_math_expression_like(&name) {
|
||||||
|
executables.push(name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
executables
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(windows)]
|
#[cfg(windows)]
|
||||||
pub fn enable_vt_processing() -> Result<(), ShellError> {
|
pub fn enable_vt_processing() -> Result<(), ShellError> {
|
||||||
use crossterm_winapi::{ConsoleMode, Handle};
|
use crossterm_winapi::{ConsoleMode, Handle};
|
||||||
|
|
Loading…
Reference in a new issue