fix: Lineno alignment, hl_mode, config options

- Config
  - Renamed auto_goto -> auto_jump (because goto implies change of
    cursor focus)
  - Renamed down/up_and_goto -> down/up_and_jump

Existing config that use the old keys *WILL STILL WORK*. But users are
recommended to update to avoid inconsistency. I promise the number of
config changes like this will decrease inverse-exponentially after the
plugin refactor :)

- Docs
  - Improved wording

- Lineno
  - Fixed alignment (no way I was taking max line num of the *Outline*
    buf this whole time!)
  - Fixed appearance of lineno column hl blending if hide_cursor is one
    (please see the comment added)
This commit is contained in:
hedy
2023-11-13 18:07:52 +08:00
parent fd22263c32
commit 1446bdd135
4 changed files with 110 additions and 68 deletions

104
README.md
View File

@@ -64,12 +64,11 @@ Table of contents
## Installation ## Installation
Packer: - GitHub repo: `"hedyhli/outline.nvim"`
```lua - Or SourceHut repo: `url = "https://git.sr.ht/~hedy/outline.nvim"` (an
use 'hedyhli/outline.nvim' equivalent key to `url` for your plugin manager)
```
Lazy: Lazy.nvim example:
```lua ```lua
{ {
"hedyhli/outline.nvim", "hedyhli/outline.nvim",
@@ -85,13 +84,13 @@ Lazy:
}, },
``` ```
Lazy with lazy-loading: Lazy.nvim with lazy-loading example:
```lua ```lua
{ {
"hedyhli/outline.nvim", "hedyhli/outline.nvim",
lazy = true,
cmd = { "Outline", "OutlineOpen" }, cmd = { "Outline", "OutlineOpen" },
keys = { keys = { -- Example mapping to toggle outline
-- Example mapping to toggle outline
{ "<leader>tt", "<cmd>Outline<CR>", desc = "Toggle outline" }, { "<leader>tt", "<cmd>Outline<CR>", desc = "Toggle outline" },
}, },
opts = { opts = {
@@ -100,7 +99,7 @@ Lazy with lazy-loading:
}, },
``` ```
This allows Lazy.nvim to lazy load the plugin on commands `Outline`, This allows Lazy.nvim to lazy-load the plugin on commands `Outline`,
`OutlineOpen`, and your keybindings. `OutlineOpen`, and your keybindings.
@@ -108,21 +107,25 @@ This allows Lazy.nvim to lazy load the plugin on commands `Outline`,
Call the setup function with your configuration options. Call the setup function with your configuration options.
Note that a call to `.setup()` is *required* for this plugin to work Note that a call to `.setup()` is **required** for this plugin to work
(simrat39/symbols-outline.nvim#213). (otherwise you might see this error: simrat39/symbols-outline.nvim#213).
```lua ```lua
require("outline").setup({}) require("outline").setup({})
``` ```
[Skip to commands](#commands)
## Configuration ## Configuration
The configuration structure has been heavily improved and refactored in this The configuration structure has been heavily improved and refactored in this
plugin. For details and reasoning, see [breaking changes](#-breaking-changes). plugin. If you're migrating from the original symbols-outline, see [#12 on
github](https://github.com/hedyhli/outline.nvim/issues/12) under "breaking
changes" section.
### Terminology ### Terminology
Check this list if you there's any confusion with the terms used in the Check this list if you have any confusion with the terms used in the
configuration. configuration.
- **Provider**: Source of the items in the outline view. Could be LSP, CoC, etc. - **Provider**: Source of the items in the outline view. Could be LSP, CoC, etc.
@@ -136,6 +139,8 @@ configuration.
provided by provider. provided by provider.
- **Focus**: Which window the cursor is in - **Focus**: Which window the cursor is in
[Skip to commands](#commands)
### Default options ### Default options
Pass a table to the setup call with your configuration options. Pass a table to the setup call with your configuration options.
@@ -165,29 +170,33 @@ Default values are shown:
-- Auto close the outline window if goto_location is triggered and not for -- Auto close the outline window if goto_location is triggered and not for
-- peek_location -- peek_location
auto_close = false, auto_close = false,
-- Automatically go to location in code when navigating outline window. -- Automatically scroll to the location in code when navigating outline window.
auto_goto = false, auto_jump = false,
-- Vim options for the outline window -- Vim options for the outline window
show_numbers = false, show_numbers = false,
show_relative_numbers = false, show_relative_numbers = false,
wrap = false,
show_cursorline = true, show_cursorline = true,
-- Enable this when you enabled cursorline so your cursor color can -- Enable this only if you enabled cursorline so your cursor color can
-- blend with the cursorline, in effect, as if your cursor is hidden -- blend with the cursorline, in effect, as if your cursor is hidden
-- in the outline window. -- in the outline window.
-- This is useful because with cursorline, there isn't really a need -- This is useful because with cursorline, there isn't really a need
-- to know the vertical column position of the cursor and it may even -- to know the vertical column position of the cursor and it may even
-- be distracting, rendering lineno/guides/icons unreadable. -- be distracting, rendering lineno/guides/icons unreadable.
-- This makes your line of cursor look the same as if the cursor wasn't -- This makes your line of cursor have the same color as if the cursor
-- focused on the outline window. -- wasn't focused on the outline window.
-- This feature is experimental.
hide_cursor = false, hide_cursor = false,
-- Whether to wrap long lines, or let them flow off the window -- Whether to auto-focus on the outline window when it is opened.
wrap = false, -- Set to false to *always* retain focus on your previous buffer when opening
-- Whether to focus on the outline window when it is opened.
-- Set to false to remain focus on your previous buffer when opening
-- outline. -- outline.
-- If you enable this you can still use bangs in :Outline! or :OutlineOpen! to
-- retain focus on your code. If this is false, retaining focus will be
-- enforced for :Outline/:OutlineOpen and you will not be able to have the
-- other behaviour.
focus_on_open = true, focus_on_open = true,
-- Winhighlight option for outline window. -- Winhighlight option for outline window.
-- See :help 'winhl' -- See :help 'winhl'
@@ -198,31 +207,33 @@ Default values are shown:
}, },
outline_items = { outline_items = {
-- Whether to highlight the currently hovered symbol (high cpu usage) -- Whether to highlight the currently hovered symbol and all direct parents
highlight_hovered_item = true, highlight_hovered_item = true,
-- Show extra details with the symbols (lsp dependent) -- Show extra details with the symbols (lsp dependent) as virtual next
show_symbol_details = true, show_symbol_details = true,
-- Show line numbers of each symbol next to them. -- Show corresponding line numbers of each symbol on the left column as
-- virtual text, for quick navigation when not focused on outline.
-- Why? See this comment: -- Why? See this comment:
-- https://github.com/simrat39/symbols-outline.nvim/issues/212#issuecomment-1793503563 -- https://github.com/simrat39/symbols-outline.nvim/issues/212#issuecomment-1793503563
show_symbol_lineno = false, show_symbol_lineno = false,
}, },
-- Options for outline guides. -- Options for outline guides which help show tree hierarchy of symbols
guides = { guides = {
enabled = true, enabled = true,
markers = { markers = {
-- It is recommended for bottom and middle markers to use the same number
-- of characters to align all child nodes vertically.
bottom = '└', bottom = '└',
middle = '├', middle = '├',
vertical = '│', vertical = '│',
horizontal = '─',
}, },
}, },
symbol_folding = { symbol_folding = {
-- Depth past which nodes will be folded by default -- Depth past which nodes will be folded by default
autofold_depth = nil, autofold_depth = nil,
-- Automatically unfold hovered symbol -- Automatically unfold currently hovered symbol
auto_unfold_hover = true, auto_unfold_hover = true,
markers = { '', '' }, markers = { '', '' },
}, },
@@ -253,7 +264,8 @@ Default values are shown:
winblend = 0 winblend = 0
}, },
-- These keymaps can be a string or a table for multiple keys -- These keymaps can be a string or a table for multiple keys.
-- Set to `{}` to disable. (Using 'nil' will fallback to default keys)
keymaps = { keymaps = {
show_help = '?', show_help = '?',
close = {"<Esc>", "q"}, close = {"<Esc>", "q"},
@@ -265,7 +277,7 @@ Default values are shown:
peek_location = "o", peek_location = "o",
-- Visit location in code and close outline immediately -- Visit location in code and close outline immediately
goto_and_close = "<S-Cr>" goto_and_close = "<S-Cr>"
-- Change cursor position of outline window to the current location in code. -- Change cursor position of outline window to match current location in code.
-- "Opposite" of goto/peek_location. -- "Opposite" of goto/peek_location.
restore_location = "<C-g>", restore_location = "<C-g>",
-- Open LSP/provider-dependent symbol hover information -- Open LSP/provider-dependent symbol hover information
@@ -287,8 +299,10 @@ Default values are shown:
unfold_all = "E", unfold_all = "E",
fold_reset = "R", fold_reset = "R",
-- Move down/up by one line and peek_location immediately. -- Move down/up by one line and peek_location immediately.
down_and_goto = "<C-j>", -- You can also use outline_window.auto_jump=true to do this for any
up_and_goto = "<C-k>", -- j/k/<down>/<up>.
down_and_jump = "<C-j>",
up_and_jump = "<C-k>",
}, },
providers = { providers = {
@@ -304,7 +318,7 @@ Default values are shown:
blacklist = {}, blacklist = {},
-- You can use a custom function that returns the icon for each symbol kind. -- You can use a custom function that returns the icon for each symbol kind.
-- This function takes a kind (string) as parameter and should return an -- This function takes a kind (string) as parameter and should return an
-- icon. -- icon as string.
icon_fetcher = nil, icon_fetcher = nil,
-- 3rd party source for fetching icons. Fallback if icon_fetcher returned -- 3rd party source for fetching icons. Fallback if icon_fetcher returned
-- empty string. Currently supported values: 'lspkind' -- empty string. Currently supported values: 'lspkind'
@@ -351,7 +365,7 @@ Default values are shown:
``` ```
To find out exactly what some of the options do, please see the To find out exactly what some of the options do, please see the
[recipes](#recipes) section of the readme at the bottom for screen-recordings. [recipes](#recipes) section at the bottom for screen-recordings/shots.
The order in which the sources for icons are checked is: The order in which the sources for icons are checked is:
@@ -367,13 +381,13 @@ string or a falsey value.
- **:Outline[!]** - **:Outline[!]**
Toggle outline. With bang (`!`) the cursor focus stays in your Toggle outline. With bang (`!`) the cursor focus stays in your
original window after opening the outline window. Set `focus_on_win = true` to original window after opening the outline window. Set `focus_on_open = true` to
always use this behaviour. always use this behaviour.
- **:OutlineOpen[!]** - **:OutlineOpen[!]**
Open outline. With bang (`!`) the cursor focus stays in your original Open outline. With bang (`!`) the cursor focus stays in your original
window after opening the outline window. Set `focus_on_win = true` to always window after opening the outline window. Set `focus_on_open = true` to always
use this behaviour. use this behaviour.
- **:OutlineClose** - **:OutlineClose**
@@ -382,7 +396,7 @@ string or a falsey value.
- **:OutlineFocus** - **:OutlineFocus**
Toggle focus on outline Toggle focus between outline and code/source window
- **:OutlineFocusOutline** - **:OutlineFocusOutline**
@@ -401,7 +415,7 @@ string or a falsey value.
Go to corresponding node in outline based on cursor position in code, and Go to corresponding node in outline based on cursor position in code, and
focus on the outline window. focus on the outline window.
With bang, retain focus on the code window. With bang (`!`), retain focus on the code window.
This can be understood as the converse of `goto_location` (see keymaps). This can be understood as the converse of `goto_location` (see keymaps).
`goto_location` sets cursor of code window to the position of outline window, `goto_location` sets cursor of code window to the position of outline window,
@@ -413,20 +427,17 @@ string or a falsey value.
## Default keymaps ## Default keymaps
These mappings are active for the outline window. These mappings are active only for the outline window.
| Key | Action | | Key | Action |
| ---------- | -------------------------------------------------- | | ---------- | -------------------------------------------------- |
| Esc / q | Close outline | | Esc / q | Close outline |
| ? | Show help |
| Enter | Go to symbol location in code | | Enter | Go to symbol location in code |
| o | Go to symbol location in code without losing focus | | o | Go to symbol location in code without losing focus |
| Shift+Enter| Go to symbol location in code and close outline | | Shift+Enter| Go to symbol location in code and close outline |
| Ctrl+k | Go up and goto location |
| Ctrl+j | Go down and goto location |
| Ctrl+g | Update outline window to focus on code location | | Ctrl+g | Update outline window to focus on code location |
| Ctrl+Space | Hover current symbol (provider action) |
| K | Toggles the current symbol preview | | K | Toggles the current symbol preview |
| Ctrl+Space | Hover current symbol (provider action) |
| r | Rename symbol | | r | Rename symbol |
| a | Code actions | | a | Code actions |
| h | Fold symbol or parent symbol | | h | Fold symbol or parent symbol |
@@ -436,6 +447,9 @@ These mappings are active for the outline window.
| W | Fold all symbols | | W | Fold all symbols |
| E | Unfold all symbols | | E | Unfold all symbols |
| R | Reset all folding | | R | Reset all folding |
| Ctrl+k | Go up and peek location |
| Ctrl+j | Go down and peek location |
| ? | Show current keymaps as a vim message |
## Highlights ## Highlights
@@ -607,7 +621,7 @@ location directly and not use the preview window:
```lua ```lua
outline_window = { outline_window = {
auto_goto = true, auto_jump = true,
}, },
``` ```
@@ -616,7 +630,7 @@ This feature was added by @stickperson in an upstream PR 🙌
https://github.com/hedyhli/outline.nvim/assets/50042066/3d06e342-97ac-400c-8598-97a9235de66c https://github.com/hedyhli/outline.nvim/assets/50042066/3d06e342-97ac-400c-8598-97a9235de66c
Or, you can use keys `<C-j>` and `<C-k>` to achieve the same effect, whilst not Or, you can use keys `<C-j>` and `<C-k>` to achieve the same effect, whilst not
having `auto_goto` on by default. having `auto_jump` on by default.
### Symbol details ### Symbol details

View File

@@ -27,7 +27,7 @@ M.defaults = {
wrap = false, wrap = false,
focus_on_open = true, focus_on_open = true,
auto_close = false, auto_close = false,
auto_goto = false, auto_jump = false,
show_numbers = false, show_numbers = false,
show_relative_numbers = false, show_relative_numbers = false,
show_cursorline = true, show_cursorline = true,
@@ -67,8 +67,8 @@ M.defaults = {
fold_all = 'W', fold_all = 'W',
unfold_all = 'E', unfold_all = 'E',
fold_reset = 'R', fold_reset = 'R',
down_and_goto = '<C-j>', down_and_jump = '<C-j>',
up_and_goto = '<C-k>', up_and_jump = '<C-k>',
}, },
providers = { providers = {
lsp = { lsp = {
@@ -195,17 +195,17 @@ function M.show_help()
print(vim.inspect(M.o.keymaps)) print(vim.inspect(M.o.keymaps))
end end
---Check for inconsistent or mutually exclusive opts. Does not alter the opts
function M.check_config() function M.check_config()
if M.o.outline_window.hide_cursor and not M.o.outline_window.show_cursorline then if M.o.outline_window.hide_cursor and not M.o.outline_window.show_cursorline then
vim.notify("[outline.config]: hide_cursor enabled WITHOUT cursorline enabled!", vim.log.levels.ERROR) vim.notify("[outline.config]: hide_cursor enabled WITHOUT cursorline enabled!", vim.log.levels.ERROR)
end end
end end
---Resolve shortcuts and deprecated option conversions
function M.resolve_config() function M.resolve_config()
local sc = M.o.outline_window.split_command local sc = M.o.outline_window.split_command
if not sc then if sc then
return
end
-- This should not be needed, nor is it failsafe. But in case user only provides -- This should not be needed, nor is it failsafe. But in case user only provides
-- the, eg, "topleft", we append the ' vs'. -- the, eg, "topleft", we append the ' vs'.
if not sc:find(' vs', 1, true) then if not sc:find(' vs', 1, true) then
@@ -213,6 +213,26 @@ function M.resolve_config()
end end
end end
local dg = M.o.keymaps.down_and_goto
local ug = M.o.keymaps.up_and_goto
if dg then
M.o.keymaps.down_and_jump = dg
M.o.keymaps.down_and_goto = nil
end
if ug then
M.o.keymaps.up_and_jump = ug
M.o.keymaps.up_and_goto = nil
end
-- if dg or ug then
-- vim.notify("[outline.config]: keymaps down/up_and_goto are renamed to down/up_and_jump. Your keymaps for the current session is converted successfully.", vim.log.levels.WARN)
-- end
if M.o.outline_window.auto_goto then
M.o.outline_window.auto_jump = M.o.outline_window.auto_goto
M.o.outline_window.auto_goto = nil
end
end
function M.setup(options) function M.setup(options)
vim.g.symbols_outline_loaded = 1 vim.g.symbols_outline_loaded = 1
M.o = vim.tbl_deep_extend('force', {}, M.defaults, options or {}) M.o = vim.tbl_deep_extend('force', {}, M.defaults, options or {})

View File

@@ -58,7 +58,7 @@ local function wipe_state()
end end
local function _update_lines() local function _update_lines()
M.state.flattened_outline_items = writer.make_outline(M.view.bufnr, M.state.outline_items) M.state.flattened_outline_items = writer.make_outline(M.view.bufnr, M.state.outline_items, M.state.code_win)
end end
---@param items outline.SymbolNode[] ---@param items outline.SymbolNode[]
@@ -127,7 +127,7 @@ function M._goto_and_close()
end end
---@param direction "up"|"down" ---@param direction "up"|"down"
function M._move_and_goto(direction) function M._move_and_jump(direction)
local move = direction == 'down' and 1 or -1 local move = direction == 'down' and 1 or -1
local cur = vim.api.nvim_win_get_cursor(0) local cur = vim.api.nvim_win_get_cursor(0)
cur[1] = cur[1] + move cur[1] = cur[1] + move
@@ -171,7 +171,7 @@ local function setup_buffer_autocmd()
callback = require('outline.preview').close, callback = require('outline.preview').close,
}) })
end end
if cfg.o.outline_window.auto_goto then if cfg.o.outline_window.auto_jump then
vim.api.nvim_create_autocmd('CursorMoved', { vim.api.nvim_create_autocmd('CursorMoved', {
buffer = 0, buffer = 0,
callback = function() callback = function()
@@ -327,12 +327,12 @@ local function setup_keymaps(bufnr)
-- Navigate to corresponding outline location for current code location -- Navigate to corresponding outline location for current code location
map(cfg.o.keymaps.goto_and_close, M._goto_and_close) map(cfg.o.keymaps.goto_and_close, M._goto_and_close)
-- Move down/up in outline and peek that location in code -- Move down/up in outline and peek that location in code
map(cfg.o.keymaps.down_and_goto, function() map(cfg.o.keymaps.down_and_jump, function()
M._move_and_goto('down') M._move_and_jump('down')
end) end)
-- Move down/up in outline and peek that location in code -- Move down/up in outline and peek that location in code
map(cfg.o.keymaps.up_and_goto, function() map(cfg.o.keymaps.up_and_jump, function()
M._move_and_goto('up') M._move_and_jump('up')
end) end)
-- hover symbol -- hover symbol
map( map(
@@ -412,7 +412,7 @@ local function handler(response, opts)
local items = parser.parse(response) local items = parser.parse(response)
M.state.outline_items = items M.state.outline_items = items
M.state.flattened_outline_items = writer.make_outline(M.view.bufnr, items) M.state.flattened_outline_items = writer.make_outline(M.view.bufnr, items, M.state.code_win)
M._highlight_current_item(M.state.code_win) M._highlight_current_item(M.state.code_win)

View File

@@ -101,10 +101,12 @@ end
---@param bufnr integer Nothing is done if is_buffer_outline(bufnr) is not true ---@param bufnr integer Nothing is done if is_buffer_outline(bufnr) is not true
---@param items outline.SymbolNode[] Tree of symbols after being parsed by parser.parse_result ---@param items outline.SymbolNode[] Tree of symbols after being parsed by parser.parse_result
---@return outline.FlatSymbolNode[]? flattened_items No return value if bufnr is invalid ---@return outline.FlatSymbolNode[]? flattened_items No return value if bufnr is invalid
function M.make_outline(bufnr, items) ---@param codewin integer code window
function M.make_outline(bufnr, items, codewin)
if not M.is_buffer_outline(bufnr) then if not M.is_buffer_outline(bufnr) then
return return
end end
local codebuf = vim.api.nvim_win_get_buf(codewin)
clear_virt_text(bufnr) clear_virt_text(bufnr)
@@ -121,7 +123,7 @@ function M.make_outline(bufnr, items)
-- Find the prefix for each line needed for the lineno space -- Find the prefix for each line needed for the lineno space
local lineno_offset = 0 local lineno_offset = 0
local lineno_prefix = "" local lineno_prefix = ""
local lineno_max_width = #tostring(vim.api.nvim_buf_line_count(bufnr) - 1) local lineno_max_width = #tostring(vim.api.nvim_buf_line_count(codebuf) - 1)
if cfg.o.outline_items.show_symbol_lineno then if cfg.o.outline_items.show_symbol_lineno then
-- Use max width-1 plus 1 space padding. -- Use max width-1 plus 1 space padding.
-- -1 because if max_width is a power of ten, don't shift the entire lineno -- -1 because if max_width is a power of ten, don't shift the entire lineno
@@ -250,13 +252,19 @@ function M.make_outline(bufnr, items)
if cfg.o.outline_items.show_symbol_lineno then if cfg.o.outline_items.show_symbol_lineno then
-- Line numbers are left padded, right aligned, positioned at the leftmost -- Line numbers are left padded, right aligned, positioned at the leftmost
-- column -- column
-- 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 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, ns, 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,
virt_text_hide = true, -- When hide_cursor + cursorline enabled, we want the lineno to also
hl_mode = 'replace', -- take on the cursorline background so wherever the cursor is, it
-- appears blended. We want 'replace' even for `hide_cursor=false
-- cursorline=true` because vim's native line numbers do not get
-- highlighted by cursorline.
hl_mode = (cfg.o.outline_window.hide_cursor and 'combine') or 'replace',
}) })
end end
end end