All Projects → rktjmp → Lush.nvim

rktjmp / Lush.nvim

Licence: mit
Define Neovim themes as a DSL in lua, with real-time feedback.

Programming Languages

lua
6591 projects

Projects that are alternatives of or similar to Lush.nvim

Toast.vim
🍞 Toast! A colorful, medium-contrast color scheme with full Vim and Neovim support and automatic light and dark variants. Easy to read without frying your retinae.
Stars: ✭ 108 (-47.06%)
Mutual labels:  neovim, neovim-plugin, color-scheme
Vim Monokai Tasty
VIM Colour scheme
Stars: ✭ 279 (+36.76%)
Mutual labels:  neovim, neovim-plugin, color-scheme
Neovim Ruby
Ruby support for Neovim
Stars: ✭ 202 (-0.98%)
Mutual labels:  neovim, neovim-plugin
Darcula
A Vim color scheme reproduction of the official JetBrains IDE Darcula theme
Stars: ✭ 158 (-22.55%)
Mutual labels:  neovim, color-scheme
Vim Dadbod Completion
Database autocompletion powered by https://github.com/tpope/vim-dadbod
Stars: ✭ 163 (-20.1%)
Mutual labels:  neovim, neovim-plugin
Lualine.nvim
A blazing fast and easy to configure neovim statusline written in pure lua.
Stars: ✭ 198 (-2.94%)
Mutual labels:  neovim, neovim-plugin
Acid.nvim
Asynchronous Clojure Interactive Development
Stars: ✭ 147 (-27.94%)
Mutual labels:  neovim, neovim-plugin
Visual Split.vim
Vim plugin to control splits with visual selections or text objects
Stars: ✭ 190 (-6.86%)
Mutual labels:  neovim, neovim-plugin
Awesome Vim Colorschemes
Collection of awesome color schemes for Neo/vim, merged for quick use.
Stars: ✭ 1,951 (+856.37%)
Mutual labels:  neovim, color-scheme
Vim Noctu
A Vim color scheme for 16-color terminals
Stars: ✭ 174 (-14.71%)
Mutual labels:  neovim, color-scheme
Animate.vim
A Vim Window Animation Library
Stars: ✭ 173 (-15.2%)
Mutual labels:  neovim, neovim-plugin
Lsp Status.nvim
Utility functions for getting diagnostic status and progress messages from LSP servers, for use in the Neovim statusline
Stars: ✭ 201 (-1.47%)
Mutual labels:  neovim, neovim-plugin
Nvim Lsputils
Better defaults for nvim-lsp actions
Stars: ✭ 142 (-30.39%)
Mutual labels:  neovim, neovim-plugin
Vem Tabline
A lightweight Vim/Neovim plugin to display buffers and tabs in the tabline
Stars: ✭ 129 (-36.76%)
Mutual labels:  neovim, neovim-plugin
Nvim Go
Go development plugin for Neovim written in pure Go
Stars: ✭ 207 (+1.47%)
Mutual labels:  neovim, neovim-plugin
Vim Clap
👏 Modern performant fuzzy picker for Vim and NeoVim
Stars: ✭ 1,802 (+783.33%)
Mutual labels:  neovim, neovim-plugin
Targets.vim
Vim plugin that provides additional text objects
Stars: ✭ 2,114 (+936.27%)
Mutual labels:  neovim, neovim-plugin
Deoplete Clang
deoplete.nvim source for C/C++/Obj-C/Obj-C++ with clang-python3
Stars: ✭ 186 (-8.82%)
Mutual labels:  neovim, neovim-plugin
Nvim Bqf
Better quickfix window in Neovim, polish old quickfix window.
Stars: ✭ 120 (-41.18%)
Mutual labels:  neovim, neovim-plugin
Neotags.nvim
Tag highlight in neovim
Stars: ✭ 124 (-39.22%)
Mutual labels:  neovim, neovim-plugin

Lush Header

Lush CI

Lush is a colorscheme creation aid, written in Lua, for Neovim.

Lush lets you define your scheme as a mini-dsl, provides HSL colour manipulation aids, and gives you real time feedback of your changes.

It also enables extension or modification of other Lush schemes.

Lush themes can be exported to plain VimL for distribution (or escape), and they can also be imported to other Lua (or VimL) files to access color) data.

Requirements

  • Neovim 0.5 or greater
    • (themes can be exported for Vim compatibilty)
  • termguicolors enabled for true color support

Installation

Install via any package management system, for example, paq:

paq 'rktjmp/lush.nvim'

Getting Started

Lush Demo

There are two interactive tutorials provided,

  • :LushRunQuickstart which will give you a few-minute overview of Lush's features. (lush_quick_start.lua in the examples folder.)

  • :LushRunTutorial, a more in-depth guide through various ways to apply Lush. (lush_tutorial.lua in the examples folder).

Usage

To create a Vim colorscheme in Lush,

  1. Copy the lush-template
  2. Create your theme
  3. (optional) Export your theme for distribution to non-Neovim clients.

The :Lushify command can be used during development for real time feedback on the appearance of your colorscheme.

See also, Advanced Usage and :h lush for more detailed documentation.

1. Copy the lush-template

Either fork, clone or recreate the repo at rktjmp/lush-template, then rename two files to match your theme name. You can automate this with the commands below (bash/zsh compatible).

First, clone down a copy of the template, picking a name for your theme; don't worry, it's easy to change this later.

git clone [email protected]:rktjmp/lush-template.git <your_theme_name>
cd <your_theme_name>

Then run the setup script:

sh << "EOF"
  git reset --soft 9069669
  git add .
  git commit --amend --no-edit
  LUSH_NAME=$(basename $(pwd))
  GIT_NAME=$(git config user.name)
  YEAR=$(date +"%Y")
  mv colors/lush_template.vim colors/$LUSH_NAME.vim
  mv lua/lush_theme/lush_template.lua lua/lush_theme/$LUSH_NAME.lua
  if command -v sed &> /dev/null; then
    sed -i "s/lush_template/$LUSH_NAME/g" colors/$LUSH_NAME.vim
    sed -i "s/COPYRIGHT_NAME/$GIT_NAME/g" LICENSE
    sed -i "s/COPYRIGHT_YEAR/$YEAR/g" LICENSE
    git add .
    git commit -m "Configure template for $LUSH_NAME, please enjoy using Lush!"
  else
    echo "Could not find sed, please manually replace 'lush_template' with '$LUSH_NAME' in colors/$LUSH_NAME.vim, and update the LICENCE file."
  fi
EOF

A lush theme has the following directory structure:

cool_name/
|-lua/
  |-lush_theme/
    |-cool_name.lua # contains your lush spec
|-colors/
  |-cool_name.vim   # exposes your lush theme to neovim

2. Create your theme

Open your lua/lush_theme/*.lua file, run :Lushify and create your lush-spec.

Remember you can define relationships between highlight groups, which makes it easy to work with color variations within a theme.

Be sure to check out the the tutorial if you haven't yet (:LushRunTutorial) or see the docs (:h lush) more details.

You may prefer to disable LSP/Linters while editing your lush spec, as they can have trouble parsing the meta programming. The examples folder contains various examples for topics like Lightline or dependency injection.

A simple lush-spec would look like this:

-- In cool_name/lua/lush_theme/cool_name.lua

-- require lush
local lush = require('lush')
locah hsl = lush.hsl

-- lush() will parse the spec and
-- return a table containing all color information.
-- We return it for use in other files.
return lush(function()
  return {
    -- Define Vim's Normal highlight group
    Normal { bg = hsl(208, 90, 30), fg = hsl(208, 80, 80) },

    -- Make whitespace slightly darker than normal.
    -- you must define Normal before deriving from it.
    Whitespace { fg = Normal.fg.darken(40) },

    -- Make comments look the same as whitespace, but with italic text
    Comment { Whitespace, gui="italic" },

    -- Clear all highlighting for CursorLine
    CursorLine { },
  }
end)

3. (optional) Export your theme for distribution to non-Neovim clients.

If you want to, you can also compile your completed theme to VimL. This is only required if you want your theme to be compatible with Vim.

Running the following will open a new floating window with a list of highlight groups as defined in VimL.

:lua require('lush').export_to_buffer(require('lush_theme.cool_name'))

You can then yank the contents of the buffer, and paste it in cool_name/colors/cool_name.vim.

Advanced Usage

Spec Extension and Merging

Lush provides two methods for extending existing lush themes, lush.extends({parsed_spec, ...}).with(spec) and lush.merge({parsed_spec, ...}).

Potential reasons you may wish to extend a spec:

  • You like a lush theme you got online, but want to change a few specific parts of it, such as the comment style, or the background color.

  • You are writing your own theme and want to make a small tweaks to create a variant, for example a high-contrast or colorblind safe mode.

Potential reasons you may wish to merge specs:

  • You have a collection of plugin highlight groups want to let users configure which highlight groups are enabled.

  • You want to apply a patch/extension to a theme that isn't provided by the main theme repo.

  • You simply want to define your theme in parts for maintenance reasons.

For more detailed usage and examples, see :h lush-extending-specs.

Using Lush Data Elsewhere

Every Lush theme is a compiled down to a Lua table. This lets you import it into other Lua modules or into other themes.

An demonstration of this is shown in the examples folder, where a parsed lush spec is used to set the lightline theme, or above when using extends.

Another example can be seen in savq/melange, where the parsed lush spec is used to generate an Alacritty terminal theme. You could extend this concept into generating colors for your diff tool, css code blocks, etc.

Q/A

Lush is too magical, will I get burned?

Meta programming can be scary. It can be confusing to reason with and can be very infrutrating to debug when something goes wrong "inside the box".

Maybe like all good magic tricks, Lush looks a lot more magical than it really is.

The metaprogramming is really only in the parser, and this is where you write a very strict subset of instructions (group names, fg, bg, etc).

As long as your spec is valid lua code (correct braces, commas, closing quotation marks, no spurious characters, etc), there shouldn't be a steep learning curve or much to actually debug. All you're really doing is writing a Lua table.

-- no magic zone
-- anything you do here is just plain old regular lua
local ten = 8 + 2

local spec = lush(function ()
  return {
    -- ~*~ some magic zone ~*~
    -- here we are defining our DSL, some magic required, no magic "leaks" out.

    Normal { fg = "red", bg = hsl(200, 40, 20) },
--  ^      ^                  ^ no magic, just returns a lua table with functions attached
--  |      | just a lua table, no magic
--  | some magic to used to turn function call Normal({...}) into table key Normal = {...}

    CursorLine { fg = Normal.fg.da(10) },
--                    ^ no magic, just a table lookup

    Comment { Normal, fg = "blue" }
--            ^ no magic, just copying one table to another
  }
end)

-- no magic zone
-- returned parsed spec is just a lua table, it has no special magic attached
-- and you can work with it like any other lua table: delete keys, copy values
-- transform values, write to json, etc.

local normal_fg = spec.Normal.fg
--                ^    ^      ^ just a table with functions attached
--                |    | just a table
--                | just a table

Similarly in your color/.vim file,

-- no magic zone
local parsed_spec = require('lush_theme.theme') 
--    ^             ^ no magic, just a normal lua module
--    | just a table
lush(parsed_spec)
--   ^ just an if check for table or function and either parses or applies the
--     theme the compiler just iterates over the spec (which is just a table)
--     and interpolates the values into some strings which get sent to vim to
--     interpret.

:Lushify is also pretty non-magic. It just reads the current buffer, sends it to the lua interpreter, hoping to get back a parsed lush spec, and then calls compile and apply in the background.

Why return ...?

By returning our theme it acts as a Lua module, which allows us to use it in other Lua code or other themes.

When we call lush(lush-spec) in our .lua file, our lush-spec is parsed and returned as a Lua table, we call this a "parsed-lush-spec". We then return this table at the end of the file.

The parsed-lush-spec can be passed to lush to apply the spec (as seen in the .vim file), but by returning the parsed-lush-spec, we can also require the lush-spec in other Lua code (require('lush_theme.cool_name')) and access it's color values.

Why lua/lush_theme/?

Lua doesn't have any strict namespacing. Anything in a plugin's lua/ directory becomes available as a module in Vim, so it's advised to nest your theme inside a lush_theme folder, providing a namespace for all lush themes. This is to avoid any collisions between themes and other modules.

This isn't a strict rule enforced in any way by Lush, simply a recommendation.

Is Lush slow?

Short answer: no.

Long answer:

There isn't a noticeable performance impact in using Lush over a raw VimL colorscheme. The parse and compile stage is generally around 1ms on a quite aged core i5 and is comparatively dwarfed by the 3ms spent waiting Vim's interpreter to apply the commands, a penalty which raw VimL schemes would share.

If you noticed a poor performance, you can always export your theme to VimL after using Lush to aid the development process.

Times measured with libuv's hrtime(), specifically around the parse, compile and apply calls. There may be a few extra nanoseconds not recorded between calling in and out of functions, as well as the initial file load time (which VimL would also incur).

Parse:   286300  ns  0.2863 ms -- resolve lush-spec into concrete values
Compile: 671900  ns  0.6719 ms -- convert concrete spec into viml commands
Apply:   3134300 ns  3.1343 ms -- pass to VimL interpreter (iterate array and call "nvim_command", "nvim_exec" performance is identical)
Total:   4092500 ns  4.0925 ms

Parse:   373500  ns  0.3735 ms
Compile: 973400  ns  0.9734 ms
Apply:   3442400 ns  3.4424 ms
Total:   4789300 ns  4.7893 ms

Parse:   388700  ns  0.3887 ms
Compile: 705500  ns  0.7055 ms
Apply:   3446900 ns  3.4469 ms
Total:   4541100 ns  4.5411 ms

Parse:   299400  ns  0.2994 ms
Compile: 814600  ns  0.8146 ms
Apply:   3065300 ns  3.0653 ms
Total:   4179300 ns  4.1793 ms

See also issue #19, where 1000, 2000 and 4000 rule specs were tested. VimL is stll consistently the bottleneck.

Note that a 1000 rule spec is likely pretty unsual. There are only about 150 base groups provided by Neovim and most plugins only provide another 5-10 (or less).

A 4k rule spec would probably mean you're loading an enourmous number of plugins, at which point your load times are probably also already enormous.

Also as per the issue, since VimL is such a huge bottleneck, you may find similarly sized colorschemes actually load faster via Lush because any maths and manipulation is done via Lua instead.

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

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

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

See Also

Note that the project description data, including the texts, logos, images, and/or trademarks, for each open source project belongs to its rightful owner. If you wish to add or remove any projects, please contact us at [email protected].