Create nu_glob::is_glob function (#14717)

# Description

Adds an `is_glob` function to the nu-glob crate that takes a string
pattern and returns whether or not it's a glob that would be expanded by
nu-glob. Right now, this just means checking if it contains `*`, `?`, or
`[`.

Previously, this same code was duplicated in the following places:
- `ls`: Determining whether to read a folder's contents or expand a glob
- `run_external.rs` in nu-command: Arguments to externals only have
n-dots and tilde expansion applied if they weren't globs
- `glob_from` in nu-engine:
  - `glob_from` can get the prefix in a simpler way for non-globs
- If the canonical path for a non-glob path contains glob
metacharacters, it needs to be escaped
- `completion_common.rs` in nu-cli: File/folder completions containing
glob metacharacters need to be wrapped in quotes

All of these locations can use `nu_glob::is_glob` now instead of rolling
their own checks. This does mean that nu-cli now has a dependency on
nu-glob.

# User-Facing Changes

Users of nu-glob will now be able to check if a given pattern is a glob
expanded by nu-glob.

For users of Nushell, completion suggestions for files containing `]`
will no longer be wrapped in quotes if they contain no other glob
metacharacters. This is because unmatched `]`s are ignored by nu-glob,
but we used to consider such file completions contaminated anyway.

# Tests + Formatting

This is a very basic function, so I just added some doctests.

# After Submitting

This is meant to be used in
https://github.com/nushell/nushell/pull/14674.
This commit is contained in:
Yash Thakur
2025-01-01 19:04:17 -05:00
committed by GitHub
parent f69b22f00b
commit 62bd6fe08b
7 changed files with 31 additions and 15 deletions

View File

@ -313,6 +313,27 @@ pub fn glob_with_parent(
}
}
const GLOB_CHARS: &[char] = &['*', '?', '['];
/// Returns true if the given pattern is a glob, false if it's merely text to be
/// matched exactly.
///
/// ```rust
/// assert!(nu_glob::is_glob("foo/*"));
/// assert!(nu_glob::is_glob("foo/**/bar"));
/// assert!(nu_glob::is_glob("foo?"));
/// assert!(nu_glob::is_glob("foo[A]"));
///
/// assert!(!nu_glob::is_glob("foo"));
/// // nu_glob will ignore an unmatched ']'
/// assert!(!nu_glob::is_glob("foo]"));
/// // nu_glob doesn't expand {}
/// assert!(!nu_glob::is_glob("foo.{txt,png}"));
/// ```
pub fn is_glob(pattern: &str) -> bool {
pattern.contains(GLOB_CHARS)
}
/// A glob iteration error.
///
/// This is typically returned when a particular path cannot be read