rktjmp / lush.nvim

Create Neovim themes with real-time feedback, export anywhere.
MIT License
1.44k stars 47 forks source link

Add nvim_set_hl support #87

Closed rktjmp closed 2 years ago

rktjmp commented 2 years ago

Updates Lush to use the new nvim_set_hl API, which is potentially quite a bit faster, relatively speaking.

set_hl: avg=0.002253ms min=0.000994ms max=0.072028ms
viml: avg=0.176153ms min=0.136388ms max=7.747195ms

In practical terms, themes go from ~1-2ms application to 1-0.5ms application, depending on the themes size.

```fennel (fn viml [cmd] ;; bench application only so assume we are given pre-computed string (vim.cmd cmd)) (fn set-hl [attrs] ;; "pre-computed string" == table (vim.api.nvim_set_hl 0 :Normal attrs)) ;; generate a list of highlights (math.randomseed (os.time)) (local highlights []) (for [i 1 10000] (let [r (math.random 16 255) g (math.random 16 255) b (math.random 16 255)] (table.insert highlights {:fg (string.format "#%x%x%x" r g b) :bg (string.format "#%x%x%x" b g r)}))) (local set-hl-times []) (each [_ {:fg fg :bg bg} (ipairs highlights)] (local a (vim.loop.hrtime)) (vim.api.nvim_set_hl 0 :Normal {:fg fg :bg bg}) (local b (vim.loop.hrtime)) (table.insert set-hl-times (- b a))) (local viml-times []) (each [_ {:fg fg :bg bg} (ipairs highlights)] (local cmd (string.format "highlight Normal guifg='%s' guibg='%s'" fg bg)) (local a (vim.loop.hrtime)) (vim.cmd cmd) (local b (vim.loop.hrtime)) (table.insert viml-times (- b a))) (fn report [name list] (fn ns-ms [ns] (/ ns 1_000_000)) (let [{:sum sum :min min :max max} (accumulate [via {:sum 0 :min 10000000 :max 0} _ t (ipairs list)] {:sum (+ via.sum t) :min (if (< t via.min) t via.min) :max (if (< via.max t) t via.max)})] (print (string.format "%s: avg=%fms min=%fms max=%fms" name (-> (/ sum (length list)) (ns-ms)) (ns-ms min) (ns-ms max))))) (report "set_hl" set-hl-times) (report "viml" viml-times) ```
MurdeRM3L0DY commented 2 years ago
  • [ ] Adjust apply to accept any key given in spec and pass that on to nvim_set_hl?

    • Better maintenance for Lush as features are automatically supported
    • Breaking change due to gui property.

maybe add to_hl or something similar to op_fns as well?

rktjmp commented 2 years ago

That would be a bit frictional I think.

Currently I am thinking there will be two (!!!) breaking releases.

The first will just require 0.7 for nvim_set_hl compatibility, not a """huge""" deal. This will retain all the same spec behaviour, and add no additional key support.

The second may drop gui in favour of accepting any key in the spec and just forwarding on what it's given. Not 100% on this yet as I don't really know if needing italic = true, bold = true is any better than gui = "italic, bold". It's closer to nvim's true API but not exactly any more ergonomic and Lush is already an abstraction anyway. I could probably inject some state into the spec env so you could go Normal {fg = ..., bold, italic} but then you'll have mixed key tables which can be annoying to work with, while also forcibly clobbering any user-defined variables with the same names, not great, but also having some protected keywords isn't too crazy.

There's also a secondary concern with "any keys" for inherit groups,

-- via gui
A { gui = "italic bold underline" }
B { A, gui = "italic"} -- automatically sets bold=false underline=false, omission implies false

-- via any-keys
A { italic = true, bold = true, underline = true}
B { A, bold = false } -- would have to set the inverse, which feels less intuitive to read,
                      -- note that underline = true here because the value would be inherited

Typing this out is probably leading me to just retain the existing gui= style and have any extra keys require a patch. New formatting modifiers are probably pretty rare all things considered (nvim added blend and the others have probably been in vim since the 90s?). The "patch" required would be basically adding one call to maybe_set("superduperunderline") and updating a test so not exactly a huge burden, but it is a bottleneck.

None of that's set in stone though, open to criticism.

rktjmp commented 2 years ago

Closing for https://github.com/rktjmp/lush.nvim/pull/88 with proper changelog.