diff --git a/src/main.rs b/src/main.rs index d66cd5b..f9e333d 100644 --- a/src/main.rs +++ b/src/main.rs @@ -178,7 +178,7 @@ fn get_file(request: &Request) -> Option<(Content, bool)> { } fn generate_index(relative_path: &str, path: &Path) -> Option { - let mut dirs: Vec<_> = path + let mut items: Vec<_> = path .read_dir() .ok()? .flatten() @@ -196,28 +196,44 @@ fn generate_index(relative_path: &str, path: &Path) -> Option { d.file_name().to_str().map(|s| (s.to_owned(), size)) }) .collect(); - dirs.sort_by(|(name_a, size_a), (name_b, size_b)| { + items.sort_by(|(name_a, size_a), (name_b, size_b)| { size_a .is_some() .cmp(&size_b.is_some()) .then(name_a.cmp(name_b)) }); - let list = dirs + let items: Vec<_> = items .into_iter() .map(|(name, size)| { - let formatted_size = size.map(format_size).unwrap_or_default(); - format!( - "{name}{trailing_slash}{formatted_size}\n", - href = PathBuf::from(relative_path).join(&name).display(), - trailing_slash = if size.is_some() { "" } else { "/" }, - ) + let href = PathBuf::from(relative_path) + .join(&name) + .display() + .to_string(); + let trailing_slash = if size.is_some() { "" } else { "/" }; + let filename = format!("{name}{trailing_slash}"); + + let link = format!("{filename}"); + let size = size.map(format_size).unwrap_or_default() + "\n"; + // NOTE: emojis in filenames will probably cause misalignment + let width = filename.chars().count(); + (link, size, width) }) - .fold(String::new(), |mut content, entry| { - content.push_str(&entry); - content - }); + .collect(); + + let name_width = items + .iter() + .map(|&(_, _, width)| width) + .max() + .unwrap_or_default(); + + let mut list = String::new(); + for (link, filesize, width) in items { + let spaces = " ".repeat(name_width - width + 1); + let entry = format!("{link}{spaces}{filesize}"); + list.push_str(&entry); + } let parent = if relative_path != "/" { - "../" + "../\n" } else { "" }; @@ -228,29 +244,28 @@ fn generate_index(relative_path: &str, path: &Path) -> Option { Index of {relative_path}

Index of {relative_path}

- -{parent} -{list} -
+
+{parent}{list}
-"#, +"# ); Some(Content::html(page)) } fn format_size(bytes: u64) -> String { if bytes < 1024 { - format!("{bytes} B") + format!("{bytes:>5} B") } else if bytes < 1024 * 1024 { - format!("{:.1} KiB", bytes as f64 / 1024.0) + format!("{:>5.1} KiB", bytes as f64 / 1024.0) } else if bytes < 1024 * 1024 * 1024 { - format!("{:.1} MiB", bytes as f64 / (1024.0 * 1024.0)) + format!("{:>5.1} MiB", bytes as f64 / (1024.0 * 1024.0)) } else { - format!("{:.1} GiB", bytes as f64 / (1024.0 * 1024.0 * 1024.0)) + format!("{:>5.1} GiB", bytes as f64 / (1024.0 * 1024.0 * 1024.0)) } }