Repository: neovim/neovim
File: runtime/lua/vim/lsp/document_color.lua (Lua)

Code before:
            api.nvim_buf_set_extmark(bufnr, client_ns[client_id], hl.range[1], hl.range[2], {
              virt_text = { { swatch, hl.hl_group } },
              virt_text_pos = 'inline',
            })
          end
        end

        bufstate.applied_version[client_id] = bufstate.processed_version[client_id]
      end
    end
  end,
})

--- @param bufstate vim.lsp.document_color.BufState
--- @return vim.lsp.document_color.HighlightInfo?, integer?
local function get_hl_info_under_cursor(bufstate)
  local cursor_row, cursor_col = unpack(api.nvim_win_get_cursor(0)) --- @type integer, integer
  cursor_row = cursor_row - 1 -- Convert to 0-based index

  for client_id, hls in pairs(bufstate.hl_info) do
    for _, hl in ipairs(hls) do
      if
        hl.lsp_info.range.start.line <= cursor_row
        and hl.lsp_info.range['end'].line >= cursor_row
        and hl.lsp_info.range.start.character <= cursor_col
        and hl.lsp_info.range['end'].character >= cursor_col
      then
        return hl, client_id
      end
    end
  end
end

--- Select from a list of presentations for the color under the cursor.
function M.color_presentation()
  local bufnr = api.nvim_get_current_buf()
  local bufstate = bufstates[bufnr]
  if not bufstate then
    vim.notify('documentColor is not enabled for this buffer.', vim.log.levels.WARN)
    return
  end

  local hl_info, client_id = get_hl_info_under_cursor(bufstate)
  if not hl_info or not client_id then
    vim.notify('No color information under cursor.', vim.log.levels.WARN)
    return
  end

  local uri = vim.uri_from_bufnr(bufnr)
  local client = assert(lsp.get_client_by_id(client_id))


Review comment (bug):
Unlikely to happen, but I think this will fail in some cases where the range is multiline. E.g. if a color span ranges from start pos (0, 0) to end pos (2, 0), we should consider the cursor position (1, 5) to be inside it (since it is between lines 0 and 2). However, this code will consider it outside because the cursor col (5) > end position col (0). Might be easier to pack the hl range into a 4-tuple and reuse the logic from `treesitter._range`?

Code after:
            local swatch = style == 'virtual' and ' ' or style
            api.nvim_buf_set_extmark(bufnr, client_ns[client_id], hl.range[1], hl.range[2], {
              virt_text = { { swatch, hl.hl_group } },
              virt_text_pos = 'inline',
            })
          end
        end

        bufstate.applied_version[client_id] = bufstate.processed_version[client_id]
      end
    end
  end,
})

--- @param bufstate vim.lsp.document_color.BufState
--- @return vim.lsp.document_color.HighlightInfo?, integer?
local function get_hl_info_under_cursor(bufstate)
  local cursor_row, cursor_col = unpack(api.nvim_win_get_cursor(0)) --- @type integer, integer
  cursor_row = cursor_row - 1 -- Convert to 0-based index
  local cursor_range = { cursor_row, cursor_col, cursor_row, cursor_col } --- @type Range4

  for client_id, hls in pairs(bufstate.hl_info) do
    for _, hl in ipairs(hls) do
      if Range.contains(hl.range, cursor_range) then
        return hl, client_id
      end
    end
  end
end

--- Select from a list of presentations for the color under the cursor.
function M.color_presentation()
  local bufnr = api.nvim_get_current_buf()
  local bufstate = bufstates[bufnr]
  if not bufstate then
    vim.notify('documentColor is not enabled for this buffer.', vim.log.levels.WARN)
    return
  end

  local hl_info, client_id = get_hl_info_under_cursor(bufstate)
  if not hl_info or not client_id then
    vim.notify('No color information under cursor.', vim.log.levels.WARN)
    return
  end

  local uri = vim.uri_from_bufnr(bufnr)
  local client = assert(lsp.get_client_by_id(client_id))

  --- @type lsp.ColorPresentationParams
  local params = {
    textDocument = { uri = uri },