mirror of
https://github.com/nushell/nushell.git
synced 2025-06-30 22:50:14 +02:00
Improve case insensitivity consistency (#10884)
# Description Add an extension trait `IgnoreCaseExt` to nu_utils which adds some case insensitivity helpers, and use them throughout nu to improve the handling of case insensitivity. Proper case folding is done via unicase, which is already a dependency via mime_guess from nu-command. In actuality a lot of code still does `to_lowercase`, because unicase only provides immediate comparison and doesn't expose a `to_folded_case` yet. And since we do a lot of `contains`/`starts_with`/`ends_with`, it's not sufficient to just have `eq_ignore_case`. But if we get access in the future, this makes us ready to use it with a change in one place. Plus, it's clearer what the purpose is at the call site to call `to_folded_case` instead of `to_lowercase` if it's exclusively for the purpose of case insensitive comparison, even if it just does `to_lowercase` still. # User-Facing Changes - Some commands that were supposed to be case insensitive remained only insensitive to ASCII case (a-z), and now are case insensitive w.r.t. non-ASCII characters as well. # Tests + Formatting - 🟢 `toolkit fmt` - 🟢 `toolkit clippy` - 🟢 `toolkit test` - 🟢 `toolkit test stdlib` --------- Co-authored-by: Stefan Holderbach <sholderbach@users.noreply.github.com>
This commit is contained in:
committed by
GitHub
parent
aed4b626b8
commit
0f600bc3f5
@ -9,6 +9,7 @@ use nu_protocol::{
|
||||
SyntaxShape, Type, Value,
|
||||
};
|
||||
use nu_system::ForegroundProcess;
|
||||
use nu_utils::IgnoreCaseExt;
|
||||
use os_pipe::PipeReader;
|
||||
use pathdiff::diff_paths;
|
||||
use std::collections::HashMap;
|
||||
@ -223,10 +224,10 @@ impl ExternalCommand {
|
||||
const CMD_INTERNAL_COMMANDS: [&str; 9] = [
|
||||
"ASSOC", "CLS", "ECHO", "FTYPE", "MKLINK", "PAUSE", "START", "VER", "VOL",
|
||||
];
|
||||
let command_name_upper = self.name.item.to_uppercase();
|
||||
let command_name = &self.name.item;
|
||||
let looks_like_cmd_internal = CMD_INTERNAL_COMMANDS
|
||||
.iter()
|
||||
.any(|&cmd| command_name_upper == cmd);
|
||||
.any(|&cmd| command_name.eq_ignore_ascii_case(cmd));
|
||||
|
||||
if looks_like_cmd_internal {
|
||||
let (cmd, new_reader) = self.create_process(&input, true, head)?;
|
||||
@ -252,9 +253,10 @@ impl ExternalCommand {
|
||||
which::which_in(&self.name.item, Some(path_with_cwd), cwd)
|
||||
{
|
||||
if let Some(file_name) = which_path.file_name() {
|
||||
let file_name_upper =
|
||||
file_name.to_string_lossy().to_uppercase();
|
||||
if file_name_upper != command_name_upper {
|
||||
if !file_name
|
||||
.to_string_lossy()
|
||||
.eq_ignore_case(command_name)
|
||||
{
|
||||
// which-rs found an executable file with a slightly different name
|
||||
// than the one the user tried. Let's try running it
|
||||
let mut new_command = self.clone();
|
||||
@ -767,11 +769,11 @@ fn trim_expand_and_apply_arg(
|
||||
/// Given an invalid command name, try to suggest an alternative
|
||||
fn suggest_command(attempted_command: &str, engine_state: &EngineState) -> Option<String> {
|
||||
let commands = engine_state.get_signatures(false);
|
||||
let command_name_lower = attempted_command.to_lowercase();
|
||||
let command_folded_case = attempted_command.to_folded_case();
|
||||
let search_term_match = commands.iter().find(|sig| {
|
||||
sig.search_terms
|
||||
.iter()
|
||||
.any(|term| term.to_lowercase() == command_name_lower)
|
||||
.any(|term| term.to_folded_case() == command_folded_case)
|
||||
});
|
||||
match search_term_match {
|
||||
Some(sig) => Some(sig.name.clone()),
|
||||
|
Reference in New Issue
Block a user