Try again with math-like externals (#4629)

* Try again with math-like externals

* clippy 1.59

* clippy 1.59

* clippy 1.59
This commit is contained in:
JT 2022-02-24 14:02:28 -05:00 committed by GitHub
parent 2c9d8c4818
commit 3c62d27c28
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
21 changed files with 77 additions and 54 deletions

View File

@ -26,8 +26,7 @@ impl NuCompleter {
fn external_command_completion(&self, prefix: &str) -> Vec<String> { fn external_command_completion(&self, prefix: &str) -> Vec<String> {
let mut executables = vec![]; let mut executables = vec![];
let paths; let paths = self.engine_state.env_vars.get("PATH");
paths = self.engine_state.env_vars.get("PATH");
if let Some(paths) = paths { if let Some(paths) = paths {
if let Ok(paths) = paths.as_list() { if let Ok(paths) = paths.as_list() {
@ -470,7 +469,7 @@ fn file_path_completion(
) -> Vec<(nu_protocol::Span, String)> { ) -> Vec<(nu_protocol::Span, String)> {
use std::path::{is_separator, Path}; use std::path::{is_separator, Path};
let partial = partial.replace("\"", ""); let partial = partial.replace('\"', "");
let (base_dir_name, partial) = { let (base_dir_name, partial) = {
// If partial is only a word we want to search in the current dir // If partial is only a word we want to search in the current dir

View File

@ -86,26 +86,26 @@ impl NushellPrompt {
impl Prompt for NushellPrompt { impl Prompt for NushellPrompt {
fn render_prompt_left(&self) -> Cow<str> { fn render_prompt_left(&self) -> Cow<str> {
if let Some(prompt_string) = &self.left_prompt_string { if let Some(prompt_string) = &self.left_prompt_string {
prompt_string.replace("\n", "\r\n").into() prompt_string.replace('\n', "\r\n").into()
} else { } else {
let default = DefaultPrompt::new(); let default = DefaultPrompt::new();
default default
.render_prompt_left() .render_prompt_left()
.to_string() .to_string()
.replace("\n", "\r\n") .replace('\n', "\r\n")
.into() .into()
} }
} }
fn render_prompt_right(&self) -> Cow<str> { fn render_prompt_right(&self) -> Cow<str> {
if let Some(prompt_string) = &self.right_prompt_string { if let Some(prompt_string) = &self.right_prompt_string {
prompt_string.replace("\n", "\r\n").into() prompt_string.replace('\n', "\r\n").into()
} else { } else {
let default = DefaultPrompt::new(); let default = DefaultPrompt::new();
default default
.render_prompt_right() .render_prompt_right()
.to_string() .to_string()
.replace("\n", "\r\n") .replace('\n', "\r\n")
.into() .into()
} }
} }

View File

@ -188,7 +188,7 @@ fn convert_int(input: &Value, head: Span, radix: u32) -> Value {
Value::Int { val, .. } => val.to_string(), Value::Int { val, .. } => val.to_string(),
Value::String { val, .. } => { Value::String { val, .. } => {
if val.starts_with("0x") || val.starts_with("0b") { if val.starts_with("0x") || val.starts_with("0b") {
match int_from_string(&val.to_string(), head) { match int_from_string(val, head) {
Ok(x) => return Value::Int { val: x, span: head }, Ok(x) => return Value::Int { val: x, span: head },
Err(e) => return Value::Error { error: e }, Err(e) => return Value::Error { error: e },
} }

View File

@ -451,7 +451,7 @@ fn html_value(value: Value, config: &Config) -> String {
} }
other => output_string.push_str( other => output_string.push_str(
&htmlescape::encode_minimal(&other.into_abbreviated_string(config)) &htmlescape::encode_minimal(&other.into_abbreviated_string(config))
.replace("\n", "<br>"), .replace('\n', "<br>"),
), ),
} }
output_string output_string

View File

@ -248,7 +248,7 @@ pub fn run_seq(
}; };
let last = { let last = {
let slice = &free[free.len() - 1][..]; let slice = &free[free.len() - 1][..];
padding = cmp::max(padding, slice.find('.').unwrap_or_else(|| slice.len())); padding = cmp::max(padding, slice.find('.').unwrap_or(slice.len()));
match parse_float(slice) { match parse_float(slice) {
Ok(n) => n, Ok(n) => n,
Err(s) => { Err(s) => {

View File

@ -423,7 +423,7 @@ fn generate_ansi_code_list(
let cols = vec!["name".into(), "short name".into(), "code".into()]; let cols = vec!["name".into(), "short name".into(), "code".into()];
let name: Value = Value::string(String::from(ansi_code.long_name), call_span); let name: Value = Value::string(String::from(ansi_code.long_name), call_span);
let short_name = Value::string(ansi_code.short_name.unwrap_or(""), call_span); let short_name = Value::string(ansi_code.short_name.unwrap_or(""), call_span);
let code_string = String::from(&ansi_code.code.replace("\u{1b}", "")); let code_string = String::from(&ansi_code.code.replace('\u{1b}', ""));
let code = Value::string(code_string, call_span); let code = Value::string(code_string, call_span);
let vals = vec![name, short_name, code]; let vals = vec![name, short_name, code];
Value::Record { Value::Record {

View File

@ -397,7 +397,7 @@ impl ExternalCommand {
// Clean the args before we use them: // Clean the args before we use them:
// https://stackoverflow.com/questions/1200235/how-to-pass-a-quoted-pipe-character-to-cmd-exe // https://stackoverflow.com/questions/1200235/how-to-pass-a-quoted-pipe-character-to-cmd-exe
// cmd.exe needs to have a caret to escape a pipe // cmd.exe needs to have a caret to escape a pipe
let arg = arg.item.replace("|", "^|"); let arg = arg.item.replace('|', "^|");
process.arg(&arg); process.arg(&arg);
} }
process process

View File

@ -928,7 +928,7 @@ where
if f1.len() <= f2.len() + 1 { if f1.len() <= f2.len() + 1 {
f1 f1
} else if !f2.contains("e-") { } else if !f2.contains("e-") {
f2.replace("e", "e+") f2.replace('e', "e+")
} else { } else {
f2 f2
} }

View File

@ -2956,9 +2956,8 @@ pub fn parse_table_expression(
{ {
match values.len().cmp(&table_headers.len()) { match values.len().cmp(&table_headers.len()) {
std::cmp::Ordering::Less => { std::cmp::Ordering::Less => {
error = error.or_else(|| { error = error
Some(ParseError::MissingColumns(table_headers.len(), span)) .or(Some(ParseError::MissingColumns(table_headers.len(), span)))
})
} }
std::cmp::Ordering::Equal => {} std::cmp::Ordering::Equal => {}
std::cmp::Ordering::Greater => { std::cmp::Ordering::Greater => {

View File

@ -259,7 +259,7 @@ impl PipelineData {
} }
/// Simplified flatmapper. For full iterator support use `.into_iter()` instead /// Simplified flatmapper. For full iterator support use `.into_iter()` instead
pub fn flat_map<U, F>( pub fn flat_map<U: 'static, F>(
self, self,
mut f: F, mut f: F,
ctrlc: Option<Arc<AtomicBool>>, ctrlc: Option<Arc<AtomicBool>>,
@ -272,10 +272,10 @@ impl PipelineData {
{ {
match self { match self {
PipelineData::Value(Value::List { vals, .. }, ..) => { PipelineData::Value(Value::List { vals, .. }, ..) => {
Ok(vals.into_iter().map(f).flatten().into_pipeline_data(ctrlc)) Ok(vals.into_iter().flat_map(f).into_pipeline_data(ctrlc))
} }
PipelineData::ListStream(stream, ..) => { PipelineData::ListStream(stream, ..) => {
Ok(stream.map(f).flatten().into_pipeline_data(ctrlc)) Ok(stream.flat_map(f).into_pipeline_data(ctrlc))
} }
PipelineData::RawStream(stream, ..) => { PipelineData::RawStream(stream, ..) => {
let collected = stream.into_bytes()?; let collected = stream.into_bytes()?;
@ -297,7 +297,7 @@ impl PipelineData {
} }
} }
PipelineData::Value(Value::Range { val, .. }, ..) => match val.into_range_iter() { PipelineData::Value(Value::Range { val, .. }, ..) => match val.into_range_iter() {
Ok(iter) => Ok(iter.map(f).flatten().into_pipeline_data(ctrlc)), Ok(iter) => Ok(iter.flat_map(f).into_pipeline_data(ctrlc)),
Err(error) => Err(error), Err(error) => Err(error),
}, },
PipelineData::Value(v, ..) => Ok(f(v).into_iter().into_pipeline_data(ctrlc)), PipelineData::Value(v, ..) => Ok(f(v).into_iter().into_pipeline_data(ctrlc)),

View File

@ -2120,7 +2120,7 @@ fn format_filesize(num_bytes: i64, config: &Config) -> String {
// Since get_locale() and Locale::from_name() don't always return the same items // Since get_locale() and Locale::from_name() don't always return the same items
// we need to try and parse it to match. For instance, a valid locale is de_DE // we need to try and parse it to match. For instance, a valid locale is de_DE
// however Locale::from_name() wants only de so we split and parse it out. // however Locale::from_name() wants only de so we split and parse it out.
let locale_string = locale_string.replace("_", "-"); // en_AU -> en-AU let locale_string = locale_string.replace('_', "-"); // en_AU -> en-AU
let locale = match Locale::from_name(&locale_string) { let locale = match Locale::from_name(&locale_string) {
Ok(loc) => loc, Ok(loc) => loc,
_ => { _ => {

View File

@ -194,7 +194,7 @@ impl ProcessInfo {
pub fn command(&self) -> String { pub fn command(&self) -> String {
if let Ok(cmd) = &self.curr_proc.cmdline() { if let Ok(cmd) = &self.curr_proc.cmdline() {
if !cmd.is_empty() { if !cmd.is_empty() {
cmd.join(" ").replace("\n", " ").replace("\t", " ") cmd.join(" ").replace('\n', " ").replace('\t', " ")
} else { } else {
self.curr_proc.stat().comm.clone() self.curr_proc.stat().comm.clone()
} }

View File

@ -324,12 +324,12 @@ impl ProcessInfo {
pub fn command(&self) -> String { pub fn command(&self) -> String {
if let Some(path) = &self.curr_path { if let Some(path) = &self.curr_path {
if !path.cmd.is_empty() { if !path.cmd.is_empty() {
path.cmd.join(" ").replace("\n", " ").replace("\t", " ") path.cmd.join(" ").replace('\n', " ").replace('\t', " ")
} else { } else {
String::from("") String::new()
} }
} else { } else {
String::from("") String::new()
} }
} }

View File

@ -209,7 +209,7 @@ pub fn collect_proc(interval: Duration, _with_thread: bool) -> Vec<ProcessInfo>
name: None, name: None,
domainname: None, domainname: None,
}); });
let groups = groups.unwrap_or_else(Vec::new); let groups = groups.unwrap_or_default();
let thread = thread.unwrap_or_default(); let thread = thread.unwrap_or_default();
let proc = ProcessInfo { let proc = ProcessInfo {

View File

@ -168,5 +168,5 @@ pub fn read_std(std: &[u8]) -> String {
let out = String::from_utf8_lossy(std); let out = String::from_utf8_lossy(std);
let out = out.lines().collect::<Vec<_>>().join("\n"); let out = out.lines().collect::<Vec<_>>().join("\n");
let out = out.replace("\r\n", ""); let out = out.replace("\r\n", "");
out.replace("\n", "") out.replace('\n', "")
} }

View File

@ -157,5 +157,5 @@ fn read_std(std: &[u8]) -> Vec<u8> {
let out = String::from_utf8_lossy(std); let out = String::from_utf8_lossy(std);
let out = out.lines().collect::<Vec<_>>().join("\n"); let out = out.lines().collect::<Vec<_>>().join("\n");
let out = out.replace("\r\n", ""); let out = out.replace("\r\n", "");
out.replace("\n", "").into_bytes() out.replace('\n', "").into_bytes()
} }

View File

@ -19,10 +19,6 @@ pub(crate) fn evaluate(
// First, set up env vars as strings only // First, set up env vars as strings only
gather_parent_env_vars(engine_state); gather_parent_env_vars(engine_state);
// 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;
// Run a command (or commands) given to us by the user // Run a command (or commands) given to us by the user
let (block, delta) = { let (block, delta) = {
let mut working_set = StateWorkingSet::new(engine_state); let mut working_set = StateWorkingSet::new(engine_state);
@ -78,6 +74,10 @@ pub(crate) fn evaluate(
} }
}; };
// Make a note of the exceptions we see for externals that look like math expressions
let exceptions = crate::utils::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) => {

View File

@ -22,10 +22,6 @@ pub(crate) fn evaluate(
// First, set up env vars as strings only // First, set up env vars as strings only
gather_parent_env_vars(engine_state); gather_parent_env_vars(engine_state);
// 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;
let mut stack = nu_protocol::engine::Stack::new(); let mut stack = nu_protocol::engine::Stack::new();
// Set up our initial config to start from // Set up our initial config to start from
@ -45,6 +41,10 @@ pub(crate) fn evaluate(
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::utils::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);

View File

@ -35,10 +35,6 @@ pub(crate) fn evaluate(
// First, set up env vars as strings only // First, set up env vars as strings only
gather_parent_env_vars(engine_state); gather_parent_env_vars(engine_state);
// 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;
// Set up our initial config to start from // Set up our initial config to start from
stack.vars.insert( stack.vars.insert(
CONFIG_VARIABLE_ID, CONFIG_VARIABLE_ID,
@ -86,6 +82,10 @@ pub(crate) fn evaluate(
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::utils::external_exceptions(engine_state, &stack);
engine_state.external_exceptions = exceptions;
// seed the cmd_duration_ms env var // seed the cmd_duration_ms env var
stack.add_env_var( stack.add_env_var(
"CMD_DURATION_MS".into(), "CMD_DURATION_MS".into(),
@ -322,7 +322,7 @@ pub(crate) fn evaluate(
} }
// Make a note of the exceptions we see for externals that look like math expressions // Make a note of the exceptions we see for externals that look like math expressions
let exceptions = crate::utils::external_exceptions(); let exceptions = crate::utils::external_exceptions(engine_state, &stack);
engine_state.external_exceptions = exceptions; engine_state.external_exceptions = exceptions;
} }
Ok(Signal::CtrlC) => { Ok(Signal::CtrlC) => {

View File

@ -102,7 +102,7 @@ fn did_chop_arguments() -> bool {
for arg in arguments { for arg in arguments {
let chopped = if arg.is_empty() { let chopped = if arg.is_empty() {
&arg arg
} else { } else {
let to = arg.len() - 1; let to = arg.len() - 1;
&arg[..to] &arg[..to]

View File

@ -255,25 +255,50 @@ pub(crate) fn eval_source(
} }
/// Finds externals that have names that look like math expressions /// Finds externals that have names that look like math expressions
pub fn external_exceptions() -> Vec<Vec<u8>> { pub fn external_exceptions(engine_state: &EngineState, stack: &Stack) -> Vec<Vec<u8>> {
let mut executables = vec![]; let mut executables = vec![];
if let Ok(path) = std::env::var("PATH") { if let Some(path) = stack.get_env_var(engine_state, "PATH") {
for path in std::env::split_paths(&path) { match path {
let path = path.to_string_lossy().to_string(); Value::List { vals, .. } => {
for val in vals {
let path = val.as_string();
if let Ok(mut contents) = std::fs::read_dir(path) { if let Ok(path) = path {
while let Some(Ok(item)) = contents.next() { if let Ok(mut contents) = std::fs::read_dir(path) {
if is_executable::is_executable(&item.path()) { while let Some(Ok(item)) = contents.next() {
if let Ok(name) = item.file_name().into_string() { if is_executable::is_executable(&item.path()) {
let name = name.as_bytes().to_vec(); if let Ok(name) = item.file_name().into_string() {
if nu_parser::is_math_expression_like(&name) { let name = name.as_bytes().to_vec();
executables.push(name); if nu_parser::is_math_expression_like(&name) {
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() {
let name = name.as_bytes().to_vec();
if nu_parser::is_math_expression_like(&name) {
executables.push(name);
}
}
}
}
}
}
}
_ => {}
} }
} }
@ -318,7 +343,7 @@ pub fn report_error(
pub(crate) fn get_init_cwd() -> PathBuf { pub(crate) fn get_init_cwd() -> PathBuf {
match std::env::current_dir() { match std::env::current_dir() {
Ok(cwd) => cwd, Ok(cwd) => cwd,
Err(_) => match std::env::var("PWD".to_string()) { Err(_) => match std::env::var("PWD") {
Ok(cwd) => PathBuf::from(cwd), Ok(cwd) => PathBuf::from(cwd),
Err(_) => match nu_path::home_dir() { Err(_) => match nu_path::home_dir() {
Some(cwd) => cwd, Some(cwd) => cwd,