diff options
| author | Fasamii <fasami0512@gmail.com> | 2026-02-05 22:53:13 +0100 |
|---|---|---|
| committer | Fasamii <fasami0512@gmail.com> | 2026-02-05 22:53:13 +0100 |
| commit | b415d15d49e78382cd53c36f786f7ff2a6a263f9 (patch) | |
| tree | 419effe2323d99dc0b825a40b664fa17111c1a45 | |
| parent | d8df2abe655ec2468bf0f6ab898dd909f8c73479 (diff) | |
| download | netrw-icons.nvim-b415d15d49e78382cd53c36f786f7ff2a6a263f9.tar.gz netrw-icons.nvim-b415d15d49e78382cd53c36f786f7ff2a6a263f9.tar.bz2 netrw-icons.nvim-b415d15d49e78382cd53c36f786f7ff2a6a263f9.tar.xz netrw-icons.nvim-b415d15d49e78382cd53c36f786f7ff2a6a263f9.tar.zst | |
semi working demo
| -rw-r--r-- | lua/netrw-icons/init.lua | 151 | ||||
| -rw-r--r-- | lua/netrw-icons/parse.lua | 130 |
2 files changed, 164 insertions, 117 deletions
diff --git a/lua/netrw-icons/init.lua b/lua/netrw-icons/init.lua index 608d479..4f378a2 100644 --- a/lua/netrw-icons/init.lua +++ b/lua/netrw-icons/init.lua @@ -7,7 +7,8 @@ -- https://github.com/prichrd/netrw.nvim local M = {} -local parse = require("netrw.parse") + +local parse = require("netrw-icons.parse") local icon_provider = nil @@ -37,43 +38,69 @@ local function get_icon_provider(prefer) return nil end -local function get_file_icon(node) - if not icon_provider then - return nil, nil - end - - if icon_provider.type == "devicons" then - local icon, hl = icon_provider.provider.get_icon(node.node, nil, { strict = true, default = false }) - return icon, hl - elseif icon_provider.type == "miniicons" then - local icon, hl = icon_provider.provider.get("file", node.node) - return icon, hl +local function get_icon_from_provider(name) + if icon_provider then + local provider = icon_provider.provider; + local type = icon_provider.type; + if type == "devicons" then + local symbol, hi = provider.get_icon(name, nil, { strict = true, default = false }); + if symbol then + return { symbol = symbol, hi = hi }; + end + elseif type == "miniicons" then + local symbol, hi = provider.get("file", name) + if symbol then + return { symbol = symbol, hi = hi }; + end + end end - return nil, nil + return nil; end -local function get_lsp_diagnostics(bufnr, node) - local diagnostics = {} - local filepath = node.dir .. "/" .. node.node - local diag = vim.diagnostic.get(nil, { path = filepath }) - - for _, d in ipairs(diag) do - if d.severity == vim.diagnostic.severity.ERROR and M.options.lsp.error then - table.insert(diagnostics, { icon = "E", hl = "DiagnosticError" }) - elseif d.severity == vim.diagnostic.severity.WARN and M.options.lsp.warn then - table.insert(diagnostics, { icon = "W", hl = "DiagnosticWarn" }) - elseif d.severity == vim.diagnostic.severity.INFO and M.options.lsp.info then - table.insert(diagnostics, { icon = "I", hl = "DiagnosticInfo" }) - elseif d.severity == vim.diagnostic.severity.HINT and M.options.lsp.hint then - table.insert(diagnostics, { icon = "H", hl = "DiagnosticHint" }) +local function get_icon(node) + if node.type == parse.TYPE_DIR and M.options.dir then + if M.options.dir then + return { symbol = M.options.dir, hi = "Normal" }; + end + elseif node.type == parse.TYPE_SYMLINK and M.options.sym then + if M.options.sym then + return { symbol = M.options.sym, hi = "Normal" }; + end + elseif node.type == parse.TYPE_FILE and M.options.file then + local file_type = vim.fn.fnamemodify(node.name, ":e"); + if string.sub(file_type, -1) == "*" then + return get_icon_from_provider("exe"); end + return get_icon_from_provider(node.name); end - return diagnostics + return nil; end +-- local function get_lsp_diagnostics(node) +-- local diagnostics = {} +-- local filepath = node.dir .. "/" .. node.node +-- +-- -- FIXME: that foo takes bufnr not path +-- local diag = vim.diagnostic.get(nil, { path = filepath }) +-- +-- for _, d in ipairs(diag) do +-- if d.severity == vim.diagnostic.severity.ERROR and M.options.lsp.error then +-- table.insert(diagnostics, { icon = "E", hl = "DiagnosticError" }) +-- elseif d.severity == vim.diagnostic.severity.WARN and M.options.lsp.warn then +-- table.insert(diagnostics, { icon = "W", hl = "DiagnosticWarn" }) +-- elseif d.severity == vim.diagnostic.severity.INFO and M.options.lsp.info then +-- table.insert(diagnostics, { icon = "I", hl = "DiagnosticInfo" }) +-- elseif d.severity == vim.diagnostic.severity.HINT and M.options.lsp.hint then +-- table.insert(diagnostics, { icon = "H", hl = "DiagnosticHint" }) +-- end +-- end +-- +-- return diagnostics +-- end + local function draw(bufnr) local namespace = vim.api.nvim_create_namespace("netrw") vim.api.nvim_buf_clear_namespace(bufnr, namespace, 0, -1) @@ -82,37 +109,18 @@ local function draw(bufnr) for i, line in ipairs(lines) do local node = parse.get_node(line) - if node then - -- Draw file/dir icon on the left - if (node.type == parse.TYPE_FILE and M.options.file) or - (node.type == parse.TYPE_DIR and M.options.dir) then - local icon, hl = get_file_icon(node) - if icon then - local opts = { - id = i * 2, -- Unique ID for icon - virt_text = hl and { { icon .. " ", hl } } or { { icon .. " " } }, - virt_text_pos = "inline", - } - vim.api.nvim_buf_set_extmark(bufnr, namespace, i - 1, node.icon_col, opts) - end - end - -- Draw LSP diagnostics on the right - if node.type == parse.TYPE_FILE then - local diagnostics = get_lsp_diagnostics(bufnr, node) - if #diagnostics > 0 then - local virt_text = {} - for _, diag in ipairs(diagnostics) do - table.insert(virt_text, { " " .. diag.icon, diag.hl }) - end + -- vim.print("[" .. line .. "] - "); + -- vim.print(node); - local opts = { - id = i * 2 + 1, -- Unique ID for LSP - virt_text = virt_text, - virt_text_pos = "inline", - } - vim.api.nvim_buf_set_extmark(bufnr, namespace, i - 1, node.lsp_col, opts) - end + if node then + local icon = get_icon(node); + if icon then + vim.api.nvim_buf_set_extmark(bufnr, namespace, i - 1, node.icon - 1, { + id = i, + virt_text_pos = "inline", + virt_text = { { " " .. icon.symbol, icon.hi } }, + }); end end end @@ -123,19 +131,10 @@ M.options = {} --- @class Config local default = { - -- Preferred icon provider: - -- nil -> auto-detect - -- "miniicons" -> use mini.icons - -- "devicons" -> use nvim-web-devicons prefer = nil, - - -- Show icons for files file = true, - - -- Show icons for directories - dir = true, - - -- LSP diagnostics integration + dir = "", + sym = false, lsp = { info = false, hint = false, @@ -150,15 +149,23 @@ function M.setup(options) if M.options.file or M.options.dir then icon_provider = get_icon_provider(M.options.prefer) + if not icon_provider then + error("No icon provider found"); + end end - vim.api.nvim_create_autocmd({ "BufEnter", "DiagnosticChanged" }, { - pattern = "*", - group = vim.api.nvim_create_augroup("netrw_icons", { clear = true }), + vim.api.nvim_create_autocmd("BufModifiedSet", { + pattern = { "*" }, + group = vim.api.nvim_create_augroup("netrw_icons", { clear = false }), callback = function(args) - if vim.bo[args.buf].filetype ~= "netrw" then + if not (vim.bo and vim.bo.filetype == "netrw") then + return + end + + if vim.b.netrw_liststyle ~= 0 and vim.b.netrw_liststyle ~= 1 and vim.b.netrw_liststyle ~= 3 then return end + draw(args.buf) end }) diff --git a/lua/netrw-icons/parse.lua b/lua/netrw-icons/parse.lua index 61460a0..c2f245c 100644 --- a/lua/netrw-icons/parse.lua +++ b/lua/netrw-icons/parse.lua @@ -12,11 +12,11 @@ M.TYPE_DIR = 0 M.TYPE_FILE = 1 M.TYPE_SYMLINK = 2 ----@alias Word {dir:string, node:string, link:string|nil, extension:string|nil, type:number, icon_col:number, name_col:number, lsp_col:number} +---@alias PWord {dir:string, node:string, link:string|nil, extension:string|nil, type:number, icon_col:number, name_col:number, lsp_col:number} ---@param line string ---@param curdir string ----@return Word|nil +---@return PWord|nil local parse_liststyle_0 = function(line, curdir) local _, _, node, link = string.find(line, "^(.+)@\t%s*%-%->%s*(.+)") if node then @@ -64,7 +64,7 @@ end ---@param line string ---@param curdir string ----@return Word|nil +---@return PWord|nil local parse_liststyle_1 = function(line, curdir) local _, _, node, link = string.find(line, "^(.+)@%s+") if node then @@ -111,62 +111,102 @@ local parse_liststyle_1 = function(line, curdir) end ---@param line string ----@return Word|nil +---@return PWord|nil local parse_liststyle_3 = function(line) - local curdir = vim.b.netrw_curdir - local _, to = string.find(line, "^[|%s]*") - local pipelessLine = string.sub(line, to + 1, #line) + local current_dir = vim.b.netrw_curdir; + local type = M.TYPE_FILE; - if pipelessLine == "" then - return nil - end + local _, tree_end = string.find(line, "^[|%s]*"); - local _, _, node, link = string.find(pipelessLine, "^(.+)@\t%s*%-%->%s*(.+)") - if node then - return { - dir = curdir, - icon_col = to, - name_col = to, - lsp_col = to + #node, - node = node, - extension = vim.fn.fnamemodify(node, ":e"), - link = link, - type = M.TYPE_SYMLINK, - } + local content = string.sub(line, tree_end + 1, #line); + if content == "" then + return nil; end - local _, _, dir = string.find(pipelessLine, "^(.*)/") - if dir then - return { - dir = curdir, - icon_col = to, - name_col = to, - lsp_col = to + #dir + 1, - node = dir, - type = M.TYPE_DIR, - } + local _, _, link, link_target = string.find(content, "^(.+)@\t%s*%-%->%s*(.+)") + if link then + type = M.TYPE_SYMLINK; end - local ext = vim.fn.fnamemodify(pipelessLine, ":e") - local clean_line = pipelessLine - if string.sub(ext, -1) == "*" then - ext = string.sub(ext, 1, -2) - clean_line = string.sub(pipelessLine, 1, -2) + local _, _, dir = string.find(content, "^(.*)/") + if dir then + type = M.TYPE_DIR; end return { - dir = curdir, - icon_col = to, - name_col = to, - lsp_col = to + #clean_line, - node = clean_line, - extension = ext, - type = M.TYPE_FILE, + name = link_target or content, + icon = tree_end, + type = type, } end + + + +-- local _, to = string.find(line, "^[|%s]*") +-- if to ~= 0 then +-- error("to: " .. to); +-- end +-- local pipelessLine = string.sub(line, to + 1, #line) +-- +-- if pipelessLine == "" then +-- return nil +-- end +-- +-- local _, _, node, link = string.find(pipelessLine, "^(.+)@\t%s*%-%->%s*(.+)") +-- if node then +-- return { +-- dir = curdir, +-- icon_col = to, +-- name_col = to, +-- lsp_col = to + #node, +-- node = node, +-- extension = vim.fn.fnamemodify(node, ":e"), +-- link = link, +-- type = M.TYPE_SYMLINK, +-- } +-- end +-- +-- local _, _, dir = string.find(pipelessLine, "^(.*)/") +-- if dir then +-- return { +-- dir = curdir, +-- icon_col = to, +-- name_col = to, +-- lsp_col = to + #dir + 1, +-- node = dir, +-- type = M.TYPE_DIR, +-- } +-- end +-- +-- local ext = vim.fn.fnamemodify(pipelessLine, ":e") +-- local clean_line = pipelessLine +-- if string.sub(ext, -1) == "*" then +-- ext = string.sub(ext, 1, -2) +-- clean_line = string.sub(pipelessLine, 1, -2) +-- end +-- +-- return { +-- current_dir = vim.b.netrw_curdir, +-- icon_col = to, +-- name_col = to, +-- lsp_col = to + #clean_line, +-- node = clean_line, +-- extension = ext, +-- type = M.TYPE_FILE, +-- } + +-- return { +-- name = "name of the file", +-- type = "type of the netrw element (dir, file, symlink)" +-- path = "full path of the file", +-- icon = "character after the | netrw symbol", +-- lsp = "two characters after the filename end", +-- } +-- end + ---@param line string ----@return Word|nil +---@return PWord|nil M.get_node = function(line) if string.find(line, '^"') then return nil |
