1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152
|
-- use treesitter over syntax (for highlighted code blocks)
vim.treesitter.start()
--- Apply current colorscheme to lists of default highlight groups
---
--- Note: {patterns} is assumed to be sorted by occurrence in the file.
--- @param patterns {start:string,stop:string,match:string}[]
local function colorize_hl_groups(patterns)
local ns = vim.api.nvim_create_namespace('nvim.vimhelp')
vim.api.nvim_buf_clear_namespace(0, ns, 0, -1)
local save_cursor = vim.fn.getcurpos()
for _, pat in pairs(patterns) do
local start_lnum = vim.fn.search(pat.start, 'c')
local end_lnum = vim.fn.search(pat.stop)
if start_lnum == 0 or end_lnum == 0 then
break
end
for lnum = start_lnum, end_lnum do
local word = vim.api.nvim_buf_get_lines(0, lnum - 1, lnum, true)[1]:match(pat.match)
if vim.fn.hlexists(word) ~= 0 then
vim.api.nvim_buf_set_extmark(0, ns, lnum - 1, 0, { end_col = #word, hl_group = word })
end
end
end
vim.fn.setpos('.', save_cursor)
end
-- Add custom highlights for list in `:h highlight-groups`.
local bufname = vim.fs.normalize(vim.api.nvim_buf_get_name(0))
if vim.endswith(bufname, '/doc/syntax.txt') then
colorize_hl_groups({
{ start = [[\*group-name\*]], stop = '^======', match = '^(%w+)\t' },
{ start = [[\*highlight-groups\*]], stop = '^======', match = '^(%w+)\t' },
})
elseif vim.endswith(bufname, '/doc/treesitter.txt') then
colorize_hl_groups({
{
start = [[\*treesitter-highlight-groups\*]],
stop = [[\*treesitter-highlight-spell\*]],
match = '^@[%w%p]+',
},
})
elseif vim.endswith(bufname, '/doc/diagnostic.txt') then
colorize_hl_groups({
{ start = [[\*diagnostic-highlights\*]], stop = '^======', match = '^(%w+)' },
})
elseif vim.endswith(bufname, '/doc/lsp.txt') then
colorize_hl_groups({
{ start = [[\*lsp-highlight\*]], stop = '^------', match = '^(%w+)' },
{ start = [[\*lsp-semantic-highlight\*]], stop = '^======', match = '^@[%w%p]+' },
})
end
vim.keymap.set('n', 'gO', function()
require('vim.treesitter._headings').show_toc()
end, { buffer = 0, silent = true, desc = 'Show an Outline of the current buffer' })
vim.keymap.set('n', ']]', function()
require('vim.treesitter._headings').jump({ count = 1 })
end, { buffer = 0, silent = false, desc = 'Jump to next section' })
vim.keymap.set('n', '[[', function()
require('vim.treesitter._headings').jump({ count = -1 })
end, { buffer = 0, silent = false, desc = 'Jump to previous section' })
local parser = assert(vim.treesitter.get_parser(0, 'vimdoc', { error = false }))
local root = parser:parse()[1]:root()
-- Add "runnables" for Lua/Vimscript code examples.
do
---@type table<integer, { lang: string, code: string }>
local code_blocks = {}
local query = vim.treesitter.query.parse(
'vimdoc',
[[
(codeblock
(language) @_lang
.
(code) @code
(#any-of? @_lang "lua" "vim")
(#set! @code lang @_lang))
]]
)
for _, match, metadata in query:iter_matches(root, 0, 0, -1) do
for id, nodes in pairs(match) do
local name = query.captures[id]
local node = nodes[1]
local start, _, end_ = node:parent():range()
if name == 'code' then
local code = vim.treesitter.get_node_text(node, 0)
local lang_node = match[metadata[id].lang][1] --[[@as TSNode]]
local lang = vim.treesitter.get_node_text(lang_node, 0)
for i = start + 1, end_ do
code_blocks[i] = { lang = lang, code = code }
end
end
end
end
vim.keymap.set('n', 'g==', function()
local pos = vim.api.nvim_win_get_cursor(0)[1]
local code_block = code_blocks[pos]
if not code_block then
vim.print('No code block found')
elseif code_block.lang == 'lua' then
vim.cmd.lua(code_block.code)
elseif code_block.lang == 'vim' then
vim.cmd(code_block.code)
end
end, { buffer = true })
end
do
local ns = vim.api.nvim_create_namespace('nvim.help.urls')
local base = 'https://neovim.io/doc/user/helptag.html?tag='
local query = vim.treesitter.query.parse(
'vimdoc',
[[
((optionlink) @helplink)
(taglink
text: (_) @helplink)
(tag
text: (_) @helplink)
]]
)
for _, match, _ in query:iter_matches(root, 0, 0, -1) do
for id, nodes in pairs(match) do
if query.captures[id] == 'helplink' then
for _, node in ipairs(nodes) do
local start_line, start_col, end_line, end_col = node:range()
local tag = vim.treesitter.get_node_text(node, 0)
vim.api.nvim_buf_set_extmark(0, ns, start_line, start_col, {
end_line = end_line,
end_col = end_col,
url = base .. vim.uri_encode(tag),
})
end
end
end
end
end
vim.b.undo_ftplugin = (vim.b.undo_ftplugin or '')
.. '\n sil! exe "nunmap <buffer> gO" | sil! exe "nunmap <buffer> g=="'
.. '\n sil! exe "nunmap <buffer> ]]" | sil! exe "nunmap <buffer> [["'
vim.b.undo_ftplugin = vim.b.undo_ftplugin .. ' | call v:lua.vim.treesitter.stop()'
|