Skip to content

Commit

Permalink
feat: basic hinting behavior with ^ and $ motions
Browse files Browse the repository at this point in the history
  • Loading branch information
willothy committed Dec 27, 2023
1 parent 9a2f371 commit 2672029
Showing 1 changed file with 76 additions and 4 deletions.
80 changes: 76 additions & 4 deletions lua/precognition/init.lua
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ local default = {
}

---@type Precognition.Config
local config = {}
local config = default

--- Show the hints until the next keypress or CursorMoved event
function M.peek()
Expand All @@ -46,14 +46,86 @@ end
function M.setup(opts)
config = vim.tbl_deep_extend("force", default, opts or {})

vim.api.nvim_create_autocmd("CursorMoved", {
local ns = vim.api.nvim_create_namespace("precognition")
local au = vim.api.nvim_create_augroup("precognition", { clear = true })

-- This is a test with basic functionality, definitely should be moved out of the setup function and into
-- functions that the public methods can call.

local re_line_start = vim.regex("^\\s*[^\\s]") --[[@as vim.regex]]

---@type integer?
local extmark -- the active extmark in the current buffer

-- clear the extmark entirely when leaving a buffer (hints should only show in current buffer)
vim.api.nvim_create_autocmd("BufLeave", {
group = au,
callback = function(ev)
vim.api.nvim_buf_clear_namespace(ev.buf, ns, 0, -1)
extmark = nil
end,
})

-- clear the extmark when the cursor moves, or when insert mode is entered
vim.api.nvim_create_autocmd({ "CursorMoved", "InsertEnter" }, {
group = au,
callback = function()
-- todo: hide the hints
if extmark then
vim.api.nvim_buf_del_extmark(0, ns, extmark)
extmark = nil
end
end,
})

vim.api.nvim_create_autocmd("CursorHold", {
group = au,
-- TODO: add debounce / delay before showing hints to reduce flickering
-- during fast movements
callback = function()
-- todo: show the hints if they're hidden
if extmark then
return
end

local cursorline, _cursorcol = unpack(vim.api.nvim_win_get_cursor(0))
local cur_line = vim.api.nvim_get_current_line()

-- vim.fn.col("^") doesn't work :(
local line_end = vim.fn.col("$") - 1

-- FIXME: does not play nice with utf-8, we need a better way to
-- get char offsets.
--
-- Notice that on a line with a string containing utf-8 symbols, the marks to not
-- appear in the correct place. We need to treat this as a char array, it seems that vim regex
-- treats it like a byte array.
local line_start = select(2, re_line_start:match_str(cur_line))

local virt_line = {}

-- create the list of hints to show in { hint, column } format
-- TODO: extract this into a function, add hints for other motions
local marks = {}
table.insert(marks, { "^", math.max(0, line_start - 1) })
table.insert(marks, { "$", line_end - 1 })

-- build the virtual line out of virt text chunks
local last_col = 0
for _, mark in ipairs(marks) do
local hint = config.hints[mark[1]] or mark[1]
local col = mark[2]
if col > last_col then
-- add padding between hints
table.insert(virt_line, { string.rep(" ", (col - last_col)) })
last_col = col + 1
end
table.insert(virt_line, { hint, "Comment" })
end

-- create (or overwrite) the extmark
extmark = vim.api.nvim_buf_set_extmark(0, ns, cursorline - 1, line_start, {
id = extmark, -- reuse the same extmark if it exists
virt_lines = { virt_line },
})
end,
})
end
Expand Down

0 comments on commit 2672029

Please sign in to comment.