diff --git a/README.md b/README.md index 06bf475..8097d42 100644 --- a/README.md +++ b/README.md @@ -35,11 +35,10 @@ 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 }, -- }, }, } @@ -47,17 +46,22 @@ return { ## ⚙️ 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]()) +### Hint priorities + +Any hints that could appear in the same place as others should have unique priorities to avoid conflicts. + ## ❔Usage ### Toggling diff --git a/lua/precognition/init.lua b/lua/precognition/init.lua index 234370c..2f0c9db 100644 --- a/lua/precognition/init.lua +++ b/lua/precognition/init.lua @@ -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 }, }, } @@ -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() diff --git a/tests/precognition/e2e_spec.lua b/tests/precognition/e2e_spec.lua index dec6d34..242839e 100644 --- a/tests/precognition/e2e_spec.lua +++ b/tests/precognition/e2e_spec.lua @@ -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)