├── LICENSE ├── README.md └── lua └── cmp-tailwind-colors └── init.lua /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) Stefan Everts 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # cmp-tailwind-colors 2 | 3 | | Some results | With transparency (requires `pumblend > 0`) | 4 | |-|-| 5 | | ![Screenshot](https://user-images.githubusercontent.com/7759571/224038448-275261a9-c707-44ca-84ad-1de8dfecce0a.png) | ![Screenshot with transparency](https://user-images.githubusercontent.com/7759571/224045809-d02accff-235d-4857-816a-d3f8db0d89b9.png) | 6 | 7 | Adds TailwindCSS color hints to `nvim-cmp` completion results. 8 | 9 | # Requirements 10 | 11 | - `nvim-cmp` 12 | - `tailwindcss-language-server` 13 | 14 | # Configuration 15 | 16 | Setup `cmp-tailwind-colors`. This is optional. Use it to change the appearance. 17 | These are the defaults. 18 | 19 | ```lua 20 | require("cmp-tailwind-colors").setup({ 21 | enable_alpha = true, -- requires pumblend > 0. 22 | 23 | format = function(itemColor) 24 | return { 25 | fg = itemColor, 26 | bg = itemColor, -- or nil if you dont want a background color 27 | text = " " -- or use an icon 28 | } 29 | end 30 | }) 31 | ``` 32 | 33 | Integrate with `nvim-cmp`. This is the simplest way to get up and running. 34 | 35 | ```lua 36 | cmp.setup({ 37 | formatting = { 38 | format = require("cmp-tailwind-colors").format 39 | } 40 | } 41 | 42 | ``` 43 | 44 | To replicate the setup shown in the screenshot above use the config below 45 | 46 | ```lua 47 | local kind_icons = { 48 | Text = "", 49 | Method = "󰆧", 50 | Function = "󰊕", 51 | Constructor = "", 52 | Field = "󰇽", 53 | Variable = "󰂡", 54 | Class = "󰠱", 55 | Interface = "", 56 | Module = "", 57 | Property = "󰜢", 58 | Unit = "", 59 | Value = "󰎠", 60 | Enum = "", 61 | Keyword = "󰌋", 62 | Snippet = "", 63 | Color = "󰏘", 64 | File = "󰈙", 65 | Reference = "", 66 | Folder = "󰉋", 67 | EnumMember = "", 68 | Constant = "󰏿", 69 | Struct = "", 70 | Event = "", 71 | Operator = "󰆕", 72 | TypeParameter = "󰅲", 73 | } 74 | 75 | cmp.setup({ 76 | formatting = { 77 | fields = { "kind", "abbr", "menu" } -- order of columns, 78 | format = function(entry, item) 79 | item.menu = item.kind 80 | item = require("cmp-tailwind-colors").format(entry, item) 81 | if kind_icons[item.kind] then 82 | item.kind = kind_icons[item.kind] .. " " 83 | end 84 | return item 85 | end, 86 | }, 87 | }) 88 | 89 | ``` 90 | 91 | Here is an opinionated example of lspkind.nvim integration with 92 | cmp-tailwind-colors. You can customize it to suit your needs. 93 | 94 | ```lua 95 | local twc = require("cmp-tailwind-colors") 96 | twc.setup({ 97 | format = function(itemColor) 98 | return { fg = itemColor, bg = nil, text = nil } 99 | end, 100 | }) 101 | 102 | local lspkindFormat = require("lspkind").cmp_format({ 103 | -- lspkind settings here to customize view 104 | }) 105 | 106 | require("cmp").setup({ 107 | formatting = { 108 | format = function(entry, item) 109 | item = twc.format(entry, item) 110 | return lspkindFormat(entry, item) 111 | end, 112 | } 113 | }), 114 | ``` 115 | -------------------------------------------------------------------------------- /lua/cmp-tailwind-colors/init.lua: -------------------------------------------------------------------------------- 1 | local config = { 2 | width = 2, -- width of color box. @deprecated use format to customize the text width 3 | enable_alpha = true, -- requires pumblend > 0 4 | } 5 | 6 | config.format = function(color, _, _) 7 | return { 8 | text = string.rep(" ", config.width), 9 | fg = color, 10 | bg = color, 11 | } 12 | end 13 | 14 | -- is there a better way to do this? 15 | local function parse_color_as_rgb(color) 16 | -- tailwind gives us integers for rgb values and a float [0,1] for the alpha value 17 | local r, g, b, a 18 | 19 | -- parse rgb 20 | r, g, b = color:match("^rgb%((%d+), (%d+), (%d+)%)$") 21 | if r and g and b then 22 | return string.format("#%02X%02X%02X", tonumber(r), tonumber(g), tonumber(b)), 100 23 | end 24 | 25 | -- parse rgba 26 | r, g, b, a = color:match("^rgba%((%d+), (%d+), (%d+), (.+)%)$") 27 | if r and g and b and a then 28 | return string.format("#%02X%02X%02X", tonumber(r), tonumber(g), tonumber(b)), tonumber(a) * 100 29 | end 30 | end 31 | 32 | local function parse_color_as_hex(color) 33 | local hex = color:match("^#%x%x%x%x%x%x%x?%x?$") 34 | local alpha = 100 35 | 36 | if hex ~= nil and hex:len() > 7 then 37 | alpha = tonumber(hex:sub(8, 10), 16) / 255 * 100 38 | hex = hex:sub(0, 7) 39 | end 40 | 41 | return hex, alpha 42 | end 43 | 44 | local function parse_color(color) 45 | local hex, alpha = parse_color_as_hex(color) 46 | if hex == nil then 47 | hex, alpha = parse_color_as_rgb(color) 48 | end 49 | 50 | return hex, alpha 51 | end 52 | 53 | local M = {} 54 | 55 | M.setup = function(options) 56 | if options == nil then 57 | return 58 | end 59 | 60 | for k, v in pairs(options) do 61 | config[k] = v 62 | end 63 | end 64 | 65 | M.format = function(entry, item) 66 | if item.kind ~= "Color" then 67 | return item 68 | end 69 | 70 | local entryItem = entry:get_completion_item() 71 | -- is this nil check necessary? 72 | if entryItem == nil then 73 | return item 74 | end 75 | 76 | local doc = entryItem.documentation 77 | if doc == nil or type(doc) ~= "string" then 78 | return item 79 | end 80 | 81 | local hex, alpha = parse_color(doc) 82 | if hex == nil then 83 | return item 84 | end 85 | 86 | local opts = config.format(hex, entry, item) 87 | 88 | local hl_group = "cmp_tailwind_colors_" .. hex:sub(2) .. alpha 89 | if vim.fn.hlexists(hl_group) == 0 then 90 | local hl_opts = { fg = opts.fg, bg = opts.bg } 91 | if config.enable_alpha then 92 | hl_opts.blend = vim.fn.float2nr(vim.fn.round(100 - alpha)) 93 | end 94 | vim.api.nvim_set_hl(0, hl_group, hl_opts) 95 | end 96 | 97 | item.kind_hl_group = hl_group 98 | if opts.text ~= nil then 99 | item.kind = opts.text 100 | end 101 | 102 | return item 103 | end 104 | 105 | return M 106 | --------------------------------------------------------------------------------