local M = {} -- NOTE: When adding new icons, remember to add an entry to the `filetypes` table, if applicable. local icons, icons_by_filename, icons_by_file_extension, icons_by_operating_system local icons_by_desktop_environment, icons_by_window_manager local default_icon = { icon = "", color = "#6d8086", cterm_color = "66", name = "Default", } function M.get_icons() return icons end function M.get_icons_by_filename() return icons_by_filename end function M.get_icons_by_extension() return icons_by_file_extension end function M.get_icons_by_operating_system() return icons_by_operating_system end function M.get_icons_by_desktop_environment() return icons_by_desktop_environment end function M.get_icons_by_window_manager() return icons_by_window_manager end local global_opts = { override = {}, strict = false, default = false, color_icons = true, } -- Set the current icons tables, depending on the 'background' option. local function refresh_icons() local theme if vim.o.background == "light" then theme = require "nvim-web-devicons.icons-light" else theme = require "nvim-web-devicons.icons-default" end icons_by_filename = theme.icons_by_filename icons_by_file_extension = theme.icons_by_file_extension icons_by_operating_system = theme.icons_by_operating_system icons_by_desktop_environment = theme.icons_by_desktop_environment icons_by_window_manager = theme.icons_by_window_manager icons = vim.tbl_extend( "keep", {}, icons_by_filename, icons_by_file_extension, icons_by_operating_system, icons_by_desktop_environment, icons_by_window_manager ) icons = vim.tbl_extend("force", icons, global_opts.override) icons[1] = default_icon end -- Map of filetypes -> icon names local filetypes = { ["apl"] = "apl", ["avif"] = "avif", ["bash"] = "bash", ["bib"] = "bib", ["bicep"] = "bicep", ["bicepparam"] = "bicepparam", ["bqn"] = "bqn", ["bzl"] = "bzl", ["brewfile"] = "brewfile", ["blueprint"] = "blp", ["checkhealth"] = "checkhealth", ["commit"] = "commit_editmsg", ["copying"] = "copying", ["gemfile"] = "gemfile$", ["lesser"] = "copying.lesser", ["vagrantfile"] = "vagrantfile$", ["awk"] = "awk", ["bmp"] = "bmp", ["c"] = "c", ["cfg"] = "cfg", ["clojure"] = "clj", ["cmake"] = "cmake", ["cobol"] = "cobol", ["coffee"] = "coffee", ["conf"] = "conf", ["cp"] = "cp", ["cpp"] = "cpp", ["cr"] = "cr", ["cs"] = "cs", ["csh"] = "csh", ["cson"] = "cson", ["css"] = "css", ["csv"] = "csv", ["cuda"] = "cu", ["d"] = "d", ["dart"] = "dart", ["desktop"] = "desktop", ["diff"] = "diff", ["doc"] = "doc", ["docx"] = "docx", ["dockerfile"] = "dockerfile", ["dosbatch"] = "bat", ["dosini"] = "ini", ["dot"] = "dot", ["drools"] = "drl", ["dropbox"] = "dropbox", ["dump"] = "dump", ["eex"] = "eex", ["ejs"] = "ejs", ["elixir"] = "ex", ["elm"] = "elm", ["epuppet"] = "epp", ["erlang"] = "erl", ["eruby"] = "erb", ["fennel"] = "fnl", ["fish"] = "fish", ["forth"] = "fs", ["fortran"] = "f90", ["fsharp"] = "f#", ["fsi"] = "fsi", ["fsscript"] = "fsscript", ["fsx"] = "fsx", ["gd"] = "gd", ["gif"] = "gif", ["git"] = "git", ["gitconfig"] = ".gitconfig", ["gitcommit"] = "commit_editmsg", ["gitignore"] = ".gitignore", ["gitattributes"] = ".gitattributes", ["glb"] = "glb", ["go"] = "go", ["godot"] = "godot", ["graphql"] = "graphql", ["groovy"] = "groovy", ["gql"] = "gql", ["gruntfile"] = "gruntfile", ["gtkrc"] = "gtkrc", ["gulpfile"] = "gulpfile", ["haml"] = "haml", ["haxe"] = "hx", ["haskell"] = "hs", ["hbs"] = "hbs", ["heex"] = "heex", ["hex"] = "hex", ["html"] = "html", ["ico"] = "ico", ["idlang"] = "pro", ["ino"] = "ino", ["import"] = "import", ["ipynb"] = "ipynb", ["java"] = "java", ["javascript"] = "js", ["javascript.jsx"] = "jsx", ["javascriptreact"] = "jsx", ["jpeg"] = "jpeg", ["jpg"] = "jpg", ["json"] = "json", ["jsonc"] = "jsonc", ["json5"] = "json5", ["julia"] = "jl", ["kotlin"] = "kt", ["leex"] = "leex", ["less"] = "less", ["liquid"] = "liquid", ["lhaskell"] = "lhs", ["license"] = "license", ["unlicense"] = "unlicense", ["log"] = "log", ["lock"] = "lock", ["lprolog"] = "sig", ["lua"] = "lua", ["make"] = "makefile", ["markdown"] = "markdown", ["material"] = "material", ["mdx"] = "mdx", ["mint"] = "mint", ["motoko"] = "mo", ["mustache"] = "mustache", ["nim"] = "nim", ["nix"] = "nix", ["nu"] = "nu", ["node"] = "node_modules", ["obj"] = "obj", ["ocaml"] = "ml", ["openscad"] = "scad", ["opus"] = "opus", ["otf"] = "otf", ["pck"] = "pck", ["pdf"] = "pdf", ["perl"] = "pl", ["php"] = "php", ["plaintex"] = "tex", ["png"] = "png", ["po"] = "po", ["postscr"] = "ai", ["ppt"] = "ppt", ["prisma"] = "prisma", ["procfile"] = "procfile", ["prolog"] = "pro", ["ps1"] = "ps1", ["psd1"] = "psd1", ["psm1"] = "psm1", ["psb"] = "psb", ["psd"] = "psd", ["puppet"] = "pp", ["pyc"] = "pyc", ["pyd"] = "pyd", ["pyo"] = "pyo", ["python"] = "py", ["query"] = "query", ["r"] = "r", ["res"] = "rescript", ["resi"] = "rescript", ["rlib"] = "rlib", ["rmd"] = "rmd", ["rproj"] = "rproj", ["ruby"] = "rb", ["rust"] = "rs", ["sass"] = "sass", ["sbt"] = "sbt", ["scala"] = "scala", ["scheme"] = "scm", ["scss"] = "scss", ["sh"] = "sh", ["slim"] = "slim", ["sln"] = "sln", ["sml"] = "sml", ["solidity"] = "sol", ["sql"] = "sql", ["sqlite"] = "sqlite", ["sqlite3"] = "sqlite3", ["srt"] = "srt", ["ssa"] = "ssa", ["styl"] = "styl", ["sublime"] = "sublime", ["suo"] = "suo", ["svelte"] = "svelte", ["svg"] = "svg", ["swift"] = "swift", ["systemverilog"] = "sv", ["tads"] = "t", ["tcl"] = "tcl", ["templ"] = "templ", ["terminal"] = "terminal", ["tex"] = "tex", ["toml"] = "toml", ["tres"] = "tres", ["tscn"] = "tscn", ["twig"] = "twig", ["txt"] = "txt", ["typescript"] = "ts", ["typescriptreact"] = "tsx", ["vala"] = "vala", ["verilog"] = "v", ["vhdl"] = "vhd", ["vim"] = "vim", ["vue"] = "vue", ["wasm"] = "wasm", ["webm"] = "webm", ["webp"] = "webp", ["webpack"] = "webpack", ["xcplayground"] = "xcplayground", ["xls"] = "xls", ["xlsx"] = "xlsx", ["xml"] = "xml", ["yaml"] = "yaml", ["zig"] = "zig", ["zsh"] = "zsh", } local function get_highlight_name(data) if not global_opts.color_icons then data = default_icon end return data.name and "DevIcon" .. data.name end local nvim_set_hl = vim.api.nvim_set_hl local function set_up_highlight(icon_data) if not global_opts.color_icons then icon_data = default_icon end local hl_group = get_highlight_name(icon_data) if hl_group and (icon_data.color or icon_data.cterm_color) then nvim_set_hl(0, get_highlight_name(icon_data), { fg = icon_data.color, ctermfg = tonumber(icon_data.cterm_color), }) end end local nvim_get_hl_by_name = vim.api.nvim_get_hl_by_name local function highlight_exists(group) if not group then return end local ok, hl = pcall(nvim_get_hl_by_name, group, true) return ok and not (hl or {})[true] end function M.set_up_highlights(allow_override) if not global_opts.color_icons then set_up_highlight(default_icon) return end for _, icon_data in pairs(icons) do local has_color = icon_data.color or icon_data.cterm_color local name_valid = icon_data.name local defined_before = highlight_exists(get_highlight_name(icon_data)) if has_color and name_valid and (allow_override or not defined_before) then set_up_highlight(icon_data) end end end local function get_highlight_foreground(icon_data) if not global_opts.color_icons then icon_data = default_icon end return string.format("#%06x", nvim_get_hl_by_name(get_highlight_name(icon_data), true).foreground) end local function get_highlight_ctermfg(icon_data) if not global_opts.color_icons then icon_data = default_icon end return nvim_get_hl_by_name(get_highlight_name(icon_data), false).foreground end local loaded = false function M.has_loaded() return loaded end local if_nil = vim.F.if_nil function M.setup(opts) if loaded then return end loaded = true local user_icons = opts or {} if user_icons.default then global_opts.default = true end if user_icons.strict then global_opts.strict = true end global_opts.color_icons = if_nil(user_icons.color_icons, global_opts.color_icons) if user_icons.override and user_icons.override.default_icon then default_icon = user_icons.override.default_icon end local user_filename_icons = user_icons.override_by_filename local user_file_ext_icons = user_icons.override_by_extension local user_operating_system_icons = user_icons.override_by_operating_system local user_desktop_environment_icons = user_icons.override_by_desktop_environment local user_window_manager_icons = user_icons.override_by_window_manager icons = vim.tbl_extend( "force", icons, user_icons.override or {}, user_filename_icons or {}, user_file_ext_icons or {}, user_operating_system_icons or {}, user_desktop_environment_icons or {}, user_window_manager_icons or {} ) global_opts.override = vim.tbl_extend( "force", global_opts.override, user_icons.override or {}, user_filename_icons or {}, user_file_ext_icons or {}, user_operating_system_icons or {}, user_desktop_environment_icons or {}, user_window_manager_icons or {} ) if user_filename_icons then icons_by_filename = vim.tbl_extend("force", icons_by_filename, user_filename_icons) end if user_file_ext_icons then icons_by_file_extension = vim.tbl_extend("force", icons_by_file_extension, user_file_ext_icons) end if user_operating_system_icons then icons_by_operating_system = vim.tbl_extend("force", icons_by_operating_system, user_operating_system_icons) end if user_desktop_environment_icons then icons_by_desktop_environment = vim.tbl_extend("force", icons_by_desktop_environment, user_desktop_environment_icons) end if user_window_manager_icons then icons_by_window_manager = vim.tbl_extend("force", icons_by_window_manager, user_window_manager_icons) end icons[1] = default_icon M.set_up_highlights() vim.api.nvim_create_autocmd("ColorScheme", { desc = "Re-apply icon colors after changing colorschemes", group = vim.api.nvim_create_augroup("NvimWebDevicons", { clear = true }), callback = M.set_up_highlights, }) -- highlight test command vim.api.nvim_create_user_command("NvimWebDeviconsHiTest", function() require "nvim-web-devicons.hi-test"( default_icon, global_opts.override, icons_by_filename, icons_by_file_extension, icons_by_operating_system, icons_by_desktop_environment, icons_by_window_manager ) end, { desc = "nvim-web-devicons: highlight test", }) end function M.get_default_icon() return default_icon end -- recursively iterate over each segment separated by '.' to parse extension with multiple dots in filename local function iterate_multi_dotted_extension(name, icon_table) if name == nil then return nil end local compound_ext = name:match "%.(.*)" local icon = icon_table[compound_ext] if icon then return icon end return iterate_multi_dotted_extension(compound_ext, icon_table) end local function get_icon_by_extension(name, ext, opts) local is_strict = if_nil(opts and opts.strict, global_opts.strict) local icon_table = is_strict and icons_by_file_extension or icons if ext ~= nil then return icon_table[ext] end return iterate_multi_dotted_extension(name, icon_table) end local function get_icon_data(name, ext, opts) if type(name) == "string" then name = name:lower() end if not loaded then M.setup() end local has_default = if_nil(opts and opts.default, global_opts.default) local is_strict = if_nil(opts and opts.strict, global_opts.strict) local icon_data if is_strict then icon_data = icons_by_filename[name] or get_icon_by_extension(name, ext, opts) or (has_default and default_icon) else icon_data = icons[name] or get_icon_by_extension(name, ext, opts) or (has_default and default_icon) end return icon_data end function M.get_icon(name, ext, opts) local icon_data = get_icon_data(name, ext, opts) if icon_data then return icon_data.icon, get_highlight_name(icon_data) end end function M.get_icon_name_by_filetype(ft) return filetypes[ft] end function M.get_icon_by_filetype(ft, opts) local name = M.get_icon_name_by_filetype(ft) opts = opts or {} opts.strict = false return M.get_icon(name or "", nil, opts) end function M.get_icon_colors(name, ext, opts) local icon_data = get_icon_data(name, ext, opts) if icon_data then local color = icon_data.color local cterm_color = icon_data.cterm_color if icon_data.name and highlight_exists(get_highlight_name(icon_data)) then color = get_highlight_foreground(icon_data) or color cterm_color = get_highlight_ctermfg(icon_data) or cterm_color end return icon_data.icon, color, cterm_color end end function M.get_icon_colors_by_filetype(ft, opts) local name = M.get_icon_name_by_filetype(ft) return M.get_icon_colors(name or "", nil, opts) end function M.get_icon_color(name, ext, opts) local data = { M.get_icon_colors(name, ext, opts) } return data[1], data[2] end function M.get_icon_color_by_filetype(ft, opts) local name = M.get_icon_name_by_filetype(ft) opts = opts or {} opts.strict = false return M.get_icon_color(name or "", nil, opts) end function M.get_icon_cterm_color(name, ext, opts) local data = { M.get_icon_colors(name, ext, opts) } return data[1], data[3] end function M.get_icon_cterm_color_by_filetype(ft, opts) local name = M.get_icon_name_by_filetype(ft) return M.get_icon_cterm_color(name or "", nil, opts) end function M.set_icon(user_icons) icons = vim.tbl_extend("force", icons, user_icons or {}) global_opts.override = vim.tbl_extend("force", global_opts.override, user_icons or {}) if not global_opts.color_icons then return end for _, icon_data in pairs(user_icons) do set_up_highlight(icon_data) end end function M.set_icon_by_filetype(user_filetypes) filetypes = vim.tbl_extend("force", filetypes, user_filetypes or {}) end function M.set_default_icon(icon, color, cterm_color) default_icon.icon = icon default_icon.color = color default_icon.cterm_color = cterm_color set_up_highlight(default_icon) end -- Load the icons already, the loaded tables depend on the 'background' setting. refresh_icons() function M.refresh() refresh_icons() M.set_up_highlights(true) end -- Change icon set on background change vim.api.nvim_create_autocmd("OptionSet", { pattern = "background", callback = M.refresh, }) return M