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-09 11:10:36 +0200
committerBenedikt Peetz <benedikt.peetz@b-peetz.de>2024-05-09 11:10:36 +0200
commitf46d845f6c1218b8e38725be1339de28dc15396e (patch)
tree66476a8c425a0383b9203dedc8fc9a7f1466e223 /sys/nixpkgs/pkgs/lf-make-map/src
parentfeat(pkgs/lf-make-map): Ensure that it works (for a depth=1) (diff)
downloadnixos-config-f46d845f6c1218b8e38725be1339de28dc15396e.tar.gz
nixos-config-f46d845f6c1218b8e38725be1339de28dc15396e.zip
feat(pkgs/lf-make-map): Support depths > 2
Diffstat (limited to '')
-rw-r--r--sys/nixpkgs/pkgs/lf-make-map/src/main.rs128
-rw-r--r--sys/nixpkgs/pkgs/lf-make-map/src/mapping/map_tree/display.rs88
-rw-r--r--sys/nixpkgs/pkgs/lf-make-map/src/mapping/map_tree/iterator.rs45
-rw-r--r--sys/nixpkgs/pkgs/lf-make-map/src/mapping/map_tree/mod.rs (renamed from sys/nixpkgs/pkgs/lf-make-map/src/mapping/map_tree.rs)182
4 files changed, 315 insertions, 128 deletions
diff --git a/sys/nixpkgs/pkgs/lf-make-map/src/main.rs b/sys/nixpkgs/pkgs/lf-make-map/src/main.rs
index 362b28db..ccda1f14 100644
--- a/sys/nixpkgs/pkgs/lf-make-map/src/main.rs
+++ b/sys/nixpkgs/pkgs/lf-make-map/src/main.rs
@@ -1,10 +1,14 @@
-use anyhow::Context;
+use std::path::{Path, PathBuf};
+
+use anyhow::{Context, Result};
 use clap::Parser;
 use cli::Args;
-use log::trace;
+use log::{debug, trace};
 use mapping::map_tree::MappingTree;
 use walkdir::{DirEntry, WalkDir};
 
+use crate::mapping::MapKey;
+
 mod cli;
 mod mapping;
 
@@ -23,39 +27,64 @@ fn main() -> anyhow::Result<()> {
     let mut mappings = MappingTree::new();
 
     for dir in args.relevant_directories {
-        for dir2 in WalkDir::new(&dir)
-            .max_depth(args.depth)
-            .into_iter()
-            .filter_entry(|e| is_dir(e))
-        {
-            let directory =
-                dir2.with_context(|| format!("Failed to read dir ('{}')", &dir.display()))?;
-
-            let path = directory
-                .path()
-                .strip_prefix(&args.home_name)
-                .with_context(|| {
-                    format!(
-                        "'{}' is not under the specified home path ('{}')!",
-                        directory.path().display(),
-                        args.home_name.display()
-                    )
-                })?;
+        trace!("Processing '{}'..", dir.display());
+        let path = strip_path(&dir, &args.home_name)?;
 
-            mappings
-                .include(path.to_str().with_context(|| {
-                    format!(
-                        "\
-Can't derive a keymapping from path: '{}' \
-because it can't be turned to a string
-",
-                        path.display()
+        mappings
+            .include(path_to_str(path)?)
+            .with_context(|| format!("Failed to include path: '{}'", path.display()))?;
+    }
+
+    let home = path_to_str(&args.home_name)?.to_owned();
+
+    let mut current_depth = 1;
+    while current_depth != args.depth {
+        for (key, value) in mappings.iter() {
+            trace!(
+                "Adding to child ('{}' -> '{}')",
+                MapKey::display(&key),
+                value
+            );
+
+            let mut local_mappings = MappingTree::new();
+            for dir in WalkDir::new(extend(&home, &value)?)
+                .min_depth(1)
+                .max_depth(1)
+                .into_iter()
+                .filter_entry(|e| is_dir(e) && !is_hidden(e))
+            {
+                let directory = dir
+                    .with_context(|| format!("Failed to read dir ('{}')", home.clone() + &value))?;
+                let path_to_strip = &PathBuf::from(extend(&home, &value)?);
+                let path = strip_path(&directory.path(), &path_to_strip)?;
+                trace!(
+                    "Including: '{}' (after stripping '{}' from '{}' -> '{}' + '/' + '{}')",
+                    path.display(),
+                    directory.path().display(),
+                    path_to_strip.display(),
+                    home,
+                    value
+                );
+
+                let gen_key = MapKey::new_ones_from_path(path_to_str(path)?, 1);
+                local_mappings
+                    .insert(
+                        &gen_key,
+                        path_to_str(strip_path(&directory.path(), &PathBuf::from(&home))?)?,
                     )
-                })?)
-                .with_context(|| format!("Failed to include path: '{}'", path.display()))?;
+                    .with_context(|| format!("Failed to include path: '{}'", path.display()))?;
+            }
+
+            trace!("{}", local_mappings);
 
-            trace!("Processed '{}'..", directory.path().display());
+            trace!(
+                "'{}' -> '{:#?}'",
+                MapKey::display(&key),
+                local_mappings.root_node()
+            );
+            mappings.interleave(&key, local_mappings.root_node().to_owned())?;
         }
+        current_depth += 1;
     }
 
     println!("{}", mappings);
@@ -63,10 +92,47 @@ because it can't be turned to a string
     Ok(())
 }
 
+fn extend(base: &str, value: &str) -> Result<String> {
+    let base_path = PathBuf::from(base);
+    let value_path = PathBuf::from(value);
+
+    Ok(path_to_str(&base_path.join(&value_path))?.to_owned())
+}
+
+fn is_hidden(entry: &DirEntry) -> bool {
+    entry
+        .file_name()
+        .to_str()
+        .map(|s| s.starts_with("."))
+        .unwrap_or(false)
+}
+
 fn is_dir(entry: &DirEntry) -> bool {
     entry.file_type().is_dir()
 }
 
+fn strip_path<'a>(path: &'a Path, to_strip: &Path) -> Result<&'a Path> {
+    path.strip_prefix(&to_strip).with_context(|| {
+        format!(
+            "'{}' is not under the specified home path ('{}')!",
+            path.display(),
+            to_strip.display()
+        )
+    })
+}
+
+fn path_to_str(path: &Path) -> Result<&str> {
+    path.to_str().with_context(|| {
+        format!(
+            "\
+Can't derive a keymapping from path: '{}' \
+because it can't be turned to a string
+",
+            path.display()
+        )
+    })
+}
+
 // fn gen_lf_mappings(home_name: PathBuf, char_num: usize, rel_dirs: Vec<PathBuf>) {
 //     let mut mappings_vec = vec![];
 //     let mut index_counter = 0;
diff --git a/sys/nixpkgs/pkgs/lf-make-map/src/mapping/map_tree/display.rs b/sys/nixpkgs/pkgs/lf-make-map/src/mapping/map_tree/display.rs
new file mode 100644
index 00000000..778ade95
--- /dev/null
+++ b/sys/nixpkgs/pkgs/lf-make-map/src/mapping/map_tree/display.rs
@@ -0,0 +1,88 @@
+use std::fmt::Display;
+
+use crate::mapping::{
+    map_tree::{Node, NodeValue},
+    MapKey,
+};
+
+use super::MappingTree;
+
+impl Display for MappingTree {
+    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+        fn write_node(
+            f: &mut std::fmt::Formatter<'_>,
+            node: &Node,
+            indention: String,
+            location: Vec<MapKey>,
+            is_last: bool,
+            is_root: bool,
+        ) -> std::fmt::Result {
+            let node_value = match &node.value {
+                NodeValue::Parent { children: _ } => "<Parent>".to_owned(),
+                NodeValue::Child { path, extandable } => {
+                    path.to_owned() + if *extandable { " [exten.]" } else { " [stop]" }
+                }
+            };
+
+            let new_idention = indention.clone()
+                + if is_root {
+                    ""
+                } else {
+                    match is_last {
+                        true => "    ",
+                        false => "│   ",
+                    }
+                };
+
+            let bullet = match is_last {
+                true => String::from("└── "),
+                false => String::from("├── "),
+            };
+
+            if is_root {
+                write!(f, ": {}\n", node_value)?;
+            } else {
+                write!(
+                    f,
+                    "{}{}\x1b[1;33m{}\x1b[0m: {}\n",
+                    indention,
+                    bullet,
+                    MapKey::display(&location),
+                    node_value,
+                )?;
+            };
+
+            match &node.value {
+                NodeValue::Parent { children } => {
+                    let mut children_vec: Vec<(&MapKey, &Node)> = children.iter().collect();
+                    children_vec.sort_by(|(a, _), (b, _)| a.key.cmp(&b.key));
+
+                    let mut counter = 1;
+                    for (key, child) in &children_vec {
+                        let mut new_location = location.clone();
+                        new_location.push((*key).to_owned());
+
+                        write_node(
+                            f,
+                            child,
+                            new_idention.clone(),
+                            new_location.clone(),
+                            counter == children_vec.len(),
+                            false,
+                        )?;
+                        counter += 1;
+                    }
+                }
+                NodeValue::Child { path: _, extandable: _ } => {
+                    // Do nothing and stop the recursion
+                }
+            }
+
+            Ok(())
+        }
+
+        write_node(f, &self.root, String::new(), vec![], false, true)?;
+
+        Ok(())
+    }
+}
diff --git a/sys/nixpkgs/pkgs/lf-make-map/src/mapping/map_tree/iterator.rs b/sys/nixpkgs/pkgs/lf-make-map/src/mapping/map_tree/iterator.rs
new file mode 100644
index 00000000..33c27540
--- /dev/null
+++ b/sys/nixpkgs/pkgs/lf-make-map/src/mapping/map_tree/iterator.rs
@@ -0,0 +1,45 @@
+use crate::mapping::MapKey;
+
+use super::{MappingTree, Node, NodeValue};
+
+pub struct MappingTreeIterator {
+    children: Vec<(Vec<MapKey>, String)>,
+}
+
+impl MappingTreeIterator {
+    pub fn new(tree: &MappingTree) -> Self {
+        let children = extract_child(vec![], &tree.root);
+
+        Self { children }
+    }
+}
+
+fn extract_child(current_key: Vec<MapKey>, node: &Node) -> Vec<(Vec<MapKey>, String)> {
+    match &node.value {
+        NodeValue::Parent { children } => children
+            .iter()
+            .map(|(key, value)| {
+                let mut new_key = current_key.clone();
+                new_key.push(key.to_owned());
+
+                extract_child(new_key, value)
+            })
+            .flatten()
+            .collect(),
+        NodeValue::Child { path, extandable } => {
+            if *extandable {
+                vec![(current_key, path.to_string())]
+            } else {
+                vec![]
+            }
+        }
+    }
+}
+
+impl Iterator for MappingTreeIterator {
+    type Item = (Vec<MapKey>, String);
+
+    fn next(&mut self) -> Option<Self::Item> {
+        self.children.pop()
+    }
+}
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/mod.rs
index 02f040b7..44adc483 100644
--- a/sys/nixpkgs/pkgs/lf-make-map/src/mapping/map_tree.rs
+++ b/sys/nixpkgs/pkgs/lf-make-map/src/mapping/map_tree/mod.rs
@@ -1,11 +1,17 @@
-use std::{collections::HashMap, fmt::Display};
+use std::{collections::HashMap, mem};
 
 use anyhow::{bail, Result};
-use log::{debug, trace};
+use log::debug;
+
+use self::iterator::MappingTreeIterator;
 
 use super::MapKey;
 
+pub mod display;
+pub mod iterator;
+
 /// A prefix tree
+#[derive(Debug)]
 pub struct MappingTree {
     root: Node,
 }
@@ -13,7 +19,7 @@ pub struct MappingTree {
 #[derive(Clone, Debug, PartialEq, Eq)]
 pub enum NodeValue {
     Parent { children: HashMap<MapKey, Node> },
-    Child { path: String },
+    Child { path: String, extandable: bool },
 }
 
 #[derive(Clone, Debug, PartialEq, Eq)]
@@ -28,6 +34,14 @@ impl MappingTree {
         }
     }
 
+    pub fn root_node(&self) -> &Node {
+        &self.root
+    }
+
+    pub fn iter(&self) -> MappingTreeIterator {
+        MappingTreeIterator::new(&self)
+    }
+
     /// Returns the node at the key, otherwise None
     pub fn get(&self, key: &[MapKey]) -> Option<&Node> {
         let mut current_node = &self.root;
@@ -90,6 +104,61 @@ impl MappingTree {
         self.insert_node(key, Node::new_child(path.to_owned()))
     }
 
+    pub fn interleave(&mut self, key: &[MapKey], node: Node) -> Result<()> {
+        let want_to_be_parent = self.get_mut(&key).expect("This value exists");
+        let (parent_value, _parent_children) = if let NodeValue::Parent { children } = node.value {
+            (
+                NodeValue::Parent {
+                    children: children.clone(),
+                },
+                children,
+            )
+        } else {
+            unreachable!("This value will be a parent")
+        };
+
+        let child_value = mem::replace(&mut want_to_be_parent.value, parent_value);
+        assert!(matches!(
+            child_value,
+            NodeValue::Child {
+                path: _,
+                extandable: _
+            }
+        ));
+
+        let child_value = if let NodeValue::Child { path, extandable } = child_value {
+            NodeValue::Child {
+                path,
+                extandable: false,
+            }
+        } else {
+            unreachable!("This is only a child value")
+        };
+
+        let child = Node { value: child_value };
+
+        let mut new_key = key.to_vec();
+        new_key.push(MapKey {
+            key: '.',
+            part_path: ".".to_owned(),
+            resolution: 1,
+        });
+        self.insert_node(&new_key, child)?;
+        Ok(())
+    }
+
+    pub fn replace_node(&mut self, key: &[MapKey], node: Node) -> Node {
+        let parent = self.get_mut(&key[..key.len() - 1]).expect("Must be some");
+
+        if let NodeValue::Parent { children } = &mut parent.value {
+            children
+                .insert(key[key.len() - 1].clone(), node)
+                .expect("This must exist, otherwise insert would have been used")
+        } else {
+            unreachable!("All parent nodes should be parent nodes");
+        }
+    }
+
     pub fn insert_node(&mut self, key: &[MapKey], node: Node) -> Result<()> {
         let (_node, found_key) = self.try_get(key).clone();
 
@@ -129,7 +198,10 @@ impl MappingTree {
                         children.insert(ch.to_owned(), next_node);
                         children.get_mut(&ch).expect("Was just inserted")
                     }
-                    NodeValue::Child { path } => {
+                    NodeValue::Child {
+                        path,
+                        extandable: _,
+                    } => {
                         // A node that should be a parent was classified
                         // as child before:
                         //
@@ -287,11 +359,14 @@ Please rename the paths to fix this.
             );
 
             let parent = self
-                .get_mut(&found_key[..=&found_key.len() - 2])
+                .get_mut(&found_key[..&found_key.len() - 1])
                 .expect("This will exist");
 
             if let NodeValue::Parent { children } = &mut parent.value {
-                if let NodeValue::Child { path: _ } = children
+                if let NodeValue::Child {
+                    path: _,
+                    extandable: _,
+                } = children
                     .get(found_key.last().expect("Exists"))
                     .expect("This node also exists")
                     .value
@@ -333,7 +408,10 @@ Please rename the paths to fix this.
 impl Node {
     pub fn new_child(path: String) -> Self {
         Self {
-            value: NodeValue::Child { path },
+            value: NodeValue::Child {
+                path,
+                extandable: true,
+            },
         }
     }
     pub fn new_parent() -> Self {
@@ -344,93 +422,3 @@ impl Node {
         }
     }
 }
-
-impl Display for MappingTree {
-    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
-        fn write_node(
-            node: &Node,
-            indention: String,
-            location: Vec<MapKey>,
-            has_parent: bool,
-            is_last: bool,
-            f: &mut std::fmt::Formatter<'_>,
-        ) -> std::fmt::Result {
-            let node_value = match &node.value {
-                NodeValue::Parent { children: _ } => "<Parent>",
-                NodeValue::Child { path } => path,
-            };
-
-            let new_idention = if !has_parent {
-                String::new()
-            } else if is_last {
-                indention.replace('│', " ") + "    "
-            } else {
-                indention.clone() + "│   "
-            };
-
-            let bullet = if has_parent {
-                if is_last {
-                    String::from("└── ")
-                } else {
-                    String::from("├── ")
-                }
-            } else {
-                String::new()
-            };
-
-            write!(
-                f,
-                "{}{}\x1b[1;33m{}\x1b[0m: {}\n",
-                indention,
-                bullet,
-                MapKey::display(&location),
-                node_value,
-            )?;
-
-            match &node.value {
-                NodeValue::Parent { children } => {
-                    let value_length = children.len();
-                    let mut counter = 1;
-
-                    let mut children_vec: Vec<(&MapKey, &Node)> = children.iter().collect();
-                    children_vec.sort_by(|(a, _), (b, _)| a.key.cmp(&b.key));
-
-                    for (key, child) in children_vec {
-                        let mut new_location = location.clone();
-                        new_location.push(key.to_owned());
-
-                        if counter == value_length {
-                            write_node(
-                                child,
-                                new_idention.clone(),
-                                new_location.clone(),
-                                true,
-                                true,
-                                f,
-                            )?;
-                        } else {
-                            write_node(
-                                child,
-                                new_idention.clone(),
-                                new_location.clone(),
-                                true,
-                                false,
-                                f,
-                            )?;
-                        };
-                        counter += 1;
-                    }
-                }
-                NodeValue::Child { path: _ } => {
-                    // Do nothing and stop the recursion
-                }
-            }
-
-            Ok(())
-        }
-
-        write_node(&self.root, String::new(), vec![], false, false, f)?;
-
-        Ok(())
-    }
-}