Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add the ability to have a list of glob excludes #9343

Merged
merged 1 commit into from Jun 2, 2023
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
58 changes: 41 additions & 17 deletions crates/nu-command/src/filesystem/glob.rs
@@ -1,6 +1,3 @@
use std::sync::atomic::AtomicBool;
use std::sync::Arc;

use nu_engine::env::current_dir;
use nu_engine::CallExt;
use nu_protocol::ast::Call;
Expand All @@ -9,6 +6,8 @@ use nu_protocol::{
Category, Example, IntoInterruptiblePipelineData, PipelineData, ShellError, Signature, Span,
Spanned, SyntaxShape, Type, Value,
};
use std::sync::atomic::AtomicBool;
use std::sync::Arc;
use wax::{Glob as WaxGlob, WalkBehavior, WalkEntry};

#[derive(Clone)]
Expand Down Expand Up @@ -46,8 +45,8 @@ impl Command for Glob {
)
.named(
"not",
SyntaxShape::String,
"Pattern to exclude from the results",
SyntaxShape::List(Box::new(SyntaxShape::String)),
"Patterns to exclude from the results",
Some('n'),
)
.category(Category::FileSystem)
Expand Down Expand Up @@ -112,10 +111,14 @@ impl Command for Glob {
},
Example {
description: "Search for files named tsconfig.json that are not in node_modules directories",
example: r#"glob **/tsconfig.json --not **/node_modules/**"#,
example: r#"glob **/tsconfig.json --not [**/node_modules/**]"#,
result: None,
},
Example {
description: "Search for all files that are not in the target nor .git directories",
example: r#"glob **/* --not [**/target/** **/.git/** */]"#,
result: None,
},

]
}

Expand All @@ -138,7 +141,18 @@ impl Command for Glob {
let no_dirs = call.has_flag("no-dir");
let no_files = call.has_flag("no-file");
let no_symlinks = call.has_flag("no-symlink");
let not_pattern: Option<Spanned<String>> = call.get_flag(engine_state, stack, "not")?;

let (not_patterns, not_pattern_span): (Vec<String>, Span) = if let Some(Value::List {
vals: pats,
span: pat_span,
}) =
call.get_flag(engine_state, stack, "not")?
{
let p = convert_patterns(pats.as_slice(), span)?;
(p, pat_span)
} else {
(vec![], span)
};

if glob_pattern.item.is_empty() {
return Err(ShellError::GenericError(
Expand Down Expand Up @@ -169,13 +183,8 @@ impl Command for Glob {
}
};

let (not_pat, not_span) = if let Some(not_pat) = not_pattern.clone() {
(not_pat.item, not_pat.span)
} else {
(String::new(), Span::test_data())
};

Ok(if not_pattern.is_some() {
Ok(if !not_patterns.is_empty() {
let np: Vec<&str> = not_patterns.iter().map(|s| s as &str).collect();
let glob_results = glob
.walk_with_behavior(
path,
Expand All @@ -184,12 +193,12 @@ impl Command for Glob {
..Default::default()
},
)
.not([not_pat.as_str()])
.not(np)
.map_err(|err| {
ShellError::GenericError(
"error with glob's not pattern".to_string(),
format!("{err}"),
Some(not_span),
Some(not_pattern_span),
None,
Vec::new(),
)
Expand Down Expand Up @@ -217,6 +226,21 @@ impl Command for Glob {
}
}

fn convert_patterns(columns: &[Value], span: Span) -> Result<Vec<String>, ShellError> {
let res = columns
.iter()
.map(|value| match &value {
Value::String { val: s, .. } => Ok(s.clone()),
_ => Err(ShellError::IncompatibleParametersSingle {
msg: "Incorrect column format, Only string as column name".to_string(),
span: value.span().unwrap_or(span),
}),
})
.collect::<Result<Vec<String>, _>>()?;

Ok(res)
}

fn glob_to_value<'a>(
ctrlc: Option<Arc<AtomicBool>>,
glob_results: impl Iterator<Item = WalkEntry<'a>>,
Expand Down