Skip to content

Instantly share code, notes, and snippets.

@shadmansaleh
Last active January 14, 2022 06:31
Show Gist options
  • Star 4 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save shadmansaleh/101d27a3593a9765a81bc548370ba018 to your computer and use it in GitHub Desktop.
Save shadmansaleh/101d27a3593a9765a81bc548370ba018 to your computer and use it in GitHub Desktop.
Genarates colorscheme for corrent highlights in neovim
-- This script has been succeeded by
-- https://github.com/shadmansaleh/colorsceme_generator.nvim
-- Thid script is nolonger maintained so please use the plugin version.
-- This file creates a colorscheme from aleady available colorscheme
-- Author : Shadman Saleh
-- Licence : You can do whatever you want with it but do provide proper cradit
-- Uses :
-- 1. Copy this script to any &rtp/lua folder mostlikely ~/.config/nvim/lua
-- so the script can be required
-- 2. Eun :lua require('colorscheme_genarator').create('colorscheme_name', load_colorscheme)
-- colorscheme_name is the name of colorzcheme load_colorscheme is a boolean
-- That indecates whether to load the colorscheme use currently
-- loaded highlights
--
--It will create a basic vim colorscheme project in current
--directory named color_name.nvim
--
--If you want to remove any chance of plugin high;ight groups start neovim with nvim -u NONE to run this script
local bit = require'bit'
-- project_dir where plugin a created . By default current dir
local project_base_dir = '.'
local path_sep = package.config:sub(1,1)
-- nvim lua flags list
local FLAGS = {
inverse = '0x01',
bold = '0x02',
italic = '0x04',
underline = '0x08',
undercurl = '0x10',
standout = '0x20',
strikethrough = '0x40',
nocombine = '0x80',
bg_indexed = '0x0100',
fg_indexed = '0x0200',
default = '0x0400',
global = '0x0800',
}
local function create_project(color_name)
local project_name = color_name .. '.nvim'
-- create project directories
vim.fn.mkdir(table.concat(
{project_base_dir, project_name, 'colors'}, path_sep), 'p')
vim.fn.mkdir(table.concat(
{project_base_dir, project_name, 'lua', color_name}, path_sep), 'p')
end
local function write_boilerplate(color_name)
local project_name = color_name .. '.nvim'
-- open files
local colorscheme_loader = io.open(table.concat(
{project_base_dir, project_name, 'colors', color_name..'.vim'}, path_sep), 'w')
local colorscheme_init = io.open(table.concat(
{project_base_dir, project_name, 'lua', color_name, 'init.lua'}, path_sep), 'w')
local colorscheme_utils = io.open(table.concat(
{project_base_dir, project_name, 'lua', color_name, 'utils.lua'}, path_sep), 'w')
local colorscheme_credits = io.open(table.concat(
{project_base_dir, project_name, 'CREDITS.md'}, path_sep), 'w')
local colorscheme_readme = io.open(table.concat(
{project_base_dir, project_name, 'README.md'}, path_sep), 'w')
-- write utils (lua/color_name/utils.lua)
colorscheme_utils:write(string.format([[
-- Clear old highlights
local utils = {}
function utils.set_namespace(ns_name)
-- Color namespace
local ns = vim.api.nvim_create_namespace(ns_name)
-- Activate namespace
-- This API isn't stable yet. It will receive breaking changes
-- and be renamed to nvim_set_hl_ns later be aware of that.
-- for more details https://github.com/neovim/neovim/issues/14090#issuecomment-799285918
vim.api.nvim__set_hl_ns(ns)
return ns
end
return utils
]]))
colorscheme_utils:close()
-- write loader (colors/color_name.vim)
colorscheme_loader:write(string.format([[
"load colorscheme
lua require("%s")
]], color_name))
colorscheme_loader:close()
-- write init (lua/color_name/init.lua)
colorscheme_init:write(string.format([[
local utils = require('%s.utils')
local color_defs = require('%s.definitions')
local highlight = vim.api.nvim_set_hl
-- Color namespace
local ns = utils.set_namespace("%s")
-- Set highlights
for color_name, param in pairs(color_defs) do
highlight(ns, color_name, param)
end
]], color_name, color_name, color_name, color_name))
colorscheme_init:close()
-- write credits (CREDITS.md)
colorscheme_credits:write([[
This colorscheme has been created by [colorscheme_generator](https://gist.github.com/shadmansaleh/101d27a3593a9765a81bc548370ba018)]])
colorscheme_credits:close()
-- write readme (README.md)
colorscheme_readme:write(string.format([[
### %s
A colorscheme made for neovim.]], color_name))
colorscheme_readme:close()
end
local function write_color_palette(palette, color_name)
local project_name = color_name .. '.nvim'
-- open files
local colorscheme_palette = io.open(table.concat(
{project_base_dir, project_name, 'lua', color_name, 'palette.lua'}, path_sep), 'w')
-- write palette
colorscheme_palette:write([[
-- =====================
-- = Color palette =
-- =====================
local palette = {
]])
for _, color in pairs(palette) do
colorscheme_palette:write(string.format([[
%8s = %-8s, -- #%06x
]], color.color_name, color.value, color.value))
end
colorscheme_palette:write(
[[}
return palette]])
colorscheme_palette:close()
end
local function write_color_defs(color_defs, inverse_palette, colorscheme_name)
local project_name = colorscheme_name .. '.nvim'
-- open files
local colorscheme_defs = io.open(table.concat(
{project_base_dir, project_name, 'lua', colorscheme_name, 'definitions.lua'}, path_sep), 'w')
-- write highlight definitions
colorscheme_defs:write(string.format([[
local palette = require("%s.palette")
-- =====================
-- = Color definitions =
-- =====================
local highlights = {
]], colorscheme_name))
for _, highlight in pairs(color_defs) do
local color_name = highlight.name
local color = highlight.params
if color.link then
colorscheme_defs:write(string.format([[ %-10s = {link = '%s'}]],
color_name, color.link) .. ',\n')
else
local command = string.format([[ %-10s = { ]], color_name)
if color.foreground ~= nil then
command = table.concat{command, 'fg = palette.',
inverse_palette[color.foreground], ', '}
color.foreground = nil
end
if color.background ~= nil then
command = table.concat{command, 'bg = palette.',
inverse_palette[color.background], ', '}
color.background = nil
end
command = command .. string.gsub(string.match(
vim.inspect(color), '{(.*)'), '\n', ' ') .. ',\n'
colorscheme_defs:write(command)
end
end
colorscheme_defs:write(
[[}
return highlights]])
colorscheme_defs:close()
end
-- Add a color to color palette if it's not used yet
local function add_to_palette(color_num, color_palette, color_count)
if not color_num then return color_palette, color_count end
-- Check if already added
local available = false
for _, color in pairs(color_palette) do
if color.value == color_num then
available = true
break
end
end
if not available then
table.insert(color_palette,
{color_name = 'color'..tostring(color_count), value = color_num})
color_count = color_count + 1
end
return color_palette, color_count
end
-- Creats a color -> color_name lookup table from palette
local function get_inverse_palette(palette)
local inverse_palette = {}
for _, color in pairs(palette) do
inverse_palette[color.value] = color.color_name
end
return inverse_palette
end
-- Creates a table of special params from special int
local function get_active_flags(special_param)
local active_flags = {
inverse = false,
bold = false,
italic = false,
underline = false,
undercurl = false,
standout = false,
strikethrough = false,
nocombine = false,
bg_indexed = false,
fg_indexed = false,
default = false,
global = false,
}
for flag, _ in pairs(active_flags) do
if bit.band(special_param, tonumber(FLAGS[flag], 16)) then
active_flags[flag] = true
end
end
-- remove false keys
vim.tbl_filter(function(key) return active_flags[key] end, active_flags)
return active_flags
end
local function load_colorscheme(color_name)
-- clear old highlights
vim.cmd('hi clear')
-- apply colorscheme
local ok, result = pcall(vim.cmd, 'colorscheme '..color_name)
if not ok then
print('Unable to create colorscheme. Error: '..result)
end
return ok
end
-- genarates palettes and highlights table
local function gen_color_table()
-- get set colors
local highlights = vim.api.nvim__get_hl_defs(0)
local color_groups = {}
-- remove empty names
vim.tbl_filter(function(key) return type(key) == 'string' and #key > 0 end, highlights)
local count = 0
local palette = {}
-- Set special flags and add colors to palette
for name, highlight in pairs(highlights) do
if type(name) == 'string' and #name > 0 then
-- remove weird key
highlight[true] = nil
if not vim.tbl_isempty(highlight) then
if highlight.special then
vim.tbl_extend('keep', highlight, get_active_flags(highlight.special))
highlight.special = nil
end
palette, count = add_to_palette(highlight.foreground, palette, count)
palette, count = add_to_palette(highlight.background, palette, count)
table.insert(color_groups, {name=name, params = highlight})
end
end
end
return color_groups, palette
end
-- creats a colorscheme
---@param color_name string: Name of colorscheme note
--- .nvim is always appended to project name as it uses
--- nvim_api from lua not present in vim
---@param load boolean:
--- Indecates whether to load colorscheme or use current
--- highlight groups. When true current highlits are
--- cleared and colorscheme name color_name is loaded
--- with colorscheme command
local function create(color_name, load)
if load and not load_colorscheme(color_name) then return end
local highlight_defs, color_palette = gen_color_table()
table.sort(highlight_defs, function(l, r)
if l.params.link == nil and r.params.link ~= nil then
return true
elseif l.params.link ~= nil and r.params.link == nil then
return false
else
return l.name < r.name
end
end)
local inverse_palette = get_inverse_palette(color_palette)
create_project(color_name)
write_boilerplate(color_name)
write_color_palette(color_palette, color_name)
write_color_defs(highlight_defs, inverse_palette, color_name)
end
return {
create = create,
}
@smithbm2316
Copy link

Hey thank you so much for your work on this! It works great 😄 ! I noticed when I was looking at the script that there were a handful of spelling/grammar errors in it, so I went ahead and cleaned up as many as I could possibly find (some were just in the comments, others were in the code itself). Here's the version I have after cleaning up the spelling/grammar issues: https://gist.github.com/smithbm2316/ccbe3ddee845be28786e8d70a150bcfc. I ran this script when I generated my colorscheme, so it seems like everything works fine still. I'll be happy to take down the gist as well if you'd like me to, I just figured this would be a small way I could say thanks for writing this great script 😃

@shadmansaleh
Copy link
Author

shadmansaleh commented Apr 1, 2021

@smithbm2316 thanks for looking into it . i've added your changes . You can keep your gist . Like the licence column states it's completely open you can do whatever you want with the code 😃

@smithbm2316
Copy link

Of course! Thanks again for taking the time to write the code for this, it's working great for me so far!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment