Neovim quick file switcher
1---@module 'snacks'
2
3local log = require("javelin.log")
4
5local Data = {}
6
7---@type JavelinConfig
8local options
9
10local data_dir
11local data_cache = {}
12
13---@param path string
14---@return string
15local function hash_path(path)
16 return vim.fn.sha256(vim.fn.resolve(path))
17end
18
19---@param root_path string
20local function get_data_file(root_path)
21 return vim.fn.resolve(data_dir .. "/" .. hash_path(root_path))
22end
23
24---@param root_path string
25---@param path string
26---@return string
27local function normalize_path(root_path, path)
28 root_path = root_path .. "/"
29 if vim.startswith(path, root_path) then
30 return path:sub(#root_path + 1)
31 end
32
33 return path
34end
35
36---@param root_path string
37---@param list string[]
38---@return string[]
39local function normalize_list(root_path, list)
40 local new_list = {}
41 for _, path in ipairs(list) do
42 if path ~= "" then
43 table.insert(new_list, path)
44 end
45 end
46
47 for i, path in ipairs(new_list) do
48 new_list[i] = normalize_path(root_path, path)
49 end
50
51 return new_list
52end
53
54---@param root_path string
55local function load(root_path)
56 local data_file = get_data_file(root_path)
57 if not vim.uv.fs_stat(data_file) then
58 return {}
59 end
60
61 return normalize_list(root_path, vim.fn.readfile(data_file))
62end
63
64---@param root_path string
65local function write(root_path)
66 vim.fn.writefile(Data.get_list(root_path), get_data_file(root_path))
67end
68
69---@param root_path string
70---@param path string
71local function add_path(root_path, path)
72 local list = Data.get_list(root_path)
73 table.insert(list, normalize_path(root_path, vim.fn.fnamemodify(path, ":~")))
74 write(root_path)
75end
76
77---@param root_path string
78---@return string[]
79function Data.get_list(root_path)
80 local hash = hash_path(root_path)
81 if data_cache[hash] == nil then
82 data_cache[hash] = load(root_path)
83 end
84
85 return data_cache[hash]
86end
87
88---@return string[]
89function Data.get_current()
90 return Data.get_list(Data.get_root())
91end
92
93function Data.add_current()
94 local filename = vim.api.nvim_buf_get_name(0)
95 local buftype = vim.api.nvim_get_option_value("buftype", { buf = 0 })
96
97 if filename ~= "" and buftype == "" then
98 add_path(Data.get_root(), filename)
99 else
100 log.warn("Cannot add this buffer")
101 end
102end
103
104---@param root_path string
105---@param lines string[]
106function Data.update(root_path, lines)
107 data_cache[hash_path(root_path)] = normalize_list(root_path, lines)
108 write(root_path)
109end
110
111---@return string
112function Data.get_root()
113 local root = vim.fn.getcwd()
114
115 if options.use_git_root then
116 local git_root = Snacks.git.get_root(root)
117 if git_root then
118 root = git_root
119 end
120 end
121
122 return vim.fn.fnamemodify(root, ":~")
123end
124
125function Data.setup(opt)
126 options = opt
127
128 data_dir = vim.fn.resolve(vim.fn.stdpath("data") .. "/javelin")
129 if not vim.uv.fs_stat(data_dir) then
130 vim.uv.fs_mkdir(data_dir, tonumber("755", 8))
131 end
132end
133
134return Data