Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: support "prio" priority value for gutter marks #43

Merged
merged 12 commits into from
Jun 2, 2024
22 changes: 13 additions & 9 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,29 +35,33 @@ return {
-- E = { text = "E", prio = 5 },
-- },
-- gutterHints = {
-- -- prio is not currently used for gutter hints
-- G = { text = "G", prio = 1 },
-- gg = { text = "gg", prio = 1 },
-- PrevParagraph = { text = "{", prio = 1 },
-- NextParagraph = { text = "}", prio = 1 },
-- G = { text = "G", prio = 10 },
-- gg = { text = "gg", prio = 9 },
-- PrevParagraph = { text = "{", prio = 8 },
-- NextParagraph = { text = "}", prio = 8 },
-- },
},
}
```

## ⚙️ Config

- Items can be hidden by settings their priority to 0, if you want to hide the
entire virtual line. Set all elements to `prio = 0` in combination with the
- `hints` can be hidden by setting their priority to 0. If you want to hide the
entire virtual line, set all elements to `prio = 0` in combination with the
below.
- `showBlankVirtLine = false`
Setting this option will mean that if a Virtual Line would be blank it wont be
Setting this option will mean that if a Virtual Line would be blank it won't be
rendered
- highlightColor can be set in two ways:
- `gutterHints` can be hidden by setting their priority to 0.
- `highlightColor` can be set in two ways:

1. As a table containing a link property pointing to an existing highlight group (see `:highlight` for valid options).
2. As a table specifying custom highlight values, such as foreground and background colors. ([more info](<https://neovim.io/doc/user/api.html#nvim_set_hl()>))

### Hint priorities

Any hints that could appear in the same place as others should have unique priorities to avoid conflicts.

## ❔Usage

### Toggling
Expand Down
67 changes: 41 additions & 26 deletions lua/precognition/init.lua
Original file line number Diff line number Diff line change
Expand Up @@ -79,11 +79,10 @@ local default = {
highlightColor = { link = "Comment" },
hints = defaultHintConfig,
gutterHints = {
--prio is not currentlt used for gutter hints
G = { text = "G", prio = 1 },
gg = { text = "gg", prio = 1 },
PrevParagraph = { text = "{", prio = 1 },
NextParagraph = { text = "}", prio = 1 },
G = { text = "G", prio = 10 },
gg = { text = "gg", prio = 9 },
PrevParagraph = { text = "{", prio = 8 },
NextParagraph = { text = "}", prio = 8 },
},
}

Expand Down Expand Up @@ -180,31 +179,47 @@ local function apply_gutter_hints(gutter_hints, bufnr)
if utils.is_blacklisted_buffer(bufnr) then
return
end

local gutter_table = {}
for hint, loc in pairs(gutter_hints) do
if config.gutterHints[hint] and loc ~= 0 and loc ~= nil then
if gutter_signs_cache[hint] then
vim.fn.sign_unplace(gutter_group, { id = gutter_signs_cache[hint].id })
gutter_signs_cache[hint] = nil
end
vim.fn.sign_define(gutter_name_prefix .. hint, {
text = config.gutterHints[hint].text,
texthl = "PrecognitionHighlight",
})
local ok, res = pcall(vim.fn.sign_place, 0, gutter_group, gutter_name_prefix .. hint, bufnr, {
lnum = loc,
priority = 100,
})
if ok then
gutter_signs_cache[hint] = { line = loc, id = res }
end
if not ok and loc ~= 0 then
vim.notify_once(
"Failed to place sign: " .. hint .. " at line " .. loc .. vim.inspect(res),
vim.log.levels.WARN
)
if gutter_signs_cache[hint] then
vim.fn.sign_unplace(gutter_group, { id = gutter_signs_cache[hint].id })
gutter_signs_cache[hint] = nil
end

local prio = config.gutterHints[hint].prio

-- Build table of valid and priorised gutter hints.
if loc ~= 0 and loc ~= nil and prio > 0 then
local existing = gutter_table[loc]
if not existing or existing.prio < prio then
gutter_table[loc] = { hint = hint, prio = prio }
end
end
end

-- Only render valid and prioritised gutter hints.
for loc, data in pairs(gutter_table) do
local hint = data.hint
local sign_name = gutter_name_prefix .. hint
vim.fn.sign_define(sign_name, {
text = config.gutterHints[hint].text,
texthl = "PrecognitionHighlight",
})
local ok, res = pcall(vim.fn.sign_place, 0, gutter_group, sign_name, bufnr, {
lnum = loc,
priority = 100,
})
if ok then
gutter_signs_cache[hint] = { line = loc, id = res }
end
if not ok and loc ~= 0 then
vim.notify_once(
"Failed to place sign: " .. hint .. " at line " .. loc .. vim.inspect(res),
vim.log.levels.WARN
)
end
end
end

local function display_marks()
Expand Down
62 changes: 62 additions & 0 deletions tests/precognition/e2e_spec.lua
Original file line number Diff line number Diff line change
Expand Up @@ -248,3 +248,65 @@ describe("e2e tests", function()
eq(customMark, vim.api.nvim_get_hl(0, { name = extmarks[3].virt_lines[1][1][2] }))
end)
end)

describe("Gutter Priority", function()
it("0 priority item is not added", function()
precognition.setup({
---@diagnostic disable-next-line: missing-fields
gutterHints = {
G = { text = "G", prio = 0 },
},
})

local testBuf = vim.api.nvim_create_buf(true, false)

vim.api.nvim_buf_set_lines(testBuf, 0, -1, false, {
"ABC",
"DEF",
"",
"GHI",
"",
"JKL",
"",
"MNO",
})
vim.api.nvim_set_current_buf(testBuf)
vim.api.nvim_win_set_cursor(0, { 4, 0 })

precognition.on_cursor_moved()

local gutter_extmarks = get_gutter_extmarks(testBuf)

for _, extmark in pairs(gutter_extmarks) do
eq(true, extmark[4].sign_text ~= "G ")
eq(true, extmark[4].sign_name ~= "precognition_gutter_G")
end
end)

it("higher priority item replaces", function()
precognition.setup({
---@diagnostic disable-next-line: missing-fields
gutterHints = {
G = { text = "G", prio = 3 },
gg = { text = "gg", prio = 100 },
NextParagraph = { text = "}", prio = 2 },
PrevParagraph = { text = "{", prio = 1 },
},
})

local testBuf = vim.api.nvim_create_buf(true, false)

vim.api.nvim_buf_set_lines(testBuf, 0, -1, false, {
"ABC",
})
vim.api.nvim_set_current_buf(testBuf)
vim.api.nvim_win_set_cursor(0, { 1, 0 })

precognition.on_cursor_moved()

local gutter_extmarks = get_gutter_extmarks(testBuf)

eq(1, vim.tbl_count(gutter_extmarks))
eq("gg", gutter_extmarks[1][4].sign_text)
end)
end)
Loading