Skip to content

Commit

Permalink
misc: update docs and handle errors
Browse files Browse the repository at this point in the history
  • Loading branch information
lewis6991 committed Jul 5, 2023
1 parent 9e72344 commit 34cdb01
Show file tree
Hide file tree
Showing 4 changed files with 127 additions and 56 deletions.
68 changes: 68 additions & 0 deletions HANDLERS.md
Original file line number Diff line number Diff line change
@@ -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.
5 changes: 1 addition & 4 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
# 🚧 WIP and EXPERIMENTAL 🚧

# satellite.nvim

`satellite.nvim` is a Neovim plugin that displays decorated scrollbars.
Expand All @@ -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

Expand Down Expand Up @@ -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

Expand Down
2 changes: 1 addition & 1 deletion lua/satellite/config.lua
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
108 changes: 57 additions & 51 deletions lua/satellite/view.lua
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down

0 comments on commit 34cdb01

Please sign in to comment.