diff options
Diffstat (limited to 'lua/colorizer/buffer_utils.lua')
-rw-r--r-- | lua/colorizer/buffer_utils.lua | 122 |
1 files changed, 108 insertions, 14 deletions
diff --git a/lua/colorizer/buffer_utils.lua b/lua/colorizer/buffer_utils.lua index 0f8517f..d0b0faa 100644 --- a/lua/colorizer/buffer_utils.lua +++ b/lua/colorizer/buffer_utils.lua @@ -13,10 +13,14 @@ local color_is_bright = color_utils.color_is_bright local matcher_utils = require "colorizer.matcher_utils" local make_matcher = matcher_utils.make_matcher +local highlight_buffer, rehighlight_buffer +local BUFFER_LINES = {} --- Default namespace used in `highlight_buffer` and `colorizer.attach_to_buffer`. -- @see highlight_buffer -- @see colorizer.attach_to_buffer local DEFAULT_NAMESPACE = create_namespace "colorizer" +-- use a different namespace for tailwind as will be cleared if kept in Default namespace +local DEFAULT_NAMESPACE_TAILWIND = create_namespace "colorizer_tailwind" local HIGHLIGHT_NAME_PREFIX = "colorizer" --- Highlight mode which will be use to render the colour local HIGHLIGHT_MODE_NAMES = { @@ -72,6 +76,13 @@ local function create_highlight(rgb_hex, options) end local function add_highlight(options, buf, ns, data) + clear_namespace( + buf, + ns, + BUFFER_LINES[buf]["old_min"] or BUFFER_LINES[buf]["min"], + BUFFER_LINES[buf]["old_max"] or BUFFER_LINES[buf]["max"] + ) + if vim.tbl_contains({ "foreground", "background" }, options.mode) then for linenr, hls in pairs(data) do for _, hl in ipairs(hls) do @@ -90,6 +101,37 @@ local function add_highlight(options, buf, ns, data) end end +local function highlight_buffer_tailwind(buf, ns, mode, options) + -- it can take some time to actually fetch the results + -- on top of that, tailwindcss is quite slow in neovim + vim.defer_fn(function() + local opts = { textDocument = vim.lsp.util.make_text_document_params() } + --@local + ---@diagnostic disable-next-line: param-type-mismatch + vim.lsp.buf_request(buf, "textDocument/documentColor", opts, function(err, results, _, _) + if err == nil and results ~= nil then + local datas = {} + for _, color in pairs(results) do + local cur_line = color.range.start.line + local r, g, b, a = color.color.red or 0, color.color.green or 0, color.color.blue or 0, color.color.alpha or 0 + local rgb_hex = string.format("%02x%02x%02x", r * a * 255, g * a * 255, b * a * 255) + local name = create_highlight(rgb_hex, mode) + local first_col = color.range.start.character + local end_col = color.range["end"].character + + local d = datas[cur_line] or {} + table.insert(d, { name = name, range = { first_col, end_col } }) + datas[cur_line] = d + end + add_highlight(options, buf, ns, datas) + end + end) + end, 10) +end + +local TW_LSP_ATTACHED = {} +local TW_LSP_AU_CREATED = {} +local TW_LSP_AU_ID = {} --- Highlight the buffer region. -- Highlight starting from `line_start` (0-indexed) for each line described by `lines` in the -- buffer `buf` and attach it to the namespace `ns`. @@ -98,7 +140,9 @@ end ---@param lines table: the lines to highlight from the buffer. ---@param line_start number: line_start should be 0-indexed ---@param options table: Configuration options as described in `setup` -local function highlight_buffer(buf, ns, lines, line_start, options) +---@param options_local table: Buffer local variables +---@return nil|boolean|number,function|nil +function highlight_buffer(buf, ns, lines, line_start, options, options_local) if buf == 0 or buf == nil then buf = api.nvim_get_current_buf() end @@ -129,19 +173,53 @@ local function highlight_buffer(buf, ns, lines, line_start, options) end end add_highlight(options, buf, ns, data) -end -local BUFFER_LINES = {} ---- Rehighlight the buffer if colorizer is active ----@param buf number: Buffer number ----@param options table: Buffer options -local function rehighlight_buffer(buf, options) - if buf == 0 or buf == nil then - buf = api.nvim_get_current_buf() + if not options.tailwind or (options.tailwind ~= "lsp" and options.tailwind ~= "both") then + return end - local ns = DEFAULT_NAMESPACE + -- create the autocmds so tailwind colours only activate when tailwindcss lsp is active + if not TW_LSP_AU_CREATED[buf] then + TW_LSP_AU_ID[buf] = {} + TW_LSP_AU_ID[buf][1] = api.nvim_create_autocmd("LspAttach", { + group = options_local.__augroup_id, + buffer = buf, + callback = function(args) + local ok, client = pcall(vim.lsp.get_client_by_id, args.data.client_id) + if ok then + if client.name == "tailwindcss" and client.supports_method "textDocument/documentColor" then + highlight_buffer_tailwind(buf, DEFAULT_NAMESPACE_TAILWIND, mode, options) + TW_LSP_ATTACHED[buf] = true + end + end + end, + }) + local function del_tailwind_stuff() + pcall(api.nvim_del_autocmd, TW_LSP_AU_ID[buf][1]) + pcall(api.nvim_del_autocmd, TW_LSP_AU_ID[buf][2]) + TW_LSP_ATTACHED[buf], TW_LSP_AU_CREATED[buf], TW_LSP_AU_ID[buf] = nil, nil, nil + end + -- make sure the autocmds are deleted after lsp server is closed + TW_LSP_AU_ID[buf][2] = api.nvim_create_autocmd("LspDetach", { + group = options_local.__augroup_id, + buffer = buf, + callback = function() + del_tailwind_stuff() + clear_namespace(buf, DEFAULT_NAMESPACE_TAILWIND, 0, -1) + end, + }) + TW_LSP_AU_CREATED[buf] = true + return DEFAULT_NAMESPACE_TAILWIND, del_tailwind_stuff + end + -- only try to do tailwindcss highlight if lsp is attached + if TW_LSP_ATTACHED[buf] then + highlight_buffer_tailwind(buf, DEFAULT_NAMESPACE_TAILWIND, mode, options) + end +end + +-- get the amount lines to highlight +local function getrow(buf) if not BUFFER_LINES[buf] then BUFFER_LINES[buf] = {} end @@ -176,15 +254,31 @@ local function rehighlight_buffer(buf, options) max = new_max end end - min = min or new_min max = max or new_max - clear_namespace(buf, ns, min, max) - local lines = buf_get_lines(buf, min, max, false) - highlight_buffer(buf, ns, lines, min, options) -- store current window position to be used later to incremently highlight BUFFER_LINES[buf]["max"] = new_max BUFFER_LINES[buf]["min"] = new_min + BUFFER_LINES[buf]["old_max"] = max + BUFFER_LINES[buf]["old_min"] = min + return min, max +end + +--- Rehighlight the buffer if colorizer is active +---@param buf number: Buffer number +---@param options table: Buffer options +---@param options_local table|nil: Buffer local variables +---@return nil|boolean|number,function|nil +function rehighlight_buffer(buf, options, options_local) + if buf == 0 or buf == nil then + buf = api.nvim_get_current_buf() + end + + local ns = DEFAULT_NAMESPACE + + local min, max = getrow(buf) + local lines = buf_get_lines(buf, min, max, false) + return highlight_buffer(buf, ns, lines, min, options, options_local or {}) end --- @export |