diff --git a/lua/catppuccin/core/integrations/native_lsp.lua b/lua/catppuccin/core/integrations/native_lsp.lua index 0a59c19..ecaea16 100644 --- a/lua/catppuccin/core/integrations/native_lsp.lua +++ b/lua/catppuccin/core/integrations/native_lsp.lua @@ -1,5 +1,5 @@ local M = {} -local util = require("catppuccin.utils.util") +local ucolors = require("catppuccin.utils.colors") function M.get(cp) @@ -20,11 +20,11 @@ function M.get(cp) LspReferenceRead = { bg = cp.surface1 }, -- used for highlighting "read" references LspReferenceWrite = { bg = cp.surface1 }, -- used for highlighting "write" references -- hightlight diagnostics in numberline - DiagnosticError = { bg = util.darken(error, darkening_percentage, cp.base), fg = error, style = virtual_text.errors }, -- Used as the mantle highlight group. Other Diagnostic highlights link to this by default - DiagnosticWarn = { bg = util.darken(warning, darkening_percentage, cp.base), fg = warning, style = virtual_text.warnings }, -- Used as the mantle highlight group. Other Diagnostic highlights link to this by default - DiagnosticInfo = { bg = util.darken(info, darkening_percentage, cp.base), fg = info, style = virtual_text.information }, -- Used as the mantle highlight group. Other Diagnostic highlights link to this by default - DiagnosticHint = { bg = util.darken(hint, darkening_percentage, cp.base), fg = hint, style = virtual_text.hints }, -- Used as the mantle highlight group. Other Diagnostic highlights link to this by default - -- util. + DiagnosticError = { bg = ucolors.darken(error, darkening_percentage, cp.base), fg = error, style = virtual_text.errors }, -- Used as the mantle highlight group. Other Diagnostic highlights link to this by default + DiagnosticWarn = { bg = ucolors.darken(warning, darkening_percentage, cp.base), fg = warning, style = virtual_text.warnings }, -- Used as the mantle highlight group. Other Diagnostic highlights link to this by default + DiagnosticInfo = { bg = ucolors.darken(info, darkening_percentage, cp.base), fg = info, style = virtual_text.information }, -- Used as the mantle highlight group. Other Diagnostic highlights link to this by default + DiagnosticHint = { bg = ucolors.darken(hint, darkening_percentage, cp.base), fg = hint, style = virtual_text.hints }, -- Used as the mantle highlight group. Other Diagnostic highlights link to this by default + -- ucolors. -- for nvim nightly DiagnosticUnderlineError = { style = underlines.errors, sp = error }, diff --git a/lua/catppuccin/core/mapper.lua b/lua/catppuccin/core/mapper.lua index 10d2571..5b9ce73 100644 --- a/lua/catppuccin/core/mapper.lua +++ b/lua/catppuccin/core/mapper.lua @@ -1,5 +1,4 @@ -local colors_util = require("catppuccin.utils.colors") -local util = require("catppuccin.utils.util") +local ucolors = require("catppuccin.utils.colors") local cp local M = {} @@ -10,7 +9,7 @@ local function get_properties() background = "dark", } - if colors_util.assert_brightness(cp.base) then + if ucolors.assert_brightness(cp.base) then props["background"] = "light" end @@ -28,7 +27,12 @@ local function get_base() lCursor = { fg = cp.base, bg = cp.text }, -- the character under the cursor when |language-mapping| is used (see 'guicursor') CursorIM = { fg = cp.base, bg = cp.text }, -- like Cursor, but used when in IME mode |CursorIM| CursorColumn = { bg = cp.mantle }, -- Screen-column at the cursor, when 'cursorcolumn' is secp. - CursorLine = { bg = colors_util.vary_color({latte = util.lighten(cp.mantle, 0.70, cp.base)}, util.darken(cp.surface0, 0.64, cp.base)) }, -- Screen-line at the cursor, when 'cursorline' is secp. Low-priority if forecrust (ctermfg OR guifg) is not secp. + CursorLine = { + bg = ucolors.vary_color( + { latte = ucolors.lighten(cp.mantle, 0.70, cp.base) }, + ucolors.darken(cp.surface0, 0.64, cp.base) + ), + }, -- Screen-line at the cursor, when 'cursorline' is secp. Low-priority if forecrust (ctermfg OR guifg) is not secp. Directory = { fg = cp.blue }, -- directory names (and other special names in listings) EndOfBuffer = { fg = cp.base }, -- filler lines (~) after the end of the buffer. By default, this is highlighted like |hl-NonText|. ErrorMsg = { fg = cp.red, style = "bold,italic" }, -- error messages on the command line @@ -38,7 +42,7 @@ local function get_base() SignColumn = { bg = cnf.transparent_background and cp.none or cp.base, fg = cp.surface1 }, -- column where |signs| are displayed SignColumnSB = { bg = cp.crust, fg = cp.surface1 }, -- column where |signs| are displayed Substitute = { bg = cp.surface1, fg = cp.pink }, -- |:substitute| replacement text highlighting - LineNr = { fg = cp.surface1 }, -- colors_util.vary_color({latte = cp.crust}, cp.surface1) }, -- Line number for ":number" and ":#" commands, and when 'number' or 'relativenumber' option is secp. + LineNr = { fg = cp.surface1 }, -- ucolors.vary_color({latte = cp.crust}, cp.surface1) }, -- Line number for ":number" and ":#" commands, and when 'number' or 'relativenumber' option is secp. CursorLineNr = { fg = cp.lavender }, -- Like LineNr when 'cursorline' or 'relativenumber' is set for the cursor line. highlights the number in numberline. MatchParen = { fg = cp.peach, style = "bold" }, -- The character under the cursor or just before it, if it is a paired bracket, and its match. |pi_paren.txt| ModeMsg = { fg = cp.text, style = "bold" }, -- 'showmode' message (e.g., "-- INSERT -- ") diff --git a/lua/catppuccin/core/palettes/frappe.lua b/lua/catppuccin/core/palettes/frappe.lua index 3f58b4a..fa8c218 100644 --- a/lua/catppuccin/core/palettes/frappe.lua +++ b/lua/catppuccin/core/palettes/frappe.lua @@ -19,7 +19,7 @@ local color_palette = { blue = "#8CAAEE", lavender = "#BABBF1", - text = "#C6D0F5", + text = "#D1D9F8", subtext1 = "#B5BFE2", subtext0 = "#A5ADCE", overlay2 = "#949CBB", diff --git a/lua/catppuccin/ui/cli.lua b/lua/catppuccin/ui/cli.lua new file mode 100644 index 0000000..9b297dc --- /dev/null +++ b/lua/catppuccin/ui/cli.lua @@ -0,0 +1,12 @@ +local M = {} + +function M.flavour_completion() + return vim.tbl_keys(require("catppuccin.utils.data").set_of({ + "latte", + "frappe", + "macchiato", + "mocha", + })) +end + +return M diff --git a/lua/catppuccin/utils/colors.lua b/lua/catppuccin/utils/colors.lua index 4d53851..f067818 100644 --- a/lua/catppuccin/utils/colors.lua +++ b/lua/catppuccin/utils/colors.lua @@ -1,6 +1,88 @@ local M = {} -local function color_is_bright(r, g, b) +local hsluv = require("catppuccin.utils.hsluv") + +---@param hex_str string hexadecimal value of a color +local hex_to_rgb = function(hex_str) + local hex = "[abcdef0-9][abcdef0-9]" + local pat = "^#(" .. hex .. ")(" .. hex .. ")(" .. hex .. ")$" + hex_str = string.lower(hex_str) + + assert(string.find(hex_str, pat) ~= nil, "hex_to_rgb: invalid hex_str: " .. tostring(hex_str)) + + local red, green, blue = string.match(hex_str, pat) + return { tonumber(red, 16), tonumber(green, 16), tonumber(blue, 16) } +end + +---@param fg string forecrust color +---@param bg string background color +---@param alpha number number between 0 and 1. 0 results in bg, 1 results in fg +function M.blend(fg, bg, alpha) + bg = hex_to_rgb(bg) + fg = hex_to_rgb(fg) + + local blendChannel = function(i) + local ret = (alpha * fg[i] + ((1 - alpha) * bg[i])) + return math.floor(math.min(math.max(0, ret), 255) + 0.5) + end + + return string.format("#%02X%02X%02X", blendChannel(1), blendChannel(2), blendChannel(3)) +end + +function M.darken(hex, amount, bg) + return M.blend(hex, bg or M.bg, math.abs(amount)) +end + +function M.lighten(hex, amount, fg) + return M.blend(hex, fg or M.fg, math.abs(amount)) +end + +function M.brighten(color, percentage) + local hsl = hsluv.hex_to_hsluv(color) + local larpSpace = 100 - hsl[3] + if percentage < 0 then + larpSpace = hsl[3] + end + hsl[3] = hsl[3] + larpSpace * percentage + return hsluv.hsluv_to_hex(hsl) +end + +function M.invertColor(color) + if color ~= "NONE" then + local hsl = hsluv.hex_to_hsluv(color) + hsl[3] = 100 - hsl[3] + if hsl[3] < 40 then + hsl[3] = hsl[3] + (100 - hsl[3]) * M.day_brightness + end + return hsluv.hsluv_to_hex(hsl) + end + return color +end + +function M.string_to_color(colors, value, default) + if not value or value == "" then + return default + end + + -- If the value is a hex color code then return it + local hex = "[abcdef0-9][abcdef0-9]" + local pat = "^#" .. hex .. hex .. hex .. "$" + if string.match(value, pat) then + return value + end + + local acceptable_colors = { "black", "red", "green", "blue", "magenta", "cyan", "text", "orange", "pink" } + for _, ac in ipairs(acceptable_colors) do + if string.match(value, ac) then + return colors[value] + end + end + + -- Did not match anything to return default + return default +end + +function M.color_is_bright(r, g, b) -- Counting the perceptive luminance - human eye favors green color local luminance = (0.299 * r + 0.587 * g + 0.114 * b) / 255 if luminance > 0.5 then @@ -20,7 +102,7 @@ function M.assert_brightness(color) local g = M.hex2rgb(string.sub(hex, 3, 4)) local b = M.hex2rgb(string.sub(hex, 5, 6)) - if color_is_bright(tonumber(r), tonumber(g), tonumber(b)) == true then + if M.color_is_bright(tonumber(r), tonumber(g), tonumber(b)) == true then return true -- bright end diff --git a/lua/catppuccin/utils/data.lua b/lua/catppuccin/utils/data.lua index 241f04f..3be43a8 100644 --- a/lua/catppuccin/utils/data.lua +++ b/lua/catppuccin/utils/data.lua @@ -8,4 +8,13 @@ function M.set_of(list) return set end +-- https://www.codegrepper.com/code-examples/lua/lua+split+string+on+comma +function M.split(s, delimiter) + local result = {} + for match in (s..delimiter):gmatch("(.-)"..delimiter) do + table.insert(result, match) + end + return result +end + return M diff --git a/lua/catppuccin/utils/os.lua b/lua/catppuccin/utils/os.lua new file mode 100644 index 0000000..e69de29 diff --git a/lua/catppuccin/utils/util.lua b/lua/catppuccin/utils/util.lua index c65324a..e8a3ca7 100644 --- a/lua/catppuccin/utils/util.lua +++ b/lua/catppuccin/utils/util.lua @@ -1,107 +1,45 @@ -local hsluv = require("catppuccin.utils.hsluv") +local udata = require("catppuccin.utils.data") local g = vim.g -local o = vim.o - local util = {} util.bg = "#000000" util.fg = "#ffffff" util.day_brightness = 0.3 ----@param hex_str string hexadecimal value of a color -local hex_to_rgb = function(hex_str) - local hex = "[abcdef0-9][abcdef0-9]" - local pat = "^#(" .. hex .. ")(" .. hex .. ")(" .. hex .. ")$" - hex_str = string.lower(hex_str) - - assert(string.find(hex_str, pat) ~= nil, "hex_to_rgb: invalid hex_str: " .. tostring(hex_str)) - - local red, green, blue = string.match(hex_str, pat) - return { tonumber(red, 16), tonumber(green, 16), tonumber(blue, 16) } -end - ----@param fg string forecrust color ----@param bg string background color ----@param alpha number number between 0 and 1. 0 results in bg, 1 results in fg -function util.blend(fg, bg, alpha) - bg = hex_to_rgb(bg) - fg = hex_to_rgb(fg) - - local blendChannel = function(i) - local ret = (alpha * fg[i] + ((1 - alpha) * bg[i])) - return math.floor(math.min(math.max(0, ret), 255) + 0.5) - end +local has_nvim07 = vim.fn.has("nvim-0.7") - return string.format("#%02X%02X%02X", blendChannel(1), blendChannel(2), blendChannel(3)) -end - -function util.darken(hex, amount, bg) - return util.blend(hex, bg or util.bg, math.abs(amount)) -end - -function util.lighten(hex, amount, fg) - return util.blend(hex, fg or util.fg, math.abs(amount)) -end - -function util.brighten(color, percentage) - local hsl = hsluv.hex_to_hsluv(color) - local larpSpace = 100 - hsl[3] - if percentage < 0 then - larpSpace = hsl[3] - end - hsl[3] = hsl[3] + larpSpace * percentage - return hsluv.hsluv_to_hex(hsl) -end - -function util.invertColor(color) - if color ~= "NONE" then - local hsl = hsluv.hex_to_hsluv(color) - hsl[3] = 100 - hsl[3] - if hsl[3] < 40 then - hsl[3] = hsl[3] + (100 - hsl[3]) * util.day_brightness +function util.highlight(group, color) + if has_nvim07 then + if color.link then + vim.api.nvim_set_hl(0, group, { + link = color.link, + }) + else + if color.style then + if color.style ~= "NONE" then + for _, style in pairs(udata.split(color.style, ",")) do + color[style] = true + end + end + end + + color.style = nil + vim.api.nvim_set_hl(0, group, color) end - return hsluv.hsluv_to_hex(hsl) - end - return color -end - -function util.string_to_color(colors, value, default) - if not value or value == "" then - return default - end - - -- If the value is a hex color code then return it - local hex = "[abcdef0-9][abcdef0-9]" - local pat = "^#" .. hex .. hex .. hex .. "$" - if string.match(value, pat) then - return value - end - - local acceptable_colors = { "black", "red", "green", "blue", "magenta", "cyan", "text", "orange", "pink" } - for _, ac in ipairs(acceptable_colors) do - if string.match(value, ac) then - return colors[value] + else + -- Doc: :h highlight-gui + local style = color.style and "gui=" .. color.style or "gui=NONE" + local fg = color.fg and "guifg=" .. color.fg or "guifg=NONE" + local bg = color.bg and "guibg=" .. color.bg or "guibg=NONE" + local sp = color.sp and "guisp=" .. color.sp or "" + local blend = color.blend and "blend=" .. color.blend or "" + local hl = "highlight " .. group .. " " .. style .. " " .. fg .. " " .. bg .. " " .. sp .. " " .. blend + vim.cmd(hl) + if color.link then + vim.cmd("highlight! link " .. group .. " " .. color.link) end end - - -- Did not match anything to return default - return default -end - -function util.highlight(group, color) - -- Doc: :h highlight-gui - local style = color.style and "gui=" .. color.style or "gui=NONE" - local fg = color.fg and "guifg=" .. color.fg or "guifg=NONE" - local bg = color.bg and "guibg=" .. color.bg or "guibg=NONE" - local sp = color.sp and "guisp=" .. color.sp or "" - local blend = color.blend and "blend=" .. color.blend or "" - local hl = "highlight " .. group .. " " .. style .. " " .. fg .. " " .. bg .. " " .. sp .. " " .. blend - - vim.cmd(hl) - if color.link then - vim.cmd("highlight! link " .. group .. " " .. color.link) - end end function util.syntax(tbl)