2022-12-23 15:34:55 +08:00
|
|
|
---@class LazyUtil: LazyUtilCore
|
2022-11-25 05:03:00 +08:00
|
|
|
local M = setmetatable({}, { __index = require("lazy.core.util") })
|
|
|
|
|
|
|
|
function M.file_exists(file)
|
2024-03-22 15:58:36 +08:00
|
|
|
return vim.uv.fs_stat(file) ~= nil
|
2022-11-25 05:03:00 +08:00
|
|
|
end
|
|
|
|
|
2023-01-05 23:52:02 +08:00
|
|
|
---@param opts? LazyFloatOptions
|
2023-07-21 05:42:38 +08:00
|
|
|
---@return LazyFloat
|
2022-12-24 18:26:29 +08:00
|
|
|
function M.float(opts)
|
2023-01-12 16:01:29 +08:00
|
|
|
return require("lazy.view.float")(opts)
|
2022-12-24 18:26:29 +08:00
|
|
|
end
|
|
|
|
|
2023-06-12 14:28:10 +08:00
|
|
|
function M.wo(win, k, v)
|
|
|
|
if vim.api.nvim_set_option_value then
|
|
|
|
vim.api.nvim_set_option_value(k, v, { scope = "local", win = win })
|
|
|
|
else
|
|
|
|
vim.wo[win][k] = v
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2024-03-23 06:35:19 +08:00
|
|
|
---@param opts? {system?:boolean}
|
|
|
|
function M.open(uri, opts)
|
|
|
|
opts = opts or {}
|
|
|
|
if not opts.system and M.file_exists(uri) then
|
2023-01-05 23:52:02 +08:00
|
|
|
return M.float({ style = "", file = uri })
|
2022-11-25 05:03:00 +08:00
|
|
|
end
|
2022-12-31 03:41:23 +08:00
|
|
|
local Config = require("lazy.core.config")
|
2022-11-25 05:03:00 +08:00
|
|
|
local cmd
|
2024-03-23 06:35:19 +08:00
|
|
|
if not opts.system and Config.options.ui.browser then
|
2022-12-31 03:41:23 +08:00
|
|
|
cmd = { Config.options.ui.browser, uri }
|
|
|
|
elseif vim.fn.has("win32") == 1 then
|
2022-12-20 19:34:24 +08:00
|
|
|
cmd = { "explorer", uri }
|
2022-11-25 05:03:00 +08:00
|
|
|
elseif vim.fn.has("macunix") == 1 then
|
|
|
|
cmd = { "open", uri }
|
|
|
|
else
|
2023-02-11 16:04:59 +08:00
|
|
|
if vim.fn.executable("xdg-open") == 1 then
|
2022-12-31 03:41:23 +08:00
|
|
|
cmd = { "xdg-open", uri }
|
2023-02-11 16:04:59 +08:00
|
|
|
elseif vim.fn.executable("wslview") == 1 then
|
2023-02-08 14:32:29 +08:00
|
|
|
cmd = { "wslview", uri }
|
2022-12-31 03:41:23 +08:00
|
|
|
else
|
|
|
|
cmd = { "open", uri }
|
|
|
|
end
|
2022-11-25 05:03:00 +08:00
|
|
|
end
|
|
|
|
|
2022-12-20 19:34:24 +08:00
|
|
|
local ret = vim.fn.jobstart(cmd, { detach = true })
|
|
|
|
if ret <= 0 then
|
2022-11-25 05:03:00 +08:00
|
|
|
local msg = {
|
|
|
|
"Failed to open uri",
|
|
|
|
ret,
|
|
|
|
vim.inspect(cmd),
|
|
|
|
}
|
|
|
|
vim.notify(table.concat(msg, "\n"), vim.log.levels.ERROR)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2022-12-15 21:06:52 +08:00
|
|
|
function M.read_file(file)
|
|
|
|
local fd = assert(io.open(file, "r"))
|
|
|
|
---@type string
|
|
|
|
local data = fd:read("*a")
|
|
|
|
fd:close()
|
|
|
|
return data
|
|
|
|
end
|
|
|
|
|
|
|
|
function M.write_file(file, contents)
|
|
|
|
local fd = assert(io.open(file, "w+"))
|
|
|
|
fd:write(contents)
|
|
|
|
fd:close()
|
|
|
|
end
|
|
|
|
|
2022-12-23 17:18:19 +08:00
|
|
|
---@generic F: fun()
|
2022-11-25 05:03:00 +08:00
|
|
|
---@param ms number
|
2022-12-23 17:18:19 +08:00
|
|
|
---@param fn F
|
|
|
|
---@return F
|
2022-11-25 05:03:00 +08:00
|
|
|
function M.throttle(ms, fn)
|
2024-03-22 15:58:36 +08:00
|
|
|
local timer = vim.uv.new_timer()
|
2022-11-25 05:03:00 +08:00
|
|
|
local running = false
|
|
|
|
local first = true
|
|
|
|
|
2022-12-23 17:18:19 +08:00
|
|
|
return function(...)
|
|
|
|
local args = { ... }
|
|
|
|
local wrapped = function()
|
|
|
|
fn(unpack(args))
|
|
|
|
end
|
2022-11-25 05:03:00 +08:00
|
|
|
if not running then
|
|
|
|
if first then
|
2022-12-23 17:18:19 +08:00
|
|
|
wrapped()
|
2022-11-25 05:03:00 +08:00
|
|
|
first = false
|
|
|
|
end
|
|
|
|
|
|
|
|
timer:start(ms, 0, function()
|
|
|
|
running = false
|
2022-12-23 17:18:19 +08:00
|
|
|
vim.schedule(wrapped)
|
2022-11-25 05:03:00 +08:00
|
|
|
end)
|
|
|
|
|
|
|
|
running = true
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2024-03-27 15:48:55 +08:00
|
|
|
--- Creates a weak reference to an object.
|
|
|
|
--- Calling the returned function will return the object if it has not been garbage collected.
|
|
|
|
---@generic T: table
|
|
|
|
---@param obj T
|
|
|
|
---@return T|fun():T?
|
|
|
|
function M.weak(obj)
|
|
|
|
local weak = { _obj = obj }
|
|
|
|
---@return table<any, any>
|
|
|
|
local function get()
|
|
|
|
local ret = rawget(weak, "_obj")
|
|
|
|
return ret == nil and error("Object has been garbage collected", 2) or ret
|
|
|
|
end
|
|
|
|
local mt = {
|
|
|
|
__mode = "v",
|
|
|
|
__call = function(t)
|
|
|
|
return rawget(t, "_obj")
|
|
|
|
end,
|
|
|
|
__index = function(_, k)
|
|
|
|
return get()[k]
|
|
|
|
end,
|
|
|
|
__newindex = function(_, k, v)
|
|
|
|
get()[k] = v
|
|
|
|
end,
|
|
|
|
__pairs = function()
|
|
|
|
return pairs(get())
|
|
|
|
end,
|
|
|
|
}
|
|
|
|
return setmetatable(weak, mt)
|
|
|
|
end
|
|
|
|
|
2023-01-06 00:36:01 +08:00
|
|
|
---@class LazyCmdOptions: LazyFloatOptions
|
2023-01-05 23:52:02 +08:00
|
|
|
---@field cwd? string
|
|
|
|
---@field env? table<string,string>
|
|
|
|
---@field float? LazyFloatOptions
|
|
|
|
|
2023-01-06 00:36:01 +08:00
|
|
|
-- Opens a floating terminal (interactive by default)
|
|
|
|
---@param cmd? string[]|string
|
|
|
|
---@param opts? LazyCmdOptions|{interactive?:boolean}
|
|
|
|
function M.float_term(cmd, opts)
|
|
|
|
cmd = cmd or {}
|
|
|
|
if type(cmd) == "string" then
|
|
|
|
cmd = { cmd }
|
|
|
|
end
|
|
|
|
if #cmd == 0 then
|
2023-04-23 21:59:31 +08:00
|
|
|
cmd = { vim.o.shell }
|
2023-01-06 00:36:01 +08:00
|
|
|
end
|
2022-12-24 18:26:53 +08:00
|
|
|
opts = opts or {}
|
2023-01-06 00:36:01 +08:00
|
|
|
local float = M.float(opts)
|
|
|
|
vim.fn.termopen(cmd, vim.tbl_isempty(opts) and vim.empty_dict() or opts)
|
|
|
|
if opts.interactive ~= false then
|
|
|
|
vim.cmd.startinsert()
|
|
|
|
vim.api.nvim_create_autocmd("TermClose", {
|
|
|
|
once = true,
|
|
|
|
buffer = float.buf,
|
|
|
|
callback = function()
|
2023-06-03 16:45:53 +08:00
|
|
|
float:close({ wipe = true })
|
2023-01-06 00:36:01 +08:00
|
|
|
vim.cmd.checktime()
|
|
|
|
end,
|
|
|
|
})
|
|
|
|
end
|
|
|
|
return float
|
|
|
|
end
|
2022-12-24 18:26:53 +08:00
|
|
|
|
2023-01-06 00:36:01 +08:00
|
|
|
--- Runs the command and shows it in a floating window
|
|
|
|
---@param cmd string[]
|
|
|
|
---@param opts? LazyCmdOptions|{filetype?:string}
|
|
|
|
function M.float_cmd(cmd, opts)
|
|
|
|
opts = opts or {}
|
|
|
|
local float = M.float(opts)
|
2022-12-24 18:26:53 +08:00
|
|
|
if opts.filetype then
|
|
|
|
vim.bo[float.buf].filetype = opts.filetype
|
|
|
|
end
|
2023-01-06 00:36:01 +08:00
|
|
|
local Process = require("lazy.manage.process")
|
|
|
|
local lines = Process.exec(cmd, { cwd = opts.cwd })
|
|
|
|
vim.api.nvim_buf_set_lines(float.buf, 0, -1, false, lines)
|
|
|
|
vim.bo[float.buf].modifiable = false
|
|
|
|
return float
|
2022-12-24 18:26:53 +08:00
|
|
|
end
|
|
|
|
|
2023-01-06 18:18:48 +08:00
|
|
|
---@deprecated use float_term or float_cmd instead
|
|
|
|
function M.open_cmd()
|
|
|
|
M.warn([[`require("lazy.util").open_cmd()` is deprecated. Please use `float_term` instead. Check the docs]])
|
|
|
|
end
|
|
|
|
|
2022-11-25 05:03:00 +08:00
|
|
|
---@return string?
|
|
|
|
function M.head(file)
|
|
|
|
local f = io.open(file)
|
|
|
|
if f then
|
|
|
|
local ret = f:read()
|
|
|
|
f:close()
|
|
|
|
return ret
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
---@return {branch: string, hash:string}?
|
|
|
|
function M.git_info(dir)
|
|
|
|
local line = M.head(dir .. "/.git/HEAD")
|
|
|
|
if line then
|
|
|
|
---@type string, string
|
|
|
|
local ref, branch = line:match("ref: (refs/heads/(.*))")
|
|
|
|
|
|
|
|
if ref then
|
|
|
|
return {
|
|
|
|
branch = branch,
|
|
|
|
hash = M.head(dir .. "/.git/" .. ref),
|
|
|
|
}
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
---@param msg string|string[]
|
|
|
|
---@param opts? table
|
|
|
|
function M.markdown(msg, opts)
|
|
|
|
if type(msg) == "table" then
|
|
|
|
msg = table.concat(msg, "\n") or msg
|
|
|
|
end
|
|
|
|
|
|
|
|
vim.notify(
|
|
|
|
msg,
|
|
|
|
vim.log.levels.INFO,
|
|
|
|
vim.tbl_deep_extend("force", {
|
|
|
|
title = "lazy.nvim",
|
|
|
|
on_open = function(win)
|
2023-06-12 14:28:10 +08:00
|
|
|
M.wo(win, "conceallevel", 3)
|
|
|
|
M.wo(win, "concealcursor", "n")
|
|
|
|
M.wo(win, "spell", false)
|
2022-11-25 05:03:00 +08:00
|
|
|
|
|
|
|
vim.treesitter.start(vim.api.nvim_win_get_buf(win), "markdown")
|
|
|
|
end,
|
|
|
|
}, opts or {})
|
|
|
|
)
|
|
|
|
end
|
|
|
|
|
2024-06-24 20:16:00 +08:00
|
|
|
---@async
|
|
|
|
---@param ms number
|
|
|
|
function M.sleep(ms)
|
|
|
|
local continue = false
|
|
|
|
vim.defer_fn(function()
|
|
|
|
continue = true
|
|
|
|
end, ms)
|
|
|
|
while not continue do
|
|
|
|
coroutine.yield()
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2022-11-25 05:03:00 +08:00
|
|
|
function M._dump(value, result)
|
|
|
|
local t = type(value)
|
|
|
|
if t == "number" or t == "boolean" then
|
|
|
|
table.insert(result, tostring(value))
|
|
|
|
elseif t == "string" then
|
|
|
|
table.insert(result, ("%q"):format(value))
|
2024-06-18 06:35:56 +08:00
|
|
|
elseif t == "table" and value._raw then
|
|
|
|
table.insert(result, value._raw)
|
2022-11-25 05:03:00 +08:00
|
|
|
elseif t == "table" then
|
|
|
|
table.insert(result, "{")
|
2024-06-19 03:54:54 +08:00
|
|
|
for _, v in ipairs(value) do
|
|
|
|
M._dump(v, result)
|
|
|
|
table.insert(result, ",")
|
|
|
|
end
|
2022-11-25 05:03:00 +08:00
|
|
|
---@diagnostic disable-next-line: no-unknown
|
|
|
|
for k, v in pairs(value) do
|
2024-06-19 03:54:54 +08:00
|
|
|
if type(k) == "string" then
|
2024-06-18 06:35:56 +08:00
|
|
|
if k:match("^[a-zA-Z]+$") then
|
|
|
|
table.insert(result, ("%s="):format(k))
|
|
|
|
else
|
|
|
|
table.insert(result, ("[%q]="):format(k))
|
|
|
|
end
|
2024-06-19 03:54:54 +08:00
|
|
|
M._dump(v, result)
|
|
|
|
table.insert(result, ",")
|
2022-11-25 05:03:00 +08:00
|
|
|
end
|
|
|
|
end
|
|
|
|
table.insert(result, "}")
|
|
|
|
else
|
|
|
|
error("Unsupported type " .. t)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
function M.dump(value)
|
|
|
|
local result = {}
|
|
|
|
M._dump(value, result)
|
|
|
|
return table.concat(result, "")
|
|
|
|
end
|
|
|
|
|
2022-12-05 21:46:11 +08:00
|
|
|
---@generic V
|
|
|
|
---@param t table<string, V>
|
|
|
|
---@param fn fun(key:string, value:V)
|
2023-09-28 18:28:05 +08:00
|
|
|
---@param opts? {case_sensitive?:boolean}
|
|
|
|
function M.foreach(t, fn, opts)
|
2022-12-05 21:46:11 +08:00
|
|
|
---@type string[]
|
|
|
|
local keys = vim.tbl_keys(t)
|
2022-12-31 06:58:01 +08:00
|
|
|
pcall(table.sort, keys, function(a, b)
|
2023-09-28 18:28:05 +08:00
|
|
|
if opts and opts.case_sensitive then
|
|
|
|
return a < b
|
|
|
|
end
|
2022-12-31 06:58:01 +08:00
|
|
|
return a:lower() < b:lower()
|
|
|
|
end)
|
2022-12-05 21:46:11 +08:00
|
|
|
for _, key in ipairs(keys) do
|
|
|
|
fn(key, t[key])
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2022-11-25 05:03:00 +08:00
|
|
|
return M
|