Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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")]
{
Expand Down
5 changes: 4 additions & 1 deletion include_dir/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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";
Expand Down
1 change: 1 addition & 0 deletions macros/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ proc-macro = true
[dependencies]
proc-macro2 = "1"
quote = "1"
glob = "0.3"

[features]
nightly = []
Expand Down
28 changes: 18 additions & 10 deletions macros/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand All @@ -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 \"{}\": {}",
Expand All @@ -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());
}
Expand Down