-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathinit.lua
More file actions
270 lines (227 loc) · 9.79 KB
/
Copy pathinit.lua
File metadata and controls
270 lines (227 loc) · 9.79 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
local M = {}
local path_sep = vim.loop.os_uname().sysname == "Windows" and "\\" or "/"
local path_sep_pattern = vim.loop.os_uname().sysname == "Windows" and "[\\\\]+" or "/+"
M.config = {
resource_path = vim.fn.expand("~/factor/"),
default_vocab_roots = {
"resource:core",
"resource:basis",
"resource:extra",
"resource:work"
},
additional_vocab_roots = nil,
vocab_roots = nil,
glob_escape = vim.loop.os_uname().sysname == "Windows" and "*[]?`{$" or "*[]?`{$\\",
new_vocab_root = function()
return "resource:work"
end,
enable_autopairs = false
}
local function remove_last_path_sep(path)
return path:gsub(path_sep_pattern .. "$", "")
end
local function ensure_last_path_sep(path)
if path:match(path_sep_pattern .. "$") then
return path
else
return path .. path_sep
end
end
local function glob(pattern, nosuf, alllinks)
nosuf = nosuf or false
alllinks = alllinks or false
local results = vim.fn.glob(pattern, nosuf, true, alllinks)
return type(results) == "table" and results or {results}
end
function M.get_vocab_roots()
if M.config.vocab_roots then
return M.config.vocab_roots
end
if not M.config.additional_vocab_roots then
local factor_roots_file = vim.fn.expand("~/.factor-roots")
local ok, lines = pcall(vim.fn.readfile, factor_roots_file)
if ok then
M.config.additional_vocab_roots = vim.tbl_map(remove_last_path_sep,
vim.tbl_filter(function(v) return v ~= "" end, lines))
else
M.config.additional_vocab_roots = {}
end
end
local all_roots = vim.list_extend(
vim.deepcopy(M.config.default_vocab_roots),
M.config.additional_vocab_roots
)
M.config.vocab_roots = vim.tbl_map(remove_last_path_sep, all_roots)
return M.config.vocab_roots
end
function M.expand_vocab_roots(vocab_roots)
local expanded_vocab_roots = {}
for _, vocab_root in ipairs(vocab_roots) do
if vocab_root:match("^vocab:") then
local expanded_vocab_roots_len = #expanded_vocab_roots
for i = 1, expanded_vocab_roots_len do
table.insert(expanded_vocab_roots,
ensure_last_path_sep(expanded_vocab_roots[i]) .. vocab_root:sub(7))
end
else
if vocab_root:match("^resource:") then
table.insert(expanded_vocab_roots,
M.config.resource_path .. vocab_root:sub(10))
else
table.insert(expanded_vocab_roots, vocab_root)
end
end
end
return expanded_vocab_roots
end
function M.detect_parent_vocab_roots(vocab_roots, fname, expr, nosuf, alllinks)
local parent_vocab_roots = {}
local expanded_vocab_roots = {}
for _, expanded_vocab_root in ipairs(M.expand_vocab_roots(vocab_roots)) do
expanded_vocab_roots[vim.fn.fnamemodify(expanded_vocab_root, ":p")] = true
end
local current_path = vim.fn.fnamemodify(fname, ":p")
while current_path ~= "" do
local current_path_glob = ensure_last_path_sep(vim.fn.escape(current_path, M.config.glob_escape))
local paths = glob(current_path_glob .. expr, nosuf, alllinks)
for _, path in ipairs(paths) do
path = vim.fn.fnamemodify(path, ":p")
if expanded_vocab_roots[path] then
table.insert(parent_vocab_roots, path)
end
end
current_path = current_path == "/" and "" or vim.fn.fnamemodify(current_path, ":h")
end
return parent_vocab_roots
end
function M.glob_factor(expr, vocab, trailing_dir_sep, output, nosuf, alllinks)
vocab = vocab or false
trailing_dir_sep = trailing_dir_sep or 0
output = output or 0
nosuf = nosuf or false
alllinks = alllinks or false
local expr_str = vocab and ("vocab:" .. expr:gsub("%.", path_sep)) or expr
local found = {}
if expr_str:match("^resource:") then
for _, path_root in ipairs(glob(vim.fn.escape(M.config.resource_path, M.config.glob_escape), true, true)) do
path_root = vim.fn.fnamemodify(path_root, ":p")
for _, path in ipairs(glob(vim.fn.escape(path_root, M.config.glob_escape) .. expr_str:sub(10), nosuf, alllinks)) do
if trailing_dir_sep == 1 then
path = vim.fn.fnamemodify(path, ":p")
elseif trailing_dir_sep == 2 then
path = remove_last_path_sep(vim.fn.fnamemodify(path, ":p"))
end
if output == 0 then
path = "resource:" .. path:sub(#path_root + 1)
end
found[path] = true
end
end
elseif expr_str:match("^vocab:") then
local expanded_vocab_roots = M.expand_vocab_roots(M.get_vocab_roots())
for _, vocab_root in ipairs(expanded_vocab_roots) do
for _, path_root in ipairs(glob(vim.fn.escape(vocab_root, M.config.glob_escape), true, true)) do
path_root = vim.fn.fnamemodify(path_root, ":p")
for _, path in ipairs(glob(vim.fn.escape(path_root, M.config.glob_escape) .. expr_str:sub(7), nosuf, alllinks)) do
if trailing_dir_sep == 1 then
path = vim.fn.fnamemodify(path, ":p")
elseif trailing_dir_sep == 2 then
path = remove_last_path_sep(vim.fn.fnamemodify(path, ":p"))
end
if output == 0 then
path = "vocab:" .. path:sub(#path_root + 1)
elseif output == 1 then
-- keep path as is
else
path = path:sub(#path_root + 1):gsub(path_sep_pattern, ".")
end
found[path] = true
end
end
end
else
if expr_str:match("^%%[resource]%*") then found["resource:"] = true end
if expr_str:match("^%%[vocab]%*") then found["vocab:"] = true end
for _, expr_path in ipairs(glob(expr_str, true, true)) do
expr_path = vim.fn.fnamemodify(expr_path, ":p")
for _, vocab_root in ipairs(M.get_vocab_roots()) do
if vocab_root:match("^resource:") or vocab_root:match("^vocab:") then
goto continue
end
for _, path_root in ipairs(glob(vim.fn.escape(vocab_root, M.config.glob_escape), true, true)) do
path_root = vim.fn.fnamemodify(path_root, ":p")
if expr_path:sub(1, #path_root) ~= path_root then
break
end
for _, path in ipairs(glob(vim.fn.escape(path_root, M.config.glob_escape) .. expr_str:sub(#path_root + 1), nosuf, alllinks)) do
if trailing_dir_sep == 1 then
path = vim.fn.fnamemodify(path, ":p")
elseif trailing_dir_sep == 2 then
path = remove_last_path_sep(vim.fn.fnamemodify(path, ":p"))
end
if output == 0 then
path = path:sub(#path_root + 1)
elseif output == 1 then
-- keep path as is
else
path = path:sub(#path_root + 1):gsub(path_sep_pattern, ".")
end
found[path] = true
end
end
::continue::
end
end
end
local result = vim.tbl_keys(found)
table.sort(result)
return result
end
function M.complete_glob(arg_lead, cmd_line, cursor_pos)
return M.glob_factor(arg_lead .. "*", false, 1)
end
function M.complete_vocab_glob(arg_lead, cmd_line, cursor_pos)
return M.glob_factor(arg_lead .. "*.", true, 2, 2)
end
function M.go_to_vocab(count, cmd, vocab)
local vocab_glob = "vocab:" .. vocab:gsub("%.", path_sep) .. path_sep .. vocab:match("[^.]*$") .. ".factor"
local vocab_files = M.glob_factor(vocab_glob, false, 2, 1)
local vocab_file = vocab_files[count] or nil
if not vocab_file then
vim.api.nvim_err_writeln("Factor: Can't find vocabulary " .. vocab .. " in vocabulary roots")
return
end
vim.cmd(cmd .. " " .. vim.fn.fnameescape(vocab_file))
end
function M.make_vocab(count, cmd, vocab)
local new_vocab_root = M.config.new_vocab_root()
local vocab_dirs = M.glob_factor(new_vocab_root, false, 1, 1)
local vocab_dir = vocab_dirs[count] or nil
if not vocab_dir then
vim.api.nvim_err_writeln("Factor: Can't find new vocabulary root " .. vim.inspect(new_vocab_root) .. " in vocabulary roots")
return
end
vocab_dir = vim.fn.fnamemodify(vocab_dir .. vocab:gsub("%.", path_sep), ":~")
local vocab_file = vocab_dir .. path_sep .. vim.fn.fnamemodify(vocab_dir, ":t") .. ".factor"
vim.fn.mkdir(vocab_dir, "p")
vim.cmd(cmd .. " " .. vim.fn.fnameescape(vocab_file))
end
function M.get_factor_file_base()
local filename = vim.fn.expand("%:r")
filename = filename:gsub("%-docs", "")
filename = filename:gsub("%-tests", "")
return filename
end
function M.go_to_factor_vocab_impl()
vim.cmd("edit " .. vim.fn.fnameescape(M.get_factor_file_base() .. ".factor"))
end
function M.go_to_factor_vocab_docs()
vim.cmd("edit " .. vim.fn.fnameescape(M.get_factor_file_base() .. "-docs.factor"))
end
function M.go_to_factor_vocab_tests()
vim.cmd("edit " .. vim.fn.fnameescape(M.get_factor_file_base() .. "-tests.factor"))
end
function M.setup(opts)
M.config = vim.tbl_deep_extend("force", M.config, opts or {})
end
return M