diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000..a13612c --- /dev/null +++ b/.editorconfig @@ -0,0 +1,20 @@ +# EditorConfig helps developers define and maintain consistent +# coding styles between different editors and IDEs +# EditorConfig is awesome: https://EditorConfig.org + +root = true + + +[*] +end_of_line = lf +charset = utf-8 +insert_final_newline = true +indent_style = tabs +indent_size = 4 + +[*.txt] +indent_style = tab +indent_size = 4 + +[*.{diff,md}] +trim_trailing_whitespace = false diff --git a/colors/catppuccino.vim b/colors/catppuccino.vim new file mode 100644 index 0000000..9cca3e8 --- /dev/null +++ b/colors/catppuccino.vim @@ -0,0 +1,12 @@ +lua << EOF +-- clear cache so this reloads changes. +package.loaded['catppuccino'] = nil +package.loaded['catppuccino.utils.util'] = nil +package.loaded['catppuccino.utils.hsluv'] = nil +package.loaded["catppuccino.color_schemes.catppuccino"] = nil +package.loaded['catppuccino.config'] = nil +package.loaded['catppuccino.main'] = nil +package.loaded['catppuccino.core.mapper'] = nil + +require('catppuccino').set() +EOF diff --git a/lua/catppuccino/color_schemes/catppuccino.lua b/lua/catppuccino/color_schemes/catppuccino.lua new file mode 100644 index 0000000..6da884d --- /dev/null +++ b/lua/catppuccino/color_schemes/catppuccino.lua @@ -0,0 +1,104 @@ +local util = require("catppuccino.utils.util") + +local M = {} + +function M.setup(config) + config = config or require("nightfox.config") + + -- References: + -- https://coolors.co/e63946-f1faee-a8dadc-457b9d-1d3557 + -- https://coolors.co/f4f1de-e07a5f-3d405b-81b29a-f2cc8f + -- https://coolors.co/264653-2a9d8f-e9c46a-f4a261-e76f51 + + -- stylua: ignore + local colors = { + none = "NONE", + bg = "#0e171c", + fg = "#CDCECF", + fg_gutter = "#3b4261", + black = "#393b44", + red = "#c94f6d", + green = "#81B29A", + yellow = "#dbc074", + blue = "#719cd6", + magenta = "#9D79D6", + cyan = "#63cdcf", + white = "#dfdfe0", + orange = "#F4A261", + pink = "#D67AD2", + black_br = "#7f8c98", + red_br = "#D6616B", + green_br = "#58cd8b", + yellow_br = "#FFE37E", + blue_br = "#84CEE4", + magenta_br = "#B8A1E3", + cyan_br = "#59F0FF", + white_br = "#F2F2F2", + orange_br = "#F6A878", + pink_br = "#DF97DB", + comment = "#526175", + git = { + add = "#70a288", + change = "#A58155", + delete = "#904A6A", + conflict = "#C07A6D" + }, + gitSigns = { + add = "#164846", + change = "#394b70", + delete = "#823c41" + } + } + + util.bg = colors.bg + + colors.bg_alt = util.darken(colors.bg, 0.75, "#000000") + colors.bg_highlight = util.brighten(colors.bg, 0.10) + + colors.fg_alt = util.darken(colors.fg, 0.80, "#000000") + + colors.diff = { + add = util.darken(colors.green, 0.15), + delete = util.darken(colors.red, 0.15), + change = util.darken(colors.blue, 0.15), + text = colors.blue + } + + colors.gitSigns = { + add = util.brighten(colors.gitSigns.add, 0.2), + change = util.brighten(colors.gitSigns.change, 0.2), + delete = util.brighten(colors.gitSigns.delete, 0.2) + } + + colors.git.ignore = colors.black + colors.black = util.darken(colors.bg, 0.8, "#000000") + colors.border_highlight = colors.blue + colors.border = colors.black + + -- Popups and statusline always get a dark background + colors.bg_popup = colors.bg_alt + colors.bg_statusline = colors.bg_alt + + -- Sidebar and Floats are configurable + -- colors.bg_sidebar = config.darkSidebar and colors.bg_alt or colors.bg + -- colors.bg_float = config.darkFloat and colors.bg_alt or colors.bg + colors.bg_sidebar = colors.bg_alt + colors.bg_float = colors.bg_alt + + colors.bg_visual = util.darken(colors.blue, 0.2) + colors.bg_search = util.darken(colors.cyan, 0.3) + colors.fg_sidebar = colors.fg_alt + + colors.error = colors.red + colors.warning = colors.yellow + colors.info = colors.blue + colors.hint = colors.cyan + + colors.variable = colors.white + + util.color_overrides(colors, config) + + return colors +end + +return M diff --git a/lua/catppuccino/config.lua b/lua/catppuccino/config.lua new file mode 100644 index 0000000..365e283 --- /dev/null +++ b/lua/catppuccino/config.lua @@ -0,0 +1,42 @@ +---@class Config +local config = {} + +config.options = { + colorscheme = "catppuccino", + transparency = false, + styles = { + comments = "italic", + fuctions = "italic", + keywords = "italic", + strings = "NONE", + variables = "NONE", + }, + integrations = { + treesitter = true, + native_lsp = true, + lsp_trouble = false, + illuminate = false, + diff = false, + lsp_saga = false, + neogit = false, + gitgutter = false, + gitsigns = false, + telescope = false, + nvimtree = false, + fern = false, + dashboard = false, + which_key = false, + bufferline = false, + barbar = false, + sneak = false, + hop = false, + + } +} + +function config.set_options(opts) + opts = opts or {} + config.options = vim.tbl_deep_extend("force", config.options, opts) +end + +return config diff --git a/lua/catppuccino/core/mapper.lua b/lua/catppuccino/core/mapper.lua new file mode 100644 index 0000000..d93f170 --- /dev/null +++ b/lua/catppuccino/core/mapper.lua @@ -0,0 +1,370 @@ +local util = require("catppuccino.utils.util") +local opts = require("catppuccino.config").options + +local M = {} + +function M.apply() + local theme = {} + local t = require("catppuccino.color_schemes." .. opts.colorscheme) + + theme.base = { + Comment = {fg = t.comment, style = opts.styles.comments}, -- any comment + ColorColumn = {bg = t.bg_visual}, -- used for the columns set with 'colorcolumn' + Conceal = {fg = t.black}, -- placeholder characters substituted for concealed text (see 'conceallevel') + Cursor = {fg = t.bg, bg = t.fg}, -- character under the cursor + lCursor = {fg = t.bg, bg = t.fg}, -- the character under the cursor when |language-mapping| is used (see 'guicursor') + CursorIM = {fg = t.bg, bg = t.fg}, -- like Cursor, but used when in IME mode |CursorIM| + CursorColumn = {bg = t.bg_highlight}, -- Screen-column at the cursor, when 'cursorcolumn' is set. + CursorLine = {bg = t.bg_highlight}, -- Screen-line at the cursor, when 'cursorline' is set. Low-priority if foreground (ctermfg OR guifg) is not set. + Directory = {fg = t.blue}, -- directory names (and other special names in listings) + DiffAdd = {bg = t.diff.add}, -- diff mode: Added line |diff.txt| + DiffChange = {bg = t.diff.change}, -- diff mode: Changed line |diff.txt| + DiffDelete = {bg = t.diff.delete}, -- diff mode: Deleted line |diff.txt| + DiffText = {bg = t.diff.text}, -- diff mode: Changed text within a changed line |diff.txt| + EndOfBuffer = {fg = t.bg}, -- filler lines (~) after the end of the buffer. By default, this is highlighted like |hl-NonText|. + TermCursor = {}, -- cursor in a focused terminal + TermCursorNC = {}, -- cursor in an unfocused terminal + ErrorMsg = {fg = t.error}, -- error messages on the command line + VertSplit = {fg = t.border}, -- the column separating vertically split windows + Folded = {fg = t.blue, bg = t.fg_gutter}, -- line used for closed folds + FoldColumn = {bg = t.bg, fg = t.comment}, -- 'foldcolumn' + SignColumn = {bg = opts.transparency and t.none or t.bg, fg = t.fg_gutter}, -- column where |signs| are displayed + SignColumnSB = {bg = t.bg_sidebar, fg = t.fg_gutter}, -- column where |signs| are displayed + Substitute = {bg = t.red, fg = t.black}, -- |:substitute| replacement text highlighting + LineNr = {fg = t.fg_gutter}, -- Line number for ":number" and ":#" commands, and when 'number' or 'relativenumber' option is set. + CursorLineNr = {fg = t.fg_alt}, -- Like LineNr when 'cursorline' or 'relativenumber' is set for the cursor line. + MatchParen = {fg = t.orange, 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 = t.fg_alt, style = "bold"}, -- 'showmode' message (e.g., "-- INSERT -- ") + MsgArea = {fg = t.fg_alt}, -- Area for messages and cmdline + MsgSeparator = {}, -- Separator for scrolled messages, `msgsep` flag of 'display' + MoreMsg = {fg = t.blue}, -- |more-prompt| + NonText = {fg = t.comment}, -- '@' at the end of the window, characters from 'showbreak' and other characters that do not really exist in the text (e.g., ">" displayed when a double-wide character doesn't fit at the end of the line). See also |hl-EndOfBuffer|. + Normal = {fg = t.fg, bg = opts.transparency and t.none or t.bg}, -- normal text + NormalNC = {fg = t.fg, bg = opts.transparency and t.none or t.bg}, -- normal text in non-current windows + NormalSB = {fg = t.fg_sidebar, bg = t.bg_sidebar}, -- normal text in non-current windows + NormalFloat = {fg = t.fg, bg = t.bg_float}, -- Normal text in floating windows. + FloatBorder = {fg = t.border_highlight}, + Pmenu = {bg = t.bg_popup, fg = t.fg}, -- Popup menu: normal item. + PmenuSel = {fg = t.cyan, bg = util.darken(t.fg_gutter, 0.8)}, -- Popup menu: selected item. + PmenuSbar = {bg = util.lighten(t.bg_popup, 0.95)}, -- Popup menu: scrollbar. + PmenuThumb = {bg = t.fg_gutter}, -- Popup menu: Thumb of the scrollbar. + Question = {fg = t.blue}, -- |hit-enter| prompt and yes/no questions + QuickFixLine = {bg = t.bg_visual, style = "bold"}, -- Current |quickfix| item in the quickfix window. Combined with |hl-CursorLine| when the cursor is there. + Search = {bg = t.bg_search, fg = t.fg}, -- Last search pattern highlighting (see 'hlsearch'). Also used for similar items that need to stand out. + IncSearch = {bg = t.cyan, fg = t.black}, -- 'incsearch' highlighting; also used for the text replaced with ":s///c" + SpecialKey = {fg = t.black}, -- Unprintable characters: text displayed differently from what it really is. But not 'listchars' whitespace. |hl-Whitespace| + SpellBad = {sp = t.error, style = "undercurl"}, -- Word that is not recognized by the spellchecker. |spell| Combined with the highlighting used otherwise. + SpellCap = {sp = t.warning, style = "undercurl"}, -- Word that should start with a capital. |spell| Combined with the highlighting used otherwise. + SpellLocal = {sp = t.info, style = "undercurl"}, -- Word that is recognized by the spellchecker as one that is used in another region. |spell| Combined with the highlighting used otherwise. + SpellRare = {sp = t.hint, style = "undercurl"}, -- Word that is recognized by the spellchecker as one that is hardly ever used. |spell| Combined with the highlighting used otherwise. + StatusLine = {fg = t.fg_sidebar, bg = t.bg_statusline}, -- status line of current window + StatusLineNC = {fg = t.fg_gutter, bg = t.bg_statusline}, -- status lines of not-current windows Note: if this is equal to "StatusLine" Vim will use "^^^" in the status line of the current window. + TabLine = {bg = t.bg_statusline, fg = t.fg_gutter}, -- tab pages line, not active tab page label + TabLineFill = {bg = t.black}, -- tab pages line, where there are no labels + TabLineSel = {fg = t.fg_alt, bg = t.fg_gutter}, -- tab pages line, active tab page label + Title = {fg = t.blue, style = "bold"}, -- titles for output from ":set all", ":autocmd" ett. + Visual = {bg = t.bg_visual}, -- Visual mode selection + VisualNOS = {bg = t.bg_visual}, -- Visual mode selection when vim is "Not Owning the Selection". + WarningMsg = {fg = t.warning}, -- warning messages + Whitespace = {fg = t.fg_gutter}, -- "nbsp", "space", "tab" and "trail" in 'listchars' + WildMenu = {bg = t.bg_visual}, -- current match in 'wildmenu' completion + -- These groups are not listed as default vim groups, + -- but they are defacto standard group names for syntax highlighting. + -- commented out groups should chain up to their "preferred" group by + -- default, + -- Uncomment and edit if you want more specific syntax highlighting. + + Constant = {fg = t.orange}, -- (preferred) any constant + String = {fg = t.green, style = opts.styles.strings}, -- a string constant: "this is a string" + Character = {fg = t.green}, -- a character constant: 'c', '\n' + Number = {fg = t.orange_br}, -- a number constant: 234, 0xff + Float = {fg = t.orange_br}, -- a floating point constant: 2.3e10 + Boolean = {fg = t.orange_br}, -- a boolean constant: TRUE, false + Identifier = {fg = t.cyan, style = opts.styles.variables}, -- (preferred) any variable name + Function = {fg = t.blue, style = opts.styles.fuctions}, -- function name (also: methods for classes) + Statement = {fg = t.magenta_br}, -- (preferred) any statement + Conditional = {fg = t.magenta_br}, -- if, then, else, endif, switch, ett. + Repeat = {fg = t.magenta_br}, -- for, do, while, ett. + Label = {fg = t.magenta_br}, -- case, default, ett. + Operator = {fg = t.fg_alt}, -- "sizeof", "+", "*", ett. + Keyword = {fg = t.magenta, style = opts.styles.keywords}, -- any other keyword + -- Exception = { }, -- try, catch, throw + + PreProc = {fg = t.pink}, -- (preferred) generic Preprocessor + Include = {fg = t.pink}, -- preprocessor #include + -- Define = { }, -- preprocessor #define + -- Macro = { }, -- same as Define + -- PreCondit = { }, -- preprocessor #if, #else, #endif, ett. + + Type = {fg = t.yellow}, -- (preferred) int, long, char, ett. + StorageClass = {fg = t.yellow}, -- static, register, volatile, ett. + Structure = {fg = t.yellow}, -- struct, union, enum, ett. + Typedef = {fg = t.yellow}, -- A typedef + Special = {fg = t.blue}, -- (preferred) any special symbol + -- SpecialChar = { }, -- special character in a constant + -- Tag = { }, -- you can use CTRL-] on this + -- Delimiter = { }, -- character that needs attention + -- SpecialComment= { }, -- special things inside a comment + -- Debug = { }, -- debugging statements + + Underlined = {style = "underline"}, -- (preferred) text that stands out, HTML links + Bold = {style = "bold"}, + Italic = {style = "italic"}, + -- ("Ignore", below, may be invisible...) + -- Ignore = { }, -- (preferred) left blank, hidden |hl-Ignore| + + Error = {fg = t.error}, -- (preferred) any erroneous construct + Todo = {bg = t.yellow, fg = t.bg}, -- (preferred) anything that needs extra attention; mostly the keywords TODO FIXME and XXX + qfLineNr = {fg = t.yellow}, + qfFileName = {fg = t.blue}, + htmlH1 = {fg = t.magenta, style = "bold"}, + htmlH2 = {fg = t.blue, style = "bold"}, + -- mkdHeading = { fg = t.orange, style = "bold" }, + -- mkdCode = { bg = t.terminal_black, fg = t.fg }, + mkdCodeDelimiter = {bg = t.terminal_black, fg = t.fg}, + mkdCodeStart = {fg = t.cyan, style = "bold"}, + mkdCodeEnd = {fg = t.cyan, style = "bold"}, + -- mkdLink = { fg = t.blue, style = "underline" }, + + markdownHeadingDelimiter = {fg = t.orange, style = "bold"}, + markdownCode = {fg = t.cyan}, + markdownCodeBlock = {fg = t.cyan}, + markdownH1 = {fg = t.magenta, style = "bold"}, + markdownH2 = {fg = t.blue, style = "bold"}, + markdownLinkText = {fg = t.blue, style = "underline"}, + debugPC = {bg = t.bg_sidebar}, -- used for highlighting the current line in terminal-debug + debugBreakpoint = {bg = util.darken(t.info, 0.1), fg = t.info}, -- used for breakpoint colors in terminal-debug + -- These groups are for the native LSP client. Some other LSP clients may + -- use these groups, or use their own. Consult your LSP client's + -- documentation. + LspReferenceText = {bg = t.fg_gutter}, -- used for highlighting "text" references + LspReferenceRead = {bg = t.fg_gutter}, -- used for highlighting "read" references + LspReferenceWrite = {bg = t.fg_gutter}, -- used for highlighting "write" references + LspDiagnosticsDefaultError = {fg = t.error}, -- Used as the base highlight group. Other LspDiagnostic highlights link to this by default (except Underline) + LspDiagnosticsDefaultWarning = {fg = t.warning}, -- Used as the base highlight group. Other LspDiagnostic highlights link to this by default (except Underline) + LspDiagnosticsDefaultInformation = {fg = t.info}, -- Used as the base highlight group. Other LspDiagnostic highlights link to this by default (except Underline) + LspDiagnosticsDefaultHint = {fg = t.hint}, -- Used as the base highlight group. Other LspDiagnostic highlights link to this by default (except Underline) + LspDiagnosticsVirtualTextError = {bg = util.darken(t.error, 0.1), fg = t.error}, -- Used for "Error" diagnostic virtual text + LspDiagnosticsVirtualTextWarning = {bg = util.darken(t.warning, 0.1), fg = t.warning}, -- Used for "Warning" diagnostic virtual text + LspDiagnosticsVirtualTextInformation = {bg = util.darken(t.info, 0.1), fg = t.info}, -- Used for "Information" diagnostic virtual text + LspDiagnosticsVirtualTextHint = {bg = util.darken(t.hint, 0.1), fg = t.hint}, -- Used for "Hint" diagnostic virtual text + LspDiagnosticsUnderlineError = {style = "undercurl", sp = t.error}, -- Used to underline "Error" diagnostics + LspDiagnosticsUnderlineWarning = {style = "undercurl", sp = t.warning}, -- Used to underline "Warning" diagnostics + LspDiagnosticsUnderlineInformation = {style = "undercurl", sp = t.info}, -- Used to underline "Information" diagnostics + LspDiagnosticsUnderlineHint = {style = "undercurl", sp = t.hint}, -- Used to underline "Hint" diagnostics + LspSignatureActiveParameter = {fg = t.orange}, + -- LspDiagnosticsFloatingError = { }, -- Used to color "Error" diagnostic messages in diagnostics float + -- LspDiagnosticsFloatingWarning = { }, -- Used to color "Warning" diagnostic messages in diagnostics float + -- LspDiagnosticsFloatingInformation = { }, -- Used to color "Information" diagnostic messages in diagnostics float + -- LspDiagnosticsFloatingHint = { }, -- Used to color "Hint" diagnostic messages in diagnostics float + + -- LspDiagnosticsSignError = { }, -- Used for "Error" signs in sign column + -- LspDiagnosticsSignWarning = { }, -- Used for "Warning" signs in sign column + -- LspDiagnosticsSignInformation = { }, -- Used for "Information" signs in sign column + -- LspDiagnosticsSignHint = { }, -- Used for "Hint" signs in sign column + + -- These groups are for the neovim tree-sitter highlights. + -- As of writing, tree-sitter support is a WIP, group names may change. + -- By default, most of these groups link to an appropriate Vim group, + -- TSError -> Error for example, so you do not have to define these unless + -- you explicitly want to support Treesitter's improved syntax awareness. + + -- TSAnnotation = { }; -- For C++/Dart attributes, annotations that can be attached to the code to denote some kind of meta information. + -- TSAttribute = { }; -- (unstable) TODO: docs + -- TSBoolean = { }; -- For booleans. + -- TSCharacter = { }; -- For characters. + -- TSComment = { }; -- For comment blocks. + TSNote = {fg = t.bg, bg = t.info}, + TSWarning = {fg = t.bg, bg = t.warning}, + TSDanger = {fg = t.bg, bg = t.error}, + TSConstructor = {fg = t.magenta}, -- For constructor calls and definitions: `= { }` in Lua, and Java constructors. + -- TSConditional = { }; -- For keywords related to conditionnals. + TSConstant = {fg = t.orange}, -- For constants + TSConstBuiltin = {fg = t.orange_br}, -- For constant that are built in the language: `nil` in Lua. + -- TSConstMacro = { }; -- For constants that are defined by macros: `NULL` in t. + -- TSError = { }; -- For syntax/parser errors. + -- TSException = { }; -- For exception related keywords. + TSField = {fg = t.blue}, -- For fields. + rustTSField = {fg = util.darken(t.white, 0.75)}, -- For fields. + -- TSFloat = { }; -- For floats. + -- TSFunction = { fg = t.fg_gutter }, -- For function (calls and definitions). + TSFuncBuiltin = {fg = t.cyan}, -- For builtin functions: `table.insert` in Lua. + TSFuncMacro = {fg = t.red}, -- For macro defined fuctions (calls and definitions): each `macro_rules` in Rust. + -- TSInclude = { }; -- For includes: `#include` in C, `use` or `extern crate` in Rust, or `require` in Lua. + TSKeyword = {fg = t.magenta, style = opts.styles.keywords}, -- For keywords that don't fall in previous categories. + TSKeywordFunction = {fg = t.magenta, style = opts.styles.fuctions}, -- For keywords used to define a fuction. + TSLabel = {fg = t.blue}, -- For labels: `label:` in C and `:label:` in Lua. + -- TSMethod = { }; -- For method calls and definitions. + TSNamespace = {fg = t.cyan}, -- For identifiers referring to modules and namespaces. + -- TSNone = { }; -- TODO: docs + -- TSNumber = { }; -- For all numbers + TSOperator = {fg = t.fg_alt}, -- For any operator: `+`, but also `->` and `*` in t. + TSParameter = {fg = t.orange_br}, -- For parameters of a function. + -- TSParameterReference= { }; -- For references to parameters of a function. + TSProperty = {fg = t.green}, -- Same as `TSField`. + tomlTSProperty = {fg = t.blue}, -- Differentiates between string and properties + TSPunctDelimiter = {fg = util.string_to_color(c, "", t.fg_alt)}, -- For delimiters ie: `.` + TSPunctBracket = {fg = t.fg_alt}, -- For brackets and parens. + TSPunctSpecial = {fg = t.white}, -- For special punctutation that does not fall in the catagories before. + -- TSRepeat = { }; -- For keywords related to loops. + -- TSString = { }; -- For strings. + TSStringRegex = {fg = t.blue, style = opts.styles.strings}, -- For regexes. + TSStringEscape = {fg = t.magenta, style = opts.styles.strings}, -- For escape characters within a string. + -- TSSymbol = { }; -- For identifiers referring to symbols or atoms. + -- TSType = { }; -- For types. + TSTypeBuiltin = {fg = t.cyan}, -- For builtin types. + TSVariable = {style = opts.styles.variables}, -- Any variable name that does not have another highlight. + TSVariableBuiltin = {fg = t.red}, -- Variable names that are defined by the languages, like `this` or `self`. + -- TSTag = { }; -- Tags like html tag names. + -- TSTagDelimiter = { }; -- Tag delimiter like `<` `>` `/` + -- TSText = { }; -- For strings considered text in a markup language. + TSTextReference = {fg = t.cyan} + -- TSEmphasis = { }; -- For text to be represented with emphasis. + -- TSUnderline = { }; -- For text to be represented with an underline. + -- TSStrike = { }; -- For strikethrough text. + -- TSTitle = { }; -- Text that is part of a title. + -- TSLiteral = { }; -- Literal text. + -- TSURI = { }; -- Any URI like a link or email. + } + + theme.plugins = { + -- LspTrouble + LspTroubleText = {fg = t.fg_alt}, + LspTroubleCount = {fg = t.magenta, bg = t.fg_gutter}, + LspTroubleNormal = {fg = t.fg_sidebar, bg = t.bg_sidebar}, + -- Illuminate + illuminatedWord = {bg = t.fg_gutter}, + illuminatedCurWord = {bg = t.fg_gutter}, + -- diff + diffAdded = {fg = t.git.add}, + diffRemoved = {fg = t.git.delete}, + diffChanged = {fg = t.git.change}, + diffOldFile = {fg = t.yellow}, + diffNewFile = {fg = t.orange}, + diffFile = {fg = t.blue}, + diffLine = {fg = t.comment}, + diffIndexLine = {fg = t.magenta}, + -- Neogit + NeogitBranch = {fg = t.magenta}, + NeogitRemote = {fg = t.pink}, + NeogitHunkHeader = {bg = t.bg_highlight, fg = t.fg}, + NeogitHunkHeaderHighlight = {bg = t.fg_gutter, fg = t.blue}, + NeogitDiffContextHighlight = {bg = util.darken(t.fg_gutter, 0.5), fg = t.fg_alt}, + NeogitDiffDeleteHighlight = {fg = t.git.delete, bg = t.diff.delete}, + NeogitDiffAddHighlight = {fg = t.git.add, bg = t.diff.add}, + -- GitGutter + GitGutterAdd = {fg = t.gitSigns.add}, -- diff mode: Added line |diff.txt| + GitGutterChange = {fg = t.gitSigns.change}, -- diff mode: Changed line |diff.txt| + GitGutterDelete = {fg = t.gitSigns.delete}, -- diff mode: Deleted line |diff.txt| + -- GitSigns + GitSignsAdd = {fg = t.gitSigns.add}, -- diff mode: Added line |diff.txt| + GitSignsChange = {fg = t.gitSigns.change}, -- diff mode: Changed line |diff.txt| + GitSignsDelete = {fg = t.gitSigns.delete}, -- diff mode: Deleted line |diff.txt| + -- Telescope + TelescopeBorder = {fg = t.border_highlight}, + TelescopeSelectionCaret = {fg = t.cyan}, + TelescopeSelection = {fg = t.cyan, bg = t.bg_highlight}, + TelescopeMatching = {fg = t.blue}, + -- NvimTree + NvimTreeNormal = {fg = t.fg_sidebar, bg = t.bg_sidebar}, + NvimTreeFolderIcon = {fg = t.comment}, + NvimTreeRootFolder = {fg = t.orange, style = "bold"}, + NvimTreeSymlink = {fg = t.magenta}, + NvimTreeFolderName = {fg = t.blue}, + NvimTreeEmptyFolderName = {fg = t.comment}, + NvimTreeOpenedFolderName = {fg = t.blue_br}, + NvimTreeOpenedFile = {fg = t.magenta}, -- TODO: not working + NvimTreeGitDirty = {fg = t.git.change}, + NvimTreeGitNew = {fg = t.git.add}, + NvimTreeGitDeleted = {fg = t.git.delete}, + NvimTreeSpecialFile = {fg = t.cyan}, + NvimTreeIndentMarker = {fg = t.fg_gutter}, + NvimTreeImageFile = {fg = t.fg_sidebar}, + LspDiagnosticsError = {fg = t.error}, + LspDiagnosticsWarning = {fg = t.warning}, + LspDiagnosticsInformation = {fg = t.info}, + LspDiagnosticsHint = {fg = t.hint}, + -- Fern + FernBranchText = {fg = t.blue}, + -- glyph palette + GlyphPalette1 = {fg = t.red}, + GlyphPalette2 = {fg = t.green}, + GlyphPalette3 = {fg = t.yellow}, + GlyphPalette4 = {fg = t.blue}, + GlyphPalette6 = {fg = t.green_br}, + GlyphPalette7 = {fg = t.fg}, + GlyphPalette9 = {fg = t.red}, + -- Dashboard + DashboardShortCut = {fg = t.cyan}, + DashboardHeader = {fg = t.yellow}, + DashboardCenter = {fg = t.green}, + DashboardFooter = {fg = t.orange, style = "italic"}, + -- WhichKey + WhichKey = {fg = t.cyan}, + WhichKeyGroup = {fg = t.blue}, + WhichKeyDesc = {fg = t.magenta}, + WhichKeySeperator = {fg = t.comment}, + WhichKeySeparator = {fg = t.comment}, + WhichKeyFloat = {bg = t.bg_sidebar}, + WhichKeyValue = {fg = t.comment}, + -- LspSaga + DiagnosticError = {fg = t.error}, + DiagnosticWarning = {fg = t.warning}, + DiagnosticInformation = {fg = t.info}, + DiagnosticHint = {fg = t.hint}, + LspFloatWinNormal = {bg = t.bg_float}, + LspFloatWinBorder = {fg = t.border_highlight}, + LspSagaBorderTitle = {fg = t.cyan}, + LspSagaHoverBorder = {fg = t.blue}, + LspSagaRenameBorder = {fg = t.green}, + LspSagaDefPreviewBorder = {fg = t.green}, + LspSagaCodeActionBorder = {fg = t.blue}, + LspSagaFinderSelection = {fg = t.bg_visual}, + LspSagaCodeActionTitle = {fg = t.blue1}, + LspSagaCodeActionContent = {fg = t.purple}, + LspSagaSignatureHelpBorder = {fg = t.red}, + ReferencesCount = {fg = t.purple}, + DefinitionCount = {fg = t.purple}, + DefinitionIcon = {fg = t.blue}, + ReferencesIcon = {fg = t.blue}, + TargetWord = {fg = t.cyan}, + -- NeoVim + healthError = {fg = t.error}, + healthSuccess = {fg = t.green_br}, + healthWarning = {fg = t.warning}, + -- BufferLine + BufferLineIndicatorSelected = {fg = t.git.change}, + BufferLineFill = {bg = t.black}, + -- Barbar + BufferCurrent = {bg = t.fg_gutter, fg = t.fg}, + BufferCurrentIndex = {bg = t.fg_gutter, fg = t.info}, + BufferCurrentMod = {bg = t.fg_gutter, fg = t.warning}, + BufferCurrentSign = {bg = t.fg_gutter, fg = t.info}, + BufferCurrentTarget = {bg = t.fg_gutter, fg = t.red}, + BufferVisible = {bg = t.bg_statusline, fg = t.fg}, + BufferVisibleIndex = {bg = t.bg_statusline, fg = t.info}, + BufferVisibleMod = {bg = t.bg_statusline, fg = t.warning}, + BufferVisibleSign = {bg = t.bg_statusline, fg = t.info}, + BufferVisibleTarget = {bg = t.bg_statusline, fg = t.red}, + BufferInactive = {bg = t.bg_statusline, fg = t.comment}, + BufferInactiveIndex = {bg = t.bg_statusline, fg = t.comment}, + BufferInactiveMod = {bg = t.bg_statusline, fg = util.darken(t.warning, 0.7)}, + BufferInactiveSign = {bg = t.bg_statusline, fg = t.border_highlight}, + BufferInactiveTarget = {bg = t.bg_statusline, fg = t.red}, + BufferTabpages = {bg = t.bg_statusline, fg = t.none}, + BufferTabpage = {bg = t.bg_statusline, fg = t.border_highlight}, + -- Sneak + Sneak = {fg = t.bg_highlight, bg = t.magenta}, + SneakScope = {bg = t.bg_visual}, + -- Hop + HopNextKey = {fg = t.cyan, style = "bold"}, + HopNextKey1 = {fg = t.blue, style = "bold"}, + HopNextKey2 = {fg = util.darken(t.blue, 0.3)}, + HopUnmatched = {fg = t.comment}, + LightspeedGreyWash = {fg = t.comment} + } + + return theme +end + +return M diff --git a/lua/catppuccino/init.lua b/lua/catppuccino/init.lua new file mode 100644 index 0000000..c580308 --- /dev/null +++ b/lua/catppuccino/init.lua @@ -0,0 +1,11 @@ +local M = {} + +function M.load() + require("catppuccino.main").main("load") +end + +function M.setup(custom_opts) + require("catppuccino.config").set_options(custom_opts) +end + +return M diff --git a/lua/catppuccino/main.lua b/lua/catppuccino/main.lua new file mode 100644 index 0000000..3dda351 --- /dev/null +++ b/lua/catppuccino/main.lua @@ -0,0 +1,15 @@ +local M = {} + +local utils = require("catppuccino.utils.util") + +function M.main(option) + option = option or "load" + + if (option == "load") then + utils.load(require("catppuccino.core.mapper").apply()) + else + print("Catppuccino: Command was not recognized") + end +end + +return M diff --git a/lua/catppuccino/utils/hsluv.lua b/lua/catppuccino/utils/hsluv.lua new file mode 100644 index 0000000..ce9507f --- /dev/null +++ b/lua/catppuccino/utils/hsluv.lua @@ -0,0 +1,338 @@ +--[[ +Lua implementation of HSLuv and HPLuv color spaces +Homepage: http://www.hsluv.org/ + +Copyright (C) 2019 Alexei Boronine + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and +associated documentation files (the "Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the +following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial +portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT +LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN +NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +]] +local hsluv = {} + +local hexChars = "0123456789abcdef" + +local distance_line_from_origin = function(line) + return math.abs(line.intercept) / math.sqrt((line.slope ^ 2) + 1) +end + +local length_of_ray_until_intersect = function(theta, line) + return line.intercept / (math.sin(theta) - line.slope * math.cos(theta)) +end + +hsluv.get_bounds = function(l) + local result = {} + local sub2 + local sub1 = ((l + 16) ^ 3) / 1560896 + if sub1 > hsluv.epsilon then + sub2 = sub1 + else + sub2 = l / hsluv.kappa + end + + for i = 1, 3 do + local m1 = hsluv.m[i][1] + local m2 = hsluv.m[i][2] + local m3 = hsluv.m[i][3] + + for t = 0, 1 do + local top1 = (284517 * m1 - 94839 * m3) * sub2 + local top2 = (838422 * m3 + 769860 * m2 + 731718 * m1) * l * sub2 - 769860 * t * l + local bottom = (632260 * m3 - 126452 * m2) * sub2 + 126452 * t + table.insert(result, {slope = top1 / bottom, intercept = top2 / bottom}) + end + end + return result +end + +hsluv.max_safe_chroma_for_l = function(l) + local bounds = hsluv.get_bounds(l) + local min = 1.7976931348623157e+308 + + for i = 1, 6 do + local length = distance_line_from_origin(bounds[i]) + if length >= 0 then + min = math.min(min, length) + end + end + return min +end + +hsluv.max_safe_chroma_for_lh = function(l, h) + local hrad = h / 360 * math.pi * 2 + local bounds = hsluv.get_bounds(l) + local min = 1.7976931348623157e+308 + + for i = 1, 6 do + local bound = bounds[i] + local length = length_of_ray_until_intersect(hrad, bound) + if length >= 0 then + min = math.min(min, length) + end + end + return min +end + +hsluv.dot_product = function(a, b) + local sum = 0 + for i = 1, 3 do + sum = sum + a[i] * b[i] + end + return sum +end + +hsluv.from_linear = function(c) + if c <= 0.0031308 then + return 12.92 * c + else + return 1.055 * (c ^ 0.416666666666666685) - 0.055 + end +end + +hsluv.to_linear = function(c) + if c > 0.04045 then + return ((c + 0.055) / 1.055) ^ 2.4 + else + return c / 12.92 + end +end + +hsluv.xyz_to_rgb = function(tuple) + return { + hsluv.from_linear(hsluv.dot_product(hsluv.m[1], tuple)), + hsluv.from_linear(hsluv.dot_product(hsluv.m[2], tuple)), + hsluv.from_linear(hsluv.dot_product(hsluv.m[3], tuple)) + } +end + +hsluv.rgb_to_xyz = function(tuple) + local rgbl = {hsluv.to_linear(tuple[1]), hsluv.to_linear(tuple[2]), hsluv.to_linear(tuple[3])} + return { + hsluv.dot_product(hsluv.minv[1], rgbl), + hsluv.dot_product(hsluv.minv[2], rgbl), + hsluv.dot_product(hsluv.minv[3], rgbl) + } +end + +hsluv.y_to_l = function(Y) + if Y <= hsluv.epsilon then + return Y / hsluv.refY * hsluv.kappa + else + return 116 * ((Y / hsluv.refY) ^ 0.333333333333333315) - 16 + end +end + +hsluv.l_to_y = function(L) + if L <= 8 then + return hsluv.refY * L / hsluv.kappa + else + return hsluv.refY * (((L + 16) / 116) ^ 3) + end +end + +hsluv.xyz_to_luv = function(tuple) + local X = tuple[1] + local Y = tuple[2] + local divider = X + 15 * Y + 3 * tuple[3] + local varU = 4 * X + local varV = 9 * Y + if divider ~= 0 then + varU = varU / divider + varV = varV / divider + else + varU = 0 + varV = 0 + end + local L = hsluv.y_to_l(Y) + if L == 0 then + return {0, 0, 0} + end + return {L, 13 * L * (varU - hsluv.refU), 13 * L * (varV - hsluv.refV)} +end + +hsluv.luv_to_xyz = function(tuple) + local L = tuple[1] + local U = tuple[2] + local V = tuple[3] + if L == 0 then + return {0, 0, 0} + end + local varU = U / (13 * L) + hsluv.refU + local varV = V / (13 * L) + hsluv.refV + local Y = hsluv.l_to_y(L) + local X = 0 - (9 * Y * varU) / (((varU - 4) * varV) - varU * varV) + return {X, Y, (9 * Y - 15 * varV * Y - varV * X) / (3 * varV)} +end + +hsluv.luv_to_lch = function(tuple) + local L = tuple[1] + local U = tuple[2] + local V = tuple[3] + local C = math.sqrt(U * U + V * V) + local H + if C < 0.00000001 then + H = 0 + else + H = math.atan2(V, U) * 180.0 / 3.1415926535897932 + if H < 0 then + H = 360 + H + end + end + return {L, C, H} +end + +hsluv.lch_to_luv = function(tuple) + local L = tuple[1] + local C = tuple[2] + local Hrad = tuple[3] / 360.0 * 2 * math.pi + return {L, math.cos(Hrad) * C, math.sin(Hrad) * C} +end + +hsluv.hsluv_to_lch = function(tuple) + local H = tuple[1] + local S = tuple[2] + local L = tuple[3] + if L > 99.9999999 then + return {100, 0, H} + end + if L < 0.00000001 then + return {0, 0, H} + end + return {L, hsluv.max_safe_chroma_for_lh(L, H) / 100 * S, H} +end + +hsluv.lch_to_hsluv = function(tuple) + local L = tuple[1] + local C = tuple[2] + local H = tuple[3] + local max_chroma = hsluv.max_safe_chroma_for_lh(L, H) + if L > 99.9999999 then + return {H, 0, 100} + end + if L < 0.00000001 then + return {H, 0, 0} + end + + return {H, C / max_chroma * 100, L} +end + +hsluv.hpluv_to_lch = function(tuple) + local H = tuple[1] + local S = tuple[2] + local L = tuple[3] + if L > 99.9999999 then + return {100, 0, H} + end + if L < 0.00000001 then + return {0, 0, H} + end + return {L, hsluv.max_safe_chroma_for_l(L) / 100 * S, H} +end + +hsluv.lch_to_hpluv = function(tuple) + local L = tuple[1] + local C = tuple[2] + local H = tuple[3] + if L > 99.9999999 then + return {H, 0, 100} + end + if L < 0.00000001 then + return {H, 0, 0} + end + return {H, C / hsluv.max_safe_chroma_for_l(L) * 100, L} +end + +hsluv.rgb_to_hex = function(tuple) + local h = "#" + for i = 1, 3 do + local c = math.floor(tuple[i] * 255 + 0.5) + local digit2 = math.fmod(c, 16) + local x = (c - digit2) / 16 + local digit1 = math.floor(x) + h = h .. string.sub(hexChars, digit1 + 1, digit1 + 1) + h = h .. string.sub(hexChars, digit2 + 1, digit2 + 1) + end + return h +end + +hsluv.hex_to_rgb = function(hex) + hex = string.lower(hex) + local ret = {} + for i = 0, 2 do + local char1 = string.sub(hex, i * 2 + 2, i * 2 + 2) + local char2 = string.sub(hex, i * 2 + 3, i * 2 + 3) + local digit1 = string.find(hexChars, char1) - 1 + local digit2 = string.find(hexChars, char2) - 1 + ret[i + 1] = (digit1 * 16 + digit2) / 255.0 + end + return ret +end + +hsluv.lch_to_rgb = function(tuple) + return hsluv.xyz_to_rgb(hsluv.luv_to_xyz(hsluv.lch_to_luv(tuple))) +end + +hsluv.rgb_to_lch = function(tuple) + return hsluv.luv_to_lch(hsluv.xyz_to_luv(hsluv.rgb_to_xyz(tuple))) +end + +hsluv.hsluv_to_rgb = function(tuple) + return hsluv.lch_to_rgb(hsluv.hsluv_to_lch(tuple)) +end + +hsluv.rgb_to_hsluv = function(tuple) + return hsluv.lch_to_hsluv(hsluv.rgb_to_lch(tuple)) +end + +hsluv.hpluv_to_rgb = function(tuple) + return hsluv.lch_to_rgb(hsluv.hpluv_to_lch(tuple)) +end + +hsluv.rgb_to_hpluv = function(tuple) + return hsluv.lch_to_hpluv(hsluv.rgb_to_lch(tuple)) +end + +hsluv.hsluv_to_hex = function(tuple) + return hsluv.rgb_to_hex(hsluv.hsluv_to_rgb(tuple)) +end + +hsluv.hpluv_to_hex = function(tuple) + return hsluv.rgb_to_hex(hsluv.hpluv_to_rgb(tuple)) +end + +hsluv.hex_to_hsluv = function(s) + return hsluv.rgb_to_hsluv(hsluv.hex_to_rgb(s)) +end + +hsluv.hex_to_hpluv = function(s) + return hsluv.rgb_to_hpluv(hsluv.hex_to_rgb(s)) +end + +hsluv.m = { + {3.240969941904521, -1.537383177570093, -0.498610760293}, + {-0.96924363628087, 1.87596750150772, 0.041555057407175}, + {0.055630079696993, -0.20397695888897, 1.056971514242878} +} +hsluv.minv = { + {0.41239079926595, 0.35758433938387, 0.18048078840183}, + {0.21263900587151, 0.71516867876775, 0.072192315360733}, + {0.019330818715591, 0.11919477979462, 0.95053215224966} +} +hsluv.refY = 1.0 +hsluv.refU = 0.19783000664283 +hsluv.refV = 0.46831999493879 +hsluv.kappa = 903.2962962 +hsluv.epsilon = 0.0088564516 + +return hsluv diff --git a/lua/catppuccino/utils/util.lua b/lua/catppuccino/utils/util.lua new file mode 100644 index 0000000..283cd39 --- /dev/null +++ b/lua/catppuccino/utils/util.lua @@ -0,0 +1,177 @@ +local hsluv = require("catppuccino.utils.hsluv") + +local g = vim.g +local o = vim.o + +local util = {} + +util.bg = "#000000" +util.fg = "#ffffff" +util.day_brightness = 0.3 + +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 foreground 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 + + 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 + end + return hsluv.hsluv_to_hex(hsl) + end + return color +end + +function util.color_overrides(colors, config) + if type(config.colors) == "table" then + for key, value in pairs(config.colors) do + if not colors[key] then + error("Color " .. key .. " does not exist") + end + + -- Patch: https://github.com/ful1e5/onedark.nvim/issues/6 + if type(colors[key]) == "table" then + util.color_overrides(colors[key], {colors = value}) + else + if value:lower() == "none" then + -- set to none + colors[key] = "NONE" + elseif string.sub(value, 1, 1) == "#" then + -- hex override + colors[key] = value + else + -- another group + if not colors[value] then + error("Color " .. value .. " does not exist") + end + colors[key] = colors[value] + end + end + end + end +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", "white", "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 util.highlight(group, color) + 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 hl = "highlight " .. group .. " " .. style .. " " .. fg .. " " .. bg .. " " .. sp + + vim.cmd(hl) + if color.link then + vim.cmd("highlight! link " .. group .. " " .. color.link) + end +end + +function util.syntax(tbl) + for group, colors in pairs(tbl) do + util.highlight(group, colors) + end +end + +function util.terminal(theme) + g.terminal_color_0 = theme.colors.black + g.terminal_color_1 = theme.colors.red + g.terminal_color_2 = theme.colors.green + g.terminal_color_3 = theme.colors.yellow + g.terminal_color_4 = theme.colors.blue + g.terminal_color_5 = theme.colors.magenta + g.terminal_color_6 = theme.colors.cyan + g.terminal_color_7 = theme.colors.white + + g.terminal_color_8 = theme.colors.black_br + g.terminal_color_9 = theme.colors.red_br + g.terminal_color_10 = theme.colors.green_br + g.terminal_color_11 = theme.colors.yellow_br + g.terminal_color_12 = theme.colors.blue_br + g.terminal_color_13 = theme.colors.magenta_br + g.terminal_color_14 = theme.colors.cyan_br + g.terminal_color_15 = theme.colors.white_br +end + +function util.load(theme) + vim.cmd("hi clear") + if vim.fn.exists("syntax_on") then + vim.cmd("syntax reset") + end + + o.background = "dark" + o.termguicolors = true + g.colors_name = "catppuccino" + + util.syntax(theme.base) + util.syntax(theme.plugins) + + if theme.config.terminal_colors then + util.terminal(theme) + end +end + +return util diff --git a/plugin/cpcmds.vim b/plugin/cpcmds.vim new file mode 100644 index 0000000..18b29f8 --- /dev/null +++ b/plugin/cpcmds.vim @@ -0,0 +1,17 @@ +" GPL-3.0 License + +" prevent the plugin's interface from loading twice +if exists('g:loaded_catppuccino') | finish | endif + +let s:save_cpo = &cpo " save user coptions +set cpo&vim " reset them to defaults + +" Interface {{{ +command! CPLoad lua require'catppuccino.main'.main('load') +" }}} + +let &cpo = s:save_cpo " restore after +unlet s:save_cpo + +" set to true the var that controls the plugin's loading +let g:loaded_catppuccino = 1