Skip to content

feat(#168): add prefixes #370

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 4 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 16 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -65,9 +65,9 @@ require'nvim-web-devicons'.setup {
-- will get overriden by `get_icons` option
default = true;
-- globally enable "strict" selection of icons - icon will be looked up in
-- different tables, first by filename, and if not found by extension; this
-- different tables, first by filename, then by prefix, and if not found by extension; this
-- prevents cases when file doesn't have any extension but still gets some icon
-- because its name happened to match some extension (default to false)
-- because its name happened to match some prefix or extension (default to false)
strict = true;
-- same as `override` but specifically for overrides by filename
-- takes effect when `strict` is true
Expand All @@ -78,6 +78,16 @@ require'nvim-web-devicons'.setup {
name = "Gitignore"
}
};
-- same as `override` but specifically for overrides by prefix
-- takes effect when `strict` is true
override_by_prefix = {
["dockerfile"] = {
icon = "󰡨",
color = "#458ee6",
cterm_color = "68",
name = "Dockerfile",
},
};
-- same as `override` but specifically for overrides by extension
-- takes effect when `strict` is true
override_by_extension = {
Expand All @@ -92,12 +102,12 @@ require'nvim-web-devicons'.setup {

### Get Icon

Get the icon for a given file by passing in the `name`, the `extension` and an _optional_ options `table`.
Get the icon for a given file by passing in the `name`, the `pre_or_ext` and an _optional_ options `table`.
The name is passed in to check for an exact match e.g. `.bashrc` if there is no exact name match the extension
is used. Calls `.setup()` if it hasn't already ran.

```lua
require'nvim-web-devicons'.get_icon(filename, extension, options)
require'nvim-web-devicons'.get_icon(filename, pre_or_ext, options)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This will break existing behaviour - a prefixed icon will be returned where none was before.

```

The optional `options` argument can used to change how the plugin works the keys include
Expand All @@ -108,7 +118,7 @@ specifically by extension, and fallback to default icon if default key is set to
e.g.

```lua
require'nvim-web-devicons'.get_icon(filename, extension, { default = true })
require'nvim-web-devicons'.get_icon(filename, pre_or_ext, { default = true })
```

You can check if the setup function was already called with:
Expand Down Expand Up @@ -171,7 +181,7 @@ require("nvim-web-devicons").get_icon_color_by_filetype(filetype, opts)
require("nvim-web-devicons").get_icon_cterm_color_by_filetype(filetype, opts)
```

These functions are the same as their counterparts without the `_by_filetype` suffix, but they take a filetype instead of a name/extension.
These functions are the same as their counterparts without the `_by_filetype` suffix, but they take a filetype instead of a name, prefix or extension.

You can also use `get_icon_name_by_filetype(filetype)` to get the icon name associated with the filetype.

Expand Down
87 changes: 73 additions & 14 deletions lua/nvim-web-devicons.lua
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
local M = {}

-- 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, icons_by_filename, icons_by_file_prefix, icons_by_file_extension, icons_by_operating_system

function M.get_icons()
return icons
Expand All @@ -17,9 +17,17 @@ local function refresh_icons()
end

icons_by_filename = theme.icons_by_filename
icons_by_file_prefix = theme.icons_by_file_prefix
icons_by_file_extension = theme.icons_by_file_extension
icons_by_operating_system = theme.icons_by_operating_system
icons = vim.tbl_extend("keep", {}, icons_by_filename, icons_by_file_extension, icons_by_operating_system)
icons = vim.tbl_extend(
"keep",
{},
icons_by_filename,
icons_by_file_prefix,
icons_by_file_extension,
Copy link
Member

@alex-courtis alex-courtis Jan 6, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure we can do that - prefixes will clobber extensions, in this case "dockerfile".

icons_by_operating_system
)
end

-- Map of filetypes -> icon names
Expand Down Expand Up @@ -332,14 +340,24 @@ function M.setup(opts)
end

local user_filename_icons = user_icons.override_by_filename
local user_file_pre_icons = user_icons.override_by_prefix
local user_file_ext_icons = user_icons.override_by_extension

icons =
vim.tbl_extend("force", icons, user_icons.override or {}, user_filename_icons or {}, user_file_ext_icons or {})
icons = vim.tbl_extend(
"force",
icons,
user_icons.override or {},
user_filename_icons or {},
user_file_pre_icons or {},
user_file_ext_icons or {}
)

if user_filename_icons then
icons_by_filename = vim.tbl_extend("force", icons_by_filename, user_filename_icons)
end
if user_file_pre_icons then
icons_by_file_prefix = vim.tbl_extend("force", icons_by_file_prefix, user_file_pre_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
Expand All @@ -359,6 +377,24 @@ function M.get_default_icon()
return default_icon
end

-- recursively iterate over each segment separated by '.' to parse prefix with multiple dots in filename
local function iterate_multi_dotted_prefix(name, icon_table)
if name == nil then
return nil
end

local compound_pre, rest = name:match "(.?[^.]*)%.(.*)"
local icon = icon_table[compound_pre]
if icon then
return icon
end
if not rest then
return nil
end

return iterate_multi_dotted_prefix(rest, icon_table)
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
Expand All @@ -374,6 +410,17 @@ local function iterate_multi_dotted_extension(name, icon_table)
return iterate_multi_dotted_extension(compound_ext, icon_table)
end

local function get_icon_by_prefix(name, prefix, opts)
local is_strict = if_nil(opts and opts.strict, global_opts.strict)
local icon_table = is_strict and icons_by_file_prefix or icons

if prefix ~= nil then
return icon_table[prefix]
end

return iterate_multi_dotted_prefix(name, 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
Expand All @@ -385,7 +432,7 @@ local function get_icon_by_extension(name, ext, opts)
return iterate_multi_dotted_extension(name, icon_table)
end

function M.get_icon(name, ext, opts)
function M.get_icon(name, pre_or_ext, opts)
if type(name) == "string" then
name = name:lower()
end
Expand All @@ -398,9 +445,15 @@ function M.get_icon(name, ext, opts)
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)
icon_data = icons_by_filename[name]
or get_icon_by_prefix(name, pre_or_ext, opts)
or get_icon_by_extension(name, pre_or_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)
icon_data = icons[name]
or get_icon_by_prefix(name, pre_or_ext, opts)
or get_icon_by_extension(name, pre_or_ext, opts)
or (has_default and default_icon)
end

if icon_data then
Expand All @@ -419,7 +472,7 @@ function M.get_icon_by_filetype(ft, opts)
return M.get_icon(name or "", nil, opts)
end

function M.get_icon_colors(name, ext, opts)
function M.get_icon_colors(name, pre_or_ext, opts)
if not loaded then
M.setup()
end
Expand All @@ -428,9 +481,15 @@ function M.get_icon_colors(name, ext, opts)
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)
icon_data = icons_by_filename[name]
or get_icon_by_prefix(name, pre_or_ext, opts)
or get_icon_by_extension(name, pre_or_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)
icon_data = icons[name]
or get_icon_by_prefix(name, pre_or_ext, opts)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This will result in a prefix being returned when users were previously expecting an extension, when the key is the same.

or get_icon_by_extension(name, pre_or_ext, opts)
or (has_default and default_icon)
end

if icon_data then
Expand All @@ -449,8 +508,8 @@ function M.get_icon_colors_by_filetype(ft, opts)
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) }
function M.get_icon_color(name, pre_or_ext, opts)
local data = { M.get_icon_colors(name, pre_or_ext, opts) }
return data[1], data[2]
end

Expand All @@ -461,8 +520,8 @@ function M.get_icon_color_by_filetype(ft, opts)
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) }
function M.get_icon_cterm_color(name, pre_or_ext, opts)
local data = { M.get_icon_colors(name, pre_or_ext, opts) }
return data[1], data[3]
end

Expand Down
26 changes: 18 additions & 8 deletions lua/nvim-web-devicons/icons-default.lua
Original file line number Diff line number Diff line change
Expand Up @@ -227,12 +227,6 @@ local icons_by_filename = {
cterm_color = "68",
name = "Dockerfile",
},
["dockerfile"] = {
icon = "󰡨",
color = "#458ee6",
cterm_color = "68",
name = "Dockerfile",
},
["favicon.ico"] = {
icon = "",
color = "#cbcb41",
Expand Down Expand Up @@ -367,13 +361,28 @@ local icons_by_filename = {
},
}

local icons_by_file_extension = {
["Dockerfile"] = {
local icons_by_file_prefix = {
[".env"] = {
icon = "",
color = "#faf743",
cterm_color = "227",
name = "Env",
},
["dockerfile"] = {
icon = "󰡨",
color = "#458ee6",
cterm_color = "68",
name = "Dockerfile",
},
[".eslintrc"] = {
icon = "",
color = "#4b32c3",
cterm_color = "56",
name = "Eslintrc",
},
}

local icons_by_file_extension = {
["R"] = {
icon = "󰟔",
color = "#2266ba",
Expand Down Expand Up @@ -2139,6 +2148,7 @@ local icons_by_operating_system = {

return {
icons_by_filename = icons_by_filename,
icons_by_file_prefix = icons_by_file_prefix,
icons_by_file_extension = icons_by_file_extension,
icons_by_operating_system = icons_by_operating_system,
}
26 changes: 18 additions & 8 deletions lua/nvim-web-devicons/icons-light.lua
Original file line number Diff line number Diff line change
Expand Up @@ -227,12 +227,6 @@ local icons_by_filename = {
cterm_color = "25",
name = "Dockerfile",
},
["dockerfile"] = {
icon = "󰡨",
color = "#2e5f99",
cterm_color = "25",
name = "Dockerfile",
},
["favicon.ico"] = {
icon = "",
color = "#666620",
Expand Down Expand Up @@ -367,13 +361,28 @@ local icons_by_filename = {
},
}

local icons_by_file_extension = {
["Dockerfile"] = {
local icons_by_file_prefix = {
[".env"] = {
icon = "",
color = "#32310d",
cterm_color = "236",
name = "Env",
},
["dockerfile"] = {
icon = "󰡨",
color = "#2e5f99",
cterm_color = "25",
name = "Dockerfile",
},
[".eslintrc"] = {
icon = "",
color = "#4b32c3",
cterm_color = "56",
name = "Eslintrc",
},
}

local icons_by_file_extension = {
["R"] = {
icon = "󰟔",
color = "#1a4c8c",
Expand Down Expand Up @@ -2139,6 +2148,7 @@ local icons_by_operating_system = {

return {
icons_by_filename = icons_by_filename,
icons_by_file_prefix = icons_by_file_prefix,
icons_by_file_extension = icons_by_file_extension,
icons_by_operating_system = icons_by_operating_system,
}
24 changes: 16 additions & 8 deletions scripts/generate_colors.lua
Original file line number Diff line number Diff line change
Expand Up @@ -136,27 +136,35 @@ end
local lines = generate_lines()

-- second table
if fn.search("^local icons_by_file_extension", "c") == 0 then
error_exit("Table 'icons_by_file_extension' not found in lua/nvim-web-devicons/icons-default.lua", 1)
if fn.search("^local icons_by_file_prefix", "c") == 0 then
error_exit("Table 'icons_by_file_prefix' not found in lua/nvim-web-devicons/icons-default.lua", 1)
end
local lines2 = generate_lines()

-- third table
if fn.search("^local icons_by_file_extension", "c") == 0 then
error_exit("Table 'icons_by_file_extension' not found in lua/nvim-web-devicons/icons-default.lua", 1)
end
local lines3 = generate_lines()

-- fourth table
if fn.search("^local icons_by_operating_system", "c") == 0 then
error_exit("Table 'icons_by_operating_system' not found in lua/nvim-web-devicons/icons-default.lua", 1)
end
local lines3 = generate_lines()
local lines4 = generate_lines()

table.insert(lines3, "return {")
table.insert(lines3, " icons_by_filename = icons_by_filename,")
table.insert(lines3, " icons_by_file_extension = icons_by_file_extension,")
table.insert(lines3, " icons_by_operating_system = icons_by_operating_system,")
table.insert(lines3, "}")
table.insert(lines4, "return {")
table.insert(lines4, " icons_by_filename = icons_by_filename,")
table.insert(lines4, " icons_by_file_prefix = icons_by_file_prefix,")
table.insert(lines4, " icons_by_file_extension = icons_by_file_extension,")
table.insert(lines4, " icons_by_operating_system = icons_by_operating_system,")
table.insert(lines4, "}")

-- write both tables to file
fn.writefile(lines, "lua/nvim-web-devicons/icons-light.lua")
fn.writefile(lines2, "lua/nvim-web-devicons/icons-light.lua", "a")
fn.writefile(lines3, "lua/nvim-web-devicons/icons-light.lua", "a")
fn.writefile(lines4, "lua/nvim-web-devicons/icons-light.lua", "a")

print "Finished creating new file!"

Expand Down