-
Notifications
You must be signed in to change notification settings - Fork 6
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
open
, rm
, umv
, cp
, rm
and du
: Don't globs if inputs are v…
…ariables or string interpolation (#11886) # Description This is a follow up to nushell/nushell#11621 (comment) Also Fixes: #11838 ## About the code change It applys the same logic when we pass variables to external commands: https://github.com/nushell/nushell/blob/0487e9ffcbc57c2d5feca606e10c3f8221ff5e00/crates/nu-command/src/system/run_external.rs#L162-L170 That is: if user input dynamic things(like variables, sub-expression, or string interpolation), it returns a quoted `NuPath`, then user input won't be globbed # User-Facing Changes Given two input files: `a*c.txt`, `abc.txt` * `let f = "a*c.txt"; rm $f` will remove one file: `a*c.txt`. ~* `let f = "a*c.txt"; rm --glob $f` will remove `a*c.txt` and `abc.txt`~ * `let f: glob = "a*c.txt"; rm $f` will remove `a*c.txt` and `abc.txt` ## Rules about globbing with *variable* Given two files: `a*c.txt`, `abc.txt` | Cmd Type | example | Result | | ----- | ------------------ | ------ | | builtin | let f = "a*c.txt"; rm $f | remove `a*c.txt` | | builtin | let f: glob = "a*c.txt"; rm $f | remove `a*c.txt` and `abc.txt` | builtin | let f = "a*c.txt"; rm ($f \| into glob) | remove `a*c.txt` and `abc.txt` | custom | def crm [f: glob] { rm $f }; let f = "a*c.txt"; crm $f | remove `a*c.txt` and `abc.txt` | custom | def crm [f: glob] { rm ($f \| into string) }; let f = "a*c.txt"; crm $f | remove `a*c.txt` | custom | def crm [f: string] { rm $f }; let f = "a*c.txt"; crm $f | remove `a*c.txt` | custom | def crm [f: string] { rm $f }; let f = "a*c.txt"; crm ($f \| into glob) | remove `a*c.txt` and `abc.txt` In general, if a variable is annotated with `glob` type, nushell will expand glob pattern. Or else, we need to use `into | glob` to expand glob pattern # Tests + Formatting Done # After Submitting I think `str glob-escape` command will be no-longer required. We can remove it.
- Loading branch information
1 parent
a2a1c16
commit f7d647a
Showing
41 changed files
with
534 additions
and
109 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,133 @@ | ||
use nu_cmd_base::input_handler::{operate, CmdArgument}; | ||
use nu_engine::CallExt; | ||
use nu_protocol::{ | ||
ast::{Call, CellPath}, | ||
engine::{Command, EngineState, Stack}, | ||
Category, Example, IntoPipelineData, PipelineData, ShellError, Signature, Span, SyntaxShape, | ||
Type, Value, | ||
}; | ||
|
||
struct Arguments { | ||
cell_paths: Option<Vec<CellPath>>, | ||
} | ||
|
||
impl CmdArgument for Arguments { | ||
fn take_cell_paths(&mut self) -> Option<Vec<CellPath>> { | ||
self.cell_paths.take() | ||
} | ||
} | ||
|
||
#[derive(Clone)] | ||
pub struct SubCommand; | ||
|
||
impl Command for SubCommand { | ||
fn name(&self) -> &str { | ||
"into glob" | ||
} | ||
|
||
fn signature(&self) -> Signature { | ||
Signature::build("into glob") | ||
.input_output_types(vec![ | ||
(Type::String, Type::Glob), | ||
( | ||
Type::List(Box::new(Type::String)), | ||
Type::List(Box::new(Type::Glob)), | ||
), | ||
(Type::Table(vec![]), Type::Table(vec![])), | ||
(Type::Record(vec![]), Type::Record(vec![])), | ||
]) | ||
.allow_variants_without_examples(true) // https://github.com/nushell/nushell/issues/7032 | ||
.rest( | ||
"rest", | ||
SyntaxShape::CellPath, | ||
"For a data structure input, convert data at the given cell paths.", | ||
) | ||
.category(Category::Conversions) | ||
} | ||
|
||
fn usage(&self) -> &str { | ||
"Convert value to glob." | ||
} | ||
|
||
fn search_terms(&self) -> Vec<&str> { | ||
vec!["convert", "text"] | ||
} | ||
|
||
fn run( | ||
&self, | ||
engine_state: &EngineState, | ||
stack: &mut Stack, | ||
call: &Call, | ||
input: PipelineData, | ||
) -> Result<PipelineData, ShellError> { | ||
glob_helper(engine_state, stack, call, input) | ||
} | ||
|
||
fn examples(&self) -> Vec<Example> { | ||
vec![ | ||
Example { | ||
description: "convert string to glob", | ||
example: "'1234' | into glob", | ||
result: Some(Value::test_string("1234")), | ||
}, | ||
Example { | ||
description: "convert filepath to string", | ||
example: "ls Cargo.toml | get name | into glob", | ||
result: None, | ||
}, | ||
] | ||
} | ||
} | ||
|
||
fn glob_helper( | ||
engine_state: &EngineState, | ||
stack: &mut Stack, | ||
call: &Call, | ||
input: PipelineData, | ||
) -> Result<PipelineData, ShellError> { | ||
let head = call.head; | ||
let cell_paths = call.rest(engine_state, stack, 0)?; | ||
let cell_paths = (!cell_paths.is_empty()).then_some(cell_paths); | ||
let args = Arguments { cell_paths }; | ||
match input { | ||
PipelineData::ExternalStream { stdout: None, .. } => { | ||
Ok(Value::glob(String::new(), false, head).into_pipeline_data()) | ||
} | ||
PipelineData::ExternalStream { | ||
stdout: Some(stream), | ||
.. | ||
} => { | ||
// TODO: in the future, we may want this to stream out, converting each to bytes | ||
let output = stream.into_string()?; | ||
Ok(Value::glob(output.item, false, head).into_pipeline_data()) | ||
} | ||
_ => operate(action, args, input, head, engine_state.ctrlc.clone()), | ||
} | ||
} | ||
|
||
fn action(input: &Value, _args: &Arguments, span: Span) -> Value { | ||
match input { | ||
Value::String { val, .. } => Value::glob(val.to_string(), false, span), | ||
x => Value::error( | ||
ShellError::CantConvert { | ||
to_type: String::from("glob"), | ||
from_type: x.get_type().to_string(), | ||
span, | ||
help: None, | ||
}, | ||
span, | ||
), | ||
} | ||
} | ||
|
||
#[cfg(test)] | ||
mod test { | ||
use super::*; | ||
|
||
#[test] | ||
fn test_examples() { | ||
use crate::test_examples; | ||
|
||
test_examples(SubCommand {}) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.