diff options
author | Benedikt Peetz <benedikt.peetz@b-peetz.de> | 2024-05-09 11:10:36 +0200 |
---|---|---|
committer | Benedikt Peetz <benedikt.peetz@b-peetz.de> | 2024-05-09 11:10:36 +0200 |
commit | f46d845f6c1218b8e38725be1339de28dc15396e (patch) | |
tree | 66476a8c425a0383b9203dedc8fc9a7f1466e223 /sys/nixpkgs/pkgs | |
parent | feat(pkgs/lf-make-map): Ensure that it works (for a depth=1) (diff) | |
download | nixos-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.rs | 128 | ||||
-rw-r--r-- | sys/nixpkgs/pkgs/lf-make-map/src/mapping/map_tree/display.rs | 88 | ||||
-rw-r--r-- | sys/nixpkgs/pkgs/lf-make-map/src/mapping/map_tree/iterator.rs | 45 | ||||
-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(()) - } -} |