• Stars
    star
    295
  • Rank 140,902 (Top 3 %)
  • Language
    Lua
  • License
    MIT License
  • Created over 1 year ago
  • Updated 3 months ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

Neovim colorschemes generated on the fly with a text prompt using ChatGPT

text-to-colorscheme

This is a neovim plugin that allows the user to generate new colorschemes by simply providing a text prompt. See the following video (and note the commands being typed at the bottom) to see usage:

Plugin usage example

Under the hood, we are using the given text prompt along with OpenAI's GPT API, to generate the new color scheme

Prerequisites

  1. Neovim 0.8.0 or higher
  2. An OpenAI API key. To use this plugin, you must have an OpenAI API key, as it is needed to generate new themes. If you don't already have one, sign up at openai.com

Installation

Using packer

use { "svermeulen/text-to-colorscheme.nvim" }

Other plugin managers should be similar

Basic Usage

Inside init.lua

vim.o.background = "dark"

require('text-to-colorscheme').setup {
  ai = {
    openai_api_key = "<OPENAI_API_KEY>",
  },
}

vim.cmd([[colorscheme text-to-colorscheme]])

Note also that if your init.lua is in source control, it is not good practice to reference your api key directly. Often a better approach is to get it from an environment variable instead, which you can do like this:

require('text-to-colorscheme').setup {
  ai = {
     openai_api_key = os.getenv("OPENAI_API_KEY"),
  },
}

Also note that by default, the plugin uses the OpenAI "gpt-4" model, which is currently in limited beta. If you don't have access to this model via your API key, you may need to switch to another model, which you can do for example like this:

require('text-to-colorscheme').setup {
  ai = {
     openai_api_key = os.getenv("OPENAI_API_KEY"),
     gpt_model = "gpt-3.5-turbo-0613",
  },
}

However - Note that gpt-4 produces much better results (it seems the extra reasoning power is helpful for this use case).

Selecting Different Themes

When a theme name is not provided, the plugin will default to using a theme resembling gruvbox.

To select a different theme, use the T2CSelect command. If you execute :T2CSelect <tab> you should see a list of themes to choose from. There are a number of built-in themes based on the most popular vim colorschemes. To generate your own and add to this list, see next section.

Generating Theme

To generate a custom theme, execute the command:

:T2CGenerate <text prompt>

Where <text prompt> is any text describing the kind of color scheme you want (see above video for some examples). I find it helps to be as descriptive as possible to give the AI more information to work with. After doing this, it will take 5-10 seconds for the new color scheme to be generated, at which point it will be automatically loaded (the video above skips this part).

Note that text-to-colorscheme currently only supports dark themes

Saving Theme Persistently

After finding a theme that you want to keep, you can have this persist across vim sessions by running the command:

:T2CSave

This should present a popup vim buffer with the color palette that was generated, with each color also automatically highlighted. You can then copy the contents of this buffer into the init.lua call to require('text-to-colorscheme').setup. For example, if using a text prompt of 'jungle' and then running T2CSave, the change to init.lua might look like this:

require('text-to-colorscheme').setup {
  ai = {
    openai_api_key = "<OPENAI_API_KEY>",
  },
  hex_palettes = {
     {
        name = "jungle",
        background_mode = "dark",
        background = "#1c2a1f",
        foreground = "#c1d3b7",
        accents = {
           "#6dbd5a",
           "#a3d16d",
           "#d1c75a",
           "#d1a35a",
           "#d15a5a",
           "#5ad1b3",
           "#5a8ad1",
        },
     },
  },
  default_palette = "jungle",
}

Note that in addition to adding to the hex_palettes list, we also need to set a value for default_palette above.

After doing the above, your custom themes should then be suggested when running the :T2CSelect <tab> command.

Tweaking Theme

Sometimes, some text prompts do not always translate well to a new color scheme on the first try. One approach to fixing this is to modify the text prompt and try again (or sometimes just trying the same prompt again). In some cases though, the generated color scheme is good, and just needs some minor adjustments around contrast, saturation, or color order. For these cases, text-to-colorscheme comes with the following commands that help you do this:

  • :T2CAddContrast X - Call this if you are finding that the foreground color is too similar to the background color. A positive value for X here will modify the current color scheme to have the foreground more distinct from the background, and a negative value will cause the foreground and background to become more similar.

  • :T2CAddSaturation X - Call this if you want to increase or reduce how intense the foreground colors are. A lower value here means the color becomes more gray / washed-out.

  • :T2CShuffleAccents - Call this if you want to change which highlight groups the various colors are applied to. It will randomize the order of the accent colors. This is useful to try a few times to see if it improves the look and feel (though I will say that I usually find the original order works best). If you want more refined control over the order, you can run :T2CSave, then save your theme, then control the order manually. This is helpful in particular if you prefer error highlights to be on the reddish side (which you can do by ensuring the most red color is ordered last).

  • :T2CResetChanges - This will reset all the changes made by the other commands here (T2CShuffleAccents, T2CAddContrast, T2CAddSaturation) and will return the color scheme to the exact values returned by ChatGPT (or the original values from your init.lua if loaded from there).

For example - it may be helpful to add commands like the following, when generating new color schemes:

vim.api.nvim_set_keymap('n', '<f9>', ':T2CAddContrast -0.1<cr>', {noremap = true, silent = true})
vim.api.nvim_set_keymap('n', '<f10>', ':T2CAddContrast 0.1<cr>', {noremap = true, silent = true})

vim.api.nvim_set_keymap('n', '<f11>', ':T2CAddSaturation -0.1<cr>', {noremap = true, silent = true})
vim.api.nvim_set_keymap('n', '<f12>', ':T2CAddSaturation 0.1<cr>', {noremap = true, silent = true})

vim.api.nvim_set_keymap('n', '<f8>', ':T2CShuffleAccents<cr>', {noremap = true, silent = true})

For example, see the following video to see what it looks like to change the contrast of the "circus" theme forwards, then backwards:

changing contrast

And see the following to see what it looks like to change saturation:

changing saturation

Note that once you are satisfied with the changes, you will want to save your theme using the :T2CSave command.

One limitation of the above is that the brightness and saturation will be changed uniformly across the entire palette, and you may want to modify these values on a per-color basis. The easiest way to do this is to change the save_as_hsv setting to true, then run :T2CSave, save to your init.lua, and directly modify the saturation/brightness on a per-color basis there. Note that when using save_as_hsv you need to add to the hsv_palettes setting instead of hex_palettes.

Advanced Configuration

Additional settings (and default values) for text-to-colorscheme are:

-- setup must be called before loading the colorscheme
-- Default options:
require("text-to-colorscheme").setup({
  ai = {
     gpt_model = "gpt-4",
     openai_api_key = nil, -- Set your own OpenAI API key to this value
     green_darkening_amount = 0.85, -- Often, the generated theme results in green colors that seem to our human eyes to be more bright than it actually is, therefore this is a fudge factor to account for this, to darken greens to better match the brightness of other colors.  Enabled or disabled with auto_darken_greens flag
     auto_darken_greens = true,
     minimum_foreground_contrast = 0.4, -- This is used to touch up the generated theme to avoid generating foregrounds that match the background too closely.  Enabled or disabled with enable_minimum_foreground_contrast flag
     enable_minimum_foreground_contrast = true,
     temperature = 0, -- Set this to a value between 0 and 1, where 0 means it will generate similar looking color schemes every time, and 1 means that each time will be very different.  See openai docs for more information on this setting
  },
  undercurl = true,
  underline = true,
  verbose_logs = false, -- When true, will output logs to echom, to help debugging issues with this plugin
  bold = true,
  italic = {
     strings = true,
     comments = true,
     operators = false,
     folds = true,
  },
  strikethrough = true,
  invert_selection = false,
  save_as_hsv = false, -- When true, T2CSave will save colors as HSV instead of hex
  invert_signs = false,
  invert_tabline = false,
  invert_intend_guides = false,
  inverse = true,
  dim_inactive = false,
  transparent_mode = false,
  hsv_palettes = {},
  hex_palettes = {},
  overrides = {},
  default_palette = "gruvbox",
})

Note that the implementation of text-to-colorscheme was originally forked from the great gruvbox.nvim plugin which is why it has similar options

Highlight Group Overrides

If you don't like the color for a specific highlight group, you can override it in the setup. For example:

require("text-to-colorscheme").setup({
    overrides = {
        SignColumn = {bg = "#ff9900"}
    }
})

Please note that the override values must follow the attributes from the highlight group map, such as:

  • fg - foreground color
  • bg - background color
  • bold - true or false for bold font
  • italic - true or false for italic font

Other values can be seen in :h synIDattr

Strong Typing Support

Note that this library is implemented using Teal and that all the lua files here are generated. If you are also using Teal, and want your calls to the text-to-colorscheme API strongly typed, you can copy and paste the teal type definition files from /teal/dist into your project (or just add this path to your tlconfig.lua file)

More Repositories

1

vim-easyclip

Simplified clipboard functionality for Vim
Vim Script
684
star
2

vim-yoink

Vim plugin that maintains a yank history to cycle between when pasting
Vim Script
366
star
3

vimpeccable

Neovim plugin that allows you to easily map keys directly to lua code inside your init.lua
Lua
359
star
4

vim-subversive

Vim plugin providing operator motions to quickly replace text
Vim Script
286
star
5

vim-macrobatics

Plugin for Vim that makes it easier to record / play / edit macros
Vim Script
81
star
6

nvim-moonmaker

Moonscript plugin support for neovim
Lua
67
star
7

UnityCoroutinesWithoutMonoBehaviours

C#
47
star
8

nvim-teal-maker

Neovim plugin that adds plugin support for teal language
Lua
32
star
9

vim-NotableFt

Vim Script
29
star
10

vim-extended-ft

Vim Script
26
star
11

lusc

Structured Async/Concurrency for Lua
Lua
17
star
12

nvim-marksman

Quick and efficient file finder for neovim
Python
17
star
13

nvim-lusc

Structured Async/Concurrency in Neovim
Lua
13
star
14

tea-leaves

A language server for the Teal language
Lua
12
star
15

logexpert

C#
8
star
16

unifind

Simple generic fuzzy finder for unity editor
C#
8
star
17

lusc_luv

Lua
5
star
18

VimDriver

Python
5
star
19

vimpeccable-lua-vimrc-advanced-example

Lua
4
star
20

vimpeccable-lua-vimrc-example

Lua
4
star
21

nvim-moonmaker-example

Moonscript plugin support example for neovim
MoonScript
3
star
22

CebuGameJam

C#
3
star
23

lua_bazel_rules

Bazel rules to build and run lua scripts
Starlark
2
star
24

vim-quickfixdo

Vim Script
2
star
25

ncm2-yoink

Vim Script
2
star
26

tlcheck

Simple command line tool to type check a given teal file/directory
Lua
2
star
27

HalifaxGameJam2012

C#
1
star
28

GradleCompositeBuildBugExample

Groovy
1
star
29

lastfm_script

Python
1
star
30

buck2_lua_rules

Buck2 rules for Lua and Teal
Starlark
1
star
31

vimpeccable-moonscript-vimrc-example

MoonScript
1
star
32

vimpeccable-moonscript-vimrc-advanced-example

MoonScript
1
star
33

uniscon

A simple implementation of structured concurrency for Unity game engine
C#
1
star
34

svelto-doofus-sample

C#
1
star