extern crate petgraph;
extern crate reingold_tilford;
mod utils;
use petgraph::graph;
const DIRS: &'static str = include_str!("../assets/open-source-directory-structure.txt");
struct Graph<'n>(graph::Graph<&'n str, ()>);
impl<'n> reingold_tilford::NodeInfo<graph::NodeIndex> for Graph<'n> {
type Key = graph::NodeIndex;
fn key(&self, node: graph::NodeIndex) -> Self::Key {
node
}
fn children(&self, node: graph::NodeIndex) -> reingold_tilford::SmallVec<graph::NodeIndex> {
self.0.neighbors(node).collect()
}
fn dimensions(&self, node: graph::NodeIndex) -> reingold_tilford::Dimensions {
let letters = self.0.node_weight(node).unwrap().as_bytes().len() as f64;
reingold_tilford::Dimensions {
top: 0.5,
right: letters / 2.0,
bottom: 0.5,
left: letters / 2.0,
}
}
fn border(&self, _node: graph::NodeIndex) -> reingold_tilford::Dimensions {
reingold_tilford::Dimensions::all(1.5)
}
}
fn child(graph: &Graph, node: graph::NodeIndex, name: &str) -> Option<graph::NodeIndex> {
for neighbor in graph.0.neighbors(node) {
if graph.0.node_weight(neighbor) == Some(&name) {
return Some(neighbor);
}
}
None
}
fn add_path<'n>(
graph: &mut Graph<'n>,
mut node: graph::NodeIndex,
path: impl Iterator<Item = &'n str>,
) {
for dir in path {
if let Some(child) = child(graph, node, dir) {
node = child;
} else {
if graph.0.neighbors(node).collect::<Vec<_>>().len() >= 3 {
break;
}
let child = graph.0.add_node(dir);
graph.0.add_edge(node, child, ());
node = child;
}
}
}
fn tree<'n>() -> (Graph<'n>, graph::NodeIndex) {
let mut graph = Graph(graph::Graph::new());
let root = graph.0.add_node(".");
for line in DIRS.lines() {
let mut path = line.split('/');
assert_eq!(Some("."), path.next());
add_path(&mut graph, root, path);
}
(graph, root)
}
fn main() {
let (tree, root) = tree();
let layout = reingold_tilford::layout(&tree, root);
utils::display(&tree, root, &layout, |t, n| {
(*t.0.node_weight(n).unwrap()).into()
});
}