globby/
lib.rs

1//! Globby is a library designed for searching all items in a given directory that match a *glob pattern*.
2//!
3//! # Examples
4//!
5//! ```rust
6//! use globby::{PatternOpts, glob_current_dir};
7//!
8//! let pattern = glob_current_dir("**/*.*").unwrap();
9//!
10//! for path in pattern {
11//!   println!("{}", path.unwrap().display());
12//! }
13//! ```
14//!
15//! This library should work on any platform.
16//!
17//! # Comparing to [`glob`](https://docs.rs/glob)
18//!
19//! The well-known glob library is more polished and has a lot more options, but also opinionated defaults that differ from this library, such as:
20//!
21//! * The base directory is not yielded in the results
22//! * Symbolic links are always followed
23//! * Directories are always yielded before their descendents
24//! * Alternate groups (matching either one sub-pattern or another) is supported
25//! * `**` matches anything, including files an hidden directories
26//!
27//!
28//! # Syntax
29//!
30//! See [`Pattern`].
31
32#![forbid(unsafe_code)]
33#![forbid(unused_must_use)]
34#![warn(unused_crate_dependencies)]
35
36mod compiler;
37mod fs_walker;
38mod parser;
39mod pattern;
40mod walker;
41
42use std::path::Path;
43
44use parsy::ParsingError;
45
46pub use self::{
47    fs_walker::NoIncomingDir,
48    pattern::{Pattern, PatternMatchResult, PatternOpts},
49    walker::Walker,
50};
51
52/// Match a pattern against a directory
53///
54/// For details on how patterns are applied, see [`Walker::new`]
55pub fn glob(pattern: &str, dir: &Path) -> Result<Walker, ParsingError> {
56    let pattern = Pattern::new(pattern)?;
57
58    Ok(Walker::new(pattern, dir))
59}
60
61/// Match a pattern against a directory
62///
63/// For details on how patterns are applied, see [`Walker::new`]
64pub fn glob_with(pattern: &str, dir: &Path, opts: PatternOpts) -> Result<Walker, ParsingError> {
65    let pattern = Pattern::new_with_opts(pattern, opts)?;
66
67    Ok(Walker::new(pattern, dir))
68}
69
70/// Match a pattern against the current directory
71///
72/// Strictly equivalent to calling [`glob`] with the canonicalized path to the current directory
73///
74/// For details on how patterns are applied, see [`Walker`]
75pub fn glob_current_dir(pattern: &str) -> Result<Walker, GlobError> {
76    let current_dir = std::env::current_dir().map_err(GlobError::FailedToGetCurrentDir)?;
77
78    glob(pattern, &current_dir).map_err(GlobError::InvalidPattern)
79}
80
81/// Match a pattern against the current directory
82///
83/// Strictly equivalent to calling [`glob`] with the canonicalized path to the current directory
84///
85/// For details on how patterns are applied, see [`Walker`]
86pub fn glob_current_dir_with(pattern: &str, opts: PatternOpts) -> Result<Walker, GlobError> {
87    let current_dir = std::env::current_dir().map_err(GlobError::FailedToGetCurrentDir)?;
88
89    glob_with(pattern, &current_dir, opts).map_err(GlobError::InvalidPattern)
90}
91
92/// Error occuring during glob execution
93#[derive(Debug)]
94pub enum GlobError {
95    /// The provided pattern is invalid
96    InvalidPattern(ParsingError),
97
98    /// Failed to get path to the current directory
99    FailedToGetCurrentDir(std::io::Error),
100}