summaryrefslogtreecommitdiffstats
path: root/src/path/special_path.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/path/special_path.rs')
-rw-r--r--src/path/special_path.rs84
1 files changed, 84 insertions, 0 deletions
diff --git a/src/path/special_path.rs b/src/path/special_path.rs
new file mode 100644
index 0000000..9462654
--- /dev/null
+++ b/src/path/special_path.rs
@@ -0,0 +1,84 @@
+use {
+ glob,
+ serde::{de::Error, Deserialize, Deserializer},
+ std::path::Path,
+};
+
+#[derive(Debug, Clone, PartialEq, Hash, Eq)]
+pub struct Glob {
+ pattern: glob::Pattern,
+}
+
+#[derive(Debug, Clone, Copy, PartialEq)]
+pub enum SpecialHandling {
+ None,
+ Enter,
+ NoEnter,
+ Hide,
+}
+
+#[derive(Debug, Clone)]
+pub struct SpecialPath {
+ pub pattern: glob::Pattern,
+ pub handling: SpecialHandling,
+}
+
+pub trait SpecialPathList {
+ fn find(self, path: &Path) -> SpecialHandling;
+}
+
+impl<'de> Deserialize<'de> for SpecialHandling {
+ fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
+ where D: Deserializer<'de>
+ {
+ let s = String::deserialize(deserializer)?;
+ let s = s.to_lowercase();
+ // we remove non letters so to accept eg "no-enter"
+ let s = regex!(r"\W+").replace_all(&s, "");
+ match s.as_ref() {
+ "none" => Ok(SpecialHandling::None),
+ "enter" => Ok(SpecialHandling::Enter),
+ "noenter" => Ok(SpecialHandling::NoEnter),
+ "hide" => Ok(SpecialHandling::Hide),
+ _ => Err(D::Error::custom(format!(
+ "unrecognized special handling: {:?}",
+ s
+ ))),
+ }
+ }
+}
+
+impl<'de> Deserialize<'de> for Glob {
+ fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
+ where D: Deserializer<'de>
+ {
+ let s = String::deserialize(deserializer)?;
+ glob::Pattern::new(&s)
+ .map_err(|e| D::Error::custom(format!("invalid glob pattern {:?} : {:?}", s, e)))
+ .map(|pattern| Glob { pattern })
+ }
+}
+
+impl SpecialPath {
+ pub fn new(glob: Glob, handling: SpecialHandling) -> Self {
+ Self {
+ pattern: glob.pattern,
+ handling,
+ }
+ }
+ pub fn can_have_matches_in(&self, path: &Path) -> bool {
+ path.to_str()
+ .map_or(false, |p| self.pattern.as_str().starts_with(p))
+ }
+}
+
+impl SpecialPathList for &[SpecialPath] {
+ fn find(self, path: &Path) -> SpecialHandling {
+ for sp in self {
+ if sp.pattern.matches_path(path) {
+ return sp.handling;
+ }
+ }
+ SpecialHandling::None
+ }
+}