/* * Copyright (C) 2012-2024 Robin Haberkorn * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include #include #include #include #include "sciteco.h" #include "curses-icons.h" typedef struct { const gchar *name; gunichar c; } teco_curses_icon_t; /* * The following icons have initially been adapted from exa, * but icons have since been added and removed. * * They require fonts with additional symbols, e.g. * Nerd Fonts (https://www.nerdfonts.com/). * * They MUST be kept presorted, so we can perform binary searches. */ /** Mapping of complete filenames to Unicode "icons" */ static const teco_curses_icon_t teco_icons_file[] = { {".Trash", 0xf1f8}, /*  */ {".atom", 0xe764}, /*  */ {".bash_history", 0xf489}, /*  */ {".bash_profile", 0xf489}, /*  */ {".bashrc", 0xf489}, /*  */ {".git", 0xf1d3}, /*  */ {".gitattributes", 0xf1d3}, /*  */ {".gitconfig", 0xf1d3}, /*  */ {".github", 0xf408}, /*  */ {".gitignore", 0xf1d3}, /*  */ {".gitmodules", 0xf1d3}, /*  */ {".rvm", 0xe21e}, /*  */ {".teco_ini", 0xedaa}, /*  */ {".teco_session", 0xedaa}, /*  */ {".vimrc", 0xe62b}, /*  */ {".vscode", 0xe70c}, /*  */ {".zshrc", 0xf489}, /*  */ {"COMMIT_EDITMSG", 0xf1d3}, /*  */ {"Cargo.lock", 0xe7a8}, /*  */ {"Dockerfile", 0xf308}, /*  */ {"GNUmakefile", 0xf489}, /*  */ {"MERGE_MSG", 0xf1d3}, /*  */ {"Makefile", 0xf489}, /*  */ {"PKGBUILD", 0xf303}, /*  */ {"TAG_EDITMSG", 0xf1d3}, /*  */ {"bin", 0xe5fc}, /*  */ {"config", 0xe5fc}, /*  */ {"docker-compose.yml", 0xf308}, /*  */ {"ds_store", 0xf179}, /*  */ {"git-rebase-todo", 0xf1d3}, /*  */ {"go.mod", 0xe626}, /*  */ {"go.sum", 0xe626}, /*  */ {"gradle", 0xe256}, /*  */ {"gruntfile.coffee", 0xe611}, /*  */ {"gruntfile.js", 0xe611}, /*  */ {"gruntfile.ls", 0xe611}, /*  */ {"gulpfile.coffee", 0xe610}, /*  */ {"gulpfile.js", 0xe610}, /*  */ {"gulpfile.ls", 0xe610}, /*  */ {"hidden", 0xf023}, /*  */ {"include", 0xe5fc}, /*  */ {"lib", 0xf121}, /*  */ {"localized", 0xf179}, /*  */ {"node_modules", 0xe718}, /*  */ {"npmignore", 0xe71e}, /*  */ {"rubydoc", 0xe73b}, /*  */ {"yarn.lock", 0xe718}, /*  */ }; /** Mapping of file extensions to Unicode "icons" */ static const teco_curses_icon_t teco_icons_ext[] = { {"DS_store", 0xf179}, /*  */ {"ai", 0xe7b4}, /*  */ {"android", 0xe70e}, /*  */ {"apk", 0xe70e}, /*  */ {"apple", 0xf179}, /*  */ {"avi", 0xf03d}, /*  */ {"avif", 0xf1c5}, /*  */ {"avro", 0xe60b}, /*  */ {"awk", 0xf489}, /*  */ {"bash", 0xf489}, /*  */ {"bat", 0xf17a}, /*  */ {"bats", 0xf489}, /*  */ {"bmp", 0xf1c5}, /*  */ {"bz", 0xf410}, /*  */ {"bz2", 0xf410}, /*  */ {"c", 0xe61e}, /*  */ {"c++", 0xe61d}, /*  */ {"cab", 0xe70f}, /*  */ {"cc", 0xe61d}, /*  */ {"cfg", 0xe615}, /*  */ {"class", 0xe256}, /*  */ {"clj", 0xe768}, /*  */ {"cljs", 0xe76a}, /*  */ {"cls", 0xf034}, /*  */ {"cmd", 0xe70f}, /*  */ {"coffee", 0xf0f4}, /*  */ {"conf", 0xe615}, /*  */ {"cp", 0xe61d}, /*  */ {"cpio", 0xf410}, /*  */ {"cpp", 0xe61d}, /*  */ {"cs", 0xf031b}, /* 󰌛 */ {"csh", 0xf489}, /*  */ {"cshtml", 0xf1fa}, /*  */ {"csproj", 0xf031b}, /* 󰌛 */ {"css", 0xe749}, /*  */ {"csv", 0xf1c3}, /*  */ {"csx", 0xf031b}, /* 󰌛 */ {"cxx", 0xe61d}, /*  */ {"d", 0xe7af}, /*  */ {"dart", 0xe798}, /*  */ {"db", 0xf1c0}, /*  */ {"deb", 0xe77d}, /*  */ {"diff", 0xf440}, /*  */ {"djvu", 0xf02d}, /*  */ {"dll", 0xe70f}, /*  */ {"doc", 0xf1c2}, /*  */ {"docx", 0xf1c2}, /*  */ {"ds_store", 0xf179}, /*  */ {"dump", 0xf1c0}, /*  */ {"ebook", 0xe28b}, /*  */ {"ebuild", 0xf30d}, /*  */ {"editorconfig", 0xe615}, /*  */ {"ejs", 0xe618}, /*  */ {"elm", 0xe62c}, /*  */ {"env", 0xf462}, /*  */ {"eot", 0xf031}, /*  */ {"epub", 0xe28a}, /*  */ {"erb", 0xe73b}, /*  */ {"erl", 0xe7b1}, /*  */ {"ex", 0xe62d}, /*  */ {"exe", 0xf17a}, /*  */ {"exs", 0xe62d}, /*  */ {"fish", 0xf489}, /*  */ {"flac", 0xf001}, /*  */ {"flv", 0xf03d}, /*  */ {"font", 0xf031}, /*  */ {"fs", 0xe7a7}, /*  */ {"fsi", 0xe7a7}, /*  */ {"fsx", 0xe7a7}, /*  */ {"gdoc", 0xf1c2}, /*  */ {"gem", 0xe21e}, /*  */ {"gemfile", 0xe21e}, /*  */ {"gemspec", 0xe21e}, /*  */ {"gform", 0xf298}, /*  */ {"gif", 0xf1c5}, /*  */ {"go", 0xe626}, /*  */ {"gradle", 0xe256}, /*  */ {"groovy", 0xe775}, /*  */ {"gsheet", 0xf1c3}, /*  */ {"gslides", 0xf1c4}, /*  */ {"guardfile", 0xe21e}, /*  */ {"gz", 0xf410}, /*  */ {"h", 0xf0fd}, /*  */ {"hbs", 0xe60f}, /*  */ {"hpp", 0xf0fd}, /*  */ {"hs", 0xe777}, /*  */ {"htm", 0xf13b}, /*  */ {"html", 0xf13b}, /*  */ {"hxx", 0xf0fd}, /*  */ {"ico", 0xf1c5}, /*  */ {"image", 0xf1c5}, /*  */ {"img", 0xe271}, /*  */ {"iml", 0xe7b5}, /*  */ {"ini", 0xf17a}, /*  */ {"ipynb", 0xe678}, /*  */ {"iso", 0xe271}, /*  */ {"j2c", 0xf1c5}, /*  */ {"j2k", 0xf1c5}, /*  */ {"jad", 0xe256}, /*  */ {"jar", 0xe256}, /*  */ {"java", 0xe256}, /*  */ {"jfi", 0xf1c5}, /*  */ {"jfif", 0xf1c5}, /*  */ {"jif", 0xf1c5}, /*  */ {"jl", 0xe624}, /*  */ {"jmd", 0xf48a}, /*  */ {"jp2", 0xf1c5}, /*  */ {"jpe", 0xf1c5}, /*  */ {"jpeg", 0xf1c5}, /*  */ {"jpg", 0xf1c5}, /*  */ {"jpx", 0xf1c5}, /*  */ {"js", 0xe74e}, /*  */ {"json", 0xe60b}, /*  */ {"jsx", 0xe7ba}, /*  */ {"jxl", 0xf1c5}, /*  */ {"ksh", 0xf489}, /*  */ {"latex", 0xf034}, /*  */ {"less", 0xe758}, /*  */ {"lhs", 0xe777}, /*  */ {"license", 0xf0219}, /* 󰈙 */ {"localized", 0xf179}, /*  */ {"lock", 0xf023}, /*  */ {"log", 0xf18d}, /*  */ {"lua", 0xe620}, /*  */ {"lz", 0xf410}, /*  */ {"lz4", 0xf410}, /*  */ {"lzh", 0xf410}, /*  */ {"lzma", 0xf410}, /*  */ {"lzo", 0xf410}, /*  */ {"m", 0xe61e}, /*  */ {"m4a", 0xf001}, /*  */ {"markdown", 0xf48a}, /*  */ {"md", 0xf48a}, /*  */ {"mjs", 0xe74e}, /*  */ {"mk", 0xf489}, /*  */ {"mkd", 0xf48a}, /*  */ {"mkv", 0xf03d}, /*  */ {"mm", 0xe61d}, /*  */ {"mobi", 0xe28b}, /*  */ {"mov", 0xf03d}, /*  */ {"mp3", 0xf001}, /*  */ {"mp4", 0xf03d}, /*  */ {"msi", 0xe70f}, /*  */ {"mustache", 0xe60f}, /*  */ {"nix", 0xf313}, /*  */ {"node", 0xf0399}, /* 󰎙 */ {"npmignore", 0xe71e}, /*  */ {"odp", 0xf1c4}, /*  */ {"ods", 0xf1c3}, /*  */ {"odt", 0xf1c2}, /*  */ {"ogg", 0xf001}, /*  */ {"ogv", 0xf03d}, /*  */ {"otf", 0xf031}, /*  */ {"part", 0xf43a}, /*  */ {"patch", 0xf440}, /*  */ {"pdf", 0xf1c1}, /*  */ {"php", 0xe73d}, /*  */ {"pl", 0xe769}, /*  */ {"plx", 0xe769}, /*  */ {"pm", 0xe769}, /*  */ {"png", 0xf1c5}, /*  */ {"pod", 0xe769}, /*  */ {"ppt", 0xf1c4}, /*  */ {"pptx", 0xf1c4}, /*  */ {"procfile", 0xe21e}, /*  */ {"properties", 0xe60b}, /*  */ {"ps1", 0xf489}, /*  */ {"psd", 0xe7b8}, /*  */ {"pxm", 0xf1c5}, /*  */ {"py", 0xe606}, /*  */ {"pyc", 0xe606}, /*  */ {"r", 0xf25d}, /*  */ {"rakefile", 0xe21e}, /*  */ {"rar", 0xf410}, /*  */ {"razor", 0xf1fa}, /*  */ {"rb", 0xe21e}, /*  */ {"rdata", 0xf25d}, /*  */ {"rdb", 0xe76d}, /*  */ {"rdoc", 0xf48a}, /*  */ {"rds", 0xf25d}, /*  */ {"readme", 0xf48a}, /*  */ {"rlib", 0xe7a8}, /*  */ {"rmd", 0xf48a}, /*  */ {"rpm", 0xe7bb}, /*  */ {"rs", 0xe7a8}, /*  */ {"rspec", 0xe21e}, /*  */ {"rspec_parallel", 0xe21e}, /*  */ {"rspec_status", 0xe21e}, /*  */ {"rss", 0xf09e}, /*  */ {"rtf", 0xf0219}, /* 󰈙 */ {"ru", 0xe21e}, /*  */ {"rubydoc", 0xe73b}, /*  */ {"sass", 0xe603}, /*  */ {"scala", 0xe737}, /*  */ {"scss", 0xe749}, /*  */ {"sh", 0xf489}, /*  */ {"shell", 0xf489}, /*  */ {"slim", 0xe73b}, /*  */ {"sln", 0xe70c}, /*  */ {"so", 0xf17c}, /*  */ {"sql", 0xf1c0}, /*  */ {"sqlite3", 0xe7c4}, /*  */ {"sty", 0xf034}, /*  */ {"styl", 0xe600}, /*  */ {"stylus", 0xe600}, /*  */ {"svg", 0xf1c5}, /*  */ {"swift", 0xe755}, /*  */ {"t", 0xe769}, /*  */ {"tar", 0xf410}, /*  */ {"taz", 0xf410}, /*  */ {"tbz", 0xf410}, /*  */ {"tbz2", 0xf410}, /*  */ {"tec", 0xedaa}, /*  */ {"tes", 0xedaa}, /*  */ {"tex", 0xf034}, /*  */ {"tgz", 0xf410}, /*  */ {"tiff", 0xf1c5}, /*  */ {"tlz", 0xf410}, /*  */ {"toml", 0xe615}, /*  */ {"torrent", 0xe275}, /*  */ {"ts", 0xe628}, /*  */ {"tsv", 0xf1c3}, /*  */ {"tsx", 0xe7ba}, /*  */ {"ttf", 0xf031}, /*  */ {"twig", 0xe61c}, /*  */ {"txt", 0xf15c}, /*  */ {"txz", 0xf410}, /*  */ {"tz", 0xf410}, /*  */ {"tzo", 0xf410}, /*  */ {"video", 0xf03d}, /*  */ {"vim", 0xe62b}, /*  */ {"vue", 0xf0844}, /* 󰡄 */ {"war", 0xe256}, /*  */ {"wav", 0xf001}, /*  */ {"webm", 0xf03d}, /*  */ {"webp", 0xf1c5}, /*  */ {"windows", 0xf17a}, /*  */ {"woff", 0xf031}, /*  */ {"woff2", 0xf031}, /*  */ {"woman", 0xeaa4}, /*  */ {"xhtml", 0xf13b}, /*  */ {"xls", 0xf1c3}, /*  */ {"xlsx", 0xf1c3}, /*  */ {"xml", 0xf05c0}, /* 󰗀 */ {"xul", 0xf05c0}, /* 󰗀 */ {"xz", 0xf410}, /*  */ {"yaml", 0xf481}, /*  */ {"yml", 0xf481}, /*  */ {"zip", 0xf410}, /*  */ {"zsh", 0xf489}, /*  */ {"zsh-theme", 0xf489}, /*  */ {"zst", 0xf410}, /*  */ }; static int teco_curses_icon_cmp(const void *a, const void *b) { const gchar *str = a; const teco_curses_icon_t *icon = b; return strcmp(str, icon->name); } gunichar teco_curses_icons_lookup_file(const gchar *filename) { g_autofree gchar *basename = g_path_get_basename(filename); const teco_curses_icon_t *icon; /* try to find icon by complete file name */ icon = bsearch(basename, teco_icons_file, G_N_ELEMENTS(teco_icons_file), sizeof(teco_icons_file[0]), teco_curses_icon_cmp); if (icon) return icon->c; /* try to find icon by extension */ const gchar *ext = strrchr(basename, '.'); if (ext) { icon = bsearch(ext+1, teco_icons_ext, G_N_ELEMENTS(teco_icons_ext), sizeof(teco_icons_ext[0]), teco_curses_icon_cmp); return icon ? icon->c : 0xf15b; /*  */ } /* default file icon for files without extension */ return 0xf016; /*  */ } gunichar teco_curses_icons_lookup_dir(const gchar *dirname) { g_autofree gchar *basename = g_path_get_basename(dirname); const teco_curses_icon_t *icon; icon = bsearch(basename, teco_icons_file, G_N_ELEMENTS(teco_icons_file), sizeof(teco_icons_file[0]), teco_curses_icon_cmp); /* default folder icon */ return icon ? icon->c : 0xf115; /*  */ }