1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98
//! Include/Exclude file pattern matching. //! //! This implements a glob `Pattern` similar to `git`'s matching done in include/exclude files, and //! some helper methods to figure out whether a file should be included given its designated path //! and a list of include/exclude patterns. //! //! Here's a rather long matching example: //! //! ``` //! # use pathpatterns::*; //! # fn test() -> Result<(), Box<dyn std::error::Error + Send + Sync + 'static>> { //! let file_list: &'static [&'static [u8]] = &[ //! b"/things", //! b"/things/file1.dat", //! b"/things/file2.dat", //! b"/things/shop", //! b"/things/shop/info.txt", //! b"/things/shop/apples", //! b"/things/shop/apples/gala.txt", //! b"/things/shop/apples/golden-delicious.txt", //! b"/things/shop/bananas", //! b"/things/shop/bananas/straight.txt", //! b"/things/shop/bananas/curved.txt", //! b"/things/shop/bananas/curved.bak", //! b"/things/shop/bananas/other.txt", //! ]; //! //! let mut list = vec![ //! MatchEntry::include(Pattern::path("shop")?), //! MatchEntry::exclude(Pattern::path("bananas")?), //! MatchEntry::include(Pattern::path("bananas/curved.*")?), //! ]; //! //! assert_eq!(list.matches("/things", None), None); //! assert_eq!(list.matches("/things/shop", None), Some(MatchType::Include)); //! assert_eq!(list.matches("/things/shop/bananas", None), Some(MatchType::Exclude)); //! assert_eq!(list.matches("/things/shop/bananas/curved.txt", None), Some(MatchType::Include)); //! assert_eq!(list.matches("/things/shop/bananas/curved.bak", None), Some(MatchType::Include)); //! //! // this will exclude the curved.bak file //! list.push(MatchEntry::exclude(Pattern::path("curved.bak")?)); //! assert_eq!(list.matches("/things/shop/bananas/curved.bak", None), Some(MatchType::Exclude)); //! list.pop(); //! # assert_eq!(list.matches("/things/shop/bananas/curved.bak", None), Some(MatchType::Include)); //! //! // but this will not: //! list.push( //! MatchEntry::new(Pattern::path("curved.bak")?, MatchType::Exclude) //! .flags(MatchFlag::ANCHORED) //! ); //! // or: list.push //! assert_eq!(list.matches("/things/shop/bananas/curved.bak", None), Some(MatchType::Include)); //! list.pop(); //! //! // let's check some patterns, anything starting with a 'c', 'f' or 's': //! let mut list = vec![MatchEntry::include(Pattern::path("[cfs]*")?)]; //! assert_eq!(list.matches("/things", None), None); //! assert_eq!(list.matches("/things/file1.dat", None), Some(MatchType::Include)); //! assert_eq!(list.matches("/things/file2.dat", None), Some(MatchType::Include)); //! assert_eq!(list.matches("/things/shop", None), Some(MatchType::Include)); //! assert_eq!(list.matches("/things/shop/info.txt", None), None); //! assert_eq!(list.matches("/things/shop/apples", None), None); //! assert_eq!(list.matches("/things/shop/apples/gala.txt", None), None); //! assert_eq!(list.matches("/things/shop/apples/golden-delicious.txt", None), None); //! assert_eq!(list.matches("/things/shop/bananas", None), None); //! assert_eq!(list.matches("/things/shop/bananas/straight.txt", None), Some(MatchType::Include)); //! assert_eq!(list.matches("/things/shop/bananas/curved.txt", None), Some(MatchType::Include)); //! assert_eq!(list.matches("/shop/bananas/curved.bak", None), Some(MatchType::Include)); //! assert_eq!(list.matches("/things/shop/bananas/other.txt", None), None); //! //! // If we add `**` we end up including the entire `shop/` subtree: //! list.push(MatchEntry::include(Pattern::path("[cfs]*/**")?)); //! assert_eq!(list.matches("/things", None), None); //! assert_eq!(list.matches("/things/file1.dat", None), Some(MatchType::Include)); //! assert_eq!(list.matches("/things/file2.dat", None), Some(MatchType::Include)); //! assert_eq!(list.matches("/things/shop", None), Some(MatchType::Include)); //! assert_eq!(list.matches("/things/shop/info.txt", None), Some(MatchType::Include)); //! assert_eq!(list.matches("/things/shop/apples", None), Some(MatchType::Include)); //! assert_eq!(list.matches("/things/shop/apples/gala.txt", None), Some(MatchType::Include)); //! assert_eq!(list.matches("/shop/apples/golden-delicious.txt", None), Some(MatchType::Include)); //! assert_eq!(list.matches("/things/shop/bananas", None), Some(MatchType::Include)); //! assert_eq!(list.matches("/things/shop/bananas/straight.txt", None), Some(MatchType::Include)); //! assert_eq!(list.matches("/things/shop/bananas/curved.txt", None), Some(MatchType::Include)); //! assert_eq!(list.matches("/shop/bananas/curved.bak", None), Some(MatchType::Include)); //! assert_eq!(list.matches("/shop/bananas/other.txt", None), Some(MatchType::Include)); //! # Ok(()) //! # } //! # test().unwrap() //! ``` mod match_list; mod pattern; #[doc(inline)] pub use match_list::{MatchEntry, MatchFlag, MatchList, MatchPattern, MatchType}; #[doc(inline)] pub use pattern::{ParseError, Pattern, PatternFlag};