Skip to content

Commit d0caa5c

Browse files
committed
feat: improve startup time by caching
1 parent 7d29687 commit d0caa5c

File tree

11 files changed

+303
-48
lines changed

11 files changed

+303
-48
lines changed

colors/one_monokai.lua

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
require("one_monokai").setup()
1+
require("one_monokai").load()

lua/one_monokai/config.lua

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,13 +5,15 @@ local config = {}
55
---@field colors colors #Custom colors
66
---@field themes fun(colors:colors):groups #Custom highlight groups
77
---@field italics boolean #Whether to italicize some highlight groups
8+
---@field compile_path string #Path to store compiled result.
89
local defaults = {
910
transparent = false,
1011
colors = {},
1112
themes = function(_)
1213
return {}
1314
end,
1415
italics = true,
16+
compile_path = vim.fn.stdpath "cache" .. "/one_monokai",
1517
}
1618

1719
config.options = vim.deepcopy(defaults)

lua/one_monokai/init.lua

Lines changed: 47 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,27 +1,60 @@
11
local M = {}
22

3-
function M.setup(opts)
4-
local set = vim.cmd
5-
local config = require "one_monokai.config"
6-
local themes = require "one_monokai.themes"
3+
local did_setup = false
4+
local config = require "one_monokai.config"
5+
local compiler = require "one_monokai.lib.compiler"
6+
local utils = require "one_monokai.utils"
77

8-
if vim.g.colors_name then
9-
set.hi "clear"
8+
function M.load()
9+
if not did_setup then
10+
M.setup()
1011
end
1112

12-
if vim.fn.exists "syntax_on" then
13-
set.syntax "reset"
13+
local compiled_path = utils.join_paths(config.compile_path, "themes")
14+
local f = loadfile(compiled_path)
15+
16+
if not f then
17+
compiler.compile()
18+
19+
f = assert(loadfile(compiled_path), "could not load cache")
1420
end
1521

16-
vim.o.background = "dark"
17-
vim.o.termguicolors = true
18-
vim.g.colors_name = "one_monokai"
22+
f()
23+
end
24+
25+
function M.setup(opts)
26+
local hasher = require "one_monokai.lib.hasher"
1927

28+
did_setup = true
2029
config:extend(opts)
21-
themes.load()
2230

23-
if opts then
24-
set.colorscheme "one_monokai"
31+
-- Get cached hash
32+
local cached_hash_path = utils.join_paths(config.compile_path, "hash")
33+
local file = io.open(cached_hash_path)
34+
local cached_hash = nil
35+
36+
if file then
37+
cached_hash = file:read()
38+
file:close()
39+
end
40+
41+
-- Get current hash
42+
local git_path = debug.getinfo(1).source:sub(2, -24) .. ".git"
43+
local git = vim.fn.getftime(git_path) -- 2x faster vim.loop.fs_stat
44+
local hash = hasher.hash(config.options)
45+
.. (git == -1 and git_path or git) -- no .git in /nix/store -> cache path
46+
.. (vim.o.winblend == 0 and 1 or 0) -- :h winblend
47+
.. (vim.o.pumblend == 0 and 1 or 0) -- :h pumblend
48+
49+
-- Recompile if hash changed
50+
if cached_hash ~= hash then
51+
compiler.compile()
52+
file = io.open(cached_hash_path, "wb")
53+
54+
if file then
55+
file:write(hash)
56+
file:close()
57+
end
2558
end
2659
end
2760

lua/one_monokai/lib/bitlib.lua

Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,101 @@
1+
---@source: https://github.com/davidm/lua-bit-numberlua/blob/master/lmod/bit/numberlua.lua
2+
---@class bitlib
3+
local bitlib = {}
4+
5+
local MOD = 2 ^ 32
6+
local floor = math.floor
7+
8+
local function memoize(f)
9+
local mt = {}
10+
local t = setmetatable({}, mt)
11+
12+
function mt:__index(k)
13+
local v = f(k)
14+
t[k] = v
15+
16+
return v
17+
end
18+
19+
return t
20+
end
21+
22+
local function make_bitop_uncached(t, m)
23+
local function bitop(a, b)
24+
local res, p = 0, 1
25+
26+
while a ~= 0 and b ~= 0 do
27+
local am, bm = a % m, b % m
28+
res = res + t[am][bm] * p
29+
a = (a - am) / m
30+
b = (b - bm) / m
31+
p = p * m
32+
end
33+
34+
res = res + (a + b) * p
35+
36+
return res
37+
end
38+
39+
return bitop
40+
end
41+
42+
local function make_bitop(t)
43+
local op1 = make_bitop_uncached(t, 2 ^ 1)
44+
local op2 = memoize(function(a)
45+
return memoize(function(b)
46+
return op1(a, b)
47+
end)
48+
end)
49+
50+
return make_bitop_uncached(op2, 2 ^ (t.n or 1))
51+
end
52+
53+
bitlib.bxor = make_bitop { [0] = { [0] = 0, [1] = 1 }, [1] = { [0] = 1, [1] = 0 }, n = 4 }
54+
local bxor = bitlib.bxor
55+
56+
local lshift, rshift
57+
58+
-- Lua5.2 inspired
59+
lshift = function(a, disp)
60+
if disp < 0 then
61+
return rshift(a, -disp)
62+
end
63+
64+
return (a * 2 ^ disp) % 2 ^ 32
65+
end
66+
67+
-- Lua5.2 inspired
68+
rshift = function(a, disp)
69+
if disp < 0 then
70+
return lshift(a, -disp)
71+
end
72+
73+
return floor(a % 2 ^ 32 / 2 ^ disp)
74+
end
75+
76+
local function bit_tobit(x)
77+
x = x % MOD
78+
79+
if x >= 0x80000000 then
80+
x = x - MOD
81+
end
82+
83+
return x
84+
end
85+
86+
local function bit_bxor(a, b, c, ...)
87+
if c then
88+
return bit_bxor(bit_bxor(a, b), c, ...)
89+
elseif b then
90+
return bit_tobit(bxor(a % MOD, b % MOD))
91+
else
92+
return bit_tobit(a)
93+
end
94+
end
95+
96+
return {
97+
bxor = bit_bxor,
98+
lshift = function(x, n)
99+
return bit_tobit(lshift(x % MOD, n % 32))
100+
end,
101+
}

lua/one_monokai/lib/compiler.lua

Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
---@class compiler
2+
---@source: https://github.com/catppuccin/nvim
3+
local compiler = {}
4+
5+
local fmt = string.format
6+
local utils = require "one_monokai.utils"
7+
8+
local function inspect(attr)
9+
local list = {}
10+
11+
for key, value in pairs(attr) do
12+
local t = type(value)
13+
14+
if t == "string" then
15+
table.insert(list, fmt([[%s = "%s"]], key, value))
16+
else
17+
table.insert(list, fmt("%s = %s", key, t == table and inspect(value) or tostring(value)))
18+
end
19+
end
20+
21+
return fmt([[{ %s }]], table.concat(list, ", "))
22+
end
23+
24+
function compiler.compile()
25+
local config = require "one_monokai.config"
26+
local themes = require "one_monokai.themes"
27+
local cached_themes_path = utils.join_paths(config.compile_path, "themes")
28+
29+
local lines = {
30+
[[
31+
return string.dump(function()
32+
local hi = vim.api.nvim_set_hl
33+
if vim.g.colors_name then vim.cmd.hi "clear" end
34+
vim.o.termguicolors = true
35+
vim.g.colors_name = "one_monokai"
36+
vim.o.background = "dark"
37+
]],
38+
}
39+
40+
for name, attrs in pairs(themes.groups) do
41+
for _, attr in pairs(attrs) do
42+
if not config.italics and attr == "italic" then
43+
attrs[attr] = false
44+
end
45+
end
46+
47+
table.insert(lines, fmt([[hi(0, "%s", %s)]], name, inspect(attrs)))
48+
end
49+
50+
table.insert(lines, "end, true)")
51+
52+
if vim.fn.isdirectory(config.compile_path) == 0 then
53+
vim.fn.mkdir(config.compile_path, "p")
54+
end
55+
56+
local f = loadstring(table.concat(lines, "\n"))
57+
58+
if not f then
59+
local err_path = os.getenv "TMP" .. "/one_monokai_error.lua"
60+
61+
print(string.format(
62+
[[One Monokai (error): Most likely some mistake made in your One Monokai config
63+
You can open %s for debugging
64+
65+
If you think this is a bug, kindly open an issue and attach %s file
66+
Below is the error message that we captured:
67+
]],
68+
err_path,
69+
err_path
70+
))
71+
72+
local err = io.open(err_path, "wb")
73+
74+
if err then
75+
err:write(table.concat(lines, "\n"))
76+
err:close()
77+
end
78+
79+
dofile(err_path)
80+
81+
return
82+
end
83+
84+
local file = assert(
85+
io.open(cached_themes_path, "wb"),
86+
"Permission denied while writing compiled file to " .. config.compile_path
87+
)
88+
89+
file:write(f())
90+
file:close()
91+
end
92+
93+
return compiler

lua/one_monokai/lib/hasher.lua

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
---@class hasher
2+
local hasher = {}
3+
4+
local bitlib = bit or bit32 or require "one_monokai.lib.bitlib"
5+
6+
---@source: https://theartincode.stanis.me/008-djb2/
7+
local function hash_str(str)
8+
local hash = 5381
9+
10+
for i = 1, #str do
11+
hash = bitlib.lshift(hash, 5) + hash + string.byte(str, i)
12+
end
13+
14+
return hash
15+
end
16+
17+
---@source https://codeforces.com/blog/entry/85900
18+
function hasher.hash(value)
19+
local colors = require "one_monokai.colors"
20+
local t = type(value)
21+
22+
if t == "table" then
23+
local hash = 0
24+
25+
for p, u in next, value do
26+
hash = bitlib.bxor(hash, hash_str(p .. hasher.hash(u)))
27+
end
28+
29+
return hash
30+
elseif t == "function" then
31+
return hasher.hash(value(colors))
32+
end
33+
34+
return tostring(value)
35+
end
36+
37+
return hasher

lua/one_monokai/themes/groups.lua renamed to lua/one_monokai/themes.lua

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,9 @@
1-
---@class groups
2-
local groups = {}
1+
---@class themes
2+
local themes = {}
33

44
local colors = require "one_monokai.colors"
55
local config = require "one_monokai.config"
66

7-
---@type groups
87
local defaults = {
98
Boolean = { fg = colors.cyan },
109
Character = { fg = colors.yellow },
@@ -572,6 +571,10 @@ for _, semantic_group in ipairs(vim.fn.getcompletion("@lsp", "highlight")) do
572571
end
573572
end
574573

575-
groups = vim.deepcopy(defaults)
574+
themes.groups = vim.deepcopy(defaults)
576575

577-
return groups
576+
for name, attrs in pairs(config.themes(colors)) do
577+
themes.groups[name] = attrs
578+
end
579+
580+
return themes

lua/one_monokai/themes/init.lua

Lines changed: 0 additions & 27 deletions
This file was deleted.

lua/one_monokai/utils.lua

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
local utils = {}
2+
3+
function utils.join_paths(...)
4+
local separator = jit and (jit.os == "Windows" and "\\" or "/") or string.sub(package.config, 1, 1)
5+
6+
return table.concat({ ... }, separator)
7+
end
8+
9+
return utils

0 commit comments

Comments
 (0)