ls but with io_uring
at main 13 kB view raw
1const std = @import("std"); 2const posix = std.posix; 3 4const main = @import("main.zig"); 5const Entry = main.Entry; 6const Options = main.Options; 7 8const Icon = @This(); 9 10icon: []const u8, 11color: []const u8, 12 13// Entry types 14const directory: Icon = .{ .icon = "󰉋", .color = Options.Colors.blue }; 15const drive: Icon = .{ .icon = "󰋊", .color = Options.Colors.blue }; 16const file: Icon = .{ .icon = "󰈤", .color = Options.Colors.fg }; 17const file_hidden: Icon = .{ .icon = "󰘓", .color = Options.Colors.fg }; 18const pipe: Icon = .{ .icon = "󰟥", .color = Options.Colors.fg }; 19const socket: Icon = .{ .icon = "󰐧", .color = Options.Colors.fg }; 20const symlink: Icon = .{ .icon = "", .color = Options.Colors.fg }; 21const symlink_dir: Icon = .{ .icon = "", .color = Options.Colors.blue }; 22 23// Broad file types 24const artifact: Icon = .{ .icon = "", .color = "\x1b[38;2;255;165;0m" }; // #FFA500 25const audio: Icon = .{ .icon = "", .color = "\x1b[38;2;72;209;204m" }; // #48D1CC 26const doc: Icon = .{ .icon = "", .color = "\x1b[38;2;255;165;0m" }; // #FFA500 27const executable: Icon = .{ .icon = "", .color = Options.Colors.green }; 28const image: Icon = .{ .icon = "", .color = Options.Colors.yellow }; 29const playlist: Icon = .{ .icon = "󰐑", .color = "\x1b[38;2;72;209;204m" }; // #48D1CC 30const text: Icon = .{ .icon = "", .color = "\x1b[38;2;255;192;203m" }; // #FFC0CB 31const video: Icon = .{ .icon = "󰸬", .color = Options.Colors.yellow }; 32 33// Filetypes 34const assembly: Icon = .{ .icon = "", .color = Options.Colors.yellow }; 35const c: Icon = .{ .icon = "󰙱", .color = "\x1b[38;2;127;139;153m" }; // #7F8B99 36const clj: Icon = .{ .icon = "", .color = "\x1b[38;2;88;129;216m" }; // #5881D8 37const cmake: Icon = .{ .icon = "", .color = "\x1b[38;2;33;153;72m" }; // #219948 38const config: Icon = .{ .icon = "", .color = Options.Colors.yellow }; 39const cpp: Icon = .{ .icon = "󰙲", .color = "\x1b[38;2;0;89;156m" }; // #00599C 40const cs: Icon = .{ .icon = "", .color = "\x1b[38;2;115;85;221m" }; // #7355dd 41const css: Icon = .{ .icon = "", .color = "\x1b[38;2;21;114;182m" }; // #1572B6 42const dart: Icon = .{ .icon = "", .color = "\x1b[38;2;1;117;194m" }; // #0175C2 43const diff: Icon = .{ .icon = "", .color = "\x1b[38;2;50;167;220m" }; // #32A7DC 44const elisp: Icon = .{ .icon = "", .color = "\x1b[38;2;127;90;182m" }; // #7f5ab6 45const erl: Icon = .{ .icon = "", .color = "\x1b[38;2;169;5;51m" }; // #A90533 46const ex: Icon = .{ .icon = "", .color = "\x1b[38;2;110;74;126m" }; // #6E4A7E 47const fennel: Icon = .{ .icon = "", .color = "" }; 48const git: Icon = .{ .icon = "󰊢", .color = Options.Colors.fg }; 49const font: Icon = .{ .icon = "", .color = "\x1b[38;2;50;167;220m" }; // #32A7DC 50const go: Icon = .{ .icon = "󰟓", .color = "\x1b[38;2;0;173;216m" }; // #00ADD8 51const h: Icon = .{ .icon = "", .color = "\x1b[38;2;81;154;186m" }; // #519ABA 52const html: Icon = .{ .icon = "", .color = "\x1b[38;2;227;79;38m" }; // #E34F26 53const hs: Icon = .{ .icon = "", .color = "\x1b[38;2;93;79;133m" }; // #5D4F85 54const java: Icon = .{ .icon = "", .color = "\x1b[38;2;0;115;150m" }; // #007396 55const javascript: Icon = .{ .icon = "", .color = "\x1b[38;2;0;187;0m" }; // #00BB00 56const json: Icon = .{ .icon = "", .color = Options.Colors.blue }; 57const key: Icon = .{ .icon = "󰌆", .color = "\x1b[38;2;255;192;203m" }; // #FFC0CB 58const kt: Icon = .{ .icon = "", .color = "\x1b[38;2;127;82;255m" }; // #7F52FF 59const license: Icon = .{ .icon = "", .color = "" }; 60const log: Icon = .{ .icon = "", .color = Options.Colors.red }; 61const lua: Icon = .{ .icon = "󰢱", .color = "\x1b[38;2;0;0;124m" }; // #00007C 62const makefile: Icon = .{ .icon = "", .color = "\x1b[38;2;227;121;51m" }; // #E37933 63const markdown: Icon = .{ .icon = "", .color = Options.Colors.fg }; 64const nim: Icon = .{ .icon = "", .color = "\x1b[38;2;254;233;89m" }; // #FEE959 65const nix: Icon = .{ .icon = "󱄅", .color = "\x1b[38;2;127;185;228m" }; // #7fb9e4 66const ocaml: Icon = .{ .icon = "", .color = "\x1b[38;2;241;136;63m" }; // #F1883F 67const package: Icon = .{ .icon = "", .color = "\x1b[38;2;127;185;228m" }; // #7FB9E4 68const pdf: Icon = .{ .icon = "", .color = "\x1b[38;2;127;185;228m" }; // #7FB9E4 69const php: Icon = .{ .icon = "", .color = "\x1b[38;2;119;123;180m" }; // #777BB4 70const pl: Icon = .{ .icon = "", .color = "\x1b[38;2;0;79;120m" }; // #004F78 71const python: Icon = .{ .icon = "", .color = "\x1b[38;2;55;118;171m" }; // #3776AB 72const rb: Icon = .{ .icon = "", .color = "\x1b[38;2;204;52;45m" }; // #CC342D 73const rlang: Icon = .{ .icon = "", .color = "\x1b[38;2;39;109;195m" }; // #276DC3 74const root: Icon = .{ .icon = "󰦣", .color = "\x1b[38;2;23;214;240m" }; // #17D6F0 75const rust: Icon = .{ .icon = "", .color = "\x1b[38;2;211;69;22m" }; // #D34516 76const scala: Icon = .{ .icon = "", .color = "\x1b[38;2;220;50;47m" }; // #DC322F 77const script: Icon = .{ .icon = "", .color = Options.Colors.green }; 78const sh: Icon = .{ .icon = "", .color = "\x1b[38;2;137;224;81m" }; // #89E051 79const sheet: Icon = .{ .icon = "", .color = "\x1b[38;2;50;167;220m" }; // #32A7DC 80const sql: Icon = .{ .icon = "", .color = "\x1b[38;2;229;101;54m" }; // #E56536 81const swift: Icon = .{ .icon = "", .color = "\x1b[38;2;240;81;56m" }; // #F05138 82const slide: Icon = .{ .icon = "", .color = "\x1b[38;2;50;167;220m" }; // #32A7DC 83const toml: Icon = .{ .icon = "", .color = "\x1b[38;2;156;66;33m" }; // #9C4221 84const typescript: Icon = .{ .icon = "", .color = "\x1b[38;2;49;120;198m" }; // #3178C6 85const xml: Icon = .{ .icon = "", .color = Options.Colors.green }; 86const yaml: Icon = .{ .icon = "", .color = "\x1b[38;2;204;25;31m" }; // #CC191F 87const zig: Icon = .{ .icon = "", .color = "\x1b[38;2;247;164;71m" }; // #F7A447 88 89const by_name: std.StaticStringMap(Icon) = .initComptime(.{ 90 .{ ".bash_aliases", Icon.sh }, 91 .{ ".bash_history", Icon.sh }, 92 .{ ".bash_logout", Icon.sh }, 93 .{ ".bash_profile", Icon.sh }, 94 .{ ".bashrc", Icon.sh }, 95 .{ ".gitattributes", Icon.git }, 96 .{ ".gitconfig", Icon.git }, 97 .{ ".gitignore", Icon.git }, 98 .{ ".mailmap", Icon.git }, 99 .{ ".rootlogon.C", Icon.root }, 100 .{ ".rootrc", Icon.root }, 101 .{ ".zshrc", Icon.sh }, 102 .{ "build.gradle", Icon.java }, 103 .{ "build.gradle.kts", Icon.kt }, 104 .{ "build.sbt", Icon.scala }, 105 .{ "cabal", Icon.hs }, 106 .{ "Cargo.lock", Icon.rust }, 107 .{ "Cargo.toml", Icon.rust }, 108 .{ "CMakeCache.txt", Icon.cmake }, 109 .{ "CMakeLists.txt", Icon.cmake }, 110 .{ "composer.json", Icon.php }, 111 .{ "composer.lock", Icon.php }, 112 .{ "cpanfile", Icon.pl }, 113 .{ "csproj", Icon.cs }, 114 .{ "DESCRIPTION", Icon.rlang }, 115 .{ "flake.lock", Icon.nix }, 116 .{ "Gemfile", Icon.rb }, 117 .{ "Gemfile.lock", Icon.rb }, 118 .{ "GNUMakefile", Icon.makefile }, 119 .{ "go.mod", Icon.go }, 120 .{ "go.sum", Icon.go }, 121 .{ "install_manifest.txt", Icon.cmake }, 122 .{ "Makefile", Icon.makefile }, 123 .{ "mix.exs", Icon.ex }, 124 .{ "package-lock.json", Icon.javascript }, 125 .{ "package.json", Icon.javascript }, 126 .{ "Package.swift", Icon.swift }, 127 .{ "pom.xml", Icon.java }, 128 .{ "project.clj", Icon.clj }, 129 .{ "pubspec.yaml", Icon.dart }, 130 .{ "rebar.config", Icon.erl }, 131 .{ "requirements.txt", Icon.python }, 132 .{ "stack.yaml", Icon.hs }, 133 .{ "tsconfig.json", Icon.typescript }, 134}); 135 136const by_extension: std.StaticStringMap(Icon) = .initComptime(.{ 137 .{ "asm", Icon.assembly }, 138 .{ "asn", Icon.script }, 139 .{ "avro", Icon.json }, 140 .{ "awk", Icon.script }, 141 .{ "bash_history", Icon.script }, 142 .{ "bash_profile", Icon.script }, 143 .{ "bash", Icon.sh }, 144 .{ "bashrc", Icon.script }, 145 .{ "bmp", Icon.image }, 146 .{ "bz2", Icon.artifact }, 147 .{ "c", Icon.c }, 148 .{ "cc", Icon.cpp }, 149 .{ "cfg", Icon.config }, 150 .{ "cjs", Icon.javascript }, 151 .{ "clj", Icon.clj }, 152 .{ "cljs", Icon.clj }, 153 .{ "cma", Icon.ocaml }, 154 .{ "cmake.in", Icon.cmake }, 155 .{ "cmake", Icon.cmake }, 156 .{ "cmi", Icon.ocaml }, 157 .{ "cmo", Icon.ocaml }, 158 .{ "cmt", Icon.ocaml }, 159 .{ "cmti", Icon.ocaml }, 160 .{ "cmx", Icon.ocaml }, 161 .{ "cmxa", Icon.ocaml }, 162 .{ "cmxs", Icon.ocaml }, 163 .{ "conf", Icon.config }, 164 .{ "cpp", Icon.cpp }, 165 .{ "cs", Icon.cs }, 166 .{ "csh", Icon.script }, 167 .{ "css", Icon.css }, 168 .{ "csv", Icon.sheet }, 169 .{ "cxx", Icon.cpp }, 170 .{ "dart", Icon.dart }, 171 .{ "deb", Icon.package }, 172 .{ "diff", Icon.diff }, 173 .{ "doc", Icon.doc }, 174 .{ "docx", Icon.doc }, 175 .{ "drv", Icon.nix }, 176 .{ "editorconf", Icon.config }, 177 .{ "el", Icon.elisp }, 178 .{ "elf", Icon.script }, 179 .{ "eot", Icon.font }, 180 .{ "erl", Icon.erl }, 181 .{ "ex", Icon.ex }, 182 .{ "exs", Icon.ex }, 183 .{ "fish", Icon.script }, 184 .{ "flac", Icon.audio }, 185 .{ "fnl", Icon.fennel }, 186 .{ "font", Icon.font }, 187 .{ "gdoc", Icon.doc }, 188 .{ "gif", Icon.image }, 189 .{ "git", Icon.git }, 190 .{ "go", Icon.go }, 191 .{ "gsheet", Icon.sheet }, 192 .{ "gslides", Icon.slide }, 193 .{ "gz", Icon.artifact }, 194 .{ "h", Icon.h }, 195 .{ "hh", Icon.h }, 196 .{ "hpp", Icon.h }, 197 .{ "hs", Icon.hs }, 198 .{ "htm", Icon.html }, 199 .{ "html", Icon.html }, 200 .{ "hxx", Icon.h }, 201 .{ "ico", Icon.image }, 202 .{ "in", Icon.text }, 203 .{ "ini", Icon.config }, 204 .{ "ipynb", Icon.python }, 205 .{ "java", Icon.java }, 206 .{ "jpeg", Icon.image }, 207 .{ "jpg", Icon.image }, 208 .{ "js", Icon.javascript }, 209 .{ "json", Icon.json }, 210 .{ "jsonc", Icon.json }, 211 .{ "jsx", Icon.javascript }, 212 .{ "key", Icon.key }, 213 .{ "ksh", Icon.script }, 214 .{ "kt", Icon.kt }, 215 .{ "kts", Icon.kt }, 216 .{ "LICENSE", Icon.license }, 217 .{ "log", Icon.log }, 218 .{ "lua", Icon.lua }, 219 .{ "m3u", Icon.playlist }, 220 .{ "m4a", Icon.audio }, 221 .{ "markdown", Icon.markdown }, 222 .{ "md", Icon.markdown }, 223 .{ "mdk", Icon.markdown }, 224 .{ "mjs", Icon.javascript }, 225 .{ "mkv", Icon.video }, 226 .{ "ml", Icon.ocaml }, 227 .{ "mli", Icon.ocaml }, 228 .{ "mp3", Icon.audio }, 229 .{ "mp4", Icon.video }, 230 .{ "nar", Icon.nix }, 231 .{ "nim", Icon.nim }, 232 .{ "nimble", Icon.nim }, 233 .{ "nix", Icon.nix }, 234 .{ "odp", Icon.slide }, 235 .{ "ods", Icon.sheet }, 236 .{ "odt", Icon.doc }, 237 .{ "ogg", Icon.audio }, 238 .{ "opam", Icon.ocaml }, 239 .{ "opus", Icon.audio }, 240 .{ "otf", Icon.font }, 241 .{ "patch", Icon.diff }, 242 .{ "pdf", Icon.pdf }, 243 .{ "pem", Icon.key }, 244 .{ "php", Icon.php }, 245 .{ "pkg", Icon.package }, 246 .{ "pl", Icon.pl }, 247 .{ "pls", Icon.playlist }, 248 .{ "png", Icon.image }, 249 .{ "ppt", Icon.slide }, 250 .{ "pptm,", Icon.slide }, 251 .{ "pptx", Icon.slide }, 252 .{ "ps1", Icon.script }, 253 .{ "pub", Icon.key }, 254 .{ "py", Icon.python }, 255 .{ "pyc", Icon.python }, 256 .{ "r", Icon.rlang }, 257 .{ "rb", Icon.rb }, 258 .{ "readme", Icon.markdown }, 259 .{ "rmd", Icon.markdown }, 260 .{ "root", Icon.root }, 261 .{ "rpm", Icon.package }, 262 .{ "rs", Icon.rust }, 263 .{ "rtf", Icon.text }, 264 .{ "s", Icon.assembly }, 265 .{ "scala", Icon.scala }, 266 .{ "sh", Icon.sh }, 267 .{ "shell", Icon.script }, 268 .{ "sig", Icon.license }, 269 .{ "sql", Icon.sql }, 270 .{ "svg", Icon.image }, 271 .{ "swift", Icon.swift }, 272 .{ "tar", Icon.artifact }, 273 .{ "tgz", Icon.artifact }, 274 .{ "tiff", Icon.image }, 275 .{ "toml", Icon.toml }, 276 .{ "ts", Icon.typescript }, 277 .{ "tsx", Icon.typescript }, 278 .{ "ttc", Icon.font }, 279 .{ "ttf", Icon.font }, 280 .{ "txt", Icon.text }, 281 .{ "vlc", Icon.playlist }, 282 .{ "wav", Icon.audio }, 283 .{ "webp", Icon.image }, 284 .{ "wma", Icon.audio }, 285 .{ "woff", Icon.font }, 286 .{ "woff2", Icon.font }, 287 .{ "xls", Icon.sheet }, 288 .{ "xlsv", Icon.sheet }, 289 .{ "xlsx", Icon.sheet }, 290 .{ "xml", Icon.xml }, 291 .{ "yaml", Icon.yaml }, 292 .{ "yml", Icon.json }, 293 .{ "zig", Icon.zig }, 294 .{ "zip", Icon.artifact }, 295 .{ "zon", Icon.zig }, 296 .{ "zsh-theme", Icon.script }, 297 .{ "zsh", Icon.script }, 298 .{ "zshrc", Icon.script }, 299}); 300 301pub fn get(entry: Entry) Icon { 302 // 1. By name 303 // 2. By type 304 // 3. By extension 305 if (by_name.get(entry.name)) |icon| return icon; 306 307 switch (entry.kind) { 308 .block_device => return drive, 309 .character_device => return drive, 310 .directory => return directory, 311 .file => { 312 const ext = std.fs.path.extension(entry.name); 313 if (ext.len > 0) { 314 const ft = ext[1..]; 315 // First try exact match for performance 316 if (by_extension.get(ft)) |icon| return icon; 317 318 // Then try case-insensitive match 319 var buf: [32]u8 = undefined; 320 if (ft.len < buf.len) { 321 const lowercase_ext = std.ascii.lowerString(&buf, ft); 322 if (by_extension.get(lowercase_ext)) |icon| return icon; 323 } 324 } 325 326 if (entry.isExecutable()) { 327 return executable; 328 } 329 return file; 330 }, 331 .named_pipe => return pipe, 332 .sym_link => { 333 if (posix.S.ISDIR(entry.statx.mode)) { 334 return symlink_dir; 335 } 336 return symlink; 337 }, 338 .unix_domain_socket => return pipe, 339 else => return file, 340 } 341}