mirror of
				https://github.com/neovim/neovim.git
				synced 2025-10-26 12:27:24 +00:00 
			
		
		
		
	fix(lua): ensure inspect_pos() only shows visible highlight extmarks
Problem:  Unpaired marks are shown with `filter.extmarks == true`, which
          should only return visible highlights. Misleading `end_col`
          included in `inspect_pos()` for unpaired mark; it is set to
          `start_col + 1` which would be a visible highlight, which it is
          not. Custom "is_here" filter used to get extmarks overlapping a
          position.
Solution: Exclude unpaired highlight extmarks with `filter.extmarks == true`.
          Set `end_col` to `start_col` for an unpaired mark. Supply
          appropriate arguments to nvim_buf_get_extmarks() to return
          overlapping extmarks; exclude marks whose end is at `{row, col}`
          with `filter.extmarks == true`.
			
			
This commit is contained in:
		 Luuk van Baal
					Luuk van Baal
				
			
				
					committed by
					
						 Christian Clason
						Christian Clason
					
				
			
			
				
	
			
			
			 Christian Clason
						Christian Clason
					
				
			
						parent
						
							1369d86812
						
					
				
				
					commit
					d40481322a
				
			| @@ -104,30 +104,32 @@ function vim.inspect_pos(bufnr, row, col, filter) | |||||||
|  |  | ||||||
|   --- Convert an extmark tuple into a table |   --- Convert an extmark tuple into a table | ||||||
|   local function to_map(extmark) |   local function to_map(extmark) | ||||||
|     extmark = { |     local opts = resolve_hl(extmark[4]) | ||||||
|  |     return { | ||||||
|       id = extmark[1], |       id = extmark[1], | ||||||
|       row = extmark[2], |       row = extmark[2], | ||||||
|       col = extmark[3], |       col = extmark[3], | ||||||
|       opts = resolve_hl(extmark[4]), |       end_row = opts.end_row or extmark[2], | ||||||
|  |       end_col = opts.end_col or extmark[3], | ||||||
|  |       opts = opts, | ||||||
|  |       ns_id = opts.ns_id, | ||||||
|  |       ns = nsmap[opts.ns_id] or '', | ||||||
|     } |     } | ||||||
|     extmark.ns_id = extmark.opts.ns_id |  | ||||||
|     extmark.ns = nsmap[extmark.ns_id] or '' |  | ||||||
|     extmark.end_row = extmark.opts.end_row or extmark.row -- inclusive |  | ||||||
|     extmark.end_col = extmark.opts.end_col or (extmark.col + 1) -- exclusive |  | ||||||
|     return extmark |  | ||||||
|   end |   end | ||||||
|  |  | ||||||
|   --- Check if an extmark overlaps this position |   --- Exclude end_col and unpaired marks from the overlapping marks, unless | ||||||
|   local function is_here(extmark) |   --- filter.extmarks == 'all' (a highlight is drawn until end_col - 1). | ||||||
|     return (row >= extmark.row and row <= extmark.end_row) -- within the rows of the extmark |   local function exclude_end_col(extmark) | ||||||
|       and (row > extmark.row or col >= extmark.col) -- either not the first row, or in range of the col |     return filter.extmarks == 'all' or row < extmark.end_row or col < extmark.end_col | ||||||
|       and (row < extmark.end_row or col < extmark.end_col) -- either not in the last row or in range of the col |  | ||||||
|   end |   end | ||||||
|  |  | ||||||
|   -- all extmarks at this position |   -- All overlapping extmarks at this position: | ||||||
|   local extmarks = vim.api.nvim_buf_get_extmarks(bufnr, -1, 0, -1, { details = true }) |   local extmarks = vim.api.nvim_buf_get_extmarks(bufnr, -1, { row, col }, { row, col }, { | ||||||
|  |     details = true, | ||||||
|  |     overlap = true, | ||||||
|  |   }) | ||||||
|   extmarks = vim.tbl_map(to_map, extmarks) |   extmarks = vim.tbl_map(to_map, extmarks) | ||||||
|   extmarks = vim.tbl_filter(is_here, extmarks) |   extmarks = vim.tbl_filter(exclude_end_col, extmarks) | ||||||
|  |  | ||||||
|   if filter.semantic_tokens then |   if filter.semantic_tokens then | ||||||
|     results.semantic_tokens = vim.tbl_filter(function(extmark) |     results.semantic_tokens = vim.tbl_filter(function(extmark) | ||||||
|   | |||||||
| @@ -12,23 +12,25 @@ describe('vim.inspect_pos', function() | |||||||
|   end) |   end) | ||||||
|  |  | ||||||
|   it('it returns items', function() |   it('it returns items', function() | ||||||
|     local buf, ns1, ns2, items, other_buf_syntax = exec_lua(function() |     local buf, ns1, ns2 = exec_lua(function() | ||||||
|       local buf = vim.api.nvim_create_buf(true, false) |       local buf = vim.api.nvim_create_buf(true, false) | ||||||
|       local buf1 = vim.api.nvim_create_buf(true, false) |       _G.buf1 = vim.api.nvim_create_buf(true, false) | ||||||
|       local ns1 = vim.api.nvim_create_namespace('ns1') |       local ns1 = vim.api.nvim_create_namespace('ns1') | ||||||
|       local ns2 = vim.api.nvim_create_namespace('') |       local ns2 = vim.api.nvim_create_namespace('') | ||||||
|       vim.api.nvim_set_current_buf(buf) |       vim.api.nvim_set_current_buf(buf) | ||||||
|       vim.api.nvim_buf_set_lines(0, 0, -1, false, { 'local a = 123' }) |       vim.api.nvim_buf_set_lines(0, 0, -1, false, { 'local a = 123' }) | ||||||
|       vim.api.nvim_buf_set_lines(buf1, 0, -1, false, { '--commentline' }) |       vim.api.nvim_buf_set_lines(_G.buf1, 0, -1, false, { '--commentline' }) | ||||||
|       vim.bo[buf].filetype = 'lua' |       vim.bo[buf].filetype = 'lua' | ||||||
|       vim.bo[buf1].filetype = 'lua' |       vim.bo[_G.buf1].filetype = 'lua' | ||||||
|       vim.api.nvim_buf_set_extmark(buf, ns1, 0, 10, { hl_group = 'Normal' }) |       vim.api.nvim_buf_set_extmark(buf, ns1, 0, 10, { hl_group = 'Normal' }) | ||||||
|       vim.api.nvim_buf_set_extmark(buf, ns2, 0, 10, { hl_group = 'Normal' }) |       vim.api.nvim_buf_set_extmark(buf, ns1, 0, 10, { hl_group = 'Normal', end_col = 10 }) | ||||||
|  |       vim.api.nvim_buf_set_extmark(buf, ns2, 0, 10, { hl_group = 'Normal', end_col = 11 }) | ||||||
|       vim.cmd('syntax on') |       vim.cmd('syntax on') | ||||||
|       return buf, ns1, ns2, vim.inspect_pos(0, 0, 10), vim.inspect_pos(buf1, 0, 10).syntax |       return buf, ns1, ns2 | ||||||
|     end) |     end) | ||||||
|  |  | ||||||
|     eq('', eval('v:errmsg')) |     eq('', eval('v:errmsg')) | ||||||
|  |     -- Only visible highlights with `filter.extmarks == true` | ||||||
|     eq({ |     eq({ | ||||||
|       buffer = buf, |       buffer = buf, | ||||||
|       col = 10, |       col = 10, | ||||||
| @@ -39,6 +41,37 @@ describe('vim.inspect_pos', function() | |||||||
|           end_col = 11, |           end_col = 11, | ||||||
|           end_row = 0, |           end_row = 0, | ||||||
|           id = 1, |           id = 1, | ||||||
|  |           ns = '', | ||||||
|  |           ns_id = ns2, | ||||||
|  |           opts = { | ||||||
|  |             end_row = 0, | ||||||
|  |             end_col = 11, | ||||||
|  |             hl_eol = false, | ||||||
|  |             hl_group = 'Normal', | ||||||
|  |             hl_group_link = 'Normal', | ||||||
|  |             ns_id = ns2, | ||||||
|  |             priority = 4096, | ||||||
|  |             right_gravity = true, | ||||||
|  |             end_right_gravity = false, | ||||||
|  |           }, | ||||||
|  |           row = 0, | ||||||
|  |         }, | ||||||
|  |       }, | ||||||
|  |       treesitter = {}, | ||||||
|  |       semantic_tokens = {}, | ||||||
|  |       syntax = { { hl_group = 'luaNumber', hl_group_link = 'Constant' } }, | ||||||
|  |     }, exec_lua('return vim.inspect_pos(0, 0, 10)')) | ||||||
|  |     -- All extmarks with `filters.extmarks == 'all'` | ||||||
|  |     eq({ | ||||||
|  |       buffer = buf, | ||||||
|  |       col = 10, | ||||||
|  |       row = 0, | ||||||
|  |       extmarks = { | ||||||
|  |         { | ||||||
|  |           col = 10, | ||||||
|  |           end_col = 10, | ||||||
|  |           end_row = 0, | ||||||
|  |           id = 1, | ||||||
|           ns = 'ns1', |           ns = 'ns1', | ||||||
|           ns_id = ns1, |           ns_id = ns1, | ||||||
|           opts = { |           opts = { | ||||||
| @@ -59,32 +92,47 @@ describe('vim.inspect_pos', function() | |||||||
|           ns = '', |           ns = '', | ||||||
|           ns_id = ns2, |           ns_id = ns2, | ||||||
|           opts = { |           opts = { | ||||||
|  |             end_row = 0, | ||||||
|  |             end_col = 11, | ||||||
|             hl_eol = false, |             hl_eol = false, | ||||||
|             hl_group = 'Normal', |             hl_group = 'Normal', | ||||||
|             hl_group_link = 'Normal', |             hl_group_link = 'Normal', | ||||||
|             ns_id = ns2, |             ns_id = ns2, | ||||||
|             priority = 4096, |             priority = 4096, | ||||||
|             right_gravity = true, |             right_gravity = true, | ||||||
|  |             end_right_gravity = false, | ||||||
|  |           }, | ||||||
|  |           row = 0, | ||||||
|  |         }, | ||||||
|  |         { | ||||||
|  |           col = 10, | ||||||
|  |           end_col = 10, | ||||||
|  |           end_row = 0, | ||||||
|  |           id = 2, | ||||||
|  |           ns = 'ns1', | ||||||
|  |           ns_id = ns1, | ||||||
|  |           opts = { | ||||||
|  |             end_row = 0, | ||||||
|  |             end_col = 10, | ||||||
|  |             hl_eol = false, | ||||||
|  |             hl_group = 'Normal', | ||||||
|  |             hl_group_link = 'Normal', | ||||||
|  |             ns_id = ns1, | ||||||
|  |             priority = 4096, | ||||||
|  |             right_gravity = true, | ||||||
|  |             end_right_gravity = false, | ||||||
|           }, |           }, | ||||||
|           row = 0, |           row = 0, | ||||||
|         }, |         }, | ||||||
|       }, |       }, | ||||||
|       treesitter = {}, |       treesitter = {}, | ||||||
|       semantic_tokens = {}, |       semantic_tokens = {}, | ||||||
|       syntax = { |       syntax = { { hl_group = 'luaNumber', hl_group_link = 'Constant' } }, | ||||||
|         { |     }, exec_lua('return vim.inspect_pos(0, 0, 10, { extmarks = "all" })')) | ||||||
|           hl_group = 'luaNumber', |     -- Syntax from other buffer. | ||||||
|           hl_group_link = 'Constant', |  | ||||||
|         }, |  | ||||||
|       }, |  | ||||||
|     }, items) |  | ||||||
|  |  | ||||||
|     eq({ |     eq({ | ||||||
|       { |       { hl_group = 'luaComment', hl_group_link = 'Comment' }, | ||||||
|         hl_group = 'luaComment', |     }, exec_lua('return vim.inspect_pos(_G.buf1, 0, 10).syntax')) | ||||||
|         hl_group_link = 'Comment', |  | ||||||
|       }, |  | ||||||
|     }, other_buf_syntax) |  | ||||||
|   end) |   end) | ||||||
| end) | end) | ||||||
|  |  | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user