= Vec::new();
let mut vertical: bool = false;
let mut show_files: bool = false;
for entry in fs::read_dir(search_path)? {
let path = &entry?.path();
if path.is_dir() {
dirs.push(path.to_path_buf());
println!("\t\t\t{:?}", path);
}
if path.is_file() {
files.push(path.to_path_buf());
if path.file_name().unwrap() == "vertical" {
vertical = true;
}
if path.file_name().unwrap() == "show_files" {
show_files = true;
}
println!("\t\t\t{:?}", path);
}
}
dirs.sort();
files.sort();
let in_path = in_path.canonicalize()?;
if vertical == true {
file.write_all(format!(r#"
"#).as_bytes())?;
} else {
file.write_all(format!(r#"
"#).as_bytes())?;
}
for dir in dirs {
let dir = dir.canonicalize()?;
let dir = dir.strip_prefix(&in_path)
.expect("could not strip in_path prefix");
let link = Path::new("/").join(dir);
let link_str = link.as_path().to_str().unwrap();
let name = link.file_name().unwrap().to_str().unwrap();
if name.starts_with(".") {
continue
}
file.write_all(format!(r#"
- {}/
"#, link_str, name).as_bytes())?;
println!("\t\t{} {}", link_str, name);
}
file.write_all(format!(r#"
"#).as_bytes())?;
if files.len() >= 1 && show_files == true {
file.write_all(format!(r#"
"#).as_bytes())?;
for f in files {
let f = f.canonicalize()?;
let f = f.strip_prefix(&in_path)
.expect("could not strip in_path prefix");
let link = Path::new("/").join(f);
let link_str = link.as_path().to_str().unwrap();
let name = link.file_name().unwrap().to_str().unwrap();
if name == "README.md"
|| name == "show_files"
|| name.starts_with(".")
{
continue
};
file.write_all(format!(r#"
- {}
"#, link_str, name).as_bytes())?;
println!("\t\t{} {}", link_str, name);
}
file.write_all(format!(r#"
"#).as_bytes())?;
}
Ok(())
}
fn write_readme_content(file: &mut File, in_path: &Path, raw_path: &Path)
-> std::io::Result<()> {
// define the path of the README.md file
let readme_file_path
= Path::new(in_path).join(raw_path).join("README.md");
// open the file and read it as a string
let mut readme_file = File::open(readme_file_path)?;
let mut readme = String::new();
readme_file.read_to_string(&mut readme)?;
file.write_all(format!("
").as_bytes())?;
// cheap markdown 2 html converter
for line in readme.split('\n') {
if line.starts_with("---") {
file.write_all(format!(r##"
"##).as_bytes())?;
} else if line.starts_with("###") {
let heading = line.get(4..).unwrap();
let heading_sanitized = sanitize(heading.to_string());
file.write_all(format!(r##"
"##, a = heading_sanitized, b = heading).as_bytes())?;
} else if line.starts_with("##") {
let heading = line.get(3..).unwrap();
let heading_sanitized = sanitize(heading.to_string());
file.write_all(format!(r##"
"##, a = heading_sanitized, b = heading).as_bytes())?;
} else if line.starts_with("#") {
let heading = line.get(2..).unwrap();
let heading_sanitized = sanitize(heading.to_string());
file.write_all(format!(r##"
"##, a = heading_sanitized, b = heading).as_bytes())?;
} else if line.starts_with("> ") {
let line = line.replace("<", "<");
let line = line.get(2..).unwrap();
file.write_all(format!("
{}
\n", line).as_bytes())?;
} else if line.starts_with(":::tree") {
// get all dirs in the current dir recursively
let tree_files_path = Path::new(in_path).join(raw_path);
let mut tree_files
= recursive_read_dir(&tree_files_path, true)?;
// sort them, otherwise we'll get complete chaos
tree_files.sort();
for path in tree_files {
// strip the inpath prefix and raw_path prefix, as we don't need
// them
let path
= path.strip_prefix(in_path)
.expect("could not strip in_file prefix")
.strip_prefix(raw_path)
.expect("could not strip raw_path prefix");
// write the link and the entry name to the file
let link = Path::new(raw_path).join(path);
let name = path.file_name().unwrap().to_str().unwrap();
if name.starts_with(".") {
continue
}
// count the amount of segments in the path and write spaces for
// each
let segments = path.iter().count();
for _ in 0..(segments-1) {
file.write_all(r#" "#.as_bytes())?;
}
file.write_all(
format!("{}\n",
link.display(), name,
).as_bytes()
)?;
}
} else if line.starts_with(":::toc") {
for line in readme.split('\n') {
if line.starts_with("###") {
let line = line.get(4..).unwrap();
file.write_all(
format!(
r##" {}
"##,
sanitize(line.to_string()),
line
).as_bytes()
)?;
} else if line.starts_with("##") {
let line = line.get(3..).unwrap();
file.write_all(
format!(
r##" {}
"##,
sanitize(line.to_string()),
line
).as_bytes()
)?;
} else if line.starts_with("#") {
let line = line.get(2..).unwrap();
file.write_all(
format!(
r##"{}
"##,
sanitize(line.to_string()),
line
).as_bytes()
)?;
}
}
} else {
// for the case that nothing of the above matches, just write the
// content into the html body as it is
file.write_all(format!("{}\n", line).as_bytes())?;
}
}
Ok(())
}
fn write_footer(file: &mut File) -> std::io::Result<()> {
file.write_all(format!(r#"
———
emile - {:?}
"#,
time::SystemTime::now()
.duration_since(time::SystemTime::UNIX_EPOCH).unwrap()
).as_bytes())?;
Ok(())
}
/// sanitize the given string (to lower + space to hypen + keep only
/// [a-zA-Z0-9])
fn sanitize(input: String) -> String {
let input = input.replace(" ", "-");
input
.chars()
.filter(|c| c.is_ascii_alphanumeric() || c.eq(&'-'))
.collect::()
.to_lowercase()
}
/// Return a list of all files in the directory, recursively.
fn recursive_read_dir(dir: &PathBuf, dir_only: bool) -> io::Result> {
// return an empty vec if the given path is not a directory
if dir.is_dir() == false {
return Ok(vec![]);
}
// get all entries in the gitignore file, if it exists
let gitignore_entries: Vec = gitignore_entries(&dir)?;
// store the child pathes
let mut entries: Vec = Vec::new();
// iterate over all items in the dir, pushing the dirs pathes to the dirs
// vector for returning it
'outer: for entry in fs::read_dir(dir)? {
let dir_entry = &entry?;
let path = dir_entry.path();
// check if the current entry is part of the gitignore, if so, skip it
for gitignore_entry in &gitignore_entries {
if gitignore_entry.to_str() == Some("") {
continue;
}
if path.ends_with(gitignore_entry) {
println!("gitignore: gitignore_entry: {:?}", gitignore_entry);
println!("gitignore: path: {:?}", path);
continue 'outer;
}
}
if dir_only == true {
if path.is_dir() {
entries.push(path.to_path_buf());
}
} else {
entries.push(path.to_path_buf());
}
// recursively push all dirs from all children to the dirs vector
let subdirs = recursive_read_dir(&path, dir_only)?;
for subdir in subdirs {
entries.push(subdir)
}
}
// return the dirs, the ones from this folder and the ones from all child folders
Ok(entries)
}
// try to open the gitignore file and read all entries from there.
fn gitignore_entries(dir: &PathBuf) -> io::Result> {
let gitignore_path = Path::new(&dir)
.join(Path::new(".gitignore"));
let mut entries: Vec = Vec::new();
if let Ok(gitignore) = File::open(&gitignore_path) {
let reader = BufReader::new(gitignore);
for line in reader.lines() {
entries.push(PathBuf::from(line?));
}
}
Ok(entries)
}