From f2691199fadd132336685f88bac1d3a8c4b9c62d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ph=E1=BA=A1m=20B=C3=ACnh=20An?= <111893501+brianhuster@users.noreply.github.com> Date: Sat, 19 Jul 2025 03:02:09 +0700 Subject: [PATCH] fix(tutor): use invalidate field in nvim_buf_set_extmark() #34989 Problem: If users delete a line containing extmark, it will move to the next line, which could highlight the next line in an unwanted way. Solution: - Use `invalidate` field in `nvim_buf_set_extmark()` to prevent the extmark from moving. - Also save from "priority" hacking, since we can check if the extmark is valid in `nvim_buf_get_extmarks()` now. --- runtime/lua/nvim/tutor.lua | 26 ++++++++++++++++---------- 1 file changed, 16 insertions(+), 10 deletions(-) diff --git a/runtime/lua/nvim/tutor.lua b/runtime/lua/nvim/tutor.lua index 2f7e571958..730469f3e6 100644 --- a/runtime/lua/nvim/tutor.lua +++ b/runtime/lua/nvim/tutor.lua @@ -21,13 +21,20 @@ local function check_line(line) if vim.b.tutor_metadata and vim.b.tutor_metadata.expect and vim.b.tutor_extmarks then local ctext = vim.fn.getline(line) - local extmarks = vim.api.nvim_buf_get_extmarks( - 0, - tutor_mark_ns, - { line - 1, 0 }, - { line - 1, -1 }, -- the extmark can move to col > 0 if users insert text there - {} - ) + ---@type vim.api.keyset.get_extmark_item[] + local extmarks = vim + .iter(vim.api.nvim_buf_get_extmarks( + 0, + tutor_mark_ns, + { line - 1, 0 }, + { line - 1, -1 }, -- the extmark can move to col > 0 if users insert text there + { details = true } + )) + :filter(function(extmark) + return not extmark[4].invalid + end) + :totable() + for _, extmark in ipairs(extmarks) do local mark_id = extmark[1] local expct = vim.b.tutor_extmarks[tostring(mark_id)] @@ -38,9 +45,7 @@ local function check_line(line) id = mark_id, sign_text = is_correct and sign_text_correct or sign_text_incorrect, sign_hl_group = is_correct and 'tutorOK' or 'tutorX', - -- This may be a hack. By default, all extmarks only move forward, so a line cannot contain - -- any extmarks that were originally created for later lines. - priority = tonumber(expct), + invalidate = true, }) end end @@ -55,6 +60,7 @@ function M.apply_marks() local lnum = tonumber(expct) ---@type integer vim.api.nvim_buf_set_extmark(0, tutor_hl_ns, lnum - 1, 0, { line_hl_group = 'tutorExpect', + invalidate = true, }) local mark_id = vim.api.nvim_buf_set_extmark(0, tutor_mark_ns, lnum - 1, 0, {})