diff --git a/README.md b/README.md index 9592ec80..4052c7db 100644 --- a/README.md +++ b/README.md @@ -7,7 +7,7 @@ Dark and light themes for Neovim 0.5 and above, written in Lua
Treesitter enabled / Fully customisable / Many popular plugins supported
- Inspired by VS Code's One Dark Pro + Inspired by VS Code's One Dark Pro

@@ -30,6 +30,7 @@ - [Configuring styles](#configuring-styles) - [Configuring colors](#configuring-colors) - [Configuring highlight groups](#configuring-highlight-groups) + - [Configuring filetype highlight groups](#configuring-filetype-highlight-groups) - [Configuring options](#configuring-options) - [Extras](#gift-extras) - [Terminal themes](#terminal-themes) @@ -39,6 +40,7 @@ ## :sparkles: Features - **Dark** and **light** versions - *onedark* and *onelight* +- Supports **custom highlighting across filetypes** - [Treesitter](https://github.com/nvim-treesitter/nvim-treesitter) support - Options to specify styles for: - Comments @@ -46,7 +48,7 @@ - Keywords - Strings - Variables -- Override default styles, colors and highlight groups +- Override default styles, colors, highlight groups and filetype highlight groups - Create custom highlight groups - [LSP](https://github.com/neovim/nvim-lspconfig) diagnostics support - Support for a large array of [vim-polygot](https://github.com/sheerun/vim-polyglot) packs (pull requests welcome) @@ -88,6 +90,8 @@ #### React Comparison to VS Code - React +> **Note:** A greater likeness to `VS Code` can be achieved by using the theme's ability to [customise highlight groups by filetype](#configuring-filetype-highlight-groups) + ### Lualine #### Dark Lualine Dark @@ -152,7 +156,7 @@ The theme's default configuration as per the [config.lua](https://github.com/oli ```lua local onedarkpro = require("onedarkpro") onedarkpro.setup({ - -- Theme can be overwritten with 'onedark' or 'onelight' as a string! + -- Theme can be overwritten with 'onedark' or 'onelight' as a string theme = function() if vim.o.background == "dark" then return "onedark" @@ -160,13 +164,14 @@ onedarkpro.setup({ return "onelight" end end, - colors = {}, -- Override default colors. Can specify colors for "onelight" or "onedark" themes by passing in a table - hlgroups = {}, -- Override default highlight groups + colors = nil, -- Override default colors by specifying colors for 'onelight' or 'onedark' themes + hlgroups = nil, -- Override default highlight groups + filetype_hlgroups = nil, -- Override default highlight groups for specific filetypes plugins = { -- Override which plugins highlight groups are loaded native_lsp = true, polygot = true, treesitter = true, - -- Others omitted for brevity + -- NOTE: Other plugins have been omitted for brevity }, styles = { strings = "NONE", -- Style that is applied to strings @@ -193,7 +198,7 @@ onedarkpro.load() Use either `onedark` or `onelight` for the dark and light themes, respectively. ```lua -theme = "onedark", -- [onedark/onelight] +theme = "onedark", -- Either "onedark" or "onelight" ``` If no value is specified, the current value of `vim.o.background` will be used to set the theme. @@ -204,21 +209,28 @@ By default, all of the plugins supported by the theme are loaded at runtime. Spe plugins = { native_lsp = false, polygot = false, - treesitter = false, + treesitter = false } ``` - Alternatively, all of the plugins can be disabled at once: ```lua plugins = { all = false } ``` +Or, all of the plugins can be disabled with only a select few enabled: +```lua +plugins = { + all = false + native_lsp = true, + treesitter = true +} +``` -> **Note:** For a full list of plugins, see the plugins [folder](https://github.com/olimorris/onedarkpro.nvim/tree/main/lua/onedarkpro/plugins) +> **Note:** For a full list of plugins supported in the theme, see the plugins [folder](https://github.com/olimorris/onedarkpro.nvim/tree/main/lua/onedarkpro/plugins) ### Configuring styles -Styles can be set by specifying the highlight group from the [theme.lua](https://github.com/olimorris/onedarkpro.nvim/blob/main/lua/onedarkpro/theme.lua) file alongside any desired styles: +Styles can be set by specifying the highlight group from the [theme.lua](https://github.com/olimorris/onedarkpro.nvim/blob/main/lua/onedarkpro/theme.lua) file (and any plugin files) alongside the desired style(s): ```lua styles = { @@ -244,13 +256,13 @@ colors = { } ``` #### Specifying new colors -New colors may be specified which will then be merged into the theme's color palette: +New colors may be specified in the configuration which will then be merged into the theme's color palette: ```lua colors = { my_new_red = "#f44336" } ``` -> **Note:** Custom colors can be referenced in highlight group overrides +> **Note:** Custom colors can also be referenced when creating custom highlight group overrides in `hlgroups` #### Specifying colors by theme It's possible to override default colors within the theme such as the `bg` color. This is a common question for those who wish to have a darker background than the default. Of course it would make sense to have different `bg` colors for the `onedark` and `onelight` themes. This can be achieved by specifying the theme name as a table, followed by the color: @@ -258,11 +270,11 @@ It's possible to override default colors within the theme such as the `bg` color ```lua colors = { onedark = { - bg = "#FFFF00", -- yellow + bg = "#FFFF00" -- yellow }, onelight = { - bg = "#00FF00", -- green - }, + bg = "#00FF00" -- green + } } ``` @@ -276,10 +288,57 @@ The [theme.lua](https://github.com/olimorris/onedarkpro.nvim/tree/main/lua/oneda hlgroups = { -- Overriding the Comment highlight group Comment = { fg = "#FF0000", bg = "#FFFF00", style = "italic" }, -- 1 Comment = { fg = "${my_new_red}" bg = "${yellow}", style = "bold,italic" }, -- 2 - Comment = { link = "Substitute" }, -- 3 + Comment = { link = "Substitute" } -- 3 } ``` +### Configuring filetype highlight groups +The original One Dark Pro utilises custom highlights based on filetype to achieve its distinctive look. This can also be achieved within the theme: + +```lua +filetype_hlgroups = { + yaml = { -- Use the filetype as per the `set filetype?` command + TSField = { fg = "${red}" } + }, + python = { + TSConstructor = { fg = "${bg}", bg = "${red}" } + } +} +``` +> **Note:** Please see [this issue](https://github.com/olimorris/onedarkpro.nvim/issues/24) for how other users are configuring their theme by filetype + +> **Note:** Currently support for highlighting in Telescope's previewer is unavailable. + +#### Ignoring filetypes and buffer types +Filetype highlight groups work by detecting the filetype of the current buffer and checking the user's config to determine if any should be applied. If neccessary, the theme's default highlight groups are reapplied if the buffer filetype has no custom filetype highlights specified. + +When using common plugins such as [Telescope](https://github.com/nvim-telescope/telescope.nvim) or [Trouble](https://github.com/folke/trouble.nvim), additional windows with distinct filetypes are opened. This can cause the theme to reapply the default highlight groups since it detects a buffer filetype change. When closing the windows, the user's custom filetype highlight groups are then lost. To prevent this from happening, the theme has a table of filetypes and buffer types to ignore: + +```lua +filetype_hlgroups_ignore = { + filetypes = { + "^aerial$", + "^alpha$", + "^fugitive$", + "^fugitiveblame$", + "^help$", + "^NvimTree$", + "^packer$", + "^qf$", + "^startify$", + "^startuptime$", + "^TelescopePrompt$", + "^TelescopeResults$", + "^terminal$", + "^toggleterm$", + "^undotree$" + }, + buftypes = { + "^terminal$" + } +``` +Additional filetypes and buffer types can be added in the config. + ### Configuring options #### Formatting @@ -292,7 +351,7 @@ options = { bold = true, -- Use the themes opinionated bold styles? italic = true, -- Use the themes opinionated italic styles? underline = true, -- Use the themes opinionated underline styles? - undercurl = true, -- Use the themes opinionated undercurl styles? + undercurl = true -- Use the themes opinionated undercurl styles? } ``` @@ -343,17 +402,17 @@ options = { ### Terminal themes The theme comes with [Alacritty](https://github.com/alacritty/alacritty) and [Kitty](https://github.com/kovidgoyal/kitty) themes. These can be found in the [extras](https://github.com/olimorris/onedarkpro.nvim/tree/main/extras) folder. -### Helper functions +### Helpers #### Theme color tables -To enable plugins to match this theme, a helper function, `get_colors()`, has been included. This returns a table of the theme's current colors. +To enable the theme's colors to be extracted and used elsewhere in the Neovim config, a helper function, `get_colors()`, has been included. This returns a table of the theme's current colors. ```lua local colors = require("onedarkpro").get_colors("onelight") print(colors.purple) -- #9a77cf ``` -Changing the theme from `onelight` to `onedark` would return a new table of colors. +> **Note:** Changing the theme from `onelight` to `onedark` would return a new table of colors. > **Note:** Setting a `ColorScheme` autocommand which refreshes the configuration of the relevant plugin will ensure that they are using the correct colors from **One Dark Pro** @@ -367,9 +426,33 @@ function ToggleTheme() else vim.o.background = "dark" end - require("onedarkpro").load() end ``` +Alongside a custom autocommand to reload the theme's config on a colorscheme change: +```lua +local autocmds = { + onedarkpro_theme_autocmds = { + { + "ColorScheme", + "*", + "lua require(\"path_to_my_theme_config\").function_to_call()" + } + } +} +require("onedarkpro.utils").create_augroups(autocmds) +``` +> **Note:** The autocommand is useful if there is deviation from the theme's default configuration + +#### Configuring styles/colors/highlight groups based on the theme +When configuring the theme, it may be useful to apply different colors or styles depending on whether `onedark` or `onelight` is active. This can be achieved by applying a conditional in the configuration: + +```lua +hlgroups = { + TSField = { + fg = (vim.o.background == "dark" and "${red}" or "${green}") + } +} +``` ## :clap: Credits @@ -382,8 +465,6 @@ Thanks to the following contributors for their work on the theme: The following themes were used as an inspiration: * [One Dark Pro](https://github.com/Binaryify/OneDark-Pro) - The inspiration for this theme -* [Nightfox](https://github.com/EdenEast/nightfox.nvim) - Originally used the theme's layout and utilities however moved away quite significantly since -* [onedark.vim](https://github.com/joshdick/onedark.vim) - For the application of `onedark` colors in Neovim * [GitHub nvim theme](https://github.com/projekt0n/github-nvim-theme) - For the logo inspiration :wink: ## :page_with_curl: License diff --git a/lua/onedarkpro/colors/onedark.lua b/lua/onedarkpro/colors/onedark.lua index 1054b95c..f8d49002 100644 --- a/lua/onedarkpro/colors/onedark.lua +++ b/lua/onedarkpro/colors/onedark.lua @@ -18,7 +18,7 @@ function M.load(config) blue = "#61afef", purple = "#c678dd", white = "#abb2bf", - black = "#1e1e1e", + black = "#282c34", gray = "#5c6370", highlight = "#e2be7d", none = "NONE" diff --git a/lua/onedarkpro/config.lua b/lua/onedarkpro/config.lua index f3168099..cd0749c9 100644 --- a/lua/onedarkpro/config.lua +++ b/lua/onedarkpro/config.lua @@ -10,8 +10,27 @@ M.config = { return "onelight" end end, - colors = {}, -- Override default colors - hlgroups = {}, -- Override default highlight groups + colors = nil, -- Override default colors + hlgroups = nil, -- Override default highlight groups + filetype_hlgroups = nil, -- Override default highlight groups for specific filetypes + filetype_hlgroups_ignore = { -- Filetypes which are ignored when applying filetype highlight groups + filetypes = { + "^aerial$", + "^alpha$", + "^fugitive$", + "^fugitiveblame$", + "^help$", + "^NvimTree$", + "^packer$", + "^qf$", + "^startify$", + "^startuptime$", + "^terminal$", + "^toggleterm$", + "^undotree$" + }, + buftypes = { "^terminal$" } + }, plugins = { -- Enable/Disable specific plugins aerial = true, barbar = true, diff --git a/lua/onedarkpro/utils.lua b/lua/onedarkpro/utils.lua index 5ad69cd7..3f353150 100644 --- a/lua/onedarkpro/utils.lua +++ b/lua/onedarkpro/utils.lua @@ -210,6 +210,108 @@ function utils.print_table(tbl) require("pl.pretty").dump(tbl) end +---Set an autocommand +---Taken from https://github.com/norcalli/nvim_utils/blob/master/lua/nvim_utils.lua#L554-L567 +-- @param definitions table +-- @return vim.api +function utils.create_augroups(definitions) + for group_name, definition in pairs(definitions) do + vim.api.nvim_command("augroup " .. group_name) + vim.api.nvim_command("autocmd!") + for _, def in ipairs(definition) do + -- if type(def) == 'table' and type(def[#def]) == 'function' then + -- def[#def] = lua_callback(def[#def]) + -- end + local command = + table.concat(vim.tbl_flatten { "autocmd", def }, " ") + vim.api.nvim_command(command) + end + vim.api.nvim_command("augroup END") + end +end + +---When a user moves from a filetype with specific hlgroups to a filetype with +---none, we need to apply the theme's default hlgroups. To make this less +---expensive, we match the users configured filetype hlgroups to the theme's +---@param table hlgroups hlgroups from the theme + the user's config +---@param table fhlgroups hlgroups for filetypes from the user's config +---@return table +local function intersect_groups(hlgroups, fhlgroups) + -- Find the intersection between the tables and extract the common hlgroups + local matched_groups = {} + for filetype, _ in pairs(fhlgroups) do + for group, _ in pairs(fhlgroups[filetype]) do + if matched_groups[group] == nil then + matched_groups[group] = true + end + end + end + + -- Then extract the matched groups from the theme's hlgroups + local retained_hlgroups = {} + for group, _ in pairs(matched_groups) do + retained_hlgroups[group] = hlgroups[group] + end + + return retained_hlgroups +end + +---Return true if any pattern in the tbl matches the provided value +---@param tbl table +---@param val string +---@return boolean +local function find_pattern_match(tbl, val) + return tbl and next(vim.tbl_filter(function(pattern) + return val:match(pattern) + end, tbl)) +end + +---Ignore a buffer based on the filetype or the buffertype +-- @return boolean +local function ignore_buffer() + local buftype = vim.bo.buftype + local filetype = vim.bo.filetype + + return + find_pattern_match(vim.g.theme_fhlgroups_ignore.filetypes, filetype) or + find_pattern_match(vim.g.theme_fhlgroups_ignore.buftypes, buftype) +end + +---Set custom hlgroups based on the buffer filetype +---@param string force_apply forcefully apply highlighting +---@return nil +function utils.set_fhlgroups(force_apply) + local filetype = vim.bo.filetype + + if (filetype == vim.g.theme_last_filetype and not force_apply) or + ignore_buffer() or filetype == "" then + return + end + + local hlgroups = vim.g.theme_hlgroups + local fhlgroups = vim.g.theme_fhlgroups + + -- If the user has moved to a new buffer filetype and there are no specific + -- configs set, then we reapply the theme's default hlgroups to override + -- any previously applied ones + if not fhlgroups[filetype] then + if vim.g.theme_applied_fhlgroups then + for group, colors in pairs(hlgroups) do + utils.create_highlights(group, colors) + end + vim.g.theme_applied_fhlgroups = false + end + return + end + + for group, colors in pairs(fhlgroups[filetype]) do + utils.create_highlights(group, colors) + end + + vim.g.theme_last_filetype = filetype + vim.g.theme_applied_fhlgroups = true +end + ---Load the desired theme ---@param theme table ---@return nil @@ -243,10 +345,36 @@ function utils.load_theme(theme) utils.terminal(theme) end - --[[ - Due to recent configuration changes, we need to check if the user is using - the "link =" annotations correcrtly. If not, warn them accordingly - ]] + -- Configure any filetype highlight groups + if theme.config.filetype_hlgroups then + -- Replace the color variables with actual colors + local fhlgroups = utils.template_table(theme.config.filetype_hlgroups, + theme.colors) + + vim.g.theme_fhlgroups_ignore = theme.config.filetype_hlgroups_ignore + + -- Set a global variable so we may access the colors after loading + vim.g.theme_fhlgroups = fhlgroups + vim.g.theme_hlgroups = intersect_groups(adjusted_hlgroups, fhlgroups) + + local autocmds = { + onedarkpro_theme_autocmds = { + { + "BufEnter", + "*", + "lua require(\"onedarkpro.utils\").set_fhlgroups()" + }, + { + "ColorScheme", + "*", + "lua require(\"onedarkpro.utils\").set_fhlgroups(true)" + } + } + } + utils.create_augroups(autocmds) + end + + -- Check if the user is using the "link =" annotations correctly local warn = 0 for _, colors in pairs(hlgroups) do for key, _ in pairs(colors) do @@ -289,7 +417,7 @@ function utils.load_theme(theme) "-----------------------------------------------------------------------------------") end - -- Trigger the colorscheme autocommand + -- Trigger an autocommand on loading the theme vim.cmd([[doautocmd ColorScheme]]) end