use std::fmt;
use std::str::FromStr;
use crate::errors::Error;
use crate::node::{Node, Nodes};
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct Filetree {
root: Node,
}
impl Filetree {
pub fn new(root: Node) -> Filetree {
Filetree { root }
}
pub fn root(&self) -> &Node {
&self.root
}
#[cfg(feature = "color")]
pub fn color_display(&self) -> Result<String, Error> {
let mut s = String::new();
for node in self.root.nodes() {
s.push_str(&format!("{}\n", node.treeline_color(self)));
}
Ok(s)
}
}
impl fmt::Display for Filetree {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let mut s = String::new();
for node in self.root.nodes() {
s.push_str(&format!("{}\n", node.treeline(self)));
}
write!(f, "{}", s)
}
}
impl FromStr for Filetree {
type Err = Error;
fn from_str(s: &str) -> Result<Self, Self::Err> {
let value: serde_yaml::Value = serde_yaml::from_str(s)?;
let mut root = Node::new(".".into(), vec![], true);
let mut children: Nodes = value.try_into()?;
root.add_children(&mut children.0);
Ok(Filetree::new(root))
}
}
#[cfg(test)]
mod tests {
use textwrap::dedent;
use wasm_bindgen_test::wasm_bindgen_test;
use super::*;
macro_rules! test_filetree {
($name:ident, $s:expr, $expected:expr) => {
#[wasm_bindgen_test]
#[test]
fn $name() -> anyhow::Result<()> {
let filetree: Filetree = $s.parse()?;
println!("{}", filetree);
assert_eq!(format!("{}", filetree), format!("{}\n", $expected.trim()));
Ok(())
}
};
}
test_filetree!(empty, "", ".");
test_filetree!(
flat,
"
- dir1:
- file1.txt
- dir2:
",
dedent(
"
.
├── dir1
├── file1.txt
└── dir2
"
)
);
test_filetree!(
nested,
"
- dir1:
- file1.txt
- subdir1:
- subdir2:
- file2.py
- dir 2:
- subdir3:
- subsubdir:
- file3.toml
- subsubdir2:
- subdir4:
- config.ini
",
dedent(
"
.
├── dir1
│ ├── file1.txt
│ ├── subdir1
│ └── subdir2
│ └── file2.py
└── dir 2
├── subdir3
│ ├── subsubdir
│ │ └── file3.toml
│ └── subsubdir2
├── subdir4
└── config.ini
"
)
);
test_filetree!(
deeply_nested,
"
- dir1:
- dir2:
- dir3:
- file
- dir4:
- file2
- dir5:
- file3
- dir6:
- file4
",
dedent(
"
.
├── dir1
│ ├── dir2
│ │ ├── dir3
│ │ │ └── file
│ │ └── dir4
│ │ └── file2
│ └── dir5
│ └── file3
└── dir6
└── file4
"
)
);
test_filetree!(
same_filename,
"
- dir:
- file
- file
",
dedent(
"
.
├── dir
│ └── file
└── file
"
)
);
#[cfg(feature = "color")]
#[wasm_bindgen_test]
#[test]
fn color_display() {
use colored::Colorize;
let s = dedent(
"
- dir1:
- file1.txt
- dir2:
",
);
let expected: String = [
".".cyan().bold().to_string(),
format!("├── {}", "dir1".cyan().bold()),
"├── file1.txt".into(),
format!("└── {}", "dir2".cyan().bold()),
]
.into_iter()
.collect::<Vec<_>>()
.join("\n");
let filetree: Filetree = s.parse().unwrap();
println!("{}", filetree.color_display().unwrap());
assert_eq!(filetree.color_display().unwrap().trim(), expected);
}
}