Skip to content

linrongbin16/colorbox.nvim

Repository files navigation

🌈 colorbox.nvim

require commons.nvim luarocks ci.yml collect.yml codecov

Do you want all the most popular (Neo)vim colorschemes than only one? Do you want to change colorscheme from time to time?

This is it! Let's load all the ultra colorschemes into the Neovim player!

shuffle-per-sec-v2.mp4
Click here to see how to configure
require("colorbox").setup({
  policy = { seconds = 1, implement = "shuffle" },
  timing = "interval",
})

It use offline github actions to weekly collect/update the colorscheme list.

Note

The most popular colorschemes are picked from below websites:

with below conditions:

  1. Github stars β‰₯ 500 (default config only enable β‰₯ 800, see Configuration).
  2. Last git commit in 5 years.
  3. For multiple plugins that contain the same color name, pick by following rules:
    1. Awesome-neovim wins vimcolorsheme (they usually support modern Neovim features).
    2. More github stars.
    3. Newer git commits.

Please check COLORSCHEMES.md for full colorschemes list.

It install via git submodules instead of copy-paste source code, so you get continuously updates from original authors.

It allow you play them with multiple playback settings (policies):

  • Suffle playback.
  • Play in order.
  • Play in reverse order.
  • Single cycle.

And multiple trigger timings:

  • On startup.
  • Fixed interval.
  • Date time (todo).
  • By filetype.

πŸ“– Table of Contents

βœ… Requirements

  • neovim β‰₯ 0.9.
  • git.

πŸ“¦ Install

Important

If this plugin provides the main colorscheme (i.e. the color show right after nvim start), then make sure:

  1. Don't lazy load it.
  2. Load it before all other plugins.

Important

Some colorschemes have specific requirements:

Please manually add these dependencies if you enable them.

With lazy.nvim
require('lazy').setup({
  {
    'linrongbin16/colorbox.nvim',

    -- don't lazy load
    lazy = false,
    -- load with highest priority
    priority = 1000,

    build = function() require("colorbox").update() end,
    config = function() require("colorbox").setup() end,
  }
})
With pckr.nvim
require('pckr').add({
  {
    'linrongbin16/colorbox.nvim',

    run = function() require("colorbox").update() end,
    config = function() require("colorbox").setup() end,
  };
})

πŸš€ Usage

When loading this plugin, it will run following steps:

  1. Run the filters, only enable the colors you choose from candidate list. See Filter.
  2. Register triggers to invoke related policies at a proper timing. See Timing & Policy.

When a timing is triggered, it will run following steps:

  1. Run registered policy and choose a colorscheme. See Timing & Policy.
  2. Refresh the background option. See Background.
  3. Run colorscheme command to actually apply the colorscheme.

You can also use command Colorbox to control the player with below subcommands:

  • update: Update all git submodules.
  • info: Show detailed information and configured status.
    • Note: use scale=0.7 to specify popup window's size in range (0, 1], by default is scale=0.7.
  • shuffle: Change to a random color.

Note

You can still use colorscheme command to change the colorscheme.

πŸ”§ Configuration

To configure options, please use:

require("colorbox").setup(opts)

The opts is an optional lua table that override the default options.

For complete default options, please see configs.lua.

Filter

There're 3 types of filter configs:

Builtin Filters

  • "primary": Only enables the main color (if there are multiple colors in one plugin).

Function Filters

Lua function that decide whether to enable/disable a color. It has below signature:

function(color:string, spec:colorbox.ColorSpec):boolean

Parameters:

  • color: Color name.
  • spec: Colorscheme meta info, which is the colorbox.ColorSpec type, see below.

Returns:

  • To enable a color, returns true.
  • To disable a color, returns false.

The colorbox.ColorSpec type is a lua table that has below fields:

  • handle: Unique plugin name, string type, for example:
    • "folke/tokyonight.nvim"
  • url: GitHub url, string type, for example:
    • "https://github.com/folke/tokyonight.nvim"
  • github_stars: Github stars, integer type, for example:
    • 4300
  • last_git_commit: Last git commit date and time, string type, for example:
    • "2023-10-25T18:20:36"
  • priority: Plugin priority, integer type, for example:
    • awesome-neovim is 100
    • vimcolorschemes is 0
  • git_path: Git submodule file path, string type, for example:
    • "folke-tokyonight.nvim"
  • git_branch: (Optional) git branch of plugin (most plugins use default branch such as main or master, while some use specific branch such as neovim), string? type, for example:
    • "neovim"
  • color_names: Color names that plugin contains, string[] type, for example:
    • ["tokyonight","tokyonight-day","tokyonight-moon","tokyonight-night","tokyonight-storm"]

List Filters

A lua list that contains multiple other filters. A color will only be enabled if all filters returns true.

Timing & Policy

On Nvim Start

To choose a color on nvim start, please use:

require("colorbox").setup({
  timing = "startup",
  policy = "shuffle",
})

There're 4 builtin policies to work with startup timing:

  • shuffle: Choose a random color.
  • in_order: Choose next color in order, color names are ordered from 'A' to 'Z'.
  • reverse_order: Choose next color in reversed order, color names are ordered from 'Z' to 'A'.
  • single: Choose a fixed color.

By Fixed Interval Time

To choose a color on a fixed interval time, please use:

require("colorbox").setup({
  timing = "interval",
  policy = { seconds = 60, implement = "in_order" },
})

The fixed interval timing needs to specify below 2 fields in its policy:

  • seconds: Change to next color every X seconds.
  • implement: The builtin policies (mentioned above) to decide which color to choose.

By File Type

To choose a color on buffer's file type change, please use:

require("colorbox").setup({
  timing = "filetype",
  policy = {
    mapping = {
      lua = "PaperColor",
      yaml = "everforest",
      markdown = "kanagawa",
      python = "iceberg",
    },
    empty = "tokyonight",
    fallback = "solarized8",
  },
})

The filetype timing needs to specify below 2 fields in its policy:

  • mapping: Lua table that map from buffer's file type to color name.
  • empty: Optional color name if file type is empty (and surely not found in mapping), do nothing if nil.
  • fallback: Optional color name if file type is not found in mapping, do nothing if nil.

Background

There're some colors (tokyonight-day, rose-pine-dawn) are forced to be light, i.e. they forced set background=light on loading. Thus the other following colors will continue use light background.

If you want to bring the dark-able colors back to dark, please use:

require("colorbox").setup({
  background = "dark",
})

It automatically set background=dark before run a colorscheme command.

Hook

To execute a hook function after policy is triggered and new colorscheme is applied, please use:

require("colorbox").setup({
  post_hook = function(color, spec)
    vim.notify(string.format("Colorscheme changed to: %s", vim.inspect(color)))
  end,
})

The hook accepts a lua function with below signature:

function(color:string, spec:colorbox.ColorSpec):nil

πŸ“ Receipts

1. Choose fixed color on nvim start

require("colorbox").setup({
  policy = "single",
  timing = "startup",
})

2. Change random color per second

require("colorbox").setup({
  policy = { seconds = 1, implement = "shuffle" },
  timing = "interval",
})

3. Enable all colors

require("colorbox").setup({
  filter = false,
})

4. Enable only top stars (β‰₯ 1000) & primary colors

require("colorbox").setup({
  filter = {
    "primary",
    function(color, spec)
      return spec.github_stars >= 1000
    end
  },
})

5. Disable by name

local function colorname_disabled(colorname)
  for _, c in ipairs({
    "iceberg",
    "ayu",
    "edge",
    "nord",
  }) do
    if string.lower(c) == string.lower(colorname) then
      return true
    end
  end
  return false
end

require("colorbox").setup({
  filter = function(color, spec)
    for _, c in ipairs(spec.color_names) do
      if colorname_disabled(c) then
        return false
      end
    end
    return true
  end
})

6. Disable by plugin

local function plugin_disabled(spec)
  for _, p in ipairs({
    "cocopon/iceberg.vim",
    "folke/tokyonight.nvim",
    "ayu-theme/ayu-vim",
    "shaunsingh/nord.nvim",
  }) do
    if string.lower(p) == string.lower(spec.handle) then
      return true
    end
  end
  return false
end

require("colorbox").setup({
  filter = function(color, spec)
    return not plugin_disabled(spec)
  end
})

✏️ Development

To develop the project and make PR, please setup with:

To run unit tests, please install below dependencies:

Then test with vusted ./spec.

🎁 Contribute

Please open issue/PR for anything about colorbox.nvim.

Like colorbox.nvim? Consider

Github Sponsor Wechat Pay Alipay