feat: config option to customize filename highlight group (#508)

* feat: highlight config

Refs #402

* perf: minimize perf impact when option not provided

* doc: regenerate documentation

* fix: symbolic link rendering

* refactor: simplify conditional

---------

Co-authored-by: Steven Arcangeli <stevearc@stevearc.com>
This commit is contained in:
Foo-x 2024-11-23 03:23:08 +09:00 committed by GitHub
parent 60e68967e5
commit 99ce32f4a2
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 76 additions and 16 deletions

View file

@ -102,6 +102,10 @@ local default_config = {
{ "type", "asc" },
{ "name", "asc" },
},
-- Customize the highlight group for the file name
highlight_filename = function(entry, is_hidden, is_link_target, is_link_orphan)
return nil
end,
},
-- Extra arguments to pass to SCP when moving/copying files over SSH
extra_scp_args = {},
@ -207,6 +211,9 @@ default_config.adapters = {
["oil-trash://"] = "trash",
}
default_config.adapter_aliases = {}
-- We want the function in the default config for documentation generation, but if we nil it out
-- here we can get some performance wins
default_config.view_options.highlight_filename = nil
---@class oil.Config
---@field adapters table<string, string> Hidden from SetupOpts
@ -281,6 +288,7 @@ local M = {}
---@field natural_order boolean|"fast"
---@field case_insensitive boolean
---@field sort oil.SortSpec[]
---@field highlight_filename? fun(entry: oil.Entry, is_hidden: boolean, is_link_target: boolean, is_link_orphan: boolean): string|nil
---@class (exact) oil.SetupViewOptions
---@field show_hidden? boolean Show files and directories that start with "."
@ -289,6 +297,7 @@ local M = {}
---@field natural_order? boolean|"fast" Sort file names with numbers in a more intuitive order for humans. Can be slow for large directories.
---@field case_insensitive? boolean Sort file and directory names case insensitive
---@field sort? oil.SortSpec[] Sort order for the file list
---@field highlight_filename? fun(entry: oil.Entry, is_hidden: boolean, is_link_target: boolean, is_link_orphan: boolean): string|nil Customize the highlight group for the file name
---@class (exact) oil.SortSpec
---@field [1] string

View file

@ -691,6 +691,28 @@ local function render_buffer(bufnr, opts)
return seek_after_render_found
end
---@param name string
---@param meta? table
---@return string filename
---@return string|nil link_target
local function get_link_text(name, meta)
local link_text
if meta then
if meta.link_stat and meta.link_stat.type == "directory" then
name = name .. "/"
end
if meta.link then
link_text = "-> " .. meta.link
if meta.link_stat and meta.link_stat.type == "directory" then
link_text = util.addslash(link_text)
end
end
end
return name, link_text
end
---@private
---@param entry oil.InternalEntry
---@param column_defs table[]
@ -723,34 +745,55 @@ M.format_entry_cols = function(entry, column_defs, col_width, adapter, is_hidden
end
-- Always add the entry name at the end
local entry_type = entry[FIELD_TYPE]
local get_custom_hl = config.view_options.highlight_filename
local link_name, link_name_hl, link_target, link_target_hl
if get_custom_hl then
local external_entry = util.export_entry(entry)
if entry_type == "link" then
link_name, link_target = get_link_text(name, meta)
local is_orphan = not (meta and meta.link_stat)
link_name_hl = get_custom_hl(external_entry, is_hidden, false, is_orphan)
if link_target then
link_target_hl = get_custom_hl(external_entry, is_hidden, true, is_orphan)
end
-- intentional fallthrough
else
local hl = get_custom_hl(external_entry, is_hidden, false, false)
if hl then
table.insert(cols, { name, hl })
return cols
end
end
end
if entry_type == "directory" then
table.insert(cols, { name .. "/", "OilDir" .. hl_suffix })
elseif entry_type == "socket" then
table.insert(cols, { name, "OilSocket" .. hl_suffix })
elseif entry_type == "link" then
local link_text
if meta then
if meta.link_stat and meta.link_stat.type == "directory" then
name = name .. "/"
end
if meta.link then
link_text = "-> " .. meta.link
if meta.link_stat and meta.link_stat.type == "directory" then
link_text = util.addslash(link_text)
end
end
if not link_name then
link_name, link_target = get_link_text(name, meta)
end
local is_orphan = not (meta and meta.link_stat)
if not link_name_hl then
link_name_hl = (is_orphan and "OilOrphanLink" or "OilLink") .. hl_suffix
end
table.insert(cols, { link_name, link_name_hl })
table.insert(cols, { name, (is_orphan and "OilOrphanLink" or "OilLink") .. hl_suffix })
if link_text then
local target_hl = (is_orphan and "OilOrphanLinkTarget" or "OilLinkTarget") .. hl_suffix
table.insert(cols, { link_text, target_hl })
if link_target then
if not link_target_hl then
link_target_hl = (is_orphan and "OilOrphanLinkTarget" or "OilLinkTarget") .. hl_suffix
end
table.insert(cols, { link_target, link_target_hl })
end
else
table.insert(cols, { name, "OilFile" .. hl_suffix })
end
return cols
end