mirror of
https://github.com/nushell/nushell.git
synced 2025-08-12 10:20:21 +02:00
do not attempt to glob expand if the file path is wrapped in quotes (#11569)
# Description Fixes: #11455 ### For arguments which is annotated with `:path/:directory/:glob` To fix the issue, we need to have a way to know if a path is originally quoted during runtime. So the information needed to be added at several levels: * parse time (from user input to expression) We need to add quoted information into `Expr::Filepath`, `Expr::Directory`, `Expr::GlobPattern` * eval time When convert from `Expr::Filepath`, `Expr::Directory`, `Expr::GlobPattern` to `Value::String` during runtime, we won't auto expanded the path if it's quoted ### For `ls` It's really special, because it accepts a `String` as a pattern, and it generates `glob` expression inside the command itself. So the idea behind the change is introducing a special SyntaxShape to ls: `SyntaxShape::LsGlobPattern`. So we can track if the pattern is originally quoted easier, and we don't auto expand the path either. Then when constructing a glob pattern inside ls, we check if input pattern is quoted, if so: we escape the input pattern, so we can run `ls a[123]b`, because it's already escaped. Finally, to accomplish the checking process, we also need to introduce a new value type called `Value::QuotedString` to differ from `Value::String`, it's used to generate an enum called `NuPath`, which is finally used in `ls` function. `ls` learned from `NuPath` to know if user input is quoted. # User-Facing Changes Actually it contains several changes ### For arguments which is annotated with `:path/:directory/:glob` #### Before ```nushell > def foo [p: path] { echo $p }; print (foo "~/a"); print (foo '~/a') /home/windsoilder/a /home/windsoilder/a > def foo [p: directory] { echo $p }; print (foo "~/a"); print (foo '~/a') /home/windsoilder/a /home/windsoilder/a > def foo [p: glob] { echo $p }; print (foo "~/a"); print (foo '~/a') /home/windsoilder/a /home/windsoilder/a ``` #### After ```nushell > def foo [p: path] { echo $p }; print (foo "~/a"); print (foo '~/a') ~/a ~/a > def foo [p: directory] { echo $p }; print (foo "~/a"); print (foo '~/a') ~/a ~/a > def foo [p: glob] { echo $p }; print (foo "~/a"); print (foo '~/a') ~/a ~/a ``` ### For ls command `touch '[uwu]'` #### Before ``` ❯ ls -D "[uwu]" Error: × No matches found for [uwu] ╭─[entry #6:1:1] 1 │ ls -D "[uwu]" · ───┬─── · ╰── Pattern, file or folder not found ╰──── help: no matches found ``` #### After ``` ❯ ls -D "[uwu]" ╭───┬───────┬──────┬──────┬──────────╮ │ # │ name │ type │ size │ modified │ ├───┼───────┼──────┼──────┼──────────┤ │ 0 │ [uwu] │ file │ 0 B │ now │ ╰───┴───────┴──────┴──────┴──────────╯ ``` # Tests + Formatting Done # After Submitting NaN
This commit is contained in:
@ -27,9 +27,9 @@ pub trait Eval {
|
||||
Expr::Int(i) => Ok(Value::int(*i, expr.span)),
|
||||
Expr::Float(f) => Ok(Value::float(*f, expr.span)),
|
||||
Expr::Binary(b) => Ok(Value::binary(b.clone(), expr.span)),
|
||||
Expr::Filepath(path) => Self::eval_filepath(state, mut_state, path.clone(), expr.span),
|
||||
Expr::Directory(path) => {
|
||||
Self::eval_directory(state, mut_state, path.clone(), expr.span)
|
||||
Expr::Filepath(path, quoted) => Self::eval_filepath(state, mut_state, path.clone(), *quoted, expr.span),
|
||||
Expr::Directory(path, quoted) => {
|
||||
Self::eval_directory(state, mut_state, path.clone(), *quoted, expr.span)
|
||||
}
|
||||
Expr::Var(var_id) => Self::eval_var(state, mut_state, *var_id, expr.span),
|
||||
Expr::CellPath(cell_path) => Ok(Value::cell_path(cell_path.clone(), expr.span)),
|
||||
@ -274,8 +274,15 @@ pub trait Eval {
|
||||
Self::eval_string_interpolation(state, mut_state, exprs, expr.span)
|
||||
}
|
||||
Expr::Overlay(_) => Self::eval_overlay(state, expr.span),
|
||||
Expr::GlobPattern(pattern) => {
|
||||
Self::eval_glob_pattern(state, mut_state, pattern.clone(), expr.span)
|
||||
Expr::GlobPattern(pattern, quoted) => {
|
||||
Self::eval_glob_pattern(state, mut_state, pattern.clone(), *quoted, expr.span)
|
||||
}
|
||||
Expr::LsGlobPattern(pattern, quoted) => {
|
||||
if *quoted {
|
||||
Ok(Value::quoted_string(pattern, expr.span))
|
||||
} else {
|
||||
Ok(Value::string(pattern, expr.span))
|
||||
}
|
||||
}
|
||||
Expr::MatchBlock(_) // match blocks are handled by `match`
|
||||
| Expr::VarDecl(_)
|
||||
@ -291,6 +298,7 @@ pub trait Eval {
|
||||
state: Self::State<'_>,
|
||||
mut_state: &mut Self::MutState,
|
||||
path: String,
|
||||
quoted: bool,
|
||||
span: Span,
|
||||
) -> Result<Value, ShellError>;
|
||||
|
||||
@ -298,6 +306,7 @@ pub trait Eval {
|
||||
state: Self::State<'_>,
|
||||
mut_state: &mut Self::MutState,
|
||||
path: String,
|
||||
quoted: bool,
|
||||
span: Span,
|
||||
) -> Result<Value, ShellError>;
|
||||
|
||||
@ -370,6 +379,7 @@ pub trait Eval {
|
||||
state: Self::State<'_>,
|
||||
mut_state: &mut Self::MutState,
|
||||
pattern: String,
|
||||
quoted: bool,
|
||||
span: Span,
|
||||
) -> Result<Value, ShellError>;
|
||||
|
||||
|
Reference in New Issue
Block a user