From 34cdb017ebb239bdba5a5ac23c6307837b5e3b7e Mon Sep 17 00:00:00 2001 From: Lewis Russell Date: Wed, 5 Jul 2023 14:30:36 +0100 Subject: [PATCH] misc: update docs and handle errors --- HANDLERS.md | 68 ++++++++++++++++++++++++ README.md | 5 +- lua/satellite/config.lua | 2 +- lua/satellite/view.lua | 108 +++++++++++++++++++++------------------ 4 files changed, 127 insertions(+), 56 deletions(-) create mode 100644 HANDLERS.md diff --git a/HANDLERS.md b/HANDLERS.md new file mode 100644 index 0000000..7328ec7 --- /dev/null +++ b/HANDLERS.md @@ -0,0 +1,68 @@ +# Handlers + +Satellite provides an API to implement handlers for the scrollbar. + +The API for the handler is as follows: + +```lua +--- @class Handler +--- +--- @field name string +--- Name of the handler +--- +--- @field setup fun(config: HandlerConfig, update: fun()) +--- Setup the handler and autocmds that are required to trigger the handler. +--- +--- @field update fun(bufnr: integer, winid: integer): SatelliteMark[] +--- This function is called when the handler needs to update. It must return +--- a list of SatelliteMark's +--- +--- @field enabled fun(): boolean +--- Whether the handler is enabled or not. +``` + +Handlers can accept any configuration but must also support the following +base class: + +```lua +--- @class HandlerConfig +--- +--- @field enable boolean +--- Whether the handler is enabled +--- +--- @field overlap boolean +--- If `true` decorations are rendered on top of the scrollbar. If `false` the +--- decorations are rendered in a separate column to the right of the scrollbar. +--- +--- @field priority integer +--- Priority of the decorations from the handler. +``` + +The handlers `update()` method returns a list of `SatelliteMark`'s which is defined as: + +```lua +--- @class SatelliteMark +--- +--- @field pos integer +--- Row of the mark, use `require('satellite.util').row_to_barpos(winid, lnum)` +--- to translate an `lnum` from window `winid` to its respective scrollbar row. +--- +--- @field highlight string +--- Highlight group of the mark. +--- +--- @field symbol string +--- Symbol of the mark. Must be a single character. +--- +--- @field unique boolean +--- By default, for each position in the scrollbar, Satellite will only use the +--- last mark with that position. This field indicates the mark is special and +--- must be rendered even if there is another mark at the same position from the +--- handler. +``` + +To register a handler call: +```lua +require('satellite.handlers').register(handler) +``` + +Please see the [cursor handler](lua/satellite/handlers/cursor.lua) as an example. diff --git a/README.md b/README.md index a8104be..79a0bb9 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,3 @@ -# 🚧 WIP and EXPERIMENTAL 🚧 - # satellite.nvim `satellite.nvim` is a Neovim plugin that displays decorated scrollbars. @@ -8,7 +6,6 @@ **NOTE**: Many API's required to implement a decorated scrollbar in Neovim do not yet exist, and because of this, this plugin implements fairly unideal and unoptimised workarounds to get desired behaviours. -Therefore, this plugin is highly experimental and currently serves as a platform to experiment, investigate and design the required API's that are needed to be implemented in Neovim core. ## Features @@ -84,7 +81,7 @@ for details. ## Handlers -TODO +Satellite provides an API to implement handlers for the scrollbar, see [HANDLERS](HANDLERS.md) for more details. ## Documentation diff --git a/lua/satellite/config.lua b/lua/satellite/config.lua index 338d32a..bc51543 100644 --- a/lua/satellite/config.lua +++ b/lua/satellite/config.lua @@ -22,7 +22,7 @@ ---@field marks MarksConfig ---@class SatelliteConfig ----@field handlers HandlerConfigs +---@field handlers HandlerConfigs ssss ---@field current_only boolean ---@field winblend integer ---@field zindex integer diff --git a/lua/satellite/view.lua b/lua/satellite/view.lua index 1e69be5..ba18f15 100644 --- a/lua/satellite/view.lua +++ b/lua/satellite/view.lua @@ -83,73 +83,79 @@ end ---@param bbufnr integer ---@param handler Handler local function render_handler(bufnr, winid, bbufnr, handler) - local name = handler.name - if not handler:enabled() then return end + if not api.nvim_buf_is_loaded(bbufnr) then + return + end + + local max_pos = api.nvim_buf_line_count(bbufnr) - 1 + local name = handler.name local handler_config = user_config.handlers[name] or {} api.nvim_buf_clear_namespace(bbufnr, handler.ns, 0, -1) for _, m in ipairs(handler.update(bufnr, winid)) do local pos, symbol = m.pos, m.symbol - local opts = { - id = not m.unique and pos + 1 or nil, - priority = handler_config.priority, - } - - if handler_config.overlap ~= false then - opts.virt_text = { { symbol, m.highlight } } - opts.virt_text_pos = 'overlay' - opts.hl_mode = 'combine' - else - -- Signs are 2 chars so fill the first char with whitespace - opts.sign_text = ' ' .. symbol - opts.sign_hl_group = m.highlight - end + if pos <= max_pos then + local opts = { + id = not m.unique and pos + 1 or nil, + priority = handler_config.priority, + } + + if handler_config.overlap ~= false then + opts.virt_text = { { symbol, m.highlight } } + opts.virt_text_pos = 'overlay' + opts.hl_mode = 'combine' + else + -- Signs are 2 chars so fill the first char with whitespace + opts.sign_text = ' ' .. symbol + opts.sign_hl_group = m.highlight + end - local ok, err = pcall(api.nvim_buf_set_extmark, bbufnr, handler.ns, pos, 0, opts) - if not ok then - print( - string.format( - 'error(satellite.nvim): handler=%s buf=%d row=%d opts=%s, err="%s"', - handler.name, - bbufnr, - pos, - vim.inspect(opts, { newline = ' ', indent = '' }), - err + local ok, err = pcall(api.nvim_buf_set_extmark, bbufnr, handler.ns, pos, 0, opts) + if not ok then + print( + string.format( + 'error(satellite.nvim): handler=%s buf=%d row=%d opts=%s, err="%s"', + handler.name, + bbufnr, + pos, + vim.inspect(opts, { newline = ' ', indent = '' }), + err + ) ) - ) + end end end end ----@param winid integer ----@param bar_winid integer ----@param toprow integer -local function reposition_bar(winid, bar_winid, toprow) - local winwidth = api.nvim_win_get_width(winid) - local wininfo = vim.fn.getwininfo(bar_winid)[1] - - --- @type integer - local signwidth = wininfo.textoff - - local cfg = { - relative = 'win', - win = winid, - row = 0, - col = winwidth - signwidth - 1, - width = 1 + signwidth, - } - - api.nvim_win_set_config(bar_winid, cfg) - - vim.w[bar_winid].col = cfg.col - vim.w[bar_winid].width = cfg.width - vim.w[bar_winid].row = toprow -end +-----@param winid integer +-----@param bar_winid integer +-----@param toprow integer +--local function reposition_bar(winid, bar_winid, toprow) +-- local winwidth = api.nvim_win_get_width(winid) +-- local wininfo = vim.fn.getwininfo(bar_winid)[1] + +-- --- @type integer +-- local signwidth = wininfo.textoff + +-- local cfg = { +-- relative = 'win', +-- win = winid, +-- row = 0, +-- col = winwidth - signwidth - 1, +-- width = 1 + signwidth, +-- } + +-- api.nvim_win_set_config(bar_winid, cfg) + +-- vim.w[bar_winid].col = cfg.col +-- vim.w[bar_winid].width = cfg.width +-- vim.w[bar_winid].row = toprow +--end ---@param bbufnr integer ---@param winid integer