lmjtfy.git / packages / tree / src / icons.rs
icons.rsannotatedicons.rssource102 lines · 3.7 KB · raw

The icon a file or folder gets in the explorer: one of Jerry's pixel icons (third-party/jerrys-pixel-icons), chosen the way the icon theme chooses, by whole name first and then by extension. icons_theme.rs is the theme's own map; OURS adds the few names this repository has that the theme has never met.

7#[path = "icons_theme.rs"]
8mod theme;

Names and extensions the theme has no entry for, given the nearest icon it has. A whole name comes before an extension, and these before the theme's.

13const OURS: &[(&str, &str)] = &[
14    // What an agent is told: the robot.
15    ("CLAUDE.md", "file-robot"),
16    ("AGENTS.md", "file-robot"),
17    ("MEMORY.md", "file-robot"),
18    (".envrc", "file-env"),
19    ("BUCK", "file-conf"),
20    (".buckconfig", "file-conf"),
21    ("lock", "file-conf"),
22    ("nix", "file-conf"),
23    ("woff2", "file-ase"),
24    ("gif", "file-png"),
25];
27fn found(table: &[(&'static str, &'static str)], key: &str) -> Option<&'static str> {
28    table.iter().find(|(name, _)| *name == key).map(|(_, icon)| *icon)
29}

The icon for the file called name.

32pub fn file(name: &str) -> &'static str {
33    let extension = name.rsplit_once('.').map_or("", |(_, extension)| extension);
34    found(OURS, name)
35        .or_else(|| found(theme::NAMES, name))
36        .or_else(|| found(OURS, extension))
37        .or_else(|| found(theme::EXTENSIONS, &extension.to_ascii_lowercase()))
38        .unwrap_or(theme::FILE)
39}

The icon for the folder called name, shut. Open, it is the same with -open (open).

43pub fn folder(name: &str) -> &'static str {
44    found(theme::FOLDERS, &name.to_ascii_lowercase()).unwrap_or(theme::FOLDER)
45}

A repository: the theme's git folder. It is asked for by this name and not through folder, because no repository here is a folder called .git.

50pub const REPOSITORY: &str = "folder-git";

A folder's icon when it is open.

53pub fn open(folder: &str) -> String {
54    format!("{folder}-open")
55}

Every icon a name can be given, for a test that each one is a file.

58pub fn all() -> Vec<String> {
59    let files = OURS.iter().chain(theme::NAMES).chain(theme::EXTENSIONS).map(|(_, icon)| (*icon).to_owned()).chain([theme::FILE.to_owned()]);
60    let folders = theme::FOLDERS.iter().map(|(_, icon)| *icon).chain([theme::FOLDER, REPOSITORY]).flat_map(|icon| [icon.to_owned(), open(icon)]);
61    let mut all: Vec<String> = files.chain(folders).collect();
62    all.sort();
63    all.dedup();
64    all
65}
67#[cfg(test)]
68mod tests {
69    use super::*;
70
71    #[test]
72    fn a_name_gets_the_icon_the_theme_would_give_it() {
73        for (name, icon) in [
74            ("lib.rs", "file-rust"),
75            ("Cargo.toml", "file-toml"),
76            ("README.md", "file-readme"),
77            ("notes.md", "file-md"),
78            ("CLAUDE.md", "file-robot"),
79            (".gitignore", "file-git"),
80            ("LICENSE", "file-license"),
81            ("page.CSS", "file-css"),
82            ("flake.lock", "file-conf"),
83            ("emoji.woff2", "file-ase"),
84            ("who-knows", "file-txt"),
85        ] {
86            assert_eq!(file(name), icon, "{name}");
87        }
88        assert_eq!(folder("src"), "folder-src");
89        assert_eq!(folder("Docs"), "folder-docs");
90        assert_eq!(folder("packages"), "folder-folder");
91        assert_eq!(open(folder("src")), "folder-src-open");
92        assert_eq!((REPOSITORY, open(REPOSITORY).as_str()), ("folder-git", "folder-git-open"));
93    }
94
95    #[test]
96    fn every_icon_a_name_can_get_is_a_file() {
97        let folder = std::path::Path::new(env!("CARGO_MANIFEST_DIR")).join("../../third-party/jerrys-pixel-icons");
98        for icon in all() {
99            assert!(folder.join(format!("{icon}.png")).is_file(), "{icon}.png is not in third-party/jerrys-pixel-icons");
100        }
101    }
102}