diff --git a/CHANGELOG.md b/CHANGELOG.md index 9d89a5d..6253739 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -62,6 +62,17 @@ option is `symbol_folding.auto_unfold` with keys `hovered` and `only`. Key `hovered` is the successor of the legacy `symbol_folding.auto_unfold_hover` option. **The old option would still work as expected.** +- Updated the default symbols icon highlights to not use highlight groups that + start with `@`. Everything should still work as expected, most highlights + should still be the same. This is to support `nvim-0.7`. The symbols icon + highlights is still configurable as before. +- Highlights used by outline.nvim are now set to default using links if they + aren't already defined. Default winhl for outline window is now an empty + string, and for preview window, `NormalFloat:` to ensure the preview window + looks similar to a normal window (since it displays a preview of the actual + code) +- Highlights will also take into account `ctermfg/bg` when setting default values. + This ensures outline.nvim highlights work if `termguicolors` is not enabled ### Fixes diff --git a/README.md b/README.md index 9683a0d..8dfacb3 100644 --- a/README.md +++ b/README.md @@ -205,10 +205,8 @@ Pass a table to the setup call with your configuration options. focus_on_open = true, -- Winhighlight option for outline window. -- See :help 'winhl' - -- To change background color to "CustomHl" for example, append "Normal:CustomHl". - -- Note that if you're adding highlight changes, you should append to this - -- default value, otherwise details/lineno will not have highlights. - winhl = "OutlineDetails:Comment,OutlineLineno:LineNr", + -- To change background color to "CustomHl" for example, use "Normal:CustomHl". + winhl = '', }, outline_items = { @@ -287,7 +285,7 @@ Pass a table to the setup call with your configuration options. -- See :help nvim_open_win() and search for "border" option. border = 'single', -- winhl options for the preview window, see ':h winhl' - winhl = '', + winhl = 'NormalFloat:', -- Pseudo-transparency of the preview window, see ':h winblend' winblend = 0 }, @@ -366,38 +364,38 @@ Pass a table to the setup call with your configuration options. -- the custom mapping of icons specified below. The icons table is also -- needed for specifying hl group. icons = { - File = { icon = '󰈔', hl = '@text.uri' }, - Module = { icon = '󰆧', hl = '@namespace' }, - Namespace = { icon = 'ó°…Ș', hl = '@namespace' }, - Package = { icon = '󰏗', hl = '@namespace' }, - Class = { icon = '𝓒', hl = '@type' }, - Method = { icon = 'ƒ', hl = '@method' }, - Property = { icon = '', hl = '@method' }, - Field = { icon = '󰆹', hl = '@field' }, - Constructor = { icon = '', hl = '@constructor' }, - Enum = { icon = 'ℰ', hl = '@type' }, - Interface = { icon = '󰜰', hl = '@type' }, - Function = { icon = '', hl = '@function' }, - Variable = { icon = '', hl = '@constant' }, - Constant = { icon = '', hl = '@constant' }, - String = { icon = '𝓐', hl = '@string' }, - Number = { icon = '#', hl = '@number' }, - Boolean = { icon = '⊹', hl = '@boolean' }, - Array = { icon = 'ó°…Ș', hl = '@constant' }, - Object = { icon = '⊿', hl = '@type' }, - Key = { icon = '🔐', hl = '@type' }, - Null = { icon = 'NULL', hl = '@type' }, - EnumMember = { icon = '', hl = '@field' }, - Struct = { icon = '𝓱', hl = '@type' }, - Event = { icon = 'đŸ—Č', hl = '@type' }, - Operator = { icon = '+', hl = '@operator' }, - TypeParameter = { icon = '𝙏', hl = '@parameter' }, - Component = { icon = '󰅮', hl = '@function' }, - Fragment = { icon = '󰅮', hl = '@constant' }, - TypeAlias = { icon = ' ', hl = '@type' }, - Parameter = { icon = 'îȘ’ ', hl = '@parameter' }, - StaticMethod = { icon = 'îȘŒ ', hl = '@function' }, - Macro = { icon = ' ', hl = '@macro' }, + File = { icon = '󰈔', hl = 'Identifier' }, + Module = { icon = '󰆧', hl = 'Include' }, + Namespace = { icon = 'ó°…Ș', hl = 'Include' }, + Package = { icon = '󰏗', hl = 'Include' }, + Class = { icon = '𝓒', hl = 'Type' }, + Method = { icon = 'ƒ', hl = 'Function' }, + Property = { icon = '', hl = 'Identifier' }, + Field = { icon = '󰆹', hl = 'Identifier' }, + Constructor = { icon = '', hl = 'Special' }, + Enum = { icon = 'ℰ', hl = 'Type' }, + Interface = { icon = '󰜰', hl = 'Type' }, + Function = { icon = '', hl = 'Function' }, + Variable = { icon = '', hl = 'Constant' }, + Constant = { icon = '', hl = 'Constant' }, + String = { icon = '𝓐', hl = 'String' }, + Number = { icon = '#', hl = 'Number' }, + Boolean = { icon = '⊹', hl = 'Boolean' }, + Array = { icon = 'ó°…Ș', hl = 'Constant' }, + Object = { icon = '⊿', hl = 'Type' }, + Key = { icon = '🔐', hl = 'Type' }, + Null = { icon = 'NULL', hl = 'Type' }, + EnumMember = { icon = '', hl = 'Identifier' }, + Struct = { icon = '𝓱', hl = 'Structure' }, + Event = { icon = 'đŸ—Č', hl = 'Type' }, + Operator = { icon = '+', hl = 'Identifier' }, + TypeParameter = { icon = '𝙏', hl = 'Identifier' }, + Component = { icon = '󰅮', hl = 'Function' }, + Fragment = { icon = '󰅮', hl = 'Constant' }, + TypeAlias = { icon = ' ', hl = 'Type' }, + Parameter = { icon = 'îȘ’ ', hl = 'Identifier' }, + StaticMethod = { icon = 'îȘŒ ', hl = 'Function' }, + Macro = { icon = ' ', hl = 'Function' }, }, }, } @@ -560,7 +558,7 @@ Default: ```lua outline_window = { - winhl = "OutlineDetails:Comment,OutlineLineno:LineNr", + winhl = '', }, ``` @@ -574,9 +572,21 @@ Possible highlight groups for the outline window: | OutlineDetails | Symbol details in virtual text | | OutlineLineno | The Lineno column virtual text | -You can customize any other highlight groups using `winhl` too, this option is +You can customize any other highlight groups using `winhl`, this option is passed directly to the `winhl` vim option unprocessed. +If any of the above highlights have not already been set before outline.setup +is called (say by a theme), the following links are used: + +| Highlight | Link | +| -------------------- | -------- | +| OutlineGuides | Comment | +| OutlineFoldMarker | Normal | +| OutlineDetails | Comment | +| OutlineLineno | LineNr | + +For `OutlineCurrent`, foreground is set to String and background CursorLine. + To customize colors of the symbol icons, use the `symbols.icons` table. See [config](#configuration). @@ -584,15 +594,15 @@ To customize colors of the symbol icons, use the `symbols.icons` table. See ```lua preview_window = { - winhl = "", + winhl = 'NormalFloat:', }, ``` ### Other highlight groups -| Highlight | Description | -| -------------------- | ---------------------------------------------------------- | -| OutlineJumpHighlight | Used for indicating cursor position when jumping/focusing | +| Highlight | Description | +| -------------------- | --------------------------------------------------------------------- | +| OutlineJumpHighlight | Indicating cursor position when jumping/focusing, defaults to Visual | You can also use `outline_window.jump_highlight_duration` to customize in milliseconds, how long the highlight is applied for. diff --git a/lua/outline/config.lua b/lua/outline/config.lua index b54d2d1..36d6bc6 100644 --- a/lua/outline/config.lua +++ b/lua/outline/config.lua @@ -43,7 +43,7 @@ M.defaults = { ---@type boolean|string? show_cursorline = true, hide_cursor = false, - winhl = 'OutlineDetails:Comment,OutlineLineno:LineNr', + winhl = '', jump_highlight_duration = 400, center_on_jump = true, }, @@ -55,7 +55,7 @@ M.defaults = { min_height = 10, border = 'single', open_hover_on_preview = false, - winhl = '', + winhl = 'NormalFloat:', winblend = 0, }, symbol_folding = { @@ -100,39 +100,39 @@ M.defaults = { icon_source = nil, icon_fetcher = nil, icons = { - File = { icon = '󰈔', hl = '@text.uri' }, - Module = { icon = '󰆧', hl = '@namespace' }, - Namespace = { icon = 'ó°…Ș', hl = '@namespace' }, - Package = { icon = '󰏗', hl = '@namespace' }, - Class = { icon = '𝓒', hl = '@type' }, - Method = { icon = 'ƒ', hl = '@method' }, - Property = { icon = '', hl = '@method' }, - Field = { icon = '󰆹', hl = '@field' }, - Constructor = { icon = '', hl = '@constructor' }, - Enum = { icon = 'ℰ', hl = '@type' }, - Interface = { icon = '󰜰', hl = '@type' }, - Function = { icon = '', hl = '@function' }, - Variable = { icon = '', hl = '@constant' }, - Constant = { icon = '', hl = '@constant' }, - String = { icon = '𝓐', hl = '@string' }, - Number = { icon = '#', hl = '@number' }, - Boolean = { icon = '⊹', hl = '@boolean' }, - Array = { icon = 'ó°…Ș', hl = '@constant' }, - Object = { icon = '⊿', hl = '@type' }, - Key = { icon = '🔐', hl = '@type' }, - Null = { icon = 'NULL', hl = '@type' }, - EnumMember = { icon = '', hl = '@field' }, - Struct = { icon = '𝓱', hl = '@type' }, - Event = { icon = 'đŸ—Č', hl = '@type' }, - Operator = { icon = '+', hl = '@operator' }, - TypeParameter = { icon = '𝙏', hl = '@parameter' }, - Component = { icon = '󰅮', hl = '@function' }, - Fragment = { icon = '󰅮', hl = '@constant' }, + File = { icon = '󰈔', hl = 'Identifier' }, + Module = { icon = '󰆧', hl = 'Include' }, + Namespace = { icon = 'ó°…Ș', hl = 'Include' }, + Package = { icon = '󰏗', hl = 'Include' }, + Class = { icon = '𝓒', hl = 'Type' }, + Method = { icon = 'ƒ', hl = 'Function' }, + Property = { icon = '', hl = 'Identifier' }, + Field = { icon = '󰆹', hl = 'Identifier' }, + Constructor = { icon = '', hl = 'Special' }, + Enum = { icon = 'ℰ', hl = 'Type' }, + Interface = { icon = '󰜰', hl = 'Type' }, + Function = { icon = '', hl = 'Function' }, + Variable = { icon = '', hl = 'Constant' }, + Constant = { icon = '', hl = 'Constant' }, + String = { icon = '𝓐', hl = 'String' }, + Number = { icon = '#', hl = 'Number' }, + Boolean = { icon = '⊹', hl = 'Boolean' }, + Array = { icon = 'ó°…Ș', hl = 'Constant' }, + Object = { icon = '⊿', hl = 'Type' }, + Key = { icon = '🔐', hl = 'Type' }, + Null = { icon = 'NULL', hl = 'Type' }, + EnumMember = { icon = '', hl = 'Identifier' }, + Struct = { icon = '𝓱', hl = 'Structure' }, + Event = { icon = 'đŸ—Č', hl = 'Type' }, + Operator = { icon = '+', hl = 'Identifier' }, + TypeParameter = { icon = '𝙏', hl = 'Identifier' }, + Component = { icon = '󰅮', hl = 'Function' }, + Fragment = { icon = '󰅮', hl = 'Constant' }, -- ccls - TypeAlias = { icon = ' ', hl = '@type' }, - Parameter = { icon = 'îȘ’ ', hl = '@parameter' }, - StaticMethod = { icon = 'îȘŒ ', hl = '@function' }, - Macro = { icon = ' ', hl = '@macro' }, + TypeAlias = { icon = ' ', hl = 'Type' }, + Parameter = { icon = 'îȘ’ ', hl = 'Identifier' }, + StaticMethod = { icon = 'îȘŒ ', hl = 'Function' }, + Macro = { icon = ' ', hl = 'Function' }, }, }, } diff --git a/lua/outline/float.lua b/lua/outline/float.lua index 06b7770..a8a4272 100644 --- a/lua/outline/float.lua +++ b/lua/outline/float.lua @@ -1,5 +1,3 @@ --- local cfg = require('outline.config') - local Float = {} ---@class outline.Float @@ -37,7 +35,7 @@ function Float:open(lines, hl, title, indent) local row = math.floor((nvim_height - height) / 2) local col = math.floor((nvim_width - width) / 2) - self.winnr = vim.api.nvim_open_win(self.bufnr, true, { + local opts = { relative = 'editor', width = width, height = height, @@ -45,9 +43,13 @@ function Float:open(lines, hl, title, indent) col = col, border = 'rounded', style = 'minimal', - title = title, - title_pos = 'center', - }) + } + if _G._outline_nvim_has[9] then + opts.title = title + opts.title_pos = 'center' + end + + self.winnr = vim.api.nvim_open_win(self.bufnr, true, opts) if indent > 0 then local pad = string.rep(' ', indent) @@ -73,13 +75,14 @@ function Float:open(lines, hl, title, indent) (h.to ~= -1 and h.to + indent) or -1 ) end - vim.api.nvim_win_set_hl_ns(self.winnr, self.ns) end end function Float:close() if self.winnr then - vim.api.nvim_buf_clear_namespace(self.bufnr, self.ns, 0, -1) + if self.ns then + vim.api.nvim_buf_clear_namespace(self.bufnr, self.ns, 0, -1) + end vim.api.nvim_win_close(self.winnr, true) self.winnr = nil self.bufnr = nil diff --git a/lua/outline/init.lua b/lua/outline/init.lua index a921480..5dab3ca 100644 --- a/lua/outline/init.lua +++ b/lua/outline/init.lua @@ -146,9 +146,6 @@ function M.__goto_location(change_focus) vim.fn.win_execute(M.state.code_win, 'normal! zz') end - if vim.fn.hlexists('OutlineJumpHighlight') == 0 then - vim.api.nvim_set_hl(0, 'OutlineJumpHighlight', { link = 'Visual' }) - end utils.flash_highlight( M.state.code_win, node.line + 1, @@ -522,9 +519,11 @@ end local function _cmd_open_with_mods(fn) return function(opts) local fnopts = { focus_outline = not opts.bang } - local sc = opts.smods.split - if sc ~= '' then - fnopts.split_command = sc .. ' vsplit' + if _G._outline_nvim_has[8] then + local sc = opts.smods.split + if sc ~= '' then + fnopts.split_command = sc .. ' vsplit' + end end fn(fnopts) @@ -681,6 +680,18 @@ end ---Set up configuration options for outline. function M.setup(opts) + local minor = vim.version().minor + + if minor < 7 then + vim.notify('outline.nvim requires nvim-0.7 or higher!', vim.log.levels.ERROR) + return + end + + _G._outline_nvim_has = { + [8] = minor >= 8, + [9] = minor >= 9, + } + cfg.setup(opts) ui.setup_highlights() diff --git a/lua/outline/ui.lua b/lua/outline/ui.lua index 3c087f6..1676b2d 100644 --- a/lua/outline/ui.lua +++ b/lua/outline/ui.lua @@ -10,29 +10,62 @@ function M.add_hover_highlight(bufnr, line, col_start) vim.api.nvim_buf_add_highlight(bufnr, M.hovered_hl_ns, 'OutlineCurrent', line, col_start, -1) end +local get_hl_by_name + +if vim.fn.has('nvim-0.9') == 1 then + get_hl_by_name = function(name) + local hl = vim.api.nvim_get_hl(0, { name = name, link = false }) + return { fg = hl.fg, bg = hl.bg, ctermfg = hl.ctermfg, ctermbg = hl.ctermbg } + end +else + get_hl_by_name = function(name) + ---@diagnostic disable-next-line undefined-field + local hlrgb = vim.api.nvim_get_hl_by_name(name, true) + ---@diagnostic disable-next-line undefined-field + local hl = vim.api.nvim_get_hl_by_name(name, false) + return { + fg = hlrgb.foreground, + bg = hlrgb.background, + ctermfg = hl.foreground, + ctermbg = hl.background, + } + end +end + function M.setup_highlights() -- Setup the OutlineCurrent highlight group if it hasn't been done already by -- a theme or manually set if vim.fn.hlexists('OutlineCurrent') == 0 then - -- TODO: Use nvim_get_hl - local cline_hl = vim.api.nvim_get_hl_by_name('CursorLine', true) - local string_hl = vim.api.nvim_get_hl_by_name('String', true) + local cline_hl = get_hl_by_name('CursorLine') + local string_hl = get_hl_by_name('String') vim.api.nvim_set_hl( 0, 'OutlineCurrent', - { bg = cline_hl.background, fg = string_hl.foreground } + { + bg = cline_hl.bg, + fg = string_hl.fg, + ctermbg = cline_hl.ctermbg, + ctermfg = string_hl.ctermfg, + } ) end - -- Some colorschemes do some funky things with the comment highlight, most - -- notably making them italic, which messes up the outline connector. Fix - -- this by copying the foreground color from the comment hl into a new - -- highlight. - local comment_fg_gui = vim.fn.synIDattr(vim.fn.synIDtrans(vim.fn.hlID('Comment')), 'fg', 'gui') - + -- Only inherit fg and bg for OutlineGuides because we do not want the other + -- stylings messing up the alignment. if vim.fn.hlexists('OutlineGuides') == 0 then - vim.cmd(string.format('hi OutlineGuides guifg=%s', comment_fg_gui)) + vim.api.nvim_set_hl(0, 'OutlineGuides', get_hl_by_name('Comment')) + end + + for name, link in pairs({ + Details = 'Comment', + Lineno = 'LineNr', + JumpHighlight = 'Visual', + FoldMarker = 'Normal', + }) do + if vim.fn.hlexists('Outline' .. name) == 0 then + vim.api.nvim_set_hl(0, 'Outline' .. name, { link = link }) + end end end diff --git a/lua/outline/writer.lua b/lua/outline/writer.lua index 130eb95..1c38b43 100644 --- a/lua/outline/writer.lua +++ b/lua/outline/writer.lua @@ -10,7 +10,7 @@ local strlen = vim.fn.strlen local M = {} local hlns = vim.api.nvim_create_namespace('outline-icon-highlight') -local ns = vim.api.nvim_create_namespace('outline-virt-text') +local vtns = vim.api.nvim_create_namespace('outline-virt-text') ---@param bufnr integer ---@return boolean @@ -36,7 +36,7 @@ end ---@param bufnr integer local function clear_virt_text(bufnr) - vim.api.nvim_buf_clear_namespace(bufnr, -1, 0, -1) + vim.api.nvim_buf_clear_namespace(bufnr, vtns, 0, -1) end ---@param bufnr integer @@ -243,7 +243,7 @@ function M.make_outline(bufnr, items, codewin, find_node) -- Add details and lineno virtual text. if cfg.o.outline_items.show_symbol_details then for index, value in ipairs(details) do - vim.api.nvim_buf_set_extmark(bufnr, ns, index - 1, -1, { + vim.api.nvim_buf_set_extmark(bufnr, vtns, index - 1, -1, { virt_text = { { value, 'OutlineDetails' } }, virt_text_pos = 'eol', hl_mode = 'combine', @@ -256,7 +256,7 @@ function M.make_outline(bufnr, items, codewin, find_node) -- TODO: Fix lineno not appearing if text in line is truncated on the right -- due to narrow window, after nvim fixes virt_text_hide. for index, value in ipairs(linenos) do - vim.api.nvim_buf_set_extmark(bufnr, ns, index - 1, -1, { + vim.api.nvim_buf_set_extmark(bufnr, vtns, index - 1, -1, { virt_text = { { value, 'OutlineLineno' } }, virt_text_pos = 'overlay', virt_text_win_col = 0,