-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathinit.lua
More file actions
324 lines (265 loc) · 7.16 KB
/
Copy pathinit.lua
File metadata and controls
324 lines (265 loc) · 7.16 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
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
-- Utility functions for diffusion.nvim
-- Common helper functions and utilities
local Utils = {}
-- Deep merge two tables
function Utils.deep_merge(target, source)
target = target or {}
source = source or {}
for key, value in pairs(source) do
if type(value) == "table" and type(target[key]) == "table" then
target[key] = Utils.deep_merge(target[key], value)
else
target[key] = value
end
end
return target
end
-- Check if table is empty
function Utils.is_empty(tbl)
return next(tbl) == nil
end
-- Get table size (number of key-value pairs)
function Utils.table_size(tbl)
local count = 0
for _ in pairs(tbl) do
count = count + 1
end
return count
end
-- Find available port in range
function Utils.find_available_port(start_port, end_port)
start_port = start_port or 10000
end_port = end_port or 65535
local ports = {}
for p = start_port, end_port do
ports[#ports + 1] = p
end
math.randomseed(os.time() + (vim.loop and (vim.loop.hrtime() % 1e6) or 0))
for i = #ports, 2, -1 do
local j = math.random(1, i)
ports[i], ports[j] = ports[j], ports[i]
end
for _, port in ipairs(ports) do
if Utils.is_port_available(port) then
return port
end
end
return nil
end
-- Check if port is available
function Utils.is_port_available(host_or_port, port)
-- Handle both single port parameter and host/port parameters
local host, actual_port
if port then
host = host_or_port
actual_port = port
else
host = "127.0.0.1"
actual_port = host_or_port
end
local handle = vim.loop.new_tcp()
if not handle then
return false
end
local success = handle:bind(host, actual_port)
handle:close()
return success
end
-- Debounce function calls
function Utils.debounce(fn, delay)
local timer = nil
return function(...)
local args = {...}
if timer then
timer:stop()
end
timer = vim.defer_fn(function()
fn(unpack(args))
timer = nil
end, delay)
end
end
-- Throttle function calls
function Utils.throttle(fn, interval)
local last_call = 0
return function(...)
local now = vim.loop.hrtime() / 1000000
if now - last_call >= interval then
last_call = now
fn(...)
end
end
end
-- Retry function with exponential backoff
function Utils.retry(fn, max_attempts, initial_delay)
max_attempts = max_attempts or 3
initial_delay = initial_delay or 1000
local function attempt(attempt_num)
local success, result = pcall(fn)
if success or attempt_num >= max_attempts then
return success, result
end
local delay = initial_delay * (2 ^ (attempt_num - 1))
vim.defer_fn(function()
return attempt(attempt_num + 1)
end, delay)
end
return attempt(1)
end
-- Generate unique ID
function Utils.generate_id(prefix)
prefix = prefix or "id"
local timestamp = os.time()
local random = math.random(1000, 9999)
return string.format("%s_%d_%d", prefix, timestamp, random)
end
-- Validate email format (basic)
function Utils.is_valid_email(email)
if type(email) ~= "string" then
return false
end
local pattern = "^[%w%._%+-]+@[%w%._%+-]+%.%w+$"
return email:match(pattern) ~= nil
end
-- Validate URL format (basic)
function Utils.is_valid_url(url)
if type(url) ~= "string" then
return false
end
local pattern = "^https?://[%w%._%+-]+"
return url:match(pattern) ~= nil
end
-- Escape string for use in regex
function Utils.escape_pattern(str)
return str:gsub("[%^%$%(%)%%%.%[%]%*%+%-%?]", "%%%1")
end
-- Split string by delimiter
function Utils.split(str, delimiter)
if type(str) ~= "string" then
return {}
end
delimiter = delimiter or "%s+"
local result = {}
for match in str:gmatch("([^" .. delimiter .. "]+)") do
table.insert(result, match)
end
return result
end
-- Trim whitespace from string
function Utils.trim(str)
if type(str) ~= "string" then
return str
end
return str:match("^%s*(.-)%s*$")
end
-- Check if string starts with prefix
function Utils.starts_with(str, prefix)
if type(str) ~= "string" or type(prefix) ~= "string" then
return false
end
return str:sub(1, #prefix) == prefix
end
-- Check if string ends with suffix
function Utils.ends_with(str, suffix)
if type(str) ~= "string" or type(suffix) ~= "string" then
return false
end
return str:sub(-#suffix) == suffix
end
-- Convert camelCase to snake_case
function Utils.camel_to_snake(str)
if type(str) ~= "string" then
return str
end
return str:gsub("([a-z])([A-Z])", "%1_%2"):lower()
end
-- Convert snake_case to camelCase
function Utils.snake_to_camel(str)
if type(str) ~= "string" then
return str
end
return str:gsub("_([a-z])", function(letter)
return letter:upper()
end)
end
-- Get current timestamp in milliseconds
function Utils.now_ms()
return vim.loop.hrtime() / 1000000
end
-- Format duration from milliseconds to human readable
function Utils.format_duration(ms)
if ms < 1000 then
return string.format("%dms", ms)
elseif ms < 60000 then
return string.format("%.1fs", ms / 1000)
elseif ms < 3600000 then
return string.format("%.1fm", ms / 60000)
else
return string.format("%.1fh", ms / 3600000)
end
end
-- Check if process is alive by PID
-- Uses os.execute which is faster and doesn't block like io.popen
function Utils.is_process_alive(pid)
if type(pid) ~= "number" or pid <= 0 then
return false
end
-- Use os.execute with kill -0 (signal 0 checks existence without sending signal)
-- This is faster than io.popen and doesn't block the UI thread
local result = os.execute("kill -0 " .. pid .. " 2>/dev/null")
-- os.execute returns different values depending on Lua version:
-- Lua 5.1: returns exit code as number (0 = success)
-- Lua 5.2+: returns true/false, exit type, exit code
if type(result) == "number" then
return result == 0
elseif type(result) == "boolean" then
return result
end
return false
end
-- Get Neovim version info
function Utils.get_nvim_version()
local version = vim.version()
return {
major = version.major,
minor = version.minor,
patch = version.patch,
prerelease = version.prerelease,
string = string.format("%d.%d.%d", version.major, version.minor, version.patch)
}
end
-- Check if Neovim version meets requirement
function Utils.check_nvim_version(required_version)
local current = Utils.get_nvim_version()
local required = Utils.split(required_version, ".")
local major = tonumber(required[1]) or 0
local minor = tonumber(required[2]) or 0
local patch = tonumber(required[3]) or 0
if current.major > major then
return true
elseif current.major == major then
if current.minor > minor then
return true
elseif current.minor == minor then
return current.patch >= patch
end
end
return false
end
-- Create directory if it doesn't exist
function Utils.ensure_dir(path)
if vim.fn.isdirectory(path) == 0 then
vim.fn.mkdir(path, "p")
end
end
-- Get operating system
function Utils.get_os()
if vim.fn.has("win32") == 1 or vim.fn.has("win64") == 1 then
return "windows"
elseif vim.fn.has("mac") == 1 then
return "macos"
else
return "linux"
end
end
return Utils