lx-ls 0.6.1

The file lister with personality! 🌟
use nu_ansi_term::Style;

use crate::fs::File;
use std::collections::HashMap;
use std::sync::LazyLock;


/// Icons for media-type classes (audio, image, video).
const ICON_AUDIO: char = '\u{f001}'; //
const ICON_IMAGE: char = '\u{f1c5}'; //
const ICON_VIDEO: char = '\u{f03d}'; //


/// Converts the style used to paint a file name into the style that should be
/// used to paint an icon.
///
/// - The background colour should be preferred to the foreground colour, as
///   if one is set, it’s the more β€œobvious” colour choice.
/// - If neither is set, just use the default style.
/// - Attributes such as bold or underline should not be used to paint the
///   icon, as they can make it look weird.
pub fn iconify_style(style: Style) -> Style {
    style.background.or(style.foreground)
         .map(Style::from)
         .unwrap_or_default()
}



static MAP_BY_NAME: LazyLock<HashMap<&'static str, char>> = LazyLock::new(|| {
        let mut m = HashMap::new();
        m.insert(".Trash", '\u{f1f8}'); // ο‡Έ
        m.insert(".atom", '\u{e764}'); // 
        m.insert(".bashprofile", '\u{e615}'); // ξ˜•
        m.insert(".bashrc", '\u{f489}'); // ο’‰
        m.insert(".git", '\u{f1d3}'); // 
        m.insert(".gitattributes", '\u{f1d3}'); // 
        m.insert(".gitconfig", '\u{f1d3}'); // 
        m.insert(".github", '\u{f408}'); // 
        m.insert(".gitignore", '\u{f1d3}'); // 
        m.insert(".gitmodules", '\u{f1d3}'); // 
        m.insert(".rvm", '\u{e21e}'); // 
        m.insert(".vimrc", '\u{e62b}'); // 
        m.insert(".vscode", '\u{e70c}'); // 
        m.insert(".zshrc", '\u{f489}'); // ο’‰
        m.insert("Cargo.lock", '\u{e7a8}'); // 
        m.insert("bin", '\u{e5fc}'); // ξ—Ό
        m.insert("config", '\u{e5fc}'); // ξ—Ό
        m.insert("docker-compose.yml", '\u{f308}'); // 
        m.insert("Dockerfile", '\u{f308}'); // 
        m.insert("ds_store", '\u{f179}'); // ο…Ή
        m.insert("gitignore_global", '\u{f1d3}'); // 
        m.insert("go.mod", '\u{e626}'); // 
        m.insert("go.sum", '\u{e626}'); // 
        m.insert("gradle", '\u{e256}'); // ξ‰–
        m.insert("gruntfile.coffee", '\u{e611}'); // ξ˜‘
        m.insert("gruntfile.js", '\u{e611}'); // ξ˜‘
        m.insert("gruntfile.ls", '\u{e611}'); // ξ˜‘
        m.insert("gulpfile.coffee", '\u{e610}'); // 
        m.insert("gulpfile.js", '\u{e610}'); // 
        m.insert("gulpfile.ls", '\u{e610}'); // 
        m.insert("hidden", '\u{f023}'); // ο€£
        m.insert("include", '\u{e5fc}'); // ξ—Ό
        m.insert("lib", '\u{f121}'); // ο„‘
        m.insert("localized", '\u{f179}'); // ο…Ή
        m.insert("Makefile", '\u{f489}'); // ο’‰
        m.insert("node_modules", '\u{e718}'); // 
        m.insert("npmignore", '\u{e71e}'); // 
        m.insert("PKGBUILD", '\u{f303}'); // οŒƒ
        m.insert("rubydoc", '\u{e73b}'); // 
        m.insert("yarn.lock", '\u{e718}'); // 

        m
});

/// Check if a file matches a media-type class and return its icon.
/// Uses the class system from config, so user-defined classes are respected.
fn class_icon(file: &File<'_>) -> Option<char> {
    static CLASS_ICONS: LazyLock<Vec<(glob::Pattern, char)>> = LazyLock::new(|| {
        let classes = crate::config::resolve_classes();
        let mut mappings = Vec::new();

        let class_to_icon: &[(&str, char)] = &[
            ("music",    ICON_AUDIO),
            ("lossless", ICON_AUDIO),
            ("image",    ICON_IMAGE),
            ("video",    ICON_VIDEO),
        ];

        for &(class_name, icon) in class_to_icon {
            if let Some(patterns) = classes.get(class_name) {
                for pat_str in patterns {
                    if let Ok(pat) = glob::Pattern::new(pat_str) {
                        mappings.push((pat, icon));
                    }
                }
            }
        }
        mappings
    });

    let name = &file.name;
    CLASS_ICONS.iter()
        .find(|(pat, _)| pat.matches(name))
        .map(|(_, icon)| *icon)
}

pub fn icon_for_file(file: &File<'_>) -> char {
    if let Some(icon) = MAP_BY_NAME.get(file.name.as_str()) { *icon }
    else if file.points_to_directory() {
        match file.name.as_str() {
            "bin"           => '\u{e5fc}', // ξ—Ό
            ".git"          => '\u{f1d3}', // 
            ".idea"         => '\u{e7b5}', // 
            _               => '\u{f115}'  // ο„•
        }
    }
    else if let Some(icon) = class_icon(file) { icon }
    else if let Some(ext) = file.ext.as_ref() {
        match ext.as_str() {
            "ai"            => '\u{e7b4}', // 
            "android"       => '\u{e70e}', // 
            "apk"           => '\u{e70e}', // 
            "apple"         => '\u{f179}', // ο…Ή
            "avi"           => '\u{f03d}', // ο€½
            "avif"          => '\u{f1c5}', // ο‡…
            "avro"          => '\u{e60b}', // ξ˜‹
            "awk"           => '\u{f489}', // ο’‰
            "bash"          => '\u{f489}', // ο’‰
            "bash_history"  => '\u{f489}', // ο’‰
            "bash_profile"  => '\u{f489}', // ο’‰
            "bashrc"        => '\u{f489}', // ο’‰
            "bat"           => '\u{f17a}', // ο…Ί
            "bats"          => '\u{f489}', // ο’‰
            "bmp"           => '\u{f1c5}', // ο‡…
            "bz"            => '\u{f410}', // 
            "bz2"           => '\u{f410}', // 
            "c"             => '\u{e61e}', // 
            "c++"           => '\u{e61d}', // 
            "cab"           => '\u{e70f}', // 
            "cc"            => '\u{e61d}', // 
            "cfg"           => '\u{e615}', // ξ˜•
            "class"         => '\u{e256}', // ξ‰–
            "clj"           => '\u{e768}', // 
            "cljs"          => '\u{e76a}', // ξͺ
            "cls"           => '\u{f034}', // 
            "cmd"           => '\u{e70f}', // 
            "coffee"        => '\u{f0f4}', // 
            "conf"          => '\u{e615}', // ξ˜•
            "cp"            => '\u{e61d}', // 
            "cpio"          => '\u{f410}', // 
            "cpp"           => '\u{e61d}', // 
            "cs"            => '\u{f031b}', // σ°Œ›
            "csh"           => '\u{f489}', // ο’‰
            "cshtml"        => '\u{f1fa}', // ο‡Ί
            "csproj"        => '\u{f031b}', // σ°Œ›
            "css"           => '\u{e749}', // 
            "csv"           => '\u{f1c3}', // 
            "csx"           => '\u{f031b}', // σ°Œ›
            "cxx"           => '\u{e61d}', // 
            "d"             => '\u{e7af}', // 
            "dart"          => '\u{e798}', // 
            "db"            => '\u{f1c0}', // 
            "deb"           => '\u{e77d}', // 
            "diff"          => '\u{f440}', // ο‘€
            "djvu"          => '\u{f02d}', // ο€­
            "dll"           => '\u{e70f}', // 
            "doc"           => '\u{f1c2}', // 
            "docx"          => '\u{f1c2}', // 
            "ds_store"      => '\u{f179}', // ο…Ή
            "DS_store"      => '\u{f179}', // ο…Ή
            "dump"          => '\u{f1c0}', // ξœ†
            "ebook"         => '\u{e28b}', // ξŠ‹
            "ebuild"        => '\u{f30d}', // 
            "editorconfig"  => '\u{e615}', // ξ˜•
            "ejs"           => '\u{e618}', // 
            "elm"           => '\u{e62c}', // 
            "env"           => '\u{f462}', // ο‘’
            "eot"           => '\u{f031}', // ο€±
            "epub"          => '\u{e28a}', // 
            "erb"           => '\u{e73b}', // 
            "erl"           => '\u{e7b1}', // 
            "ex"            => '\u{e62d}', // 
            "exe"           => '\u{f17a}', // ο…Ί
            "exs"           => '\u{e62d}', // 
            "fish"          => '\u{f489}', // ο’‰
            "flac"          => '\u{f001}', // 
            "flv"           => '\u{f03d}', // ο€½
            "font"          => '\u{f031}', // ο€±
            "fs"            => '\u{e7a7}', // 
            "fsi"           => '\u{e7a7}', // 
            "fsx"           => '\u{e7a7}', // 
            "gdoc"          => '\u{f1c2}', // 
            "gem"           => '\u{e21e}', // 
            "gemfile"       => '\u{e21e}', // 
            "gemspec"       => '\u{e21e}', // 
            "gform"         => '\u{f298}', // 
            "gif"           => '\u{f1c5}', // ο‡…
            "git"           => '\u{f1d3}', // 
            "gitattributes" => '\u{f1d3}', // 
            "gitignore"     => '\u{f1d3}', // 
            "gitmodules"    => '\u{f1d3}', // 
            "go"            => '\u{e626}', // 
            "gradle"        => '\u{e256}', // ξ‰–
            "groovy"        => '\u{e775}', // 
            "gsheet"        => '\u{f1c3}', // 
            "gslides"       => '\u{f1c4}', // 
            "guardfile"     => '\u{e21e}', // 
            "gz"            => '\u{f410}', // 
            "h"             => '\u{f0fd}', // 
            "hbs"           => '\u{e60f}', // 
            "hpp"           => '\u{f0fd}', // 
            "hs"            => '\u{e777}', // 
            "htm"           => '\u{f13b}', // ο„»
            "html"          => '\u{f13b}', // ο„»
            "hxx"           => '\u{f0fd}', // 
            "ico"           => '\u{f1c5}', // ο‡…
            "image"         => '\u{f1c5}', // ο‡…
            "img"           => '\u{e271}', // 
            "iml"           => '\u{e7b5}', // 
            "ini"           => '\u{f17a}', // ο…Ί
            "ipynb"         => '\u{e678}', // ξ˜†
            "iso"           => '\u{e271}', // 
            "j2c"           => '\u{f1c5}', // ο‡…
            "j2k"           => '\u{f1c5}', // ο‡…
            "jad"           => '\u{e256}', // ξ‰–
            "jar"           => '\u{e256}', // ξ‰–
            "java"          => '\u{e256}', // ξ‰–
            "jfi"           => '\u{f1c5}', // ο‡…
            "jfif"          => '\u{f1c5}', // ο‡…
            "jif"           => '\u{f1c5}', // ο‡…
            "jl"            => '\u{e624}', // 
            "jmd"           => '\u{f48a}', // ο’Š
            "jp2"           => '\u{f1c5}', // ο‡…
            "jpe"           => '\u{f1c5}', // ο‡…
            "jpeg"          => '\u{f1c5}', // ο‡…
            "jpg"           => '\u{f1c5}', // ο‡…
            "jpx"           => '\u{f1c5}', // ο‡…
            "js"            => '\u{e74e}', // 
            "json"          => '\u{e60b}', // ξ˜‹
            "jsx"           => '\u{e7ba}', // 
            "jxl"           => '\u{f1c5}', // ο‡…
            "ksh"           => '\u{f489}', // ο’‰
            "latex"         => '\u{f034}', // 
            "less"          => '\u{e758}', // 
            "lhs"           => '\u{e777}', // 
            "license"       => '\u{f0219}', // σ°ˆ™
            "localized"     => '\u{f179}', // ο…Ή
            "lock"          => '\u{f023}', // ο€£
            "log"           => '\u{f18d}', // 
            "lua"           => '\u{e620}', // 
            "lz"            => '\u{f410}', // 
            "lz4"           => '\u{f410}', // 
            "lzh"           => '\u{f410}', // 
            "lzma"          => '\u{f410}', // 
            "lzo"           => '\u{f410}', // 
            "m"             => '\u{e61e}', // 
            "mm"            => '\u{e61d}', // 
            "m4a"           => '\u{f001}', // 
            "markdown"      => '\u{f48a}', // ο’Š
            "md"            => '\u{f48a}', // ο’Š
            "mjs"           => '\u{e74e}', // 
            "mk"            => '\u{f489}', // ο’‰
            "mkd"           => '\u{f48a}', // ο’Š
            "mkv"           => '\u{f03d}', // ο€½
            "mobi"          => '\u{e28b}', // ξŠ‹
            "mov"           => '\u{f03d}', // ο€½
            "mp3"           => '\u{f001}', // 
            "mp4"           => '\u{f03d}', // ο€½
            "msi"           => '\u{e70f}', // 
            "mustache"      => '\u{e60f}', // 
            "nix"           => '\u{f313}', // οŒ“
            "node"          => '\u{f0399}', // σ°Ž™
            "npmignore"     => '\u{e71e}', // 
            "odp"           => '\u{f1c4}', // 
            "ods"           => '\u{f1c3}', // 
            "odt"           => '\u{f1c2}', // 
            "ogg"           => '\u{f001}', // 
            "ogv"           => '\u{f03d}', // ο€½
            "otf"           => '\u{f031}', // ο€±
            "part"          => '\u{f43a}', // 
            "patch"         => '\u{f440}', // ο‘€
            "pdf"           => '\u{f1c1}', // 
            "php"           => '\u{e73d}', // 
            "pl"            => '\u{e769}', // 
            "plx"           => '\u{e769}', // 
            "pm"            => '\u{e769}', // 
            "png"           => '\u{f1c5}', // ο‡…
            "pod"           => '\u{e769}', // 
            "ppt"           => '\u{f1c4}', // 
            "pptx"          => '\u{f1c4}', // 
            "procfile"      => '\u{e21e}', // 
            "properties"    => '\u{e60b}', // ξ˜‹
            "ps1"           => '\u{f489}', // ο’‰
            "psd"           => '\u{e7b8}', // 
            "pxm"           => '\u{f1c5}', // ο‡…
            "py"            => '\u{e606}', // ξ˜†
            "pyc"           => '\u{e606}', // ξ˜†
            "r"             => '\u{f25d}', // 
            "rakefile"      => '\u{e21e}', // 
            "rar"           => '\u{f410}', // 
            "razor"         => '\u{f1fa}', // ο‡Ί
            "rb"            => '\u{e21e}', // 
            "rdata"         => '\u{f25d}', // 
            "rdb"           => '\u{e76d}', // 
            "rdoc"          => '\u{f48a}', // ο’Š
            "rds"           => '\u{f25d}', // 
            "readme"        => '\u{f48a}', // ο’Š
            "rlib"          => '\u{e7a8}', // 
            "rmd"           => '\u{f48a}', // ο’Š
            "rpm"           => '\u{e7bb}', // 
            "rs"            => '\u{e7a8}', // 
            "rspec"         => '\u{e21e}', // 
            "rspec_parallel"=> '\u{e21e}', // 
            "rspec_status"  => '\u{e21e}', // 
            "rss"           => '\u{f09e}', // ο‚ž
            "rtf"           => '\u{f0219}', // σ°ˆ™
            "ru"            => '\u{e21e}', // 
            "rubydoc"       => '\u{e73b}', // 
            "sass"          => '\u{e603}', // ξ˜ƒ
            "scala"         => '\u{e737}', // 
            "scss"          => '\u{e749}', // 
            "sh"            => '\u{f489}', // ο’‰
            "shell"         => '\u{f489}', // ο’‰
            "slim"          => '\u{e73b}', // 
            "sln"           => '\u{e70c}', // 
            "so"            => '\u{f17c}', // ο…Ό
            "sql"           => '\u{f1c0}', // ξœ†
            "sqlite3"       => '\u{e7c4}', // ξŸ„
            "sty"           => '\u{f034}', // 
            "styl"          => '\u{e600}', // ξ˜€
            "stylus"        => '\u{e600}', // ξ˜€
            "svg"           => '\u{f1c5}', // ο‡…
            "swift"         => '\u{e755}', // 
            "t"             => '\u{e769}', // 
            "tar"           => '\u{f410}', // 
            "taz"           => '\u{f410}', // 
            "tbz"           => '\u{f410}', // 
            "tbz2"          => '\u{f410}', // 
            "tex"           => '\u{f034}', // 
            "tgz"           => '\u{f410}', // 
            "tiff"          => '\u{f1c5}', // ο‡…
            "tlz"           => '\u{f410}', // 
            "toml"          => '\u{e615}', // ξ˜•
            "torrent"       => '\u{e275}', // 
            "ts"            => '\u{e628}', // 
            "tsv"           => '\u{f1c3}', // 
            "tsx"           => '\u{e7ba}', // 
            "ttf"           => '\u{f031}', // ο€±
            "twig"          => '\u{e61c}', // 
            "txt"           => '\u{f15c}', // ο…œ
            "txz"           => '\u{f410}', // 
            "tz"            => '\u{f410}', // 
            "tzo"           => '\u{f410}', // 
            "video"         => '\u{f03d}', // ο€½
            "vim"           => '\u{e62b}', // 
            "vue"           => '\u{f0844}', // σ°‘„
            "war"           => '\u{e256}', // ξ‰–
            "wav"           => '\u{f001}', // 
            "webm"          => '\u{f03d}', // ο€½
            "webp"          => '\u{f1c5}', // ο‡…
            "windows"       => '\u{f17a}', // ο…Ί
            "woff"          => '\u{f031}', // ο€±
            "woff2"         => '\u{f031}', // ο€±
            "xhtml"         => '\u{f13b}', // ο„»
            "xls"           => '\u{f1c3}', // 
            "xlsx"          => '\u{f1c3}', // 
            "xml"           => '\u{f05c0}', // σ°—€
            "xul"           => '\u{f05c0}', // σ°—€
            "xz"            => '\u{f410}', // 
            "yaml"          => '\u{f481}', // 
            "yml"           => '\u{f481}', // 
            "zip"           => '\u{f410}', // 
            "zsh"           => '\u{f489}', // ο’‰
            "zsh-theme"     => '\u{f489}', // ο’‰
            "zshrc"         => '\u{f489}', // ο’‰
            "zst"           => '\u{f410}', // 
            _               => '\u{f15b}'  // ο…›
        }
    }
    else {
        '\u{f016}'
    }
}