rktjmp / lush.nvim

Create Neovim themes with real-time feedback, export anywhere.

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

How to import a single highlight ?

teto opened this issue · comments

hi,

This may be more of a support question than a bug but here is my scenario:
I have cursorline enabled but my current hardcoded color for "CursorLine" is too close to "Normal", i.e. hardly visible. So I want to set the CursorLine guibg to a lighter "Normal".

To rephrase it, I would like to import the "Normal" highlight and assign it with a lighter guibg to CursorLine. I've looked at lush's code and lua/lush/importer.lua seems to contain the code I want to use but it just exports capture_current. I would like to access a "import_highlight("Normal")" that loads the current "Normal" highlight and transforms it into a lush value so that I can apply lush functions on it.

It sounds like you're not currently using Lush, but want to grab the current Normal highlight (as given by :hi Normal), then use Lush's color functions to adjust the color?

The importer only exists as a shortcut for people who have an existing colorscheme that they want to convert wholesale for use "in the lush ecosystem" (eg: you want to use Nord but tweak it via Lush). You're only expected to run it once then work on the Lush spec directly, so it doesn't provide any tools for individual groups (you could run it and copy-paste separate groups out).

So, assuming I understand the idea you probably want something like this?

local function via_viml_ish()
  -- broadly compatible
  -- get current hl
  local normal_viml = vim.fn.execute("highlight Normal")
  -- code copied from from importer
  local group_name, rules = string.match(normal_viml, "\n([%w_]+)%s+xxx%s+(%w.+)")
  local attrs = {
    -- fg = string.match(rules, "guifg=([%w#]+)"),
    bg = string.match(rules, "guibg=([%w#]+)"),
    -- sp = string.match(rules, "guisp=([%w#]+)"),
    -- gui = string.match(rules, "gui=([%w,]+)"),
    -- blend = string.match(rules, "blend=([%d]+)"),
  }
  -- get lush for hsl
  local lush = require("lush")
  -- convert string to hsl, apply mods, get hex value
  local bg = lush.hsl(attrs.bg).ro(99).li(29).hex
  -- apply adjusted highlight, viml highlight function will *patch* current afaik
  vim.fn.execute(string.format("highlight CursorLine guibg=%s", bg))
end

local function via_new_api()
  -- 0.7+, maybe even 0.8+ as some bugs have been fixed around getting values
  local normal = vim.api.nvim_get_hl_by_name("Normal", true)
  -- must convert RRGGBB int to RRGGBB hex
  local normal_bg = string.format("#%0X", normal.background)
  -- get lush for hsl
  local lush = require("lush")
  -- convert string to hsl, apply mods, get hex value
  local bg = lush.hsl(normal_bg).ro(180).li(10).hex
  -- set_hl will *not* patch current hl, so if it has additional styles you
  -- will have to get and parse them as we did for Normal at the start.
  vim.api.nvim_set_hl(0, "Cursorline", {bg = bg})
end

@rktjmp that's exactly it, your description was clearer than mine sry ^^

The importer only exists as a shortcut for people who have an existing colorscheme that they want to convert wholesale for use "in the lush ecosystem" (eg: you want to use Nord but tweak it via Lush). You're only expected to run it once then work on the Lush spec directly, so it doesn't provide any tools for individual groups (you could run it and copy-paste separate groups out).

That's what I would like to challenge, the functions are there, why not expose them ?
There could be a LushHighlight "object" with toNvim / fromNvim / apply members ? As you mention, I am just looking into lush now so you may have a better idea. It would make lush more usable as a library (without having to go "full colorscheme").

NB: thanks for keeping #58 open. I've merged rockspec support in nixpkgs, i.e., packaging vim plugins with a rockspec is now a breeze, nix can get the metadata from the rockspec and install vim plugin dependencies automatically. I will submit an update to this PR today or tomorrow

Not against the idea, but it does add some API complexity and maintenance burden to something that isn't at present core to Lush's use case. That said, Lush's goal is to let people create - or modify - their own colorschemes easily, so this could become part of Lush's use case.

Is there a specific reason you don't want to just dump your colorscheme into a lush-spec and work with it as normal?

I imagine the API would be something like

-- get one group
normal = lush.bridge.get("Normal")
print(normal)
-- {
--   fg = #RRGGBB
--   bg = #RRGGBB
--   -- non-set keys are not included (nil'd)
-- }

-- assignment required as lush operators return new values by design
normal.fg = normal.fg.da(20)
lush.bridge.set("Normal", normal)

-- get collection of groups
groups = lush.bridge.get(["Normal", "Comment"])
print(groups)
-- {
--   Normal = { fg ... },
--   Comment { fg ... }
-- }
groups.Normal.fg = "red"
lush.bridge.set(groups)

Link groups may just return values (this mirrors nvim_get_hl_by_name) and discard link information or maybe return a link key, which mirrors nvim_set_hl.

-- hi Normal guifg=red
-- hi Comment link Normal
groups = lush.bridge.get(["Normal", "Comment"])
print(groups.Normal)
-- {
--   fg = red
-- }
print(groups.Comment)
-- {
--   fg = red
-- }
-- or maybe
-- {
--  link = "Normal"
-- }
  • bridge.set would always apply via nvim_set_hl meaning missing values will be cleared.
  • possibly 0.8 required for neovim/neovim#18981 neovim/neovim#18820
  • you cant set link groups, probably. Perhaps lush.bridge.link("Normal", "Comment"). {link = "Comment"}

I think I would ditch groups = lush.bridge.get(["Normal", "Comment"]) as it makes the API more complex for little benefit, e.g., users can do a loop themselves.

I agree with

-- get one group
normal = lush.bridge.get("Normal")
print(normal)
-- {
--   fg = #RRGGBB
--   bg = #RRGGBB
--   -- non-set keys are not included (nil'd)
-- }

If we consider normal as an object, we could end up with normal.apply() instead of lush.bridge.set("Normal", normal). Not saying it's better, just a suggestion.

Is there a specific reason you don't want to just dump your colorscheme into a lush-spec and work with it as normal?

I have a pretty fluid setup as I tend to try a few things as a neovim contributor/package maintainer for neovim. I sometimes change colorschemes and while I am not deep into aesthetics, there are some highlights I especially care about like CursorLine, CursorLineNr. I thought I could adjust those automatically the way I liked for any colorscheme by setting theme to a brighter Normal. So I looked for a library that could change the "lightness" of any color and I immediately thought of lush.
I think the API would be worth adding because mandating to go for a full "lush" colorscheme is too big a commitment.