about summary refs log tree commit diff stats
path: root/sys/nixpkgs/pkgs/lf-make-map/src/mapping
diff options
context:
space:
mode:
authorBenedikt Peetz <benedikt.peetz@b-peetz.de>2024-05-05 14:02:09 +0200
committerBenedikt Peetz <benedikt.peetz@b-peetz.de>2024-05-05 14:02:09 +0200
commit47e3b82d0f8c9c4abcaf8588764fa934446dbdc8 (patch)
tree807f4874f1b945b82c00ec5cd666b4173bd09aab /sys/nixpkgs/pkgs/lf-make-map/src/mapping
parentfeat(pkgs/lf-make-map): Init (diff)
downloadnixos-config-47e3b82d0f8c9c4abcaf8588764fa934446dbdc8.zip
feat(pkgs/lf-make-map): Change the key to custom type and add visuals
Diffstat (limited to 'sys/nixpkgs/pkgs/lf-make-map/src/mapping')
-rw-r--r--sys/nixpkgs/pkgs/lf-make-map/src/mapping/map_tree.rs107
-rw-r--r--sys/nixpkgs/pkgs/lf-make-map/src/mapping/mod.rs145
2 files changed, 170 insertions, 82 deletions
diff --git a/sys/nixpkgs/pkgs/lf-make-map/src/mapping/map_tree.rs b/sys/nixpkgs/pkgs/lf-make-map/src/mapping/map_tree.rs
index 44165ed1..90296044 100644
--- a/sys/nixpkgs/pkgs/lf-make-map/src/mapping/map_tree.rs
+++ b/sys/nixpkgs/pkgs/lf-make-map/src/mapping/map_tree.rs
@@ -1,6 +1,6 @@
-use std::collections::HashMap;
+use std::{collections::HashMap, fmt::Display, path::PathBuf};
 
-use super::{error, Mapping};
+use super::{error, MapKey, Mapping};
 
 /// A prefix tree
 pub struct MappingTree {
@@ -9,33 +9,33 @@ pub struct MappingTree {
 
 #[derive(Clone)]
 pub struct Node {
-    children: HashMap<char, Node>,
+    children: HashMap<MapKey, Node>,
     value: Option<Mapping>,
 
     /// The key needed to get to this node
-    location: String,
+    location: Vec<MapKey>,
 }
 
 impl MappingTree {
     pub fn new() -> Self {
         Self {
-            root: Node::new(String::new(), None),
+            root: Node::new(vec![], None),
         }
     }
 
     /// Returns the node at the key, otherwise None
-    pub fn get(&self, key: &str) -> Option<&Node> {
+    pub fn get(&self, key: &[MapKey]) -> Option<&Node> {
         let mut current_node = &self.root;
-        for ch in key.chars() {
+        for ch in key.iter() {
             current_node = current_node.children.get(&ch)?
         }
 
         Some(current_node)
     }
     /// Returns the node at the key, otherwise None. The node can be changed
-    pub fn get_mut(&mut self, key: &str) -> Option<&mut Node> {
+    pub fn get_mut(&mut self, key: &[MapKey]) -> Option<&mut Node> {
         let mut current_node = &mut self.root;
-        for ch in key.chars() {
+        for ch in key.iter() {
             current_node = current_node.children.get_mut(&ch)?
         }
 
@@ -43,9 +43,9 @@ impl MappingTree {
     }
 
     /// Returns the node at the key, otherwise the last node that matched.
-    pub fn try_get(&self, key: &str) -> &Node {
+    pub fn try_get(&self, key: &[MapKey]) -> &Node {
         let mut current_node = &self.root;
-        for ch in key.chars() {
+        for ch in key.iter() {
             if let Some(node) = current_node.children.get(&ch) {
                 current_node = node;
             } else {
@@ -56,20 +56,22 @@ impl MappingTree {
         current_node
     }
 
-    pub fn insert(&mut self, key: &str, mapping: Mapping) -> Result<(), error::Error> {
+    pub fn insert(&mut self, key: &[MapKey], mapping: Mapping) -> Result<(), error::Error> {
         let node = self.try_get(key).clone();
-        if node.location.as_str() != key {
-            let needed_nodes_key = key.trim_start_matches(node.location.as_str());
-            let needed_nodes_length = needed_nodes_key.chars().count();
+        if node.location.as_slice() != key {
+            let needed_nodes_key = key
+                .strip_prefix(node.location.as_slice())
+                .expect("The node's location is a prefix");
+            let needed_nodes_length = needed_nodes_key.iter().count();
 
             let mut current_node = self
                 .get_mut(&node.location)
                 .expect("This should always exists");
             let mut current_location = node.location.clone();
-            let mut counter = 0;
+            let mut counter = 1;
 
-            for ch in needed_nodes_key.chars() {
-                current_location.push(ch);
+            for ch in needed_nodes_key.iter() {
+                current_location.push(ch.to_owned());
 
                 let next_node = if counter == needed_nodes_length {
                     Node::new(current_location.clone(), Some(mapping.clone()))
@@ -77,7 +79,7 @@ impl MappingTree {
                     Node::new(current_location.clone(), None)
                 };
 
-                current_node.children.insert(ch, next_node);
+                current_node.children.insert(ch.to_owned(), next_node);
                 current_node = current_node
                     .children
                     .get_mut(&ch)
@@ -85,7 +87,7 @@ impl MappingTree {
                 counter += 1;
             }
         } else {
-            return Err(error::Error::NodeExits(key.to_owned()));
+            return Err(error::Error::NodeExits(MapKey::display(key)));
         }
 
         Ok(())
@@ -93,7 +95,7 @@ impl MappingTree {
 }
 
 impl Node {
-    pub fn new(location: String, mapping: Option<Mapping>) -> Self {
+    pub fn new(location: Vec<MapKey>, mapping: Option<Mapping>) -> Self {
         Self {
             children: HashMap::new(),
             location,
@@ -101,3 +103,66 @@ impl Node {
         }
     }
 }
+
+impl Display for MappingTree {
+    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+        fn write_node(
+            node: &Node,
+            indention: String,
+            has_parent: bool,
+            is_last: bool,
+            f: &mut std::fmt::Formatter<'_>,
+        ) -> std::fmt::Result {
+            let bullet = if has_parent {
+                if is_last {
+                    String::from("└── ")
+                } else {
+                    String::from("├── ")
+                }
+            } else {
+                String::new()
+            };
+
+            let node_value = if let Some(value) = &node.value {
+                value.to_string()
+            } else {
+                "[No Value]".to_owned()
+            };
+
+            let new_idention = if !has_parent {
+                String::new()
+            } else if is_last {
+                indention.replace('│', " ") + "    "
+            } else {
+                indention.clone() + "│   "
+            };
+
+            write!(
+                f,
+                "{}{}\x1b[1;33m{}\x1b[0m: {}\n",
+                indention,
+                bullet,
+                MapKey::display(&node.location),
+                node_value,
+            )?;
+
+            let value_length = node.children.len();
+            let mut counter = 1;
+
+            for child in node.children.values() {
+                if counter == value_length {
+                    write_node(child, new_idention.clone(), true, true, f)?;
+                } else {
+                    write_node(child, new_idention.clone(), true, false, f)?;
+                };
+                counter += 1;
+            }
+
+            Ok(())
+        }
+
+        write_node(&self.root, String::new(), false, false, f)?;
+
+        Ok(())
+    }
+}
diff --git a/sys/nixpkgs/pkgs/lf-make-map/src/mapping/mod.rs b/sys/nixpkgs/pkgs/lf-make-map/src/mapping/mod.rs
index 7de1ca5d..d05d3417 100644
--- a/sys/nixpkgs/pkgs/lf-make-map/src/mapping/mod.rs
+++ b/sys/nixpkgs/pkgs/lf-make-map/src/mapping/mod.rs
@@ -1,4 +1,7 @@
-use std::path::{Path, PathBuf};
+use std::{
+    fmt::Display,
+    path::{Path, PathBuf},
+};
 
 use log::debug;
 
@@ -11,15 +14,42 @@ pub struct Mapping {
 
     pub keys: usize,
 
-    pub key: String,
+    pub key: Vec<MapKey>,
 }
+
+#[derive(Clone, Debug, PartialEq, PartialOrd, Ord, Hash, Eq)]
+pub struct MapKey {
+    value: String,
+}
+
+impl MapKey {
+    pub fn new(value: String) -> Self {
+        Self { value }
+    }
+    pub fn display(values: &[Self]) -> String {
+        values.iter().map(|value| value.value.clone()).collect()
+    }
+}
+
+impl Display for MapKey {
+    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+        f.write_str(&self.value)
+    }
+}
+
+impl Display for Mapping {
+    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+        write!(f, "{}", self.raw_path.display())
+    }
+}
+
 impl Mapping {
     pub fn new(home_path: &Path, initial_path: PathBuf) -> Mapping {
         let raw_path = initial_path
             .strip_prefix(home_path)
             .expect("Must always be under the `home_path`");
 
-        let key = Self::path_to_key(raw_path.to_str().expect("Should be a valid &str"));
+        let key = Self::path_to_keys(raw_path.to_str().expect("Should be a valid &str"));
 
         Self {
             raw_path: raw_path.to_owned(),
@@ -28,71 +58,64 @@ impl Mapping {
         }
     }
 
-    fn path_to_key(path: &str) -> String {
-        let key: String = path
-            .split('/')
-            .map(|part| part.chars().nth(0).expect("Must have a first element"))
-            .collect();
-        debug!("'{}' -> '{}'", path, key);
+    fn path_to_keys(path: &str) -> Vec<MapKey> {
+        let key: Vec<MapKey> = path.split('/').map(Self::part_path_to_key).collect();
+        debug!("Will insert: '{}' -> '{}'", path, MapKey::display(&key));
         key
     }
-}
 
-pub fn gen_hot_key(path: &Path, base_path: &Path, amount_of_chars: usize) -> String {
-    let path_filename_as_str = path
-        .file_name()
-        .expect("All paths here should have a file name")
-        .to_str()
-        .expect("The OSstr should be convertible");
-
-    let mut return_val = String::from("g");
-    if path != base_path {
-        return_val.push(
-            base_path
-                .file_name()
-                .expect("All paths here should have a file name")
-                .to_str()
-                .expect("The OSstr should be convertible")
-                .chars()
-                .nth(0)
-                .expect("All names should have a first char"),
-        );
-    }
-    if path_filename_as_str.contains("_") {
-        path_filename_as_str.split("_").for_each(|a| {
-            return_val.push(
-                a.chars()
-                    .nth(0)
-                    .expect("All names should have a first char"),
-            )
-        });
-    } else {
-        if path == base_path {
-            return_val.push(
-                path_filename_as_str
-                    .chars()
-                    .nth(0)
-                    .expect("All names should have a first char"),
-            );
+    fn part_path_to_key(part: &str) -> MapKey {
+        let value = if part.contains('_') {
+            part.split('_').filter_map(|ch| ch.chars().nth(0)).collect()
+        } else if part.contains('-') {
+            part.split('-').filter_map(|ch| ch.chars().nth(0)).collect()
         } else {
-            for a in 0..amount_of_chars {
-                return_val.push(if let Some(b) = path_filename_as_str.chars().nth(a) {
-                    b
-                } else {
-                    path_filename_as_str
-                        .chars()
-                        .nth(0)
-                        .expect("All names should have a first char")
-                });
-            }
-        }
-    }
-    if path == base_path {
-        return_val.push('.');
+            part.chars()
+                .nth(0)
+                .expect("Must have a first element")
+                .to_string()
+        };
+        MapKey::new(value)
     }
-    return_val
 }
 
+// pub fn gen_hot_key(path: &Path, base_path: &Path, amount_of_chars: usize) -> String {
+//     let mut return_val = String::from("g");
+//     if path_filename_as_str.contains("_") {
+//         path_filename_as_str.split("_").for_each(|a| {
+//             return_val.push(
+//                 a.chars()
+//                     .nth(0)
+//                     .expect("All names should have a first char"),
+//             )
+//         });
+//     } else {
+//         if path == base_path {
+//             return_val.push(
+//                 path_filename_as_str
+//                     .chars()
+//                     .nth(0)
+//                     .expect("All names should have a first char"),
+//             );
+//         } else {
+//             for a in 0..amount_of_chars {
+//                 return_val.push(if let Some(b) = path_filename_as_str.chars().nth(a) {
+//                     b
+//                 } else {
+//                     path_filename_as_str
+//                         .chars()
+//                         .nth(0)
+//                         .expect("All names should have a first char")
+//                 });
+//             }
+//         }
+//     }
+//     if path == base_path {
+//         return_val.push('.');
+//     }
+//     return_val
+// }
+
 #[cfg(test)]
 mod tests {
     use super::*;