reingold-tilford 1.0.0

A Rust library for laying out aesthetically pleasing trees (the data structure, not the plant).
Documentation
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 {
		// Yes I know I'm assuming ASCII, but I'm making far bigger assumptions elsewhere.
		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 {
				// Ensure the graph doesn't get too large, since there's no fancy rendering.
				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('/');
		// Ignore current directory.
		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()
	});
}