options.lua (2621B)
1 local api = vim.api 2 3 local M = {} 4 5 local function get_ftplugin_runtime(filetype) 6 local files = api.nvim__get_runtime({ 7 string.format('ftplugin/%s.vim', filetype), 8 string.format('ftplugin/%s_*.vim', filetype), 9 string.format('ftplugin/%s/*.vim', filetype), 10 string.format('ftplugin/%s.lua', filetype), 11 string.format('ftplugin/%s_*.lua', filetype), 12 string.format('ftplugin/%s/*.lua', filetype), 13 }, true, {}) --[[@as string[] ]] 14 15 local r = {} ---@type string[] 16 for _, f in ipairs(files) do 17 -- VIMRUNTIME should be static so shouldn't need to worry about it changing 18 if not vim.startswith(f, vim.env.VIMRUNTIME) then 19 r[#r + 1] = f 20 end 21 end 22 return r 23 end 24 25 -- Keep track of ftplugin files 26 local ftplugin_cache = {} ---@type table<string,table<string,integer>> 27 28 -- Keep track of total number of FileType autocmds 29 local ft_autocmd_num ---@type integer? 30 31 -- Keep track of filetype options 32 local ft_option_cache = {} ---@type table<string,table<string,any>> 33 34 --- @param path string 35 --- @return integer 36 local function hash(path) 37 local mtime0 = vim.uv.fs_stat(path).mtime 38 return mtime0.sec * 1000000000 + mtime0.nsec 39 end 40 41 --- Only update the cache on changes to the number of FileType autocmds 42 --- and changes to any ftplugin/ file. This isn't guaranteed to catch everything 43 --- but should be good enough. 44 --- @param filetype string 45 local function update_ft_option_cache(filetype) 46 local new_ftautos = #api.nvim_get_autocmds({ event = 'FileType' }) 47 if new_ftautos ~= ft_autocmd_num then 48 -- invalidate 49 ft_option_cache[filetype] = nil 50 ft_autocmd_num = new_ftautos 51 end 52 53 local files = get_ftplugin_runtime(filetype) 54 55 ftplugin_cache[filetype] = ftplugin_cache[filetype] or {} 56 57 if #files ~= #vim.tbl_keys(ftplugin_cache[filetype]) then 58 -- invalidate 59 ft_option_cache[filetype] = nil 60 ftplugin_cache[filetype] = {} 61 end 62 63 for _, f in ipairs(files) do 64 local mtime = hash(f) 65 if ftplugin_cache[filetype][f] ~= mtime then 66 -- invalidate 67 ft_option_cache[filetype] = nil 68 ftplugin_cache[filetype][f] = mtime 69 end 70 end 71 end 72 73 --- @nodoc 74 --- @param filetype string Filetype 75 --- @param option string Option name 76 --- @return string|integer|boolean 77 function M.get_option(filetype, option) 78 update_ft_option_cache(filetype) 79 80 if not ft_option_cache[filetype] or ft_option_cache[filetype][option] == nil then 81 ft_option_cache[filetype] = ft_option_cache[filetype] or {} 82 ft_option_cache[filetype][option] = api.nvim_get_option_value(option, { filetype = filetype }) 83 end 84 85 return ft_option_cache[filetype][option] 86 end 87 88 return M