mirror of
https://github.com/nushell/nushell.git
synced 2025-04-24 21:28:20 +02:00
Consolidate suggestions code (#2597)
This commit is contained in:
parent
bd9e598bf0
commit
a8b65e35ec
@ -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,
|
||||||
|
@ -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,
|
||||||
|
@ -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;
|
||||||
|
@ -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;
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
pub mod suggestions;
|
||||||
pub mod test_bins;
|
pub mod test_bins;
|
||||||
|
|
||||||
use crate::path::canonicalize;
|
use crate::path::canonicalize;
|
||||||
|
21
crates/nu-cli/src/utils/suggestions.rs
Normal file
21
crates/nu-cli/src/utils/suggestions.rs
Normal 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(),
|
||||||
|
),
|
||||||
|
}
|
||||||
|
}
|
@ -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))
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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]),
|
||||||
|
@ -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",
|
||||||
|
Loading…
Reference in New Issue
Block a user