mirror of
https://github.com/nushell/nushell.git
synced 2025-05-08 00:42:57 +00:00
* Test commands for proper names and search terms Assert that the `Command.name()` is equal to `Signature.name` Check that search terms are not just substrings of the command name as they would not help finding the command. * Clean up search terms Remove redundant terms that just replicate the command name. Try to eliminate substring between search terms, clean up where necessary.
142 lines
4.4 KiB
Rust
142 lines
4.4 KiB
Rust
use nu_engine::env::current_dir;
|
|
use nu_engine::CallExt;
|
|
use nu_protocol::ast::Call;
|
|
use nu_protocol::engine::{Command, EngineState, Stack};
|
|
use nu_protocol::{
|
|
Category, Example, IntoInterruptiblePipelineData, PipelineData, ShellError, Signature, Spanned,
|
|
SyntaxShape, Value,
|
|
};
|
|
use wax::{Glob as WaxGlob, WalkBehavior};
|
|
|
|
#[derive(Clone)]
|
|
pub struct Glob;
|
|
|
|
impl Command for Glob {
|
|
fn name(&self) -> &str {
|
|
"glob"
|
|
}
|
|
|
|
fn signature(&self) -> Signature {
|
|
Signature::build("glob")
|
|
.required("glob", SyntaxShape::String, "the glob expression")
|
|
.named(
|
|
"depth",
|
|
SyntaxShape::Int,
|
|
"directory depth to search",
|
|
Some('d'),
|
|
)
|
|
.category(Category::FileSystem)
|
|
}
|
|
|
|
fn usage(&self) -> &str {
|
|
"Creates a list of files and/or folders based on the glob pattern provided."
|
|
}
|
|
|
|
fn search_terms(&self) -> Vec<&str> {
|
|
vec!["pattern", "files", "folders", "list", "ls"]
|
|
}
|
|
|
|
fn examples(&self) -> Vec<Example> {
|
|
vec![
|
|
Example {
|
|
description: "Search for *.rs files",
|
|
example: "glob *.rs",
|
|
result: None,
|
|
},
|
|
Example {
|
|
description: "Search for *.rs and *.toml files recursively up to 2 folders deep",
|
|
example: "glob **/*.{rs,toml} --depth 2",
|
|
result: None,
|
|
},
|
|
Example {
|
|
description:
|
|
"Search for files and folders that begin with uppercase C and lowercase c",
|
|
example: r#"glob "[Cc]*""#,
|
|
result: None,
|
|
},
|
|
Example {
|
|
description:
|
|
"Search for files and folders like abc or xyz substituting a character for ?",
|
|
example: r#"glob "{a?c,x?z}""#,
|
|
result: None,
|
|
},
|
|
Example {
|
|
description: "A case-insensitive search for files and folders that begin with c",
|
|
example: r#"glob "(?i)c*""#,
|
|
result: None,
|
|
},
|
|
Example {
|
|
description: "Search for files for folders that do not begin with c, C, b, M, or s",
|
|
example: r#"glob "[!cCbMs]*""#,
|
|
result: None,
|
|
},
|
|
Example {
|
|
description: "Search for files or folders with 3 a's in a row in the name",
|
|
example: "glob <a*:3>",
|
|
result: None,
|
|
},
|
|
Example {
|
|
description: "Search for files or folders with only a, b, c, or d in the file name between 1 and 10 times",
|
|
example: "glob <[a-d]:1,10>",
|
|
result: None,
|
|
},
|
|
]
|
|
}
|
|
|
|
fn extra_usage(&self) -> &str {
|
|
r#"For more glob pattern help please refer to https://github.com/olson-sean-k/wax"#
|
|
}
|
|
|
|
fn run(
|
|
&self,
|
|
engine_state: &EngineState,
|
|
stack: &mut Stack,
|
|
call: &Call,
|
|
_input: PipelineData,
|
|
) -> Result<PipelineData, ShellError> {
|
|
let span = call.head;
|
|
let path = current_dir(engine_state, stack)?;
|
|
let glob_pattern: Spanned<String> = call.req(engine_state, stack, 0)?;
|
|
let depth = call.get_flag(engine_state, stack, "depth")?;
|
|
|
|
let folder_depth = if let Some(depth) = depth {
|
|
depth
|
|
} else {
|
|
usize::MAX
|
|
};
|
|
|
|
let glob = match WaxGlob::new(&glob_pattern.item) {
|
|
Ok(p) => p,
|
|
Err(e) => {
|
|
return Err(ShellError::GenericError(
|
|
"error with glob pattern".to_string(),
|
|
"".to_string(),
|
|
None,
|
|
Some(format!("{}", e)),
|
|
Vec::new(),
|
|
))
|
|
}
|
|
};
|
|
|
|
#[allow(clippy::needless_collect)]
|
|
let glob_results: Vec<Value> = glob
|
|
.walk_with_behavior(
|
|
path,
|
|
WalkBehavior {
|
|
depth: folder_depth,
|
|
..Default::default()
|
|
},
|
|
)
|
|
.flatten()
|
|
.map(|entry| Value::String {
|
|
val: entry.into_path().to_string_lossy().to_string(),
|
|
span,
|
|
})
|
|
.collect();
|
|
|
|
Ok(glob_results
|
|
.into_iter()
|
|
.into_pipeline_data(engine_state.ctrlc.clone()))
|
|
}
|
|
}
|