diff --git a/.gitignore b/.gitignore index 1079f63b2353..4c234e523be3 100644 --- a/.gitignore +++ b/.gitignore @@ -17,3 +17,6 @@ debian/nu/ # JetBrains' IDE items .idea/* + +# VSCode's IDE items +.vscode/* diff --git a/Cargo.lock b/Cargo.lock index bb97240b86fa..e21eea5ce12a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2175,6 +2175,7 @@ dependencies = [ "quickcheck", "quickcheck_macros", "rand", + "rayon", "regex", "roxmltree", "rusqlite", @@ -2210,6 +2211,7 @@ dependencies = [ "bigdecimal", "derive-new", "getset", + "glob", "language-reporting", "nu-build", "nu-source", diff --git a/crates/nu-cli/Cargo.toml b/crates/nu-cli/Cargo.toml index 6368b7b815f5..ce33967d6543 100644 --- a/crates/nu-cli/Cargo.toml +++ b/crates/nu-cli/Cargo.toml @@ -89,6 +89,7 @@ which = "3" trash = { version = "1.0.0", optional = true } clipboard = { version = "0.5", optional = true } starship = { version = "0.39.0", optional = true } +rayon = "1.3.0" [target.'cfg(unix)'.dependencies] users = "0.10.0" diff --git a/crates/nu-cli/src/cli.rs b/crates/nu-cli/src/cli.rs index 5d3abb40df1b..82c911288220 100644 --- a/crates/nu-cli/src/cli.rs +++ b/crates/nu-cli/src/cli.rs @@ -26,6 +26,8 @@ use std::iter::Iterator; use std::path::{Path, PathBuf}; use std::sync::atomic::Ordering; +use rayon::prelude::*; + fn load_plugin(path: &std::path::Path, context: &mut Context) -> Result<(), ShellError> { let mut child = std::process::Command::new(path) .stdin(std::process::Stdio::piped()) @@ -132,58 +134,60 @@ pub fn load_plugins(context: &mut Context) -> Result<(), ShellError> { pattern.push(std::path::Path::new("nu_plugin_[a-z0-9][a-z0-9]*")); - match glob::glob_with(&pattern.to_string_lossy(), opts) { - Err(_) => {} - Ok(binaries) => { - for bin in binaries.filter_map(Result::ok) { - let bin_name = { - if let Some(name) = bin.file_name() { - match name.to_str() { - Some(raw) => raw, - None => continue, - } - } else { - continue; + let plugs: Vec<_> = glob::glob_with(&pattern.to_string_lossy(), opts)? + .filter_map(|x| x.ok()) + .collect(); + + let _failures: Vec<_> = plugs + .par_iter() + .map(|path| { + let bin_name = { + if let Some(name) = path.file_name() { + match name.to_str() { + Some(raw) => raw, + None => "", } - }; + } else { + "" + } + }; - let is_valid_name = { - #[cfg(windows)] - { - bin_name - .chars() - .all(|c| c.is_ascii_alphanumeric() || c == '_' || c == '.') - } + let is_valid_name = { + #[cfg(windows)] + { + bin_name + .chars() + .all(|c| c.is_ascii_alphanumeric() || c == '_' || c == '.') + } - #[cfg(not(windows))] - { - bin_name - .chars() - .all(|c| c.is_ascii_alphanumeric() || c == '_') - } - }; + #[cfg(not(windows))] + { + bin_name + .chars() + .all(|c| c.is_ascii_alphanumeric() || c == '_') + } + }; - let is_executable = { - #[cfg(windows)] - { - bin_name.ends_with(".exe") || bin_name.ends_with(".bat") - } + let is_executable = { + #[cfg(windows)] + { + bin_name.ends_with(".exe") || bin_name.ends_with(".bat") + } - #[cfg(not(windows))] - { - true - } - }; + #[cfg(not(windows))] + { + true + } + }; - if is_valid_name && is_executable { - trace!("Trying {:?}", bin.display()); + if is_valid_name && is_executable { + trace!("Trying {:?}", path.display()); - // we are ok if this plugin load fails - let _ = load_plugin(&bin, context); - } + // we are ok if this plugin load fails + let _ = load_plugin(&path, &mut context.clone()); } - } - } + }) + .collect(); } Ok(()) diff --git a/crates/nu-errors/Cargo.toml b/crates/nu-errors/Cargo.toml index 77dfcffa594f..8dbc74b8bcbf 100644 --- a/crates/nu-errors/Cargo.toml +++ b/crates/nu-errors/Cargo.toml @@ -25,6 +25,7 @@ getset = "0.1.0" serde_yaml = "0.8" toml = "0.5.6" serde_json = "1.0.51" +glob = "0.3.0" [build-dependencies] nu-build = { version = "0.13.0", path = "../nu-build" } diff --git a/crates/nu-errors/src/lib.rs b/crates/nu-errors/src/lib.rs index 36cd7bc93231..031c93c25229 100644 --- a/crates/nu-errors/src/lib.rs +++ b/crates/nu-errors/src/lib.rs @@ -864,6 +864,12 @@ impl std::convert::From> for ShellError } } +impl std::convert::From for ShellError { + fn from(input: glob::PatternError) -> ShellError { + ShellError::untagged_runtime_error(format!("{:?}", input)) + } +} + pub trait CoerceInto { fn coerce_into(self, operation: impl Into) -> Result; }