Closed rktjmp closed 2 years ago
I'm really excited for this. I was in the middle of restructuring my build system but glad to see that lush is having something that is quite extensible and more powerful. I'll be moving to lush's build system when it's ready.
I'd like to share an idea about a vim compatible structure that doesn't need a separate colors file. Basically we don't need to have a separate colors/zenbones.vim
and colors/zenbones_compat.vim
. The structure of the colorscheme file would look like a simple branch:
...
let g:colors_name = 'zenbones'
if has('nvim')
lua require("zenbones.util").apply_colorscheme() " wrapper to just apply specs, term colors etc
else
call {g:colors_name . '_' . &background}#load() " use autoload files to store vim compat hl groups
endif
There will be two autoload files that will be generated by lush builder: autoload/zenbones_light.vim
autoload/zenbones_dark.vim
. Just each one containing light and dark hl groups respectively.
With this way, I can separate generated stuff from actual written code. I can even publish it in a separate repo as an optional dependency (mcchrish/zenbones_artifacts.vim
) if one wants the compatible option.
This is at least what I plan to do.
Goals
The main goal of this is to allow theme developers to use Lush solely as a theme creation tool with it's live updates, extension system and DSL syntax, while not forcing end users to install Lush. Part of this includes exporting your theme to VimL, but it also includes a Lua exporter with hooks to provide enduser configuration.
As a side effect, it also aims to let you export your Lush data easily to other formats.
WIP PR #77 (sort of misnamed
compiler-plugins
branch).RFC:
Preamble
The Lush build system is designed to take a lush spec (i.e. the color and group data from your theme) and apply any number of transforms to that data. These transforms can include conversion to a vim theme, terminal emulator theme, writing to different files, etc.
Some prerequisite knowledge
The builder simply pushes data through a function pipeline, these functions are termed "transforms".
There are two kinds of transforms: "head" and "tail".
Head transforms must accept a parsed lush spec (returned by
require("theme")
). It must return a table of any content. You will place a head transform at the start of your pipeline.Tail transforms must accept a table and must return a table. The contents of these tables is not enforced, they could be strings (a table of lines), functions (such as closures around data), other tables, etc.
Transforms can take any additional number of arguments after the table.
Lush ships with some default transforms:
viml
(head)lua
(head)prepend
(tail)append
(tail)overwrite
(tail)patchwrite
(tail)contrib.alacritty
(head)contrib.kitty
(head)contrib.wezterm
(head)These transforms are automatically injected into the build environment along with
lush
andrun
.You can provide any of your own transforms just by writing a function, either in the build file or in another module.
We will discuss the simplest example, where you have a theme with no variations or configuration options and simply want to let non-lush users use your theme.
A basic theme, exported to VimL
To ship our theme as a viml file, we simply must load our theme, convert it to viml and save the output to a file.
We will use the
viml
andoverwrite
transforms.Our build file would look something like this:
You can run
:LushBuild <build_file>
which will load and execute the given build file, or if no buildfile is specified,lush_build.lua
is used. You probably want to do this from your lush themes root dir but you can run it anywhere.Take Aways and Notes
It's important to remember:
run()
accepts a parsed lush spec, so you can uselush.extends
to generate variations in or outside of the build file.As a further example, we will write our own transform next.
Converting a Lush theme into an Alacritty theme
As an example, we will convert a theme into a (truncated) Alacritty theme.
To do this we will need to:
#000000
hex values to0x000000
Exporting as configurable lua
The lua transform generates code you can call to load and apply a lush theme without lush. It will require you to provide a support context around it.
By using the
patchwrite
transform, we can instruct the lush build system to only update its own code, leaving our support code intact.Before running this build file, we should prepare the destination for
patchwrite
.After running
:LushBuild
, we will have alush_apply
function.By default,
lush_apply
will convert your theme (now compiled as a table) into viml highlight commands and apply them, but you can provide optional function hooks tolush_apply
to alter data along the way.The following hooks are provided:
configure_group_fn = function(group) ... end
generate_group_fn = function(group) .. end
apply
will understand.highlight ...
vim command but you could return other viml, raw lua, different tables, etc.before_apply_fn = function(rules) ... end
apply_fn = function(rules) ... end
generate_group -> before_apply
) and should do something to apply these rules as highlights.vim.cmd
but you could write your own handler to usenvim_set_hl
, etc.For complete details, see the documentation in the generated code (or
lua/lush/transformer/lua.lua
in the branch)Now that our theme has been exported, we can adjust our
theme.lua
file to use the generated loader.Note, you don't have to run this exported lua directly, you could still have your "core theme file" that takes a config and requires which ever theme is appropriate.
Pipelines are composable
Since run itself is a transform, you can pipe any table value into it, along with a list of transforms to run in that context.
Other Transform Ideas or LushBuild concepts
TextmateEmacs themes.nvim_set_hl
becomes stable with 10000x performance increase, you could easily swapviml
for aset_hl
transform and providetheme.lua
andtheme_nvim_5_1.vim
.Issues