academic.lua

· ficd's pastes · raw

expires: 2025-10-29

 1M = {}
 2
 3---@class AcademicOptions
 4M.opts = {
 5	auto_install = true,
 6	auto_rebuild = false,
 7}
 8
 9local function get_root()
10	return vim.fn.fnamemodify(debug.getinfo(1, "S").source:sub(2), ":h:h")
11end
12
13local function get_dictionary()
14	local root = get_root()
15	local dict_path = root .. "/words/en-academic"
16	return dict_path
17end
18
19local function get_spell(dir)
20	local spell_dir = vim.fn["spellfile#WritableSpellDir"]() .. "/"
21	if dir then
22		return spell_dir
23	else
24		return spell_dir .. "en-academic"
25	end
26end
27
28---@param msg string # Message to show user before generation.
29M.generate_spellfile = function(msg)
30	vim.notify("Academic: " .. msg)
31	-- Create spell_dir if it doesn't exist
32	vim.fn.mkdir(get_spell(true), "p")
33	vim.cmd("mkspell! " .. get_spell() .. " " .. get_dictionary())
34	vim.notify("Academic: Done!")
35end
36
37local add_lang = function(lang)
38	local current = vim.opt.spelllang:get()
39	if not vim.tbl_contains(current, lang) then
40		table.insert(current, lang)
41	end
42	vim.opt.spelllang = current
43end
44
45local function get_spl_stat()
46	return vim.uv.fs_stat(get_spell() .. ".utf-8.spl") or vim.uv.fs_stat(get_spell() .. ".ascii.spl")
47end
48
49local function check_build()
50	local stat_plug = vim.uv.fs_stat(get_dictionary())
51	local stat_spell = get_spl_stat()
52	if not stat_plug then
53		vim.notify("Academic wordlist missing!", vim.log.levels.ERROR)
54		return false
55	else
56		if not stat_spell then
57			return true
58		end
59	end
60	-- helper function for time comparison
61	local function time(stat)
62		return stat.mtime.sec + stat.mtime.nsec * 1e-9
63	end
64	-- compare whether our wordlist is newer than user's generated one
65	if time(stat_plug) > time(stat_spell) then
66		return true
67	else
68		return false
69	end
70end
71
72M.update = function()
73	local cmd = { "bash", "-c", get_root() .. "/scripts/generate-wordlist.sh" }
74	local success = pcall(function()
75		vim.system(cmd, {}, function()
76			vim.notify("Academic dictionary updated!", vim.log.levels.INFO)
77		end)
78	end)
79	if not success then
80		vim.notify("Manual update requires bash, curl, and hunspell!", vim.log.levels.WARN)
81	end
82	M.load()
83end
84
85M.load = function()
86	-- We generate the spellfile if it doesn't exist
87	if M.opts.auto_install and not get_spl_stat() then
88		M.generate_spellfile("No spellfile, installing now...")
89	elseif M.opts.auto_rebuild and check_build() then
90		M.generate_spellfile("Spellfile out of date, rebuilding now...")
91	end
92	add_lang("en-academic")
93end
94
95M.setup = function(opts)
96	M.opts = vim.tbl_deep_extend("force", M.opts, opts or {})
97end
98
99return M