Skip to content

Commit

Permalink
feat(toc): add config for enabling synchronized cursorline in toc window
Browse files Browse the repository at this point in the history
  • Loading branch information
champignoom committed Nov 27, 2023
1 parent 3ec8abf commit e910a76
Showing 1 changed file with 63 additions and 0 deletions.
63 changes: 63 additions & 0 deletions lua/neorg/modules/core/qol/toc/module.lua
Original file line number Diff line number Diff line change
Expand Up @@ -55,8 +55,15 @@ module.config.public = {
-- A function that takes node type as argument and returns true if this
-- type of node should appear in the Table of Contents
toc_filter = function(node_type) return node_type:match("^heading") end,

-- If `true`, `cursurline` will be enabled (highlighted) in the ToC window,
-- and the cursor position between ToC and content window will be synchronized.
sync_cursorline = true,
}

local start_lines_of_toc_buf = {}
local last_row_of_norg_win = {}

module.public = {
parse_toc_macro = function(buffer)
local toc, toc_name = false, nil
Expand Down Expand Up @@ -153,6 +160,8 @@ module.public = {

local prefix, title
local extmarks = {}
local start_lines = { offset = offset }
start_lines_of_toc_buf[ui_buffer] = start_lines
local toc_filter = module.config.public.toc_filter

local success = module.required["core.integrations.treesitter"].execute_query(
Expand Down Expand Up @@ -181,11 +190,15 @@ module.public = {

if prefix and title then
local _, column = title:start()

table.insert(
extmarks,
vim.api.nvim_buf_set_extmark(original_buffer, namespace, (prefix:start()), column, {})
)

local row_0b, _, _, _ = node:range()
table.insert(start_lines, row_0b)

local prefix_text =
module.required["core.integrations.treesitter"].get_node_text(prefix, original_buffer)
local title_text =
Expand Down Expand Up @@ -246,6 +259,24 @@ local function get_max_virtcol()
return result
end

local function upper_bound(array, v)
-- assume array is sorted
-- find index of first element in array that is > v
local l = 1
local r = #array

while l <= r do
local m = math.floor((l+r)/2)
if v >= array[m] then
l = m + 1
else
r = m - 1
end
end

return l
end

module.on_event = function(event)
if event.split_type[2] ~= module.name then
return
Expand Down Expand Up @@ -276,6 +307,10 @@ module.on_event = function(event)

vim.api.nvim_win_set_option(window, "scrolloff", 999)
vim.api.nvim_win_set_option(window, "conceallevel", 0)
if module.config.public.sync_cursorline then
vim.api.nvim_win_set_option(window, "cursorline", true)
end

module.public.update_toc(namespace, toc_title, event.buffer, event.window, buffer, window)

if module.config.public.fit_width then
Expand Down Expand Up @@ -336,6 +371,34 @@ module.on_event = function(event)
module.public.update_toc(namespace, toc_title, buf, previous_window, buffer, window)
end,
})

if module.config.public.sync_cursorline then
vim.api.nvim_create_autocmd({"CursorMoved", "CursorMovedI"}, {
-- pattern = "*.norg",
buffer = previous_buffer,
callback = function(ev)
assert(ev.buf == previous_buffer)
local content_window = vim.fn.bufwinid(ev.buf)

if not vim.api.nvim_buf_is_valid(buffer) or not vim.api.nvim_buf_is_loaded(buffer) then
return true
end

local current_row_1b = vim.fn.line('.', content_window)
if last_row_of_norg_win[content_window] == current_row_1b then
return
end
last_row_of_norg_win[content_window] = current_row_1b

local start_lines = start_lines_of_toc_buf[buffer]
assert(start_lines)

local current_toc_item_idx = upper_bound(start_lines, current_row_1b-1) - 1
local current_toc_row = current_toc_item_idx==0 and 1 or current_toc_item_idx + start_lines.offset
vim.api.nvim_win_set_cursor(window, { current_toc_row, 0 })
end,
})
end
end
end

Expand Down

0 comments on commit e910a76

Please sign in to comment.