From fa8b7d308f4d99222c061b456a99c80b389f15f2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Patrick=20Jos=C3=A9=20Pereira?= Date: Tue, 15 Apr 2025 09:15:55 -0300 Subject: [PATCH 1/4] README: Update with glob pattern MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Patrick José Pereira --- README.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/README.md b/README.md index 06be106026..70eb7facf4 100644 --- a/README.md +++ b/README.md @@ -31,6 +31,9 @@ let lib_rs = PROJECT_DIR.get_file("src/lib.rs").unwrap(); let body = lib_rs.contents_utf8().unwrap(); assert!(body.contains("SOME_INTERESTING_STRING")); +// you can filter which files are included using a glob pattern +static RUST_FILES: Dir = include_dir!("$CARGO_MANIFEST_DIR", "**/*.rs"); + // you can search for files (and directories) using glob patterns #[cfg(feature = "glob")] { From 3e1361f49e337cc1ec91c34267f949d20ea74b35 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Patrick=20Jos=C3=A9=20Pereira?= Date: Tue, 15 Apr 2025 09:17:16 -0300 Subject: [PATCH 2/4] include_dir: Update lib with glob pattern MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Patrick José Pereira --- include_dir/src/lib.rs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/include_dir/src/lib.rs b/include_dir/src/lib.rs index b9380b931c..e2524b2f00 100644 --- a/include_dir/src/lib.rs +++ b/include_dir/src/lib.rs @@ -33,7 +33,10 @@ //! let body = lib_rs.contents_utf8().unwrap(); //! assert!(body.contains("SOME_INTERESTING_STRING")); //! -//! // if you enable the `glob` feature, you can for files (and directories) using glob patterns +//! // you can filter which files are included using a glob pattern +//! static RUST_FILES: Dir<'_> = include_dir!("$CARGO_MANIFEST_DIR", "**/*.rs"); +//! +//! // or search for files (and directories) using glob patterns after inclusion //! #[cfg(feature = "glob")] //! { //! let glob = "**/*.rs"; From ef38b52e77444444afdfaa38b79ebcba32a5e05b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Patrick=20Jos=C3=A9=20Pereira?= Date: Tue, 15 Apr 2025 09:18:03 -0300 Subject: [PATCH 3/4] macros: Cargo: Add glob MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Patrick José Pereira --- macros/Cargo.toml | 1 + 1 file changed, 1 insertion(+) diff --git a/macros/Cargo.toml b/macros/Cargo.toml index 8990fbc7e4..2df8188cdb 100644 --- a/macros/Cargo.toml +++ b/macros/Cargo.toml @@ -17,6 +17,7 @@ proc-macro = true [dependencies] proc-macro2 = "1" quote = "1" +glob = "0.3" [features] nightly = [] From 4b047932000e3e58c93c0f2598e1ca7c76d25ec6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Patrick=20Jos=C3=A9=20Pereira?= Date: Tue, 15 Apr 2025 09:18:35 -0300 Subject: [PATCH 4/4] macros: Add glob argument MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Patrick José Pereira --- macros/src/lib.rs | 28 ++++++++++++++++++---------- 1 file changed, 18 insertions(+), 10 deletions(-) diff --git a/macros/src/lib.rs b/macros/src/lib.rs index 4a881f029b..16d93f58d7 100644 --- a/macros/src/lib.rs +++ b/macros/src/lib.rs @@ -12,20 +12,25 @@ use std::{ path::{Path, PathBuf}, time::SystemTime, }; +use glob::Pattern; /// Embed the contents of a directory in your crate. #[proc_macro] pub fn include_dir(input: TokenStream) -> TokenStream { let tokens: Vec<_> = input.into_iter().collect(); - let path = match tokens.as_slice() { - [TokenTree::Literal(lit)] => unwrap_string_literal(lit), - _ => panic!("This macro only accepts a single, non-empty string argument"), + let (path, glob_pattern) = match tokens.as_slice() { + [TokenTree::Literal(lit)] => (unwrap_string_literal(lit), None), + [TokenTree::Literal(lit1), TokenTree::Punct(_), TokenTree::Literal(lit2)] => { + (unwrap_string_literal(lit1), Some(unwrap_string_literal(lit2))) + } + _ => panic!("This macro accepts either a single string argument (directory path) or two string arguments (directory path and glob pattern)"), }; let path = resolve_path(&path, get_env).unwrap(); + let glob_pattern = glob_pattern.map(|p| Pattern::new(&p).expect("Invalid glob pattern")); - expand_dir(&path, &path).into() + expand_dir(&path, &path, glob_pattern.as_ref()).into() } fn unwrap_string_literal(lit: &proc_macro::Literal) -> String { @@ -40,7 +45,7 @@ fn unwrap_string_literal(lit: &proc_macro::Literal) -> String { repr } -fn expand_dir(root: &Path, path: &Path) -> proc_macro2::TokenStream { +fn expand_dir(root: &Path, path: &Path, glob_pattern: Option<&Pattern>) -> proc_macro2::TokenStream { let children = read_dir(path).unwrap_or_else(|e| { panic!( "Unable to read the entries in \"{}\": {}", @@ -53,15 +58,18 @@ fn expand_dir(root: &Path, path: &Path) -> proc_macro2::TokenStream { for child in children { if child.is_dir() { - let tokens = expand_dir(root, &child); + let tokens = expand_dir(root, &child, glob_pattern); child_tokens.push(quote! { include_dir::DirEntry::Dir(#tokens) }); } else if child.is_file() { - let tokens = expand_file(root, &child); - child_tokens.push(quote! { - include_dir::DirEntry::File(#tokens) - }); + let normalized_path = normalize_path(root, &child); + if glob_pattern.map_or(true, |p| p.matches(&normalized_path)) { + let tokens = expand_file(root, &child); + child_tokens.push(quote! { + include_dir::DirEntry::File(#tokens) + }); + } } else { panic!("\"{}\" is neither a file nor a directory", child.display()); }