Consolidate suggestions code (#2597)

This commit is contained in:
Chris Gillespie 2020-09-24 20:44:24 -07:00 committed by GitHub
parent bd9e598bf0
commit a8b65e35ec
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 39 additions and 100 deletions

View File

@ -129,7 +129,7 @@ pub fn get_column_path(path: &ColumnPath, obj: &Value) -> Result<Value, ShellErr
_ => {} _ => {}
} }
if let Some(suggestions) = did_you_mean(&obj_source, column_path_tried) { if let Some(suggestions) = did_you_mean(&obj_source, column_path_tried.as_string()) {
ShellError::labeled_error( ShellError::labeled_error(
"Unknown column", "Unknown column",
format!("did you mean '{}'?", suggestions[0]), format!("did you mean '{}'?", suggestions[0]),
@ -155,7 +155,7 @@ pub fn get_column_path_from_table_error(
let suggestions: IndexSet<_> = rows let suggestions: IndexSet<_> = rows
.iter() .iter()
.filter_map(|r| did_you_mean(&r, &column_path_tried)) .filter_map(|r| did_you_mean(&r, column_path_tried.as_string()))
.map(|s| s[0].to_owned()) .map(|s| s[0].to_owned())
.collect(); .collect();
let mut existing_columns: IndexSet<_> = IndexSet::default(); let mut existing_columns: IndexSet<_> = IndexSet::default();
@ -232,7 +232,7 @@ pub fn get_column_from_row_error(
} => { } => {
let primary_label = format!("There isn't a column named '{}'", &column); let primary_label = format!("There isn't a column named '{}'", &column);
if let Some(suggestions) = did_you_mean(&obj_source, column_path_tried) { if let Some(suggestions) = did_you_mean(&obj_source, column_path_tried.as_string()) {
Some(ShellError::labeled_error_with_secondary( Some(ShellError::labeled_error_with_secondary(
"Unknown column", "Unknown column",
primary_label, primary_label,

View File

@ -1,5 +1,6 @@
use crate::commands::WholeStreamCommand; use crate::commands::WholeStreamCommand;
use crate::prelude::*; use crate::prelude::*;
use crate::utils::suggestions::suggestions;
use indexmap::indexmap; use indexmap::indexmap;
use nu_errors::ShellError; use nu_errors::ShellError;
use nu_protocol::{ReturnSuccess, Signature, SyntaxShape, UntaggedValue, Value}; use nu_protocol::{ReturnSuccess, Signature, SyntaxShape, UntaggedValue, Value};
@ -187,31 +188,6 @@ pub async fn group_by(
Ok(OutputStream::one(ReturnSuccess::value(group_value?))) Ok(OutputStream::one(ReturnSuccess::value(group_value?)))
} }
pub fn suggestions(tried: Tagged<&str>, for_value: &Value) -> ShellError {
let possibilities = for_value.data_descriptors();
let mut possible_matches: Vec<_> = possibilities
.iter()
.map(|x| (natural::distance::levenshtein_distance(x, &tried), x))
.collect();
possible_matches.sort();
if !possible_matches.is_empty() {
ShellError::labeled_error(
"Unknown column",
format!("did you mean '{}'?", possible_matches[0].1),
tried.tag(),
)
} else {
ShellError::labeled_error(
"Unknown column",
"row does not contain this column",
tried.tag(),
)
}
}
pub fn group( pub fn group(
column_name: &Option<Tagged<String>>, column_name: &Option<Tagged<String>>,
values: &Value, values: &Value,

View File

@ -1,5 +1,6 @@
use crate::commands::WholeStreamCommand; use crate::commands::WholeStreamCommand;
use crate::prelude::*; use crate::prelude::*;
use crate::utils::suggestions::suggestions;
use nu_errors::ShellError; use nu_errors::ShellError;
use nu_protocol::{ReturnSuccess, Signature, SyntaxShape, UntaggedValue, Value}; use nu_protocol::{ReturnSuccess, Signature, SyntaxShape, UntaggedValue, Value};
use nu_source::Tagged; use nu_source::Tagged;
@ -137,31 +138,6 @@ pub async fn group_by_date(
} }
} }
pub fn suggestions(tried: Tagged<&str>, for_value: &Value) -> ShellError {
let possibilities = for_value.data_descriptors();
let mut possible_matches: Vec<_> = possibilities
.iter()
.map(|x| (natural::distance::levenshtein_distance(x, &tried), x))
.collect();
possible_matches.sort();
if !possible_matches.is_empty() {
ShellError::labeled_error(
"Unknown column",
format!("did you mean '{}'?", possible_matches[0].1),
tried.tag(),
)
} else {
ShellError::labeled_error(
"Unknown column",
"row does not contain this column",
tried.tag(),
)
}
}
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use super::GroupByDate; use super::GroupByDate;

View File

@ -1,5 +1,6 @@
use crate::commands::WholeStreamCommand; use crate::commands::WholeStreamCommand;
use crate::prelude::*; use crate::prelude::*;
use crate::utils::suggestions::suggestions;
use nu_errors::ShellError; use nu_errors::ShellError;
use nu_protocol::{ReturnSuccess, Signature, SyntaxShape, Value}; use nu_protocol::{ReturnSuccess, Signature, SyntaxShape, Value};
use nu_source::Tagged; use nu_source::Tagged;
@ -96,31 +97,6 @@ pub fn split(
} }
} }
pub fn suggestions(tried: Tagged<&str>, for_value: &Value) -> ShellError {
let possibilities = for_value.data_descriptors();
let mut possible_matches: Vec<_> = possibilities
.iter()
.map(|x| (natural::distance::levenshtein_distance(x, &tried), x))
.collect();
possible_matches.sort();
if !possible_matches.is_empty() {
ShellError::labeled_error(
"Unknown column",
format!("did you mean '{}'?", possible_matches[0].1),
tried.tag(),
)
} else {
ShellError::labeled_error(
"Unknown column",
"row does not contain this column",
tried.tag(),
)
}
}
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use super::split; use super::split;

View File

@ -1,3 +1,4 @@
pub mod suggestions;
pub mod test_bins; pub mod test_bins;
use crate::path::canonicalize; use crate::path::canonicalize;

View File

@ -0,0 +1,21 @@
use crate::did_you_mean;
use nu_errors::ShellError;
use nu_protocol::Value;
use nu_source::Tagged;
pub fn suggestions(tried: Tagged<&str>, for_value: &Value) -> ShellError {
let possibilities = did_you_mean(for_value, tried.to_string());
match possibilities {
Some(p) => ShellError::labeled_error(
"Unknown column",
format!("did you mean '{}'?", p[0]),
tried.tag(),
),
None => ShellError::labeled_error(
"Unknown column",
"row does not contain this column",
tried.tag(),
),
}
}

View File

@ -114,12 +114,7 @@ impl PathMember {
} }
/// Prepares a list of "sounds like" matches (using edit distance) for the string you're trying to find /// Prepares a list of "sounds like" matches (using edit distance) for the string you're trying to find
pub fn did_you_mean(obj_source: &Value, field_tried: &PathMember) -> Option<Vec<String>> { pub fn did_you_mean(obj_source: &Value, field_tried: String) -> Option<Vec<String>> {
let field_tried = match &field_tried.unspanned {
UnspannedPathMember::String(string) => string.clone(),
UnspannedPathMember::Int(int) => format!("{}", int),
};
let possibilities = obj_source.data_descriptors(); let possibilities = obj_source.data_descriptors();
let mut possible_matches: Vec<_> = possibilities let mut possible_matches: Vec<_> = possibilities
@ -159,18 +154,13 @@ mod test {
value, value,
}; };
let guess = PathMember {
unspanned: UnspannedPathMember::String("hat".to_string()),
span: Default::default(),
};
assert_eq!( assert_eq!(
Some(vec![ Some(vec![
"cat".to_string(), "cat".to_string(),
"alt".to_string(), "alt".to_string(),
"dog".to_string() "dog".to_string()
]), ]),
did_you_mean(&source, &guess) did_you_mean(&source, "hat".to_string())
) )
} }
@ -181,11 +171,6 @@ mod test {
value: UntaggedValue::row(indexmap! {}), value: UntaggedValue::row(indexmap! {}),
}; };
let guess = PathMember { assert_eq!(None, did_you_mean(&empty_source, "hat".to_string()))
unspanned: UnspannedPathMember::String("hat".to_string()),
span: Default::default(),
};
assert_eq!(None, did_you_mean(&empty_source, &guess))
} }
} }

View File

@ -238,7 +238,9 @@ where
let suggestions: IndexSet<_> = rows let suggestions: IndexSet<_> = rows
.iter() .iter()
.filter_map(|r| nu_protocol::did_you_mean(&r, &column_path_tried)) .filter_map(|r| {
nu_protocol::did_you_mean(&r, column_path_tried.as_string())
})
.map(|s| s[0].to_owned()) .map(|s| s[0].to_owned())
.collect(); .collect();
let mut existing_columns: IndexSet<_> = IndexSet::default(); let mut existing_columns: IndexSet<_> = IndexSet::default();
@ -308,7 +310,7 @@ where
let primary_label = format!("There isn't a column named '{}'", &column); let primary_label = format!("There isn't a column named '{}'", &column);
if let Some(suggestions) = if let Some(suggestions) =
nu_protocol::did_you_mean(&obj_source, &column_path_tried) nu_protocol::did_you_mean(&obj_source, column_path_tried.as_string())
{ {
return ShellError::labeled_error_with_secondary( return ShellError::labeled_error_with_secondary(
"Unknown column", "Unknown column",
@ -342,7 +344,9 @@ where
_ => {} _ => {}
} }
if let Some(suggestions) = nu_protocol::did_you_mean(&obj_source, &column_path_tried) { if let Some(suggestions) =
nu_protocol::did_you_mean(&obj_source, column_path_tried.as_string())
{
return ShellError::labeled_error( return ShellError::labeled_error(
"Unknown column", "Unknown column",
format!("did you mean '{}'?", suggestions[0]), format!("did you mean '{}'?", suggestions[0]),

View File

@ -105,7 +105,7 @@ impl Inc {
&f, &f,
move |obj_source, column_path_tried, _| match did_you_mean( move |obj_source, column_path_tried, _| match did_you_mean(
&obj_source, &obj_source,
&column_path_tried, column_path_tried.as_string(),
) { ) {
Some(suggestions) => ShellError::labeled_error( Some(suggestions) => ShellError::labeled_error(
"Unknown column", "Unknown column",