diff --git a/README.md b/README.md index 684ff24..f690904 100644 --- a/README.md +++ b/README.md @@ -232,6 +232,10 @@ require("oil").setup({ { "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 = {}, diff --git a/doc/oil.txt b/doc/oil.txt index 87d4bbb..63bca11 100644 --- a/doc/oil.txt +++ b/doc/oil.txt @@ -117,6 +117,10 @@ CONFIG *oil-confi { "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 = {}, diff --git a/lua/oil/config.lua b/lua/oil/config.lua index 185cb15..0374e43 100644 --- a/lua/oil/config.lua +++ b/lua/oil/config.lua @@ -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 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 diff --git a/lua/oil/view.lua b/lua/oil/view.lua index 74ab145..6b26182 100644 --- a/lua/oil/view.lua +++ b/lua/oil/view.lua @@ -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