rktjmp / lush.nvim

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

augrouping/conditionals for sets of highlights #19

Closed rktjmp closed 3 years ago

rktjmp commented 3 years ago

https://github.com/rktjmp/lush.nvim/issues/13#issuecomment-791275252

Would it be possible to make syntax to provide conditions similarly to something like the packer.nvim definition of packages? This could maybe compile into autocmds that are for a given filetype or similar... (You do not need groups for filetypes, that are not actually open before opening them). The final compilation would be into something similar to this:

augroup rust 
    autocmd FileType rust hi RustComment gui=italic, guibg=red ...
    ...
augroup END

This could make the colourscheme much smaller and faster to load with the same amount of definitions... right?

rktjmp commented 3 years ago

Most syntax plugins should:

I'm not sure how common the use case for wanting to define different groups for different languages is, or how real world heavy defining those actually would be (i.e. is loading a 100 rule color scheme meaningfully different to a 1000 rule scheme? Benchmarks?) I can imagine where you might want to define a few language specific operators differently perhaps.

At any rate, something like this could probably be written by using the manual parser -> compiler tool chain, where you parse all your bits, then pass a wrapper to each compile call (like compile(rust_spec, {augroup: {name: rust, ft: rust}).

The reason you would have to use the tool chain instead of just lush() is that the specs wouldn't know what groups are for what augroup.

It's possible that it could be exposed as an option and the extra metadata could be stored in __lush on the spec, but the data would be lost on any extends() call since the specs are rolled into one.

You would also have to use lush's export function to create and save out the viml file otherwise lush is probably doing more work building the scheme with augroups than just building and applying them all in one go.

I would like to see benchmarks first. Not sure what a big theme is, and whether there are performance differences between defining more or less properties on a group or linking groups.

@kunzaatko

kunzaatko commented 3 years ago

Benchmarks:

i.e. is loading a 100 rule color scheme meaningfully different to a 1000 rule scheme? Benchmarks?

There is some difference recorded by a benchmark. Whether it is meaningful (and also whether it is the whole story) is a different topic. I made the benchmarks: daycula (1808 LOC)

000.014  000.014: --- VIM STARTING --
...
112.376  014.257  013.533: sourcing /home/kunzaatko/.config/vim/plugged/daycula-vim/colors/daycula.vim
130.717  018.101  016.675: sourcing /home/kunzaatko/.config/vim/plugged/daycula-vim/colors/daycula.vim
...
389.002  000.002: --- VIM STARTED ---

So that is a total of about 32 ms on 390 ms of vim startup time. delek (55 LOC)

000.010  000.010: --- VIM STARTING ---
...
087.142  001.011  000.798: sourcing /usr/share/vim/vim82/colors/delek.vim
088.927  001.338  001.090: sourcing /usr/share/vim/vim82/colors/delek.vim
...
336.556  000.003: --- VIM STARTED ---

So that is a total of about 2 ms on 336 ms of vim startup time. However the vim startup times when loading with daycula are consistently ~60 ms slower than when starting with delek. I do not know if there are any other parts that are linked with the colourscheme besides sourcing the colourscheme file. Do you think that the difference is caused by the colourscheme? @rktjmp This is not so much of a difference when starting vim with the start time of ~400 ms, but when I am starting nvim with ~150 ms startup time, it is relatively much more significant...

Usefulness

I do not actually know whether the definitions of the specifics are needed, but most of the colourschemes out there define these, so I guess that it is. Maybe a further investigation would be good for answering if the schemes are not just redefining the defaults... (daycula, iceberg, ... (most all of them))

"Solution"

(So these are the benchmarks, now about the possible "solution") I think that a better approach after all would be to compile these specifics into the syntax folder with the ft name and not autocmds... I found a check_colors.vim script (on my distribution it is at /usr/share/vim/vim82/colors/tools/check_colors.vim) and it checks that language specific groups are not set. It also recommends to put them to syntax files...

I think that also a feature that could later be usefull (? @rktjmp) is to check the colourscheme for overlap with defaults and to remove them in the compilation / inform the creator of the colourscheme... That would be usefull, because the bottleneck is in the actual compiled script sourcing (is that right @rktjmp? It is also in the README.md of lush...) so that the eliminating of these would make it run faster...

rktjmp commented 3 years ago

Not sure if bench marking vim loading vim colorschemes is all that appropriate to benching Lush.

daycular defines many of its groups via repeated calls to a vimscript function (with a lot of partial string manip calls). I would bet that is why it's slow.

Testing lush with a garbage generated template, of 1000, 2000 and 4000 rules, I get these timings:

1k rules
--------
parse time:   4095342ns,  4.095342ms
compile time: 863515ns,   0.863515ms
apply time:   13150290ns, 13.15029ms

2k rules
--------
parse time:   8310824ns,  8.310824ms
compile time: 1791501ns,  1.791501ms
apply time:   34649903ns, 34.649903ms

4k rules
--------
parse time:   15170685ns, 15.170685ms
compile time: 6865722ns,  6.865722ms
apply time:   82630480ns, 82.63048ms

I think if you decide to load a 4k line theme that makes no effort to pick and choose rules based on need, you deserve to eat the 80ms load (which isn't even that bad IMO).

The vast cost is in viml, so I think if your theme provides a huge number of groups (that you are redefining over the plugins (would-be-autoloaded?) syntax files for some reason), you might want to provide a user config setup so less rules get passed out to vim.

Otherwise I think this is a solution in search of a problem.

Also Lush always provides you with the ability to export a theme to viml and manually/script augroup creation if you really truely felt it was required.