feat: Properly support nvim-0.7, and fix highlights

This commit is contained in:
hedy
2023-11-21 08:39:05 +08:00
parent b03c3a4e3d
commit 699bc85cc5
7 changed files with 174 additions and 106 deletions

View File

@@ -62,6 +62,17 @@
option is `symbol_folding.auto_unfold` with keys `hovered` and `only`. option is `symbol_folding.auto_unfold` with keys `hovered` and `only`.
Key `hovered` is the successor of the legacy `symbol_folding.auto_unfold_hover` Key `hovered` is the successor of the legacy `symbol_folding.auto_unfold_hover`
option. **The old option would still work as expected.** 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 ### Fixes

View File

@@ -205,10 +205,8 @@ Pass a table to the setup call with your configuration options.
focus_on_open = true, focus_on_open = true,
-- Winhighlight option for outline window. -- Winhighlight option for outline window.
-- See :help 'winhl' -- See :help 'winhl'
-- To change background color to "CustomHl" for example, append "Normal:CustomHl". -- To change background color to "CustomHl" for example, use "Normal:CustomHl".
-- Note that if you're adding highlight changes, you should append to this winhl = '',
-- default value, otherwise details/lineno will not have highlights.
winhl = "OutlineDetails:Comment,OutlineLineno:LineNr",
}, },
outline_items = { 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. -- See :help nvim_open_win() and search for "border" option.
border = 'single', border = 'single',
-- winhl options for the preview window, see ':h winhl' -- winhl options for the preview window, see ':h winhl'
winhl = '', winhl = 'NormalFloat:',
-- Pseudo-transparency of the preview window, see ':h winblend' -- Pseudo-transparency of the preview window, see ':h winblend'
winblend = 0 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 -- the custom mapping of icons specified below. The icons table is also
-- needed for specifying hl group. -- needed for specifying hl group.
icons = { icons = {
File = { icon = '󰈔', hl = '@text.uri' }, File = { icon = '󰈔', hl = 'Identifier' },
Module = { icon = '󰆧', hl = '@namespace' }, Module = { icon = '󰆧', hl = 'Include' },
Namespace = { icon = '󰅪', hl = '@namespace' }, Namespace = { icon = '󰅪', hl = 'Include' },
Package = { icon = '󰏗', hl = '@namespace' }, Package = { icon = '󰏗', hl = 'Include' },
Class = { icon = '𝓒', hl = '@type' }, Class = { icon = '𝓒', hl = 'Type' },
Method = { icon = 'ƒ', hl = '@method' }, Method = { icon = 'ƒ', hl = 'Function' },
Property = { icon = '', hl = '@method' }, Property = { icon = '', hl = 'Identifier' },
Field = { icon = '󰆨', hl = '@field' }, Field = { icon = '󰆨', hl = 'Identifier' },
Constructor = { icon = '', hl = '@constructor' }, Constructor = { icon = '', hl = 'Special' },
Enum = { icon = '', hl = '@type' }, Enum = { icon = '', hl = 'Type' },
Interface = { icon = '󰜰', hl = '@type' }, Interface = { icon = '󰜰', hl = 'Type' },
Function = { icon = '', hl = '@function' }, Function = { icon = '', hl = 'Function' },
Variable = { icon = '', hl = '@constant' }, Variable = { icon = '', hl = 'Constant' },
Constant = { icon = '', hl = '@constant' }, Constant = { icon = '', hl = 'Constant' },
String = { icon = '𝓐', hl = '@string' }, String = { icon = '𝓐', hl = 'String' },
Number = { icon = '#', hl = '@number' }, Number = { icon = '#', hl = 'Number' },
Boolean = { icon = '⊨', hl = '@boolean' }, Boolean = { icon = '⊨', hl = 'Boolean' },
Array = { icon = '󰅪', hl = '@constant' }, Array = { icon = '󰅪', hl = 'Constant' },
Object = { icon = '⦿', hl = '@type' }, Object = { icon = '⦿', hl = 'Type' },
Key = { icon = '🔐', hl = '@type' }, Key = { icon = '🔐', hl = 'Type' },
Null = { icon = 'NULL', hl = '@type' }, Null = { icon = 'NULL', hl = 'Type' },
EnumMember = { icon = '', hl = '@field' }, EnumMember = { icon = '', hl = 'Identifier' },
Struct = { icon = '𝓢', hl = '@type' }, Struct = { icon = '𝓢', hl = 'Structure' },
Event = { icon = '🗲', hl = '@type' }, Event = { icon = '🗲', hl = 'Type' },
Operator = { icon = '+', hl = '@operator' }, Operator = { icon = '+', hl = 'Identifier' },
TypeParameter = { icon = '𝙏', hl = '@parameter' }, TypeParameter = { icon = '𝙏', hl = 'Identifier' },
Component = { icon = '󰅴', hl = '@function' }, Component = { icon = '󰅴', hl = 'Function' },
Fragment = { icon = '󰅴', hl = '@constant' }, Fragment = { icon = '󰅴', hl = 'Constant' },
TypeAlias = { icon = ' ', hl = '@type' }, TypeAlias = { icon = ' ', hl = 'Type' },
Parameter = { icon = ' ', hl = '@parameter' }, Parameter = { icon = ' ', hl = 'Identifier' },
StaticMethod = { icon = ' ', hl = '@function' }, StaticMethod = { icon = ' ', hl = 'Function' },
Macro = { icon = ' ', hl = '@macro' }, Macro = { icon = ' ', hl = 'Function' },
}, },
}, },
} }
@@ -560,7 +558,7 @@ Default:
```lua ```lua
outline_window = { 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 | | OutlineDetails | Symbol details in virtual text |
| OutlineLineno | The Lineno column 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. 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 To customize colors of the symbol icons, use the `symbols.icons` table. See
[config](#configuration). [config](#configuration).
@@ -584,15 +594,15 @@ To customize colors of the symbol icons, use the `symbols.icons` table. See
```lua ```lua
preview_window = { preview_window = {
winhl = "", winhl = 'NormalFloat:',
}, },
``` ```
### Other highlight groups ### Other highlight groups
| Highlight | Description | | Highlight | Description |
| -------------------- | ---------------------------------------------------------- | | -------------------- | --------------------------------------------------------------------- |
| OutlineJumpHighlight | Used for indicating cursor position when jumping/focusing | | OutlineJumpHighlight | Indicating cursor position when jumping/focusing, defaults to Visual |
You can also use `outline_window.jump_highlight_duration` to customize in milliseconds, You can also use `outline_window.jump_highlight_duration` to customize in milliseconds,
how long the highlight is applied for. how long the highlight is applied for.

View File

@@ -43,7 +43,7 @@ M.defaults = {
---@type boolean|string? ---@type boolean|string?
show_cursorline = true, show_cursorline = true,
hide_cursor = false, hide_cursor = false,
winhl = 'OutlineDetails:Comment,OutlineLineno:LineNr', winhl = '',
jump_highlight_duration = 400, jump_highlight_duration = 400,
center_on_jump = true, center_on_jump = true,
}, },
@@ -55,7 +55,7 @@ M.defaults = {
min_height = 10, min_height = 10,
border = 'single', border = 'single',
open_hover_on_preview = false, open_hover_on_preview = false,
winhl = '', winhl = 'NormalFloat:',
winblend = 0, winblend = 0,
}, },
symbol_folding = { symbol_folding = {
@@ -100,39 +100,39 @@ M.defaults = {
icon_source = nil, icon_source = nil,
icon_fetcher = nil, icon_fetcher = nil,
icons = { icons = {
File = { icon = '󰈔', hl = '@text.uri' }, File = { icon = '󰈔', hl = 'Identifier' },
Module = { icon = '󰆧', hl = '@namespace' }, Module = { icon = '󰆧', hl = 'Include' },
Namespace = { icon = '󰅪', hl = '@namespace' }, Namespace = { icon = '󰅪', hl = 'Include' },
Package = { icon = '󰏗', hl = '@namespace' }, Package = { icon = '󰏗', hl = 'Include' },
Class = { icon = '𝓒', hl = '@type' }, Class = { icon = '𝓒', hl = 'Type' },
Method = { icon = 'ƒ', hl = '@method' }, Method = { icon = 'ƒ', hl = 'Function' },
Property = { icon = '', hl = '@method' }, Property = { icon = '', hl = 'Identifier' },
Field = { icon = '󰆨', hl = '@field' }, Field = { icon = '󰆨', hl = 'Identifier' },
Constructor = { icon = '', hl = '@constructor' }, Constructor = { icon = '', hl = 'Special' },
Enum = { icon = '', hl = '@type' }, Enum = { icon = '', hl = 'Type' },
Interface = { icon = '󰜰', hl = '@type' }, Interface = { icon = '󰜰', hl = 'Type' },
Function = { icon = '', hl = '@function' }, Function = { icon = '', hl = 'Function' },
Variable = { icon = '', hl = '@constant' }, Variable = { icon = '', hl = 'Constant' },
Constant = { icon = '', hl = '@constant' }, Constant = { icon = '', hl = 'Constant' },
String = { icon = '𝓐', hl = '@string' }, String = { icon = '𝓐', hl = 'String' },
Number = { icon = '#', hl = '@number' }, Number = { icon = '#', hl = 'Number' },
Boolean = { icon = '', hl = '@boolean' }, Boolean = { icon = '', hl = 'Boolean' },
Array = { icon = '󰅪', hl = '@constant' }, Array = { icon = '󰅪', hl = 'Constant' },
Object = { icon = '⦿', hl = '@type' }, Object = { icon = '⦿', hl = 'Type' },
Key = { icon = '🔐', hl = '@type' }, Key = { icon = '🔐', hl = 'Type' },
Null = { icon = 'NULL', hl = '@type' }, Null = { icon = 'NULL', hl = 'Type' },
EnumMember = { icon = '', hl = '@field' }, EnumMember = { icon = '', hl = 'Identifier' },
Struct = { icon = '𝓢', hl = '@type' }, Struct = { icon = '𝓢', hl = 'Structure' },
Event = { icon = '🗲', hl = '@type' }, Event = { icon = '🗲', hl = 'Type' },
Operator = { icon = '+', hl = '@operator' }, Operator = { icon = '+', hl = 'Identifier' },
TypeParameter = { icon = '𝙏', hl = '@parameter' }, TypeParameter = { icon = '𝙏', hl = 'Identifier' },
Component = { icon = '󰅴', hl = '@function' }, Component = { icon = '󰅴', hl = 'Function' },
Fragment = { icon = '󰅴', hl = '@constant' }, Fragment = { icon = '󰅴', hl = 'Constant' },
-- ccls -- ccls
TypeAlias = { icon = '', hl = '@type' }, TypeAlias = { icon = '', hl = 'Type' },
Parameter = { icon = '', hl = '@parameter' }, Parameter = { icon = '', hl = 'Identifier' },
StaticMethod = { icon = '', hl = '@function' }, StaticMethod = { icon = '', hl = 'Function' },
Macro = { icon = '', hl = '@macro' }, Macro = { icon = '', hl = 'Function' },
}, },
}, },
} }

View File

@@ -1,5 +1,3 @@
-- local cfg = require('outline.config')
local Float = {} local Float = {}
---@class outline.Float ---@class outline.Float
@@ -37,7 +35,7 @@ function Float:open(lines, hl, title, indent)
local row = math.floor((nvim_height - height) / 2) local row = math.floor((nvim_height - height) / 2)
local col = math.floor((nvim_width - width) / 2) local col = math.floor((nvim_width - width) / 2)
self.winnr = vim.api.nvim_open_win(self.bufnr, true, { local opts = {
relative = 'editor', relative = 'editor',
width = width, width = width,
height = height, height = height,
@@ -45,9 +43,13 @@ function Float:open(lines, hl, title, indent)
col = col, col = col,
border = 'rounded', border = 'rounded',
style = 'minimal', 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 if indent > 0 then
local pad = string.rep(' ', indent) 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 (h.to ~= -1 and h.to + indent) or -1
) )
end end
vim.api.nvim_win_set_hl_ns(self.winnr, self.ns)
end end
end end
function Float:close() function Float:close()
if self.winnr then if self.winnr then
if self.ns then
vim.api.nvim_buf_clear_namespace(self.bufnr, self.ns, 0, -1) vim.api.nvim_buf_clear_namespace(self.bufnr, self.ns, 0, -1)
end
vim.api.nvim_win_close(self.winnr, true) vim.api.nvim_win_close(self.winnr, true)
self.winnr = nil self.winnr = nil
self.bufnr = nil self.bufnr = nil

View File

@@ -146,9 +146,6 @@ function M.__goto_location(change_focus)
vim.fn.win_execute(M.state.code_win, 'normal! zz') vim.fn.win_execute(M.state.code_win, 'normal! zz')
end end
if vim.fn.hlexists('OutlineJumpHighlight') == 0 then
vim.api.nvim_set_hl(0, 'OutlineJumpHighlight', { link = 'Visual' })
end
utils.flash_highlight( utils.flash_highlight(
M.state.code_win, M.state.code_win,
node.line + 1, node.line + 1,
@@ -522,10 +519,12 @@ end
local function _cmd_open_with_mods(fn) local function _cmd_open_with_mods(fn)
return function(opts) return function(opts)
local fnopts = { focus_outline = not opts.bang } local fnopts = { focus_outline = not opts.bang }
if _G._outline_nvim_has[8] then
local sc = opts.smods.split local sc = opts.smods.split
if sc ~= '' then if sc ~= '' then
fnopts.split_command = sc .. ' vsplit' fnopts.split_command = sc .. ' vsplit'
end end
end
fn(fnopts) fn(fnopts)
end end
@@ -681,6 +680,18 @@ end
---Set up configuration options for outline. ---Set up configuration options for outline.
function M.setup(opts) 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) cfg.setup(opts)
ui.setup_highlights() ui.setup_highlights()

View File

@@ -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) vim.api.nvim_buf_add_highlight(bufnr, M.hovered_hl_ns, 'OutlineCurrent', line, col_start, -1)
end 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() function M.setup_highlights()
-- Setup the OutlineCurrent highlight group if it hasn't been done already by -- Setup the OutlineCurrent highlight group if it hasn't been done already by
-- a theme or manually set -- a theme or manually set
if vim.fn.hlexists('OutlineCurrent') == 0 then if vim.fn.hlexists('OutlineCurrent') == 0 then
-- TODO: Use nvim_get_hl local cline_hl = get_hl_by_name('CursorLine')
local cline_hl = vim.api.nvim_get_hl_by_name('CursorLine', true) local string_hl = get_hl_by_name('String')
local string_hl = vim.api.nvim_get_hl_by_name('String', true)
vim.api.nvim_set_hl( vim.api.nvim_set_hl(
0, 0,
'OutlineCurrent', '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 end
-- Some colorschemes do some funky things with the comment highlight, most -- Only inherit fg and bg for OutlineGuides because we do not want the other
-- notably making them italic, which messes up the outline connector. Fix -- stylings messing up the alignment.
-- 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')
if vim.fn.hlexists('OutlineGuides') == 0 then 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
end end

View File

@@ -10,7 +10,7 @@ local strlen = vim.fn.strlen
local M = {} local M = {}
local hlns = vim.api.nvim_create_namespace('outline-icon-highlight') 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 ---@param bufnr integer
---@return boolean ---@return boolean
@@ -36,7 +36,7 @@ end
---@param bufnr integer ---@param bufnr integer
local function clear_virt_text(bufnr) 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 end
---@param bufnr integer ---@param bufnr integer
@@ -243,7 +243,7 @@ function M.make_outline(bufnr, items, codewin, find_node)
-- Add details and lineno virtual text. -- Add details and lineno virtual text.
if cfg.o.outline_items.show_symbol_details then if cfg.o.outline_items.show_symbol_details then
for index, value in ipairs(details) do 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 = { { value, 'OutlineDetails' } },
virt_text_pos = 'eol', virt_text_pos = 'eol',
hl_mode = 'combine', 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 -- TODO: Fix lineno not appearing if text in line is truncated on the right
-- due to narrow window, after nvim fixes virt_text_hide. -- due to narrow window, after nvim fixes virt_text_hide.
for index, value in ipairs(linenos) do 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 = { { value, 'OutlineLineno' } },
virt_text_pos = 'overlay', virt_text_pos = 'overlay',
virt_text_win_col = 0, virt_text_win_col = 0,