nu-cli/completions: verify case for matching dir, .nu, file and command (#5506)

* nu-cli/completions: verify case for matching dir, .nu, file and command

* avoid copy

* fix clippy
This commit is contained in:
Herlon Aguiar 2022-05-11 23:16:52 +02:00 committed by GitHub
parent 2145feff5d
commit a92567489f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 19 additions and 12 deletions

View File

@ -236,7 +236,7 @@ impl Completer for CommandCompletion {
// let prefix = working_set.get_span_contents(flat.0); // let prefix = working_set.get_span_contents(flat.0);
let prefix = String::from_utf8_lossy(&prefix).to_string(); let prefix = String::from_utf8_lossy(&prefix).to_string();
file_path_completion(span, &prefix, &cwd, options.match_algorithm) file_path_completion(span, &prefix, &cwd, options)
.into_iter() .into_iter()
.map(move |x| { .map(move |x| {
if self.flat_idx == 0 { if self.flat_idx == 0 {

View File

@ -8,7 +8,7 @@ use std::fs;
use std::path::Path; use std::path::Path;
use std::sync::Arc; use std::sync::Arc;
use super::{partial_from, prepend_base_dir, MatchAlgorithm}; use super::{partial_from, prepend_base_dir};
const SEP: char = std::path::MAIN_SEPARATOR; const SEP: char = std::path::MAIN_SEPARATOR;
@ -44,7 +44,7 @@ impl Completer for DirectoryCompletion {
let partial = String::from_utf8_lossy(&prefix).to_string(); let partial = String::from_utf8_lossy(&prefix).to_string();
// Filter only the folders // Filter only the folders
let output: Vec<_> = directory_completion(span, &partial, &cwd, options.match_algorithm) let output: Vec<_> = directory_completion(span, &partial, &cwd, options)
.into_iter() .into_iter()
.map(move |x| Suggestion { .map(move |x| Suggestion {
value: x.1, value: x.1,
@ -103,7 +103,7 @@ pub fn directory_completion(
span: nu_protocol::Span, span: nu_protocol::Span,
partial: &str, partial: &str,
cwd: &str, cwd: &str,
match_algorithm: MatchAlgorithm, options: &CompletionOptions,
) -> Vec<(nu_protocol::Span, String)> { ) -> Vec<(nu_protocol::Span, String)> {
let original_input = partial; let original_input = partial;
@ -124,7 +124,7 @@ pub fn directory_completion(
if let Ok(metadata) = fs::metadata(entry.path()) { if let Ok(metadata) = fs::metadata(entry.path()) {
if metadata.is_dir() { if metadata.is_dir() {
let mut file_name = entry.file_name().to_string_lossy().into_owned(); let mut file_name = entry.file_name().to_string_lossy().into_owned();
if matches(&partial, &file_name, match_algorithm) { if matches(&partial, &file_name, options) {
let mut path = if prepend_base_dir(original_input, &base_dir_name) { let mut path = if prepend_base_dir(original_input, &base_dir_name) {
format!("{}{}", base_dir_name, file_name) format!("{}{}", base_dir_name, file_name)
} else { } else {

View File

@ -91,7 +91,7 @@ impl Completer for DotNuCompletion {
let output: Vec<Suggestion> = search_dirs let output: Vec<Suggestion> = search_dirs
.into_iter() .into_iter()
.flat_map(|it| { .flat_map(|it| {
file_path_completion(span, &partial, &it, options.match_algorithm) file_path_completion(span, &partial, &it, options)
.into_iter() .into_iter()
.filter(|it| { .filter(|it| {
// Different base dir, so we list the .nu files or folders // Different base dir, so we list the .nu files or folders

View File

@ -1,4 +1,4 @@
use crate::completions::{Completer, CompletionOptions, MatchAlgorithm}; use crate::completions::{Completer, CompletionOptions};
use nu_protocol::{ use nu_protocol::{
engine::{EngineState, StateWorkingSet}, engine::{EngineState, StateWorkingSet},
levenshtein_distance, Span, levenshtein_distance, Span,
@ -39,7 +39,7 @@ impl Completer for FileCompletion {
"".to_string() "".to_string()
}; };
let prefix = String::from_utf8_lossy(&prefix).to_string(); let prefix = String::from_utf8_lossy(&prefix).to_string();
let output: Vec<_> = file_path_completion(span, &prefix, &cwd, options.match_algorithm) let output: Vec<_> = file_path_completion(span, &prefix, &cwd, options)
.into_iter() .into_iter()
.map(move |x| Suggestion { .map(move |x| Suggestion {
value: x.1, value: x.1,
@ -112,7 +112,7 @@ pub fn file_path_completion(
span: nu_protocol::Span, span: nu_protocol::Span,
partial: &str, partial: &str,
cwd: &str, cwd: &str,
match_algorithm: MatchAlgorithm, options: &CompletionOptions,
) -> Vec<(nu_protocol::Span, String)> { ) -> Vec<(nu_protocol::Span, String)> {
let original_input = partial; let original_input = partial;
let (base_dir_name, partial) = partial_from(partial); let (base_dir_name, partial) = partial_from(partial);
@ -129,7 +129,7 @@ pub fn file_path_completion(
.filter_map(|entry| { .filter_map(|entry| {
entry.ok().and_then(|entry| { entry.ok().and_then(|entry| {
let mut file_name = entry.file_name().to_string_lossy().into_owned(); let mut file_name = entry.file_name().to_string_lossy().into_owned();
if matches(&partial, &file_name, match_algorithm) { if matches(&partial, &file_name, options) {
let mut path = if prepend_base_dir(original_input, &base_dir_name) { let mut path = if prepend_base_dir(original_input, &base_dir_name) {
format!("{}{}", base_dir_name, file_name) format!("{}{}", base_dir_name, file_name)
} else { } else {
@ -158,8 +158,15 @@ pub fn file_path_completion(
Vec::new() Vec::new()
} }
pub fn matches(partial: &str, from: &str, match_algorithm: MatchAlgorithm) -> bool { pub fn matches(partial: &str, from: &str, options: &CompletionOptions) -> bool {
match_algorithm.matches_str(&from.to_ascii_lowercase(), &partial.to_ascii_lowercase()) // Check for case sensitive
if !options.case_sensitive {
return options
.match_algorithm
.matches_str(&from.to_ascii_lowercase(), &partial.to_ascii_lowercase());
}
options.match_algorithm.matches_str(from, partial)
} }
/// Returns whether the base_dir should be prepended to the file path /// Returns whether the base_dir should be prepended to the file path