about summary refs log tree commit diff stats
path: root/sys/nixpkgs/pkgs/lf-make-map/src
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
parentfeat(pkgs/lf-make-map): Init (diff)
downloadnixos-config-47e3b82d0f8c9c4abcaf8588764fa934446dbdc8.tar.gz
nixos-config-47e3b82d0f8c9c4abcaf8588764fa934446dbdc8.zip
feat(pkgs/lf-make-map): Change the key to custom type and add visuals
Diffstat (limited to '')
-rw-r--r--sys/nixpkgs/pkgs/lf-make-map/src/generator/mod.rs16
-rw-r--r--sys/nixpkgs/pkgs/lf-make-map/src/generator/mod.rs.old165
-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
4 files changed, 181 insertions, 252 deletions
diff --git a/sys/nixpkgs/pkgs/lf-make-map/src/generator/mod.rs b/sys/nixpkgs/pkgs/lf-make-map/src/generator/mod.rs
index 48df027f..c03b33dc 100644
--- a/sys/nixpkgs/pkgs/lf-make-map/src/generator/mod.rs
+++ b/sys/nixpkgs/pkgs/lf-make-map/src/generator/mod.rs
@@ -1,10 +1,10 @@
 use std::path::PathBuf;
 
 use anyhow::{Context, Result};
-use log::{debug, info, trace};
+use log::trace;
 use walkdir::{DirEntry, WalkDir};
 
-use crate::mapping::{map_tree::MappingTree, Mapping};
+use crate::mapping::{map_tree::MappingTree, MapKey, Mapping};
 
 pub struct MappingsGenerator {
     mappings: MappingTree,
@@ -35,9 +35,15 @@ impl MappingsGenerator {
                 trace!("Processed '{}'..", directory.path().display());
 
                 let mapping = Mapping::new(&home_path, directory.path().to_path_buf());
-                mappings
-                    .insert(&mapping.key.clone(), mapping)
-                    .context("Failed to insert a key")?;
+                let mapping_key = mapping.key.clone();
+                mappings.insert(&mapping_key, mapping).with_context(|| {
+                    format!(
+                        "Failed to insert '{}' for path: '{}'\nMapTree is now: \n{}",
+                        MapKey::display(&mapping_key),
+                        directory.path().display(),
+                        mappings,
+                    )
+                })?;
             }
         }
         todo!()
diff --git a/sys/nixpkgs/pkgs/lf-make-map/src/generator/mod.rs.old b/sys/nixpkgs/pkgs/lf-make-map/src/generator/mod.rs.old
deleted file mode 100644
index 406b1996..00000000
--- a/sys/nixpkgs/pkgs/lf-make-map/src/generator/mod.rs.old
+++ /dev/null
@@ -1,165 +0,0 @@
-use std::{
-    collections::HashMap,
-    path::{Path, PathBuf},
-};
-
-use anyhow::{bail, Context, Result};
-use futures::{Stream, StreamExt, TryStreamExt};
-use log::info;
-use tokio::{
-    fs::{self, DirEntry},
-    io,
-    sync::mpsc::{self, Receiver, Sender},
-    task::JoinHandle,
-};
-use tokio_stream::wrappers::{ReadDirStream, ReceiverStream};
-
-pub struct MappingGenerator {
-    current_mappings: HashMap<String, PathBuf>,
-    paths_to_process: Vec<PathBuf>,
-}
-
-pub struct MappingGeneratorHelper {
-    tx: Sender<(PathBuf, oneshotSender<PathBuf>)>,
-    handle: JoinHandle<()>,
-    done: Vec<PathBuf>,
-}
-
-impl MappingGeneratorHelper {
-    pub fn new() -> Self {
-        let (rx, tx) = mpsc::channel(100);
-
-        let handle = tokio::spawn(async move {
-            while let Some(dir) = rx.recv().await {
-                info!("processing '{}'..", dir.display());
-                get_dir(dir);
-            }
-        });
-
-        Self { tx, handle }
-    }
-
-    pub async fn process(&self, dir: PathBuf) -> Result<()> {
-        let (tx, rx) =
-        self.tx.send(dir).await?;
-        Ok(())
-    }
-}
-
-impl MappingGenerator {
-    pub async fn new(directories_to_scan: Vec<PathBuf>, depth: usize) -> Result<Self> {
-        let cleaned_directories: Vec<PathBuf> = directories_to_scan
-            .into_iter()
-            .map(check_dir)
-            .collect::<Result<_>>()?;
-
-        let helper = MappingGeneratorHelper::new();
-
-        cleaned_directories
-            .into_iter()
-            .for_each(|dir| helper.process(dir));
-
-        info!(
-            "Will process:\n  {}",
-            all_directories
-                .iter()
-                .map(|pat| pat.display().to_string())
-                .collect::<Vec<_>>()
-                .join("\n  ")
-        );
-        Ok(Self {
-            current_mappings: HashMap::new(),
-            paths_to_process: all_directories,
-        })
-    }
-}
-
-fn check_dir(dir: PathBuf) -> Result<PathBuf> {
-    match dir.metadata() {
-        Ok(_) => Ok(dir),
-        Err(e) => bail!(
-            "'{}' is not a valid path; Error was: '{}'",
-            dir.display(),
-            e
-        ),
-    }
-}
-
-pub async fn get_dir(dir: PathBuf, current_depth: usize, max_depth: usize) -> Result<Vec<PathBuf>> {
-    let (tx, rx) = mpsc::channel(100);
-
-    let handle = tokio::spawn(async move { get_dir_recursive(dir, current_depth, max_depth, tx) });
-
-    let out = ReceiverStream::new(rx).collect::<Vec<PathBuf>>().await;
-    handle.await?;
-    Ok(out)
-}
-
-async fn get_dir_recursive(
-    dir: PathBuf,
-    current_depth: usize,
-    max_depth: usize,
-    tx: Sender<PathBuf>,
-) -> Result<()> {
-    if dir.is_dir() && current_depth != max_depth {
-        tx.send(dir).await?;
-
-        match fs::read_dir(&dir).await {
-            Ok(directories) => {
-                let mut handles: Vec<JoinHandle<Result<(), anyhow::Error>>> = vec![];
-                while let Some(entry) = directories
-                    .next_entry()
-                    .await
-                    .with_context(|| format!("Failed to read directory: '{}'", dir.display()))?
-                {
-                    let tx_new = tx.clone();
-                    handles.push(tokio::spawn(async move {
-                        get_dir_recursive(entry.path(), current_depth + 1, max_depth, tx_new)
-                            .await
-                            .with_context(|| {
-                                format!("Failed to get child directories to '{}'", dir.display())
-                            })?;
-
-                        Ok(())
-                    }));
-                }
-
-                let out: Vec<_> = tokio_stream::iter(handles)
-                    .then(|handle| async move { handle.await })
-                    .collect()
-                    .await;
-
-                // I have no idea what happened here to the type system
-                for i in out {
-                    i??
-                }
-
-                Ok(())
-            }
-
-            Err(e) => {
-                bail!(
-                    "Unable to read directory {}, skipping; error: {}",
-                    dir.display(),
-                    e
-                );
-            }
-        }
-    } else {
-        return Ok(());
-    }
-}
-
-#[cfg(test)]
-mod test {
-    use std::path::PathBuf;
-
-    use super::get_dir;
-
-    #[test]
-    fn test_get_dir() {
-        let dirs = get_dir(PathBuf::from("~/repos"));
-        let expected_dirs = vec![PathBuf::from("~/repos/rust")];
-        assert_eq!(dirs, expected_dirs);
-    }
-}
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::*;