A pretty preview window for Neovim that provides VSCode-like peek preview functionality for LSP locations. Glance enables you to preview, navigate, and edit LSP-provided code locations without leaving your current context.
- Seamless integration with LSP for:
- Definitions
- Type definitions
- References
- Implementations
- Full editing capabilities within the preview window
- Smart UI highlighting that adapts to your colorscheme
- Intuitive UI
- Minimal configuration required
- Properly configured LSP client
- Neovim >= 0.7.0
Using lazy.nvim
:
{
'dnlhc/glance.nvim',
cmd = 'Glance'
}
Using mini.deps
MiniDeps.add({
source = 'dnlhc/glance.nvim',
})
Using packer.nvim
use({
'dnlhc/glance.nvim',
cmd = 'Glance'
})
vim.keymap.set('n', 'gD', '<CMD>Glance definitions<CR>')
vim.keymap.set('n', 'gR', '<CMD>Glance references<CR>')
vim.keymap.set('n', 'gY', '<CMD>Glance type_definitions<CR>')
vim.keymap.set('n', 'gM', '<CMD>Glance implementations<CR>')
Using Vimscript
nnoremap gR <CMD>Glance references<CR>
nnoremap gD <CMD>Glance definitions<CR>
nnoremap gY <CMD>Glance type_definitions<CR>
nnoremap gM <CMD>Glance implementations<CR>
Default configuration
The following is the default configuration:-- Lua configuration
local glance = require('glance')
local actions = glance.actions
glance.setup({
height = 18, -- Height of the window
zindex = 45,
-- When enabled, adds virtual lines behind the preview window to maintain context in the parent window
-- Requires Neovim >= 0.10.0
preserve_win_context = true,
-- Controls whether the preview window is "embedded" within your parent window or floating
-- above all windows.
detached = function(winid)
-- Automatically detach when parent window width < 100 columns
return vim.api.nvim_win_get_width(winid) < 100
end,
-- Or use a fixed setting: detached = true,
preview_win_opts = { -- Configure preview window options
cursorline = true,
number = true,
wrap = true,
},
border = {
enable = false, -- Show window borders. Only horizontal borders allowed
top_char = '―',
bottom_char = '―',
},
list = {
position = 'right', -- Position of the list window 'left'|'right'
width = 0.33, -- Width as percentage (0.1 to 0.5)
},
theme = {
enable = true, -- Generate colors based on current colorscheme
mode = 'auto', -- 'brighten'|'darken'|'auto', 'auto' will set mode based on the brightness of your colorscheme
},
mappings = {
list = {
['j'] = actions.next, -- Next item
['k'] = actions.previous, -- Previous item
['<Down>'] = actions.next,
['<Up>'] = actions.previous,
['<Tab>'] = actions.next_location, -- Next location (skips groups, cycles)
['<S-Tab>'] = actions.previous_location, -- Previous location (skips groups, cycles)
['<C-u>'] = actions.preview_scroll_win(5), -- Scroll up the preview window
['<C-d>'] = actions.preview_scroll_win(-5), -- Scroll down the preview window
['v'] = actions.jump_vsplit, -- Open location in vertical split
['s'] = actions.jump_split, -- Open location in horizontal split
['t'] = actions.jump_tab, -- Open in new tab
['<CR>'] = actions.jump, -- Jump to location
['o'] = actions.jump,
['l'] = actions.open_fold,
['h'] = actions.close_fold,
['<leader>l'] = actions.enter_win('preview'), -- Focus preview window
['q'] = actions.close, -- Closes Glance window
['Q'] = actions.close,
['<Esc>'] = actions.close,
['<C-q>'] = actions.quickfix, -- Send all locations to quickfix list
-- ['<Esc>'] = false -- Disable a mapping
},
preview = {
['Q'] = actions.close,
['<Tab>'] = actions.next_location, -- Next location (skips groups, cycles)
['<S-Tab>'] = actions.previous_location, -- Previous location (skips groups, cycles)
['<leader>l'] = actions.enter_win('list'), -- Focus list window
},
},
hooks = {}, -- Described in Hooks section
folds = {
fold_closed = '',
fold_open = '',
folded = true, -- Automatically fold list on startup
},
indent_lines = {
enable = true, -- Show indent guidelines
icon = '│',
},
winbar = {
enable = true, -- Enable winbar for the preview (requires neovim-0.8+)
},
use_trouble_qf = false -- Quickfix action will open trouble.nvim instead of built-in quickfix list
})
Commands
:Glance references
Show references of the word under the cursor from the LSP server:Glance definitions
Show definitions of the word under the cursor from the LSP server:Glance type_definitions
Show type definitions of the word under the cursor from the LSP server:Glance implementations
Show implementations of the word under the cursor from the LSP server:Glance resume
Resume previously closed session
API
Glance provides built-in actions accessed through require('glance').actions
.
These are used in the mappings.
local actions = require('glance').actions
---Opens Glance with specified method, can recieve optional table with hooks
---@param method GlanceMethod
---@param opts? { hooks: GlanceHooks }
actions.open(method, opts)
---Closes the Glance window
actions.close
---Resumes last Glance session
actions.resume
---Enters specified window
---@param win "preview"|"list"
---@return fun() function callback to focus specified window
actions.enter_win(win)
---Moves cursor to the next item in the list
actions.next
---Moves cursor to the previous item in the list
actions.previous
---Moves to next location (skips groups, cycles)
actions.next_location
---Moves to previous location (skips groups, cycles)
actions.previous_location
-- Jump to the selected location
-- Example using a Vim command
actions.jump({ cmd = 'vsplit' })
-- Example using a callback function
actions.jump({
cmd = function(selected_item)
vim.cmd('topleft split')
-- Perform custom actions with the selected item
end
})
---Jumps to location in vertical split
actions.jump_vsplit
---Jumps to location in horizontal split
actions.jump_split
---Jumps to location in new tab
actions.jump_tab
---Toggles fold state
actions.toggle_fold
---Opens fold
actions.open_fold
---Closes fold
actions.close_fold
---Scrolls preview window
---@param distance integer Number of lines to scroll (negative scrolls up, positive scrolls down)
---@return fun() function callback to scroll the preview window
actions.preview_scroll_win(distance)
---Sends locations to quickfix list
actions.quickfix
-- Check if Glance is currently open
require('glance').is_open()
Glance supports extending its functionality by registering custom LSP methods that are not part of the standard LSP specification. This is particularly useful when working with language servers that provide additional capabilities through non-standard methods.
Important: Custom methods must be registered before calling the glance setup
.
require('glance').register_method({
method = 'volar/client/findFileReference', -- The LSP method name to be called
name = 'vue_references', -- The command name (used as :Glance vue_references)
label = 'References', -- Display name shown in the Glance UI
})
Once registered, you can use the custom method with the command :Glance vue_references
. The command will trigger the LSP request using the specified custom method.
Hooks
Hooks allow you to customize Glance's behavior at specific points in its lifecycle. Define them in the setup configuration:require('glance').setup({
hooks = {
-- your hooks here
}
})
Called after recieving results from LSP but before opening the preview window. Use this hook to modify the default opening behavior or modify results.
Note: This is a blocking hook - Glance won't open until you call the open
callback.
Parameters:
results
: Table of LSP locationsopen
: Callback to open Glance windowjump
: Callback to jump to a locationmethod
: String indicating the call type ('definitions', 'references', etc.)
hooks = {
before_open = function(results, open, jump, method)
open(results)
end,
}
More examples
Skip Glance window and jump directly when there's only one result:
hooks = {
before_open = function(results, open, jump, method)
if #results == 1 then
jump(results[1])
else
open(results)
end
end,
}
Skip Glance window for single results in current buffer only:
hooks = {
before_open = function(results, open, jump, method)
if #results == 1 then
local uri = vim.uri_from_bufnr(0)
local target_uri = results[1].uri or results[1].targetUri
if target_uri == uri then
jump(results[1])
else
open(results)
end
else
open(results)
end
end,
}
Called right before the Glance window closes.
Called after the Glance window closes.
Highlight groups
GlancePreviewNormal
GlancePreviewMatch
GlancePreviewCursorLine
GlancePreviewSignColumn
GlancePreviewEndOfBuffer
GlancePreviewLineNr
GlancePreviewBorderBottom
GlanceWinBarFilename
GlanceWinBarFilepath
GlanceWinBarTitle
GlanceListNormal
GlanceListFilename
GlanceListFilepath
GlanceListCount
GlanceListMatch
GlanceListCursorLine
GlanceListEndOfBuffer
GlanceListBorderBottom
GlanceFoldIcon
GlanceIndent
GlanceBorderTop