-
Notifications
You must be signed in to change notification settings - Fork 17
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: Norg provider and support of external providers
- Closes #3 - Ref: simrat39/symbols-outline.nvim#190 Norg contains indents and different types of verbatim tags, I was rather lazy to read the spec properly and parse norg using regex line-by-line like markdown, so used treesitter instead. The only requirement is the `norg` parser for treesitter to be installed. Tested on nvim 0.7.2. This should lead the way for supporting vimdoc files in a similar manner. Documentation for how external providers could look like as of now has been added. In the future we could let the provider determine what to do for each keymap, such as `goto_location` and `toggle_preview`. This would allow the zk extension[1] to work properly without having to override existing functions (bad practice). [1]: zk-org/zk-nvim#134
- Loading branch information
Showing
4 changed files
with
201 additions
and
5 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,135 @@ | ||
local M = { | ||
name = 'norg', | ||
query = [[ | ||
[ | ||
(heading1 (heading1_prefix) | ||
title: (paragraph_segment) @name) | ||
(heading2 (heading2_prefix) | ||
title: (paragraph_segment) @name) | ||
(heading3 (heading3_prefix) | ||
title: (paragraph_segment) @name) | ||
(heading4 (heading4_prefix) | ||
title: (paragraph_segment) @name) | ||
(heading5 (heading5_prefix) | ||
title: (paragraph_segment) @name) | ||
(heading6 (heading6_prefix) | ||
title: (paragraph_segment) @name) | ||
] | ||
]], | ||
} | ||
|
||
function M.supports_buffer(bufnr) | ||
if vim.api.nvim_buf_get_option(bufnr, 'ft') ~= 'norg' then | ||
return false | ||
end | ||
|
||
local status, parser = pcall(vim.treesitter.get_parser, bufnr, 'norg') | ||
if not status or not parser then | ||
return false | ||
end | ||
|
||
M.parser = parser | ||
return true | ||
end | ||
|
||
local is_ancestor = vim.treesitter.is_ancestor | ||
|
||
if not _G._outline_nvim_has[8] then | ||
is_ancestor = function(dest, source) | ||
if not (dest and source) then | ||
return false | ||
end | ||
|
||
local current = source | ||
while current ~= nil do | ||
if current == dest then | ||
return true | ||
end | ||
|
||
current = current:parent() | ||
end | ||
|
||
return false | ||
end | ||
end | ||
|
||
local function rec_remove_field(node, field) | ||
node[field] = nil | ||
if node.children then | ||
for _, child in ipairs(node.children) do | ||
rec_remove_field(child, field) | ||
end | ||
end | ||
end | ||
|
||
function M.request_symbols(callback, opts) | ||
if not M.parser then | ||
local status, parser = pcall(vim.treesitter.get_parser, 0, 'norg') | ||
|
||
if not status or not parser then | ||
callback(nil, opts) | ||
return | ||
end | ||
|
||
M.parser = parser | ||
end | ||
|
||
local root = M.parser:parse()[1]:root() | ||
if not root then | ||
callback(nil, opts) | ||
return | ||
end | ||
|
||
local r = { children = {}, tsnode = root, name = 'root' } | ||
local stack = { r } | ||
|
||
local query | ||
if _G._outline_nvim_has[9] then | ||
query = vim.treesitter.query.parse('norg', M.query) | ||
else | ||
---@diagnostic disable-next-line: deprecated | ||
query = vim.treesitter.query.parse_query('norg', M.query) | ||
end | ||
---@diagnostic disable-next-line: missing-parameter | ||
for _, captured_node, _ in query:iter_captures(root, 0) do | ||
local row1, col1, row2, col2 = captured_node:range() | ||
local title = vim.api.nvim_buf_get_text(0, row1, col1, row2, col2, {})[1] | ||
local heading_node = captured_node:parent() | ||
row1, col1, row2, col2 = heading_node:range() | ||
|
||
title = title:gsub('^%s+', '') | ||
|
||
local current = { | ||
kind = 15, | ||
name = title, | ||
selectionRange = { | ||
start = { character = col1, line = row1 }, | ||
['end'] = { character = col2, line = row2 - 1 }, | ||
}, | ||
range = { | ||
start = { character = col1, line = row1 }, | ||
['end'] = { character = col2, line = row2 - 1 }, | ||
}, | ||
children = {}, | ||
tsnode = heading_node, | ||
} | ||
|
||
while #stack > 0 do | ||
local top = stack[#stack] | ||
if is_ancestor(top.tsnode, heading_node) then | ||
current.parent = top | ||
table.insert(top.children, current) | ||
break | ||
end | ||
table.remove(stack, #stack) | ||
end | ||
|
||
table.insert(stack, current) | ||
end | ||
|
||
rec_remove_field(r, 'tsnode') | ||
|
||
callback(r.children, opts) | ||
end | ||
|
||
return M |