diff --git a/README.md b/README.md index 07fe61f..d6c1ba6 100644 --- a/README.md +++ b/README.md @@ -14,6 +14,30 @@ Why fluo? Because it's simply cool! ![flow-multiple-terminal](https://github.com/user-attachments/assets/9d1f367a-7a9d-478d-9fe0-a67bd33eca1a) +## Variants + +Flow colorscheme family offers two variants: + +- `default`: is the original version of the colorscheme providing a wide range of colors. + This variant is recommended for people that likes selected colors for every semantic syntax in the UI. + +- `mono`: the mono variant desaturates all syntax colors to metallic grey shades with a cool blue + hue, while mapping keywords and operators to the selected fluo accent color. Diagnostics also use + fluo shades. This variant is recommended for people that want a super focusing environment where + the accent color draws attention to what matters most. + +To variant can be selected by loading the colorscheme with the specific name: + +```lua + vim.cmd("colorscheme flow") +``` + +Or: + +```lua + vim.cmd("colorscheme flow-mono") +``` + ## Palette Flow uses a palette of nine HSL-based colors, chosen to create a cohesive and visually appealing @@ -92,7 +116,7 @@ return { }, }, ui = { - borders = "inverse", -- "theme" | "inverse" | "fluo" | "none" + borders = "none", -- "light" | "dark" | "none" aggressive_spell = false, -- true | false }, }, diff --git a/colors/flow-mono.lua b/colors/flow-mono.lua new file mode 100644 index 0000000..697e047 --- /dev/null +++ b/colors/flow-mono.lua @@ -0,0 +1 @@ +require("flow").load("mono") diff --git a/colors/flow.lua b/colors/flow.lua index 42e44c6..5a9568d 100644 --- a/colors/flow.lua +++ b/colors/flow.lua @@ -1 +1 @@ -require("flow").load() +require("flow").load("classic") diff --git a/doc/flow.nvim.txt b/doc/flow.nvim.txt index 340f95f..fbe9648 100644 --- a/doc/flow.nvim.txt +++ b/doc/flow.nvim.txt @@ -5,6 +5,7 @@ Table of Contents *flow.nvim-table-of-contents* 1. 🌊 Flow |flow.nvim-🌊-flow| - Showcase |flow.nvim-🌊-flow-showcase| + - Variants |flow.nvim-🌊-flow-variants| - Palette |flow.nvim-🌊-flow-palette| - Requirements |flow.nvim-🌊-flow-requirements| - Installation |flow.nvim-🌊-flow-installation| @@ -31,6 +32,33 @@ Why fluo? Because it’s simply cool! SHOWCASE *flow.nvim-🌊-flow-showcase* +VARIANTS *flow.nvim-🌊-flow-variants* + +Flow colorscheme family offers two variants: + +- `default`: is the original version of the colorscheme providing a wide range + of colors. This variant is recommended for people that likes selected colors + for every semantic syntax in the UI. + +- `mono`: the mono variant desaturates all syntax colors to metallic grey shades + with a cool blue hue, while mapping keywords and operators to the selected + fluo accent color. Diagnostics also use fluo shades. This variant is + recommended for people that want a super focusing environment where the + accent color draws attention to what matters most. + +The variant can be selected by loading the colorscheme with the specific name: + +>lua + vim.cmd("colorscheme flow") +< + +Or: + +>lua + vim.cmd("colorscheme flow-mono") +< + + PALETTE *flow.nvim-🌊-flow-palette* Flow uses a palette of nine HSL-based colors, chosen to create a cohesive and @@ -114,7 +142,7 @@ DEFAULT ~ }, }, ui = { - borders = "inverse", -- "theme" | "inverse" | "fluo" | "none" + borders = "none", -- "light" | "dark" | "none" aggressive_spell = false, -- true | false }, }, diff --git a/lua/flow/colors.lua b/lua/flow/colors.lua index 3653028..245dd9e 100644 --- a/lua/flow/colors.lua +++ b/lua/flow/colors.lua @@ -1,23 +1,35 @@ -local M = {} - -M.colors = nil - -M._color_names = - { "orange", "yellow", "red", "purple", "blue", "light_blue", "sky_blue", "cyan", "green" } +local palette = require("flow.palette") + +local M = { + --- Names of the colors used in the colorscheme. + names = { + "blue", + "cyan", + "green", + "light_blue", + "orange", + "purple", + "red", + "sky_blue", + "yellow", + }, + + colors = nil, +} --- Setup the colorscheme colors based on the options and palette. ---- @param opts FlowConfig: The options to setup the colorscheme. ---- @return table: The colors used by the colorscheme. -function M.setup(opts) - local default_palette = require("flow.palette").get(opts or {}) +--- @param config FlowConfig The configuration options to setup the colorscheme. +--- @return table The colors used by the colorscheme. +function M.setup(config) + config = config or {} - opts = opts or {} + local default_palette = palette.get(config) -- Get the configured fluo color (with fallback to default) - local fluo_color = (opts.colors and opts.colors.fluo) or "pink" + local fluo_color = (config.colors and config.colors.fluo) or "pink" local colors = { - -- Core colors + -- Core colors. transparent = default_palette.transparent, black = default_palette.black, white = default_palette.white, @@ -32,20 +44,25 @@ function M.setup(opts) to_check = default_palette.fluo.green.default, } - M._apply_opts(default_palette, colors, opts) + M._apply_opts(default_palette, colors, config) - for _, key in ipairs(M._color_names) do + for _, key in ipairs(M.names) do -- Set the specific mode of the colors. - colors[key] = default_palette[key][opts.colors.mode] + colors[key] = default_palette[key][config.colors.mode] -- Store all the color variations. These variables are used for hi that - -- requires contrasts with the current theme, like git. + -- require contrasts with the current theme, like git. local Key = key:gsub("^%l", string.upper) colors[Key] = default_palette[key] end + -- Yellow is perceptually too light for light backgrounds, use the dark shade instead. + if config.theme.style ~= "dark" then + colors.yellow = colors.Yellow.dark + end + -- Comments - use lighter grey for light theme - colors.comment = opts.theme.style == "dark" and colors.grey[7] -- Dark theme: 50% lightness - or colors.grey[4] -- Light theme: inverts to 65% lightness (less dark) + colors.comment = config.theme.style == "dark" and colors.grey[7] -- Dark theme: 50% lightness + or colors.grey[6] -- Light theme: darker grey for readability against light background -- +----------------------------------------------------------------------------------------+ -- | Sidebar (e.g., NERDTree, Telescope, Quickfix) | <- Sidebar @@ -74,16 +91,29 @@ function M.setup(opts) colors.fg_sidebar = default_palette.grey[8] colors.bg_sidebar = colors.bg - local is_transparent = opts.theme.transparent == true + local is_transparent = config.theme.transparent == true -- Gutter: used for line numbers, signs, and fold column. colors.fg_gutter = colors.grey[5] colors.bg_gutter = (is_transparent and default_palette.transparent) or colors.bg - + -- + -- -- CursorLine background. + -- + -- -- Visual selection background. + -- visual_bg = { + -- dark = hsl_to_hex(fluo_hue_value, 90, 23), -- For dark theme + -- light = hsl_to_hex(fluo_hue_value, 90, 77), -- For light theme + -- }, + -- + + -- -- Float window colors. + -- float_bg = { + -- dark = hsl_to_hex(203, 20, 18), -- For dark theme + -- light = hsl_to_hex(203, 20, 82), -- For light theme + -- }, -- Float: used for visual elements that are floating and triggered by the user. colors.fg_float = colors.grey[8] - colors.bg_float = opts.theme.style == "dark" and default_palette.float_bg.dark - or default_palette.float_bg.light + colors.bg_float = default_palette.grey[2] -- Popups: use for completion menu and all visual components that appears autonomously. colors.fg_popup = default_palette.grey[9] @@ -97,9 +127,12 @@ function M.setup(opts) colors.fg_highlight = colors.grey[6] colors.bg_highlight = colors.grey[2] + -- visual_bg = { + -- dark = hsl_to_hex(fluo_hue_value, 90, 23), -- For dark theme + -- light = hsl_to_hex(fluo_hue_value, 90, 77), -- For light theme + -- }, -- Visual - uses configured fluo color - colors.bg_visual = opts.theme.style == "dark" and default_palette.visual_bg.dark - or default_palette.visual_bg.light + colors.bg_visual = config.theme.style == "dark" and colors.Fluo.dark or colors.Fluo.light colors.fg_visual = colors.grey[2] -- Git @@ -111,7 +144,7 @@ function M.setup(opts) untracked = colors.sky_blue, -- New untracked files } - local is_dark = opts.theme.style == "dark" + local is_dark = config.theme.style == "dark" colors.diff = { add = not is_dark and colors.Green.very_light or colors.Green.very_dark, delete = not is_dark and colors.Red.very_light or colors.Red.very_dark, @@ -132,6 +165,11 @@ function M.setup(opts) colors.fixme = is_dark and colors.Red.default or colors.Red.dark -- FIXME comments colors.hack = is_dark and colors.Yellow.default or colors.Yellow.dark -- HACK comments + -- Apply monochrome transformation if enabled + if config.variant == "mono" then + require("flow.mono").apply(colors, config) + end + M.colors = colors return colors @@ -154,33 +192,35 @@ function M._swap(t, a, b) t[a], t[b] = t[b], t[a] end ---- @param opts FlowConfig -function M._apply_opts(default_palette, colors, opts) - if opts.colors.fluo then - colors.fluo = default_palette.fluo[opts.colors.fluo].default - colors.Fluo = default_palette.fluo[opts.colors.fluo] +--- @param default_palette table +--- @param colors table +--- @param config FlowConfig +function M._apply_opts(default_palette, colors, config) + if config.colors.fluo then + colors.fluo = default_palette.fluo[config.colors.fluo].default + colors.Fluo = default_palette.fluo[config.colors.fluo] end -- Apply changes if the theme is not dark. -- HACK: this has to be executed before all changes that involves white, black, and grey. - if opts.theme.style ~= "dark" then + if config.theme.style ~= "dark" then M._invert_colors_for_theme(colors) end -- If high contrast the darkest color is swap for the next color and the -- lightest color is swap for the color before. - if opts.theme.contrast == "high" then + if config.theme.contrast == "high" then M._invert_colors_for_contrast(colors) end - colors.bg = (opts.theme.transparent and default_palette.transparent) or default_palette.grey[3] -- used for theme background - colors.fg = (opts.theme.style == "dark" and colors.grey[8]) or colors.grey[8] + colors.bg = (config.theme.transparent and default_palette.transparent) or default_palette.grey[3] -- used for theme background + colors.fg = (config.theme.style == "dark" and colors.grey[8]) or colors.grey[8] -- Borders - if opts.ui.borders == "none" then + if config.ui.borders == "none" then colors.fg_border = colors.bg -- Match background to make borders invisible colors.fg_vsplit = colors.grey[2] - elseif opts.ui.borders == "light" then + elseif config.ui.borders == "light" then colors.fg_border = colors.grey[4] colors.fg_vsplit = colors.grey[4] else -- dark (default) @@ -188,9 +228,13 @@ function M._apply_opts(default_palette, colors, opts) colors.fg_vsplit = colors.grey[1] end + -- cursorline_bg = { + -- dark = hsl_to_hex(fluo_hue_value, 20, 13), -- For dark theme + -- light = hsl_to_hex(fluo_hue_value, 20, 87), -- For light theme + -- }, -- CursorLine background - uses configured fluo color - colors.bg_cursorline = opts.theme.style == "dark" and default_palette.cursorline_bg.dark - or default_palette.cursorline_bg.light + colors.bg_cursorline = config.theme.style == "dark" and colors.Fluo.very_dark + or colors.Fluo.very_light -- NOTE bg_border is currently not used. colors.bg_border = colors.grey[7] diff --git a/lua/flow/config.lua b/lua/flow/config.lua index c652e70..0243544 100644 --- a/lua/flow/config.lua +++ b/lua/flow/config.lua @@ -1,144 +1,132 @@ -local M = {} +--- Stores allowed values for configuration options. +--- @class ConfigEnum +--- @field name string The name of the enum. +--- @field path string[] The path to get the enum field in the config. +--- @field valid string[] Valid values. + +local M = { + --- ConfigEnum[] + enum_values = { + { name = "style", path = { "theme", "style" }, valid = { "dark", "light" } }, + { + name = "contrast", + path = { "theme", "contrast" }, + valid = { "default", "high" }, + }, + { name = "mode", path = { "colors", "mode" }, valid = { "default", "dark", "light" } }, + { + path = { "colors", "fluo" }, + valid = { "pink", "cyan", "yellow", "orange", "green" }, + name = "fluo color", + }, + { + name = "borders", + path = { "ui", "borders" }, + valid = { "light", "dark", "none" }, + }, + }, +} --- Default configuration options for the colorscheme. --- @class FlowConfig M.defaults = { - --- @class Theme + --- @class FlowThemeConfig + --- @field style "dark" | "light" Defines the colorscheme theme style. + --- @field contrast "default" | "high" Defines whether details contrasts should be accentuated or not. + --- @field transparent boolean Defines whether neovim background should be transparent (fallback to terminal value) or not. theme = { - ---@alias Style "dark" | "light" style = "dark", - ---@alias Contrast "default" | "high" contrast = "default", - ---@boolean transparent = false, }, + --- @class FlowColorsConfig + --- @field mode "default" | "dark" | "light" Defines the colors used in the syntax and UI. + --- @field fluo "pink" | "cyan" | "yellow" | "orange" | "green" Fluo color used in the theme. + --- @field custom { saturation: string, lightness: string } Allows to specify custom saturation + --- (0, 100) and lightness (0, 100) for theme. Despite the option is present for maximum + --- customizability, it is recommended to use defaults. colors = { - ---@alias Mode "default" | "dark" | "light" mode = "default", - ---@alias Fluo "pink" | "cyan" | "yellow" | "orange" | "green" fluo = "pink", - ---@alias CustomSaturation string A number between 0-100 as string or empty string - ---@alias CustomLight string A number between 0-100 as string or empty string - custom = { - ---@type CustomSaturation - saturation = "", -- Custom saturation value (0-100) - ---@type CustomLight - light = "", -- Custom lightness value (0-100) - }, + custom = { saturation = "", lightness = "" }, }, + --- @class FlowUiConfig + --- @field borders "light" | "dark" | "none" Defines how borders of elements are displayed. + --- @field aggressive_spell boolean Defines if spell errors have to be highlighted with + --- a more outstanding color. + --- @field aggressive_special_comment boolean Defines if special comments (TODO, FIX, etc.) + --- has to be highlighted with different colors. ui = { - ---@alias Borders "light" | "dark" | "none" - borders = "dark", - ---@boolean + borders = "none", aggressive_spell = false, - ---@boolean aggressive_special_comment = false, }, } +--- Used to store colorscheme configuration with user provided custom values. --- @type FlowConfig M.options = {} ---- Valid values for configuration options -M.valid_options = { - fluo_colors = { "pink", "cyan", "yellow", "orange", "green" }, - modes = { "default", "dark", "light" }, - borders = { "light", "dark", "none" }, - contrast = { "default", "high" }, - custom_ranges = { - saturation = { min = 0, max = 100 }, - light = { min = 0, max = 100 }, - }, -} - ---- Validate configuration options ---- @param opts FlowConfig +--- Validate configuration options. +--- @param config FlowConfig --- @return boolean, string? -local function validate_options(opts) - -- Validate theme options. - if opts.theme then - if - opts.theme.contrast and not vim.tbl_contains(M.valid_options.contrast, opts.theme.contrast) - then - return false, string.format("Invalid border: %s", opts.theme.contrast) +function M.validate_options(config) + for _, v in ipairs(M.enum_values) do + local val = config + for _, key in ipairs(v.path) do + val = val and val[key] end - end - - -- Validate color options. - if opts.colors then - if opts.colors.fluo and not vim.tbl_contains(M.valid_options.fluo_colors, opts.colors.fluo) then - return false, string.format("Invalid fluo color: %s", opts.colors.fluo) + if val and not vim.tbl_contains(v.valid, val) then + return false, string.format("Invalid %s: %s", v.name, val) end + end - if opts.colors.mode and not vim.tbl_contains(M.valid_options.modes, opts.colors.mode) then - return false, string.format("Invalid mode: %s", opts.colors.mode) - end + -- Validate custom color values for hue and light. + if config.colors and config.colors.custom then + local sl = { saturation = { 0, 100 }, lightness = { 0, 100 } } + for property, range in pairs(sl) do + local min, max = range[1], range[2] - -- Validate custom color values for hue and light - if opts.colors.custom then - if opts.colors.custom.saturation and opts.colors.custom.saturation ~= "" then - local s = tonumber(opts.colors.custom.saturation) - if - not s - or s < M.valid_options.custom_ranges.saturation.min - or s > M.valid_options.custom_ranges.saturation.max - then + local custom_val = config.colors.custom[property] + if custom_val and custom_val ~= "" then + local val = tonumber(custom_val) + if not val or val < min or val > max then return false, string.format( - "Invalid saturation value: %s (must be between %d and %d)", - opts.colors.custom.saturation, - M.valid_options.custom_ranges.saturation.min, - M.valid_options.custom_ranges.saturation.max - ) - end - end - if opts.colors.custom.light and opts.colors.custom.light ~= "" then - local l = tonumber(opts.colors.custom.light) - if - not l - or l < M.valid_options.custom_ranges.light.min - or l > M.valid_options.custom_ranges.light.max - then - return false, - string.format( - "Invalid light value: %s (must be between %d and %d)", - opts.colors.custom.light, - M.valid_options.custom_ranges.light.min, - M.valid_options.custom_ranges.light.max + "Invalid %s value: %s (must be between %d and %d)", + property, + custom_val, + min, + max ) end end end end - -- Validate ui options - if opts.ui then - if opts.ui.borders and not vim.tbl_contains(M.valid_options.borders, opts.ui.borders) then - return false, string.format("Invalid border: %s", opts.ui.borders) - end - end - return true end --- This is the entry point of the configuration before loading the plugin. ---- It sets up the colorscheme options by merging the provided options with +--- It sets the colorscheme options by merging the user provided ones with --- the default configuration. ---- @param opts FlowConfig? Optional table to customize the colorscheme setup. -function M._setup(opts) - -- -- Short circuit if options have been already set. This happen when the colorscheme is loaded from - -- -- the plugin manager because first set the options,and then set the colorscheme. +--- @param config FlowConfig? Optional table to customize the colorscheme configuration. +function M._setup(config) + -- Short circuit if options have been already set. This happen when the colorscheme is loaded from + -- the plugin manager because it first set the options, and then set the colorscheme. if not vim.tbl_isempty(M.options) then return end - local ok, err = validate_options(opts or {}) - if not ok then - opts = {} - vim.notify("Error setting user options, fallback to defaults: " .. err, vim.log.levels.WARN) + if config then + local ok, err = M.validate_options(config) + if not ok then + config = {} + end end - M.options = vim.tbl_deep_extend("force", {}, M.defaults, opts or {}) + -- Set to the table the default config updated with the user provided one. + M.options = vim.tbl_deep_extend("force", {}, M.defaults, config or {}) end return M diff --git a/lua/flow/highlights/base.lua b/lua/flow/highlights/base.lua index 8d394c6..bbf1384 100644 --- a/lua/flow/highlights/base.lua +++ b/lua/flow/highlights/base.lua @@ -135,6 +135,47 @@ function M.get(c, o) FlowInfo = { fg = c.light_blue }, -- Info/neutral action state } + -- Monochrome: collapse FlowKind groups to ~6 grey lightness tiers. + if o.variant == "mono" then + -- Tier 1: Keywords/constructors/classes + theme.FlowKindKeyword = { fg = c.red, bold = true } + theme.FlowKindConstructor = { fg = c.red, bold = true } + theme.FlowKindClass = { fg = c.red, bold = true } + theme.FlowKindInterface = { fg = c.red, bold = true } + theme.FlowKindStruct = { fg = c.red, bold = true } + theme.FlowKindEnum = { fg = c.red, bold = true } + theme.FlowKindEnumMember = { fg = c.red, bold = true } + + -- Tier 2: Functions/methods. + theme.FlowKindFunction = { fg = c.light_blue } + theme.FlowKindMethod = { fg = c.light_blue } + + -- Tier 3: Variables/fields/properties. + theme.FlowKindVariable = { fg = c.cyan } + theme.FlowKindField = { fg = c.cyan } + theme.FlowKindProperty = { fg = c.cyan } + + -- Tier 4: Constants/values. + theme.FlowKindConstant = { fg = c.yellow } + theme.FlowKindValue = { fg = c.yellow } + theme.FlowKindUnit = { fg = c.yellow } + + -- Tier 5: Modules/files. + theme.FlowKindModule = { fg = c.blue } + theme.FlowKindFile = { fg = c.blue } + theme.FlowKindFolder = { fg = c.blue } + + -- Tier 6: Others. + theme.FlowKindText = { fg = c.purple, italic = true } + theme.FlowKindSnippet = { fg = c.purple, italic = true } + theme.FlowKindColor = { fg = c.purple, italic = true } + theme.FlowKindEvent = { fg = c.purple, italic = true } + theme.FlowKindOperator = { fg = c.cyan } + theme.FlowKindReference = { fg = c.grey[8] } + theme.FlowKindTypeParameter = { fg = c.grey[8] } + theme.FlowKindType = { fg = c.light_blue } + end + return theme end diff --git a/lua/flow/highlights/render-markdown.lua b/lua/flow/highlights/render-markdown.lua index 617101f..9585245 100644 --- a/lua/flow/highlights/render-markdown.lua +++ b/lua/flow/highlights/render-markdown.lua @@ -1,47 +1,36 @@ local M = {} ---- @param c table: The available colors. ---- @param o FlowConfig: The available options. ---- @return table: Render markdown plugin highlights. -function M.get(c, o) +--- @param colors table The available colors. +--- @param config FlowConfig The available options. +--- @return table Render markdown plugin highlights. +function M.get(colors, config) local theme = { - RenderMarkdownCode = { link = "@markup.raw.block" }, -- Code blocks. - RenderMarkdownCodeInline = { link = "@markup.raw.markdown_inline" }, -- Code inline. + RenderMarkdownCode = { link = "@markup.raw.block" }, + RenderMarkdownCodeInline = { link = "@markup.raw.markdown_inline" }, RenderMarkdownBullet = { link = "@markup.list" }, RenderMarkdownDash = { link = "Comment" }, - - -- TODO: complete - -- | RenderMarkdownTableHead | @markup.heading | Pipe table heading rows | - -- | RenderMarkdownTableRow | Normal | Pipe table body rows | - -- | RenderMarkdownTableFill | Conceal | Pipe table inline padding | - -- | RenderMarkdownSuccess | DiagnosticOk | Success related callouts | - -- | RenderMarkdownInfo | DiagnosticInfo | Info related callouts | - -- | RenderMarkdownHint | DiagnosticHint | Hint related callouts | - -- | RenderMarkdownWarn | DiagnosticWarn | Warning related callouts | - -- | RenderMarkdownError | DiagnosticError | Error related callouts | } -- Sequentially define headers background colors. local headersBg = { - c.Fluo.light, - c.Blue.very_light, - c.Light_blue.very_light, - c.Cyan.very_light, - c.Sky_blue.very_light, + colors.Fluo.light, + colors.Blue.very_light, + colors.Light_blue.very_light, + colors.Cyan.very_light, + colors.Sky_blue.very_light, } - if o.theme.style == "dark" then + if config.theme.style == "dark" then headersBg = { - c.Fluo.dark, - c.Blue.very_dark, - c.Light_blue.very_dark, - c.Cyan.very_dark, - c.Sky_blue.very_dark, + colors.Fluo.dark, + colors.Blue.very_dark, + colors.Light_blue.very_dark, + colors.Cyan.very_dark, + colors.Sky_blue.very_dark, } end - -- TODO: hardcoded transparent background but should be based on config. for i, _ in ipairs(headersBg) do - theme["RenderMarkdownH" .. i .. "Bg"] = { bg = c.transparent, bold = true } + theme["RenderMarkdownH" .. i .. "Bg"] = { bg = colors.transparent, bold = true } end return theme diff --git a/lua/flow/highlights/syntax.lua b/lua/flow/highlights/syntax.lua index 41bc022..b7b9cb2 100644 --- a/lua/flow/highlights/syntax.lua +++ b/lua/flow/highlights/syntax.lua @@ -94,6 +94,15 @@ function M.get(c, o) theme.Hack = { fg = c.hack, bg = c.comment } end + -- Monochrome: bold keywords/operators, italic comments/delimiters/special. + if o.variant == "mono" then + theme.Comment = { fg = c.comment, italic = true } + theme.Keyword = { fg = c.red, bold = true } + theme.Operator = { fg = c.red, bold = true } + theme.Delimiter = { fg = c.bracket } + theme.Special = { fg = c.purple, italic = true } + end + return theme end diff --git a/lua/flow/highlights/treesitter.lua b/lua/flow/highlights/treesitter.lua index 465c820..f699ff0 100644 --- a/lua/flow/highlights/treesitter.lua +++ b/lua/flow/highlights/treesitter.lua @@ -1,8 +1,9 @@ local M = {} --- @param c table: The available colors. +--- @param o FlowConfig: The available options. --- @return table: Treesitter plugin highlights. -function M.get(c, _) +function M.get(c, o) local theme = { TreesitterContext = { bg = c.grey[2] }, @@ -143,6 +144,22 @@ function M.get(c, _) ["@lsp.typemod.variable.injected"] = { link = "@variable" }, ["@lsp.typemod.variable.static"] = { link = "@constant" }, + -- Lua: clear LSP semantic tokens inside doc comments so luadoc + -- captures (linked to Comment above) are not overridden. + ["@lsp.type.keyword.lua"] = {}, + ["@lsp.type.property.lua"] = {}, + ["@lsp.type.type.lua"] = {}, + ["@lsp.type.variable.lua"] = {}, + -- Lua docstrings: keep all luadoc captures as comments so annotations + -- like @param, @return, @type don't mix syntax colors into docstrings. + ["@keyword.luadoc"] = { link = "Comment" }, + ["@type.luadoc"] = { link = "Comment" }, + ["@variable.parameter.luadoc"] = { link = "Comment" }, + ["@operator.luadoc"] = { link = "Comment" }, + ["@punctuation.delimiter.luadoc"] = { link = "Comment" }, + ["@punctuation.bracket.luadoc"] = { link = "Comment" }, + ["@string.luadoc"] = { link = "Comment" }, + -- Golang ["@module.go"] = { fg = c.blue }, ["@keyword.function.go"] = { link = "Statement" }, @@ -160,6 +177,13 @@ function M.get(c, _) ["@function.call.just"] = { link = "@variable.parameter" }, } + -- Monochrome: italic fields/properties to distinguish from comments. + if o.variant == "mono" then + theme["@variable.member"] = { fg = c.light_blue, italic = true } + theme["@property"] = { fg = c.cyan, italic = true } + theme["@punctuation.bracket"] = { fg = c.bracket } + end + return theme end diff --git a/lua/flow/init.lua b/lua/flow/init.lua index 8dac904..ef2b34b 100644 --- a/lua/flow/init.lua +++ b/lua/flow/init.lua @@ -1,9 +1,13 @@ local config = require("flow.config") local theme = require("flow.theme") +local util = require("flow.util") -local M = {} - -M.name = "flow" +local M = { + names = { + classic = "flow", + mono = "flow-mono", + }, +} --- This function is called to setup the colorscheme options. --- NOTE: this function is not called when executing `vim.cmd("colorscheme flow")` @@ -13,29 +17,32 @@ M.setup = config._setup --- It sets up the colorscheme by clearing existing highlights, --- enabling true color support, setting the colorscheme name, --- and applying the highlight groups defined in the theme. ---- @param opts FlowConfig? -function M.load(opts) +--- This method is called with `vim.cmd("colorscheme flow")`. +--- @param variant string +--- +function M.load(variant) -- Check if the current colorscheme is different from the one to be loaded. - if vim.g.colors_name ~= M.name then + if not vim.tbl_contains(M.names, vim.g.colors_name) then -- Clear existing highlights. vim.cmd("hi clear") -- Enable true color support. vim.o.termguicolors = true -- Set the current colorscheme name. -- `:lua print(vim.g.colors_name)` - vim.g.colors_name = M.name + vim.g.colors_name = M.names[variant] end - if opts then - M.config(opts) - end + -- Set the variant on the config so highlight modules can check it. + config.options.variant = variant - local highlights = theme.configure() + local highlights, colors = theme.configure() -- The heart of the plugin, where highlight groups are set. - for group, c in pairs(highlights) do - vim.api.nvim_set_hl(0, group, c) + for group, hi in pairs(highlights) do + vim.api.nvim_set_hl(0, group, hi) end + + util.terminal(colors) end return M diff --git a/lua/flow/mono.lua b/lua/flow/mono.lua new file mode 100644 index 0000000..f9917e6 --- /dev/null +++ b/lua/flow/mono.lua @@ -0,0 +1,103 @@ +local hsl = require("flow.util").hsl_to_hex + +local M = {} + +--- Cool blue hue and low saturation for a metallic/steel tone on syntax colors. +M.hue = 220 +M.sat = 3 + +--- Lightness values for desaturated chromatic color replacements. +--- Each color maps to a unique grey lightness for visual distinction. +--- @type table +M.dark_lightness = { + light_blue = 75, + cyan = 68, + purple = 50, + yellow = 82, + green = 62, + orange = 72, + blue = 55, + sky_blue = 78, + -- red is special: replaced by fluo +} + +--- Build a 5-shade metallic color at a given base lightness. +--- @param base_l number Base lightness (0-100) +--- @return table +local function metallic_shades(base_l) + return { + very_dark = hsl(M.hue, M.sat, math.max(base_l - 30, 5)), + dark = hsl(M.hue, M.sat, math.max(base_l - 15, 10)), + default = hsl(M.hue, M.sat, base_l), + light = hsl(M.hue, M.sat, math.min(base_l + 10, 90)), + very_light = hsl(M.hue, M.sat, math.min(base_l + 20, 95)), + } +end + +--- Apply monochrome transformation to the colors table. +--- Desaturates chromatic syntax colors to metallic grey shades and maps +--- keywords (red) to the fluorescent accent color. +--- Greys, black, white, and all UI scaffolding colors are left untouched. +--- @param colors table The colors table from colors.setup() +--- @param opts FlowConfig The configuration options +function M.apply(colors, opts) + local is_dark = opts.theme.style == "dark" + + -- 1. Desaturate chromatic colors to unique metallic grey lightness values + for name, base_l in pairs(M.dark_lightness) do + local l = is_dark and base_l or (100 - base_l) + colors[name] = hsl(M.hue, M.sat, l) + local Key = name:gsub("^%l", string.upper) + colors[Key] = metallic_shades(l) + end + + -- 2. Override red β†’ fluo (keywords/operators use c.red in syntax.lua) + colors.red = colors.fluo + colors.Red = { + very_dark = colors.Fluo.dark, + dark = colors.Fluo.dark, + default = colors.Fluo.default, + light = colors.Fluo.light, + very_light = colors.Fluo.light, + } + + -- 3. Remap semantic colors + -- Diagnostics: fluo shades for error/warning/info, grey for hint + colors.error = colors.Fluo.default + colors.warning = colors.Fluo.dark + colors.info = colors.Fluo.light + colors.hint = colors.grey[7] + + -- Git: distinct metallic grey values + colors.git = { + add = colors.green, + change = colors.light_blue, + delete = colors.red, + ignore = colors.grey[7], + untracked = colors.sky_blue, + } + + -- Diff: use existing greys for subtle background differences + local n = #colors.grey + colors.diff = { + add = is_dark and colors.grey[4] or colors.grey[n - 3], + delete = is_dark and colors.grey[2] or colors.grey[n - 1], + change = is_dark and colors.grey[5] or colors.grey[n - 4], + text = is_dark and colors.grey[4] or colors.grey[n - 3], + parent = is_dark and colors.grey[5] or colors.grey[n - 4], + } + + -- Parentheses/brackets: use fluo accent, dark shade for dark theme, light for light. + colors.bracket = is_dark and colors.Fluo.dark or colors.Fluo.light + + -- Comments: use a grey that's clearly dimmer than syntax elements + colors.comment = is_dark and colors.grey[7] or colors.grey[6] + + -- Special comments: fluo for fixme (urgent), grey for others + colors.fixme = colors.Fluo.default + colors.todo = is_dark and colors.grey[9] or colors.grey[2] + colors.note = is_dark and colors.grey[8] or colors.grey[3] + colors.hack = is_dark and colors.grey[7] or colors.grey[4] +end + +return M diff --git a/lua/flow/palette.lua b/lua/flow/palette.lua index 0df88e3..c0d5106 100644 --- a/lua/flow/palette.lua +++ b/lua/flow/palette.lua @@ -1,210 +1,158 @@ -local hsl = require("flow.util").hsl_to_hex - -local M = {} - ----Generates and returns a color palette using HSL and HEX values. ---- @param o FlowConfig: The available options. ----@return table -function M.get(o) - local is_dark = o.theme.style == "dark" - -- The colorscheme support 5 shades of colors. - local shade = { - very_dark = { S = 27, L = 20 }, - dark = { S = 50, L = 35 }, - default = { - S = (not is_dark and 40) or 60, - L = (not is_dark and 55) or 65, +local util = require("flow.util") +local hsl_to_hex = util.hsl_to_hex + +--- @class HSL +--- @field h number Hue (0-360) +--- @field s number Saturation (0-100) +--- @field l number Lightness (0-100) +local HSL = {} +HSL.__index = HSL + +--- @param h number +--- @param s number +--- @param l number +--- @return HSL +function HSL.new(h, s, l) + return setmetatable({ h = h, s = s, l = l }, HSL) +end + +local M = { + fluo = { + default = "pink", + hue = { + pink = 331, + cyan = 187, + green = 115, + yellow = 61, + orange = 25, + }, + shade = { + very_dark = { S = 25, L = 13 }, + dark = { S = 90, L = 25 }, + default = { S = 100, L = 50 }, + light = { S = 100, L = 77 }, + very_light = { S = 100, L = 90 }, }, - light = { S = 40, L = 65 }, - very_light = { S = 50, L = 85 }, + }, + grey = { + lightness = util.n_chebyshev_values(15, 10, 90), + hue = 203, + saturation = 20, + }, + base = { + hue = { + red = 355, + purple = 270, + blue = 230, + light_blue = 205, + sky_blue = 190, + cyan = 165, + green = 115, + yellow = 60, + orange = 25, + }, + shade = { + very_dark = { S = 27, L = 20 }, + dark = { S = 50, L = 35 }, + default = { S = 40, L = 55 }, + light = { S = 40, L = 65 }, + very_light = { S = 50, L = 85 }, + }, + }, +} + +--- Build an n-step grey scale. +--- @param hue number Hue (0 for achromatic). +--- @param saturation number +--- @param lightness number[] Array of grey lightness values. +--- @return string[] +function M.build_greys(hue, saturation, lightness) + local grey = {} + for i = 1, #lightness do + grey[i] = hsl_to_hex(hue, saturation, lightness[i]) + end + return grey +end + +--- Build a 5-shade color from a hue and shade definition. +--- @param h number Hue value +--- @param shade table Shade definitions with S (saturation) and L (light) for each level +--- @return table +function M.build_color(h, shade) + return { + very_dark = hsl_to_hex(h, shade.very_dark.S, shade.very_dark.L), + dark = hsl_to_hex(h, shade.dark.S, shade.dark.L), + default = hsl_to_hex(h, shade.default.S, shade.default.L), + light = hsl_to_hex(h, shade.light.S, shade.light.L), + very_light = hsl_to_hex(h, shade.very_light.S, shade.very_light.L), } +end - if o.colors.custom.light ~= "" then - ---@diagnostic disable-next-line: assign-type-mismatch - shade[o.colors.mode].L = tonumber(o.colors.custom.light) +--- Update default saturation and light of the selected mode if user provided +--- custom values. +--- @param shade table +--- @param mode string +--- @param l string +--- @param s string +--- @return table +function M.update_light_and_saturation(shade, mode, l, s) + if l ~= "" then + shade[mode].L = tonumber(l) end - if o.colors.custom.saturation ~= "" then - ---@diagnostic disable-next-line: assign-type-mismatch - shade[o.colors.mode].S = tonumber(o.colors.custom.saturation) + if s ~= "" then + shade[mode].S = tonumber(s) end - local hue = { - red = 355, - purple = 270, - blue = 230, - light_blue = 205, - sky_blue = 190, - cyan = 165, - green = 115, - yellow = 60, - orange = 25, - } + return shade +end - local fluo_hue = { - pink = 331, - cyan = 187, - green = 115, - yellow = 61, - orange = 25, - } +--- Generates and returns a color palette using HSL and HEX values. +--- @param config FlowConfig The available theme configuration options. +--- @return table +function M.get(config) + -- Deep copy to avoid mutating the module-level shade table across calls. + local shade = vim.deepcopy(M.base.shade) - -- Get the configured fluo color - local configured_fluo = (o.colors and o.colors.fluo) or "pink" - local fluo_hue_value = fluo_hue[configured_fluo] + local is_dark = config.theme.style == "dark" - local palette = { - -- Transparent color - transparent = "NONE", + if is_dark then + shade.default = { S = 60, L = 65 } + end - -- Base colors - black = hsl(0, 0, 5), - white = hsl(0, 0, 95), - - -- Greyscale colors - grey = { - [1] = hsl(203, 20, 10), -- Very dark grey - [2] = hsl(203, 20, 13), - [3] = hsl(203, 20, 15), - [4] = hsl(203, 12, 18), - [5] = hsl(203, 15, 24), - [6] = hsl(203, 20, 29), - [7] = hsl(203, 20, 50), - [8] = hsl(203, 20, 65), - [9] = hsl(203, 20, 85), - [10] = hsl(203, 20, 88), - [11] = hsl(203, 20, 90), -- Very light grey - }, + shade = M.update_light_and_saturation( + shade, + config.colors.mode, + config.colors.custom.lightness, + config.colors.custom.saturation + ) - -- CursorLine background - uses configured fluo color hue - cursorline_bg = { - dark = hsl(fluo_hue_value, 20, 13), -- For dark theme - light = hsl(fluo_hue_value, 20, 87), -- For light theme - }, + local palette = { + -- Transparent color. + transparent = "NONE", - -- Visual selection background - uses configured fluo color hue - visual_bg = { - dark = hsl(fluo_hue_value, 90, 23), -- For dark theme - light = hsl(fluo_hue_value, 90, 77), -- For light theme (inverted lightness) - }, + -- Base colors. + black = hsl_to_hex(0, 0, 5), + white = hsl_to_hex(0, 0, 95), - -- Float window colors - float_bg = { - dark = hsl(203, 20, 18), -- For dark theme - light = hsl(203, 20, 82), -- For light theme (inverted lightness) - }, + -- Greyscale colors. + grey = M.build_greys(M.grey.hue, M.grey.saturation, M.grey.lightness), - -- Fluorescent colors + -- Fluorescent colors. fluo = { - pink = { - default = hsl(fluo_hue.pink, 100, 50), - light = hsl(fluo_hue.pink, 100, 90), - dark = hsl(fluo_hue.pink, 100, 35), - }, - cyan = { - default = hsl(fluo_hue.cyan, 100, 50), - light = hsl(fluo_hue.cyan, 100, 90), - dark = hsl(fluo_hue.cyan, 100, 30), - }, - green = { - default = hsl(fluo_hue.green, 100, 50), - light = hsl(fluo_hue.green, 100, 100), - dark = hsl(fluo_hue.green, 100, 30), - }, - orange = { - default = hsl(fluo_hue.orange, 100, 50), - light = hsl(fluo_hue.orange, 100, 90), - dark = hsl(fluo_hue.orange, 100, 35), - }, - yellow = { - default = hsl(fluo_hue.yellow, 100, 50), - light = hsl(fluo_hue.yellow, 100, 90), - dark = hsl(fluo_hue.yellow, 100, 30), - }, - }, - - -- Red shades - red = { - very_dark = hsl(hue.red, shade.very_dark.S, shade.very_dark.L), - dark = hsl(hue.red, shade.dark.S, shade.dark.L), - default = hsl(hue.red, shade.default.S, shade.default.L), - light = hsl(hue.red, shade.light.S, shade.light.L), - very_light = hsl(hue.red, shade.very_light.S, shade.very_light.L), - }, - - -- Purple shades - purple = { - very_dark = hsl(hue.purple, shade.very_dark.S, shade.very_dark.L), - dark = hsl(hue.purple, shade.dark.S, shade.dark.L), - default = hsl(hue.purple, shade.default.S, shade.default.L), - light = hsl(hue.purple, shade.light.S, shade.light.L), - very_light = hsl(hue.purple, shade.very_light.S, shade.very_light.L), - }, - - -- Blue shades - blue = { - very_dark = hsl(hue.blue, shade.very_dark.S, shade.very_dark.L), - dark = hsl(hue.blue, shade.dark.S, shade.dark.L), - default = hsl(hue.blue, shade.default.S, shade.default.L), - light = hsl(hue.blue, shade.light.S, shade.light.L), - very_light = hsl(hue.blue, shade.very_light.S, shade.very_light.L), - }, - - -- Light blue shades - light_blue = { - very_dark = hsl(hue.light_blue, shade.very_dark.S, shade.very_dark.L), - dark = hsl(hue.light_blue, shade.dark.S, shade.dark.L), - default = hsl(hue.light_blue, shade.default.S, shade.default.L), - light = hsl(hue.light_blue, shade.light.S, shade.light.L), - very_light = hsl(hue.light_blue, shade.very_light.S, shade.very_light.L), - }, - - -- Sky blue shades - sky_blue = { - very_dark = hsl(hue.sky_blue, shade.very_dark.S, shade.very_dark.L), - dark = hsl(hue.sky_blue, shade.dark.S, shade.dark.L), - default = hsl(hue.sky_blue, shade.default.S, shade.default.L), - light = hsl(hue.sky_blue, shade.light.S, shade.light.L), - very_light = hsl(hue.sky_blue, shade.very_light.S, shade.very_light.L), - }, - - -- Cyan shades - cyan = { - very_dark = hsl(hue.cyan, shade.very_dark.S, shade.very_dark.L), - dark = hsl(hue.cyan, shade.dark.S, shade.dark.L), - default = hsl(hue.cyan, shade.default.S, shade.default.L), - light = hsl(hue.cyan, shade.light.S, shade.light.L), - very_light = hsl(hue.cyan, shade.very_light.S, shade.very_light.L), - }, - - -- Green shades - green = { - very_dark = hsl(hue.green, shade.very_dark.S, shade.very_dark.L), - dark = hsl(hue.green, shade.dark.S, shade.dark.L), - default = hsl(hue.green, shade.default.S, shade.default.L), - light = hsl(hue.green, shade.light.S, shade.light.L), - very_light = hsl(hue.green, shade.very_light.S, shade.very_light.L), - }, - - -- Orange shades - orange = { - very_dark = hsl(hue.orange, shade.very_dark.S, shade.very_dark.L), - dark = hsl(hue.orange, shade.dark.S, shade.dark.L), - default = hsl(hue.orange, shade.default.S, shade.default.L), - light = hsl(hue.orange, shade.light.S, shade.light.L), - very_light = hsl(hue.orange, shade.very_light.S, shade.very_light.L), - }, - - -- Yellow shades - yellow = { - very_dark = hsl(hue.yellow, shade.very_dark.S, shade.very_dark.L), - dark = hsl(hue.yellow, shade.dark.S, shade.dark.L), - default = hsl(hue.yellow, shade.default.S, shade.default.L), - light = hsl(hue.yellow, shade.light.S, shade.light.L), - very_light = hsl(hue.yellow, shade.very_light.S, shade.very_light.L), + pink = M.build_color(M.fluo.hue.pink, M.fluo.shade), + orange = M.build_color(M.fluo.hue.orange, M.fluo.shade), + cyan = M.build_color(M.fluo.hue.cyan, M.fluo.shade), + green = M.build_color(M.fluo.hue.green, M.fluo.shade), + yellow = M.build_color(M.fluo.hue.yellow, M.fluo.shade), }, } + -- Build chromatic colors. + for name, h in pairs(M.base.hue) do + palette[name] = M.build_color(h, shade) + end + return palette end diff --git a/lua/flow/theme.lua b/lua/flow/theme.lua index f573b9d..d9974ed 100644 --- a/lua/flow/theme.lua +++ b/lua/flow/theme.lua @@ -1,68 +1,62 @@ -local flow_colors = require("flow.colors") +local colors = require("flow.colors") local util = require("flow.util") -local M = {} - ---- List of active highlight groups to be configured. ---- @type string[] -M.active_highlights = { - "base", - "blink", - "syntax", - "markdown", - "completion", - "dap", - "diagnostic", - "flash", - "fzf-lua", - "git", - "ibl", - "lazy", - "lsp", - "mini-hipatterns", - "mini-files", - "oil", - "render-markdown", - "statusline", - "telescope", - "todo-comments", - "treesitter", - "trouble", - "whichkey", - "winbar", - "undotree", - "vim-highlighturl", - "mason", - "avante", +local M = { + --- List of active pulugins highlight groups to be configured. + --- @type string[] + active_highlights = { + "avante", + "base", + "blink", + "completion", + "dap", + "diagnostic", + "flash", + "fzf-lua", + "git", + "ibl", + "lazy", + "lsp", + "mini-hipatterns", + "mini-files", + "markdown", + "mason", + "oil", + "render-markdown", + "statusline", + "syntax", + "telescope", + "todo-comments", + "treesitter", + "trouble", + "whichkey", + "winbar", + "undotree", + "vim-highlighturl", + }, } -M.b = {} - ---- Configure the colorscheme highlights. ---- This function sets up the highlight groups by merging the colors +--- Sets the highlight groups up by merging the colors --- and options for each active highlight group. ---- @return table: A table of configured highlight groups. +--- @return table Highlight groups. +--- @return table Flow colors. function M.configure() -- Options retrieved can be the default one or those modified by the call to - -- `require("flow").config{}` + -- `require("flow").setup{}` local options = require("flow.config").options - local colors = flow_colors.setup(options) + local flow_colors = colors.setup(options) local highlights = {} for _, h in ipairs(M.active_highlights) do local group_path = "flow.highlights." .. h local group = require(group_path) - local hi = group.get(colors, options) + local hi = group.get(flow_colors, options) highlights = util.merge(highlights, hi) end - vim.api.nvim_set_hl(0, "@lsp.type.property.lua", {}) - - -- util.autocmds() - - return highlights + return highlights, flow_colors end return M diff --git a/lua/flow/util.lua b/lua/flow/util.lua index 73a2bee..e026165 100644 --- a/lua/flow/util.lua +++ b/lua/flow/util.lua @@ -9,6 +9,34 @@ function M.merge(left, right) return left end +function M.n_equidistant_values(n, range) + assert(n >= 2, "number of points should be >= 2") + local step = math.floor(range / n) + + local values = {} + for i = 0, n do + values[i + 1] = i * step + step + end + + return values +end + +--- Generate n+1 Chebyshev-spaced values over [low, high]. +--- Nodes cluster near both endpoints, giving finer gradation in the +--- darks and lights with wider spacing through the mid-tones. +function M.n_chebyshev_values(n, low, high) + assert(n >= 2, "number of points should be >= 2") + + local values = {} + for i = 0, n do + -- Chebyshev nodes on [-1, 1]: cos(i * pi / n), mapped to [low, high] + local node = math.cos(i * math.pi / n) + values[i + 1] = math.floor((1 - node) / 2 * (high - low) + low + 0.5) + end + + return values +end + function M.hsl_to_hex(h, s, l) local r, g, b = M.hsl_to_rbg(h, s, l) return M.rgb_to_hex(r, g, b) @@ -60,34 +88,38 @@ function M.hsl_to_rbg(h, s, l) return math.floor(0.5 + r * 255), math.floor(0.5 + g * 255), math.floor(0.5 + b * 255) end --- TODO: complete function M.terminal(colors) - -- dark + -- black vim.g.terminal_color_0 = colors.black - vim.g.terminal_color_8 = colors.terminal_black + vim.g.terminal_color_8 = colors.grey[5] - -- light - vim.g.terminal_color_7 = colors.terminal_white - vim.g.terminal_color_15 = colors.fg + -- red + vim.g.terminal_color_1 = colors.Red.dark + vim.g.terminal_color_9 = colors.Red.light - -- colors - vim.g.terminal_color_1 = colors.red - vim.g.terminal_color_9 = colors.red + -- green + vim.g.terminal_color_2 = colors.Green.dark + vim.g.terminal_color_10 = colors.Green.light - vim.g.terminal_color_2 = colors.cyan - vim.g.terminal_color_10 = colors.cyan + -- yellow + vim.g.terminal_color_3 = colors.Yellow.dark + vim.g.terminal_color_11 = colors.Yellow.light - vim.g.terminal_color_3 = colors.yellow - vim.g.terminal_color_11 = colors.yellow + -- blue + vim.g.terminal_color_4 = colors.Blue.dark + vim.g.terminal_color_12 = colors.Blue.light - vim.g.terminal_color_4 = colors.blue - vim.g.terminal_color_12 = colors.blue + -- magenta + vim.g.terminal_color_5 = colors.Purple.dark + vim.g.terminal_color_13 = colors.Purple.light - vim.g.terminal_color_5 = colors.purple - vim.g.terminal_color_13 = colors.purple + -- cyan + vim.g.terminal_color_6 = colors.Cyan.dark + vim.g.terminal_color_14 = colors.Cyan.light - vim.g.terminal_color_6 = colors.cyan - vim.g.terminal_color_14 = colors.cyan + -- white + vim.g.terminal_color_7 = colors.grey[7] + vim.g.terminal_color_15 = colors.white end --- Interpolates a string by replacing placeholders with corresponding values from a table. diff --git a/lua/lualine/themes/flow.lua b/lua/lualine/themes/flow.lua index a575daf..a574114 100644 --- a/lua/lualine/themes/flow.lua +++ b/lua/lualine/themes/flow.lua @@ -1,53 +1,76 @@ local colors = require("flow.colors").colors +local is_mono = vim.g.colors_name == "flow-mono" local flow = {} --- Normal mode colors. a will be used also for x, --- b for y, and c for z to have a symmetrical coloration. -flow.normal = { - a = { bg = colors.light_blue, fg = colors.bg_highlight }, - b = { bg = colors.bg_highlight, fg = colors.light_blue }, - c = { bg = colors.bg_statusline, fg = colors.fg_statusline }, -} - --- Insert mode colors. a will be used also for x, --- b for y, and c for z to have a symmetrical coloration. -flow.insert = { - a = { bg = colors.cyan, fg = colors.bg_highlight }, - b = { bg = colors.bg_highlight, fg = colors.cyan }, -} - --- Command mode colors. a will be used also for x, --- b for y, and c for z to have a symmetrical coloration. -flow.command = { - a = { bg = colors.yellow, fg = colors.bg_highlight }, - b = { bg = colors.bg_highlight, fg = colors.yellow }, -} - --- Visual mode colors. a will be used also for x, --- b for y, and c for z to have a symmetrical coloration. -flow.visual = { - a = { bg = colors.purple, fg = colors.bg_highlight }, - b = { bg = colors.bg_highlight, fg = colors.purple }, -} - --- Replace mode colors. a will be used also for x, --- b for y, and c for z to have a symmetrical coloration. -flow.replace = { - a = { bg = colors.red, fg = colors.bg_highlight }, - b = { bg = colors.bg_highlight, fg = colors.red }, -} - --- Terminal mode colors. a will be used also for x, --- b for y, and c for z to have a symmetrical coloration. -flow.terminal = { - a = { bg = colors.green, fg = colors.bg_highlight }, - b = { bg = colors.bg_highlight, fg = colors.green }, -} - --- Inactive mode colors. Only c seems to be applied here -flow.inactive = { - c = { bg = colors.bg_statusline, fg = colors.fg_gutter }, -} +if is_mono then + -- Monochrome: grey backgrounds, fluo for active mode indicator. + -- All vim modes shares the same colors. + local grey_a = { bg = colors.grey[6], fg = colors.bg_highlight } + local grey_b = { bg = colors.bg_highlight, fg = colors.grey[6] } + local fluo_a = { bg = colors.fluo, fg = colors.bg_highlight } + + flow.normal = { + a = fluo_a, + b = grey_b, + c = { bg = colors.bg_statusline, fg = colors.fg_statusline }, + } + flow.insert = { a = grey_a, b = grey_b } + flow.command = { a = grey_a, b = grey_b } + flow.visual = { a = grey_a, b = grey_b } + flow.replace = { a = grey_a, b = grey_b } + flow.terminal = { a = grey_a, b = grey_b } + flow.inactive = { + c = { bg = colors.bg_statusline, fg = colors.fg_gutter }, + } +else + -- Normal mode colors. a will be used also for x, + -- b for y, and c for z to have a symmetrical coloration. + flow.normal = { + a = { bg = colors.light_blue, fg = colors.bg_highlight }, + b = { bg = colors.bg_highlight, fg = colors.light_blue }, + c = { bg = colors.bg_statusline, fg = colors.fg_statusline }, + } + + -- Insert mode colors. a will be used also for x, + -- b for y, and c for z to have a symmetrical coloration. + flow.insert = { + a = { bg = colors.cyan, fg = colors.bg_highlight }, + b = { bg = colors.bg_highlight, fg = colors.cyan }, + } + + -- Command mode colors. a will be used also for x, + -- b for y, and c for z to have a symmetrical coloration. + flow.command = { + a = { bg = colors.yellow, fg = colors.bg_highlight }, + b = { bg = colors.bg_highlight, fg = colors.yellow }, + } + + -- Visual mode colors. a will be used also for x, + -- b for y, and c for z to have a symmetrical coloration. + flow.visual = { + a = { bg = colors.purple, fg = colors.bg_highlight }, + b = { bg = colors.bg_highlight, fg = colors.purple }, + } + + -- Replace mode colors. a will be used also for x, + -- b for y, and c for z to have a symmetrical coloration. + flow.replace = { + a = { bg = colors.red, fg = colors.bg_highlight }, + b = { bg = colors.bg_highlight, fg = colors.red }, + } + + -- Terminal mode colors. a will be used also for x, + -- b for y, and c for z to have a symmetrical coloration. + flow.terminal = { + a = { bg = colors.green, fg = colors.bg_highlight }, + b = { bg = colors.bg_highlight, fg = colors.green }, + } + + -- Inactive mode colors. Only c seems to be applied here + flow.inactive = { + c = { bg = colors.bg_statusline, fg = colors.fg_gutter }, + } +end return flow