-
Notifications
You must be signed in to change notification settings - Fork 162
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
37 changed files
with
2,756 additions
and
1,451 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
{ | ||
"neodev": { | ||
"library": { | ||
"plugins": [ | ||
"plenary.nvim", | ||
"nvim-web-devicons" | ||
] | ||
} | ||
}, | ||
"lspconfig": { | ||
"lua_ls": { | ||
"Lua.runtime.version": "LuaJIT", | ||
"Lua.workspace.checkThirdParty": false | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,134 @@ | ||
local M = {} | ||
|
||
M.budget = 1 | ||
local Scheduler = {} | ||
Scheduler._queue = {} | ||
Scheduler._executor = assert(vim.loop.new_check()) | ||
|
||
function Scheduler.step() | ||
local budget = M.budget * 1e6 | ||
local start = vim.loop.hrtime() | ||
while #Scheduler._queue > 0 and vim.loop.hrtime() - start < budget do | ||
local a = table.remove(Scheduler._queue, 1) | ||
a:_step() | ||
if a.running then | ||
table.insert(Scheduler._queue, a) | ||
end | ||
end | ||
if #Scheduler._queue == 0 then | ||
return Scheduler._executor:stop() | ||
end | ||
end | ||
|
||
---@param a Async | ||
function Scheduler.add(a) | ||
table.insert(Scheduler._queue, a) | ||
if not Scheduler._executor:is_active() then | ||
Scheduler._executor:start(vim.schedule_wrap(Scheduler.step)) | ||
end | ||
end | ||
|
||
--- @alias AsyncCallback fun(result?:any, error?:string) | ||
|
||
--- @class Async | ||
--- @field running boolean | ||
--- @field result? any | ||
--- @field error? string | ||
--- @field callbacks AsyncCallback[] | ||
--- @field thread thread | ||
local Async = {} | ||
Async.__index = Async | ||
|
||
function Async.new(fn) | ||
local self = setmetatable({}, Async) | ||
self.callbacks = {} | ||
self.running = true | ||
self.thread = coroutine.create(fn) | ||
Scheduler.add(self) | ||
return self | ||
end | ||
|
||
---@param result? any | ||
---@param error? string | ||
function Async:_done(result, error) | ||
if self.running then | ||
self.running = false | ||
self.result = result | ||
self.error = error | ||
end | ||
for _, callback in ipairs(self.callbacks) do | ||
callback(result, error) | ||
end | ||
-- only run each callback once. | ||
-- _done can possibly be called multiple times. | ||
-- so we need to clear callbacks after executing them. | ||
self.callbacks = {} | ||
end | ||
|
||
function Async:_step() | ||
local ok, res = coroutine.resume(self.thread) | ||
if not ok then | ||
return self:_done(nil, res) | ||
elseif res == "abort" then | ||
return self:_done(nil, "abort") | ||
elseif coroutine.status(self.thread) == "dead" then | ||
return self:_done(res) | ||
end | ||
end | ||
|
||
function Async:cancel() | ||
self:_done(nil, "abort") | ||
end | ||
|
||
---@param cb AsyncCallback | ||
function Async:await(cb) | ||
if not cb then | ||
error("callback is required") | ||
end | ||
if self.running then | ||
table.insert(self.callbacks, cb) | ||
else | ||
cb(self.result, self.error) | ||
end | ||
end | ||
|
||
function Async:sync() | ||
while self.running do | ||
vim.wait(10) | ||
end | ||
return self.error and error(self.error) or self.result | ||
end | ||
|
||
--- @return boolean | ||
function M.is_async(obj) | ||
return obj and type(obj) == "table" and getmetatable(obj) == Async | ||
end | ||
|
||
---@generic F | ||
---@param fn F | ||
---@return F|fun(...): Async | ||
function M.wrap(fn) | ||
return function(...) | ||
local args = { ... } | ||
return Async.new(function() | ||
return fn(unpack(args)) | ||
end) | ||
end | ||
end | ||
|
||
-- This will yield when called from a coroutine | ||
---@async | ||
function M.yield(...) | ||
if coroutine.running() == nil then | ||
error("Trying to yield from a non-yieldable context") | ||
return ... | ||
end | ||
return coroutine.yield(...) | ||
end | ||
|
||
---@async | ||
function M.abort() | ||
return M.yield("abort") | ||
end | ||
|
||
return M |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,53 @@ | ||
---@class trouble.CacheM: {[string]: trouble.Cache} | ||
local M = {} | ||
|
||
---@type table<string, {name:string, hit: number, miss: number, ratio?:number}> | ||
M.stats = {} | ||
|
||
---@class trouble.Cache: {[string]: any} | ||
---@field data table<string, any> | ||
---@field name string | ||
local C = {} | ||
|
||
function C:__index(key) | ||
local ret = C[key] | ||
if ret then | ||
return ret | ||
end | ||
ret = self.data[key] | ||
M.stats[self.name] = M.stats[self.name] or { name = self.name, hit = 0, miss = 0 } | ||
local stats = M.stats[self.name] | ||
if ret ~= nil then | ||
stats.hit = stats.hit + 1 | ||
else | ||
stats.miss = stats.miss + 1 | ||
end | ||
return ret | ||
end | ||
|
||
function C:__newindex(key, value) | ||
self.data[key] = value | ||
end | ||
|
||
function C:clear() | ||
self.data = {} | ||
end | ||
|
||
function M.new(name) | ||
return setmetatable({ data = {}, name = name }, C) | ||
end | ||
|
||
function M.report() | ||
for _, v in pairs(M.stats) do | ||
v.ratio = math.ceil(v.hit / (v.hit + v.miss) * 100) | ||
end | ||
return M.stats | ||
end | ||
|
||
function M.__index(_, k) | ||
M[k] = M.new(k) | ||
return M[k] | ||
end | ||
|
||
local ret = setmetatable(M, M) | ||
return ret |
This file was deleted.
Oops, something went wrong.
This file was deleted.
Oops, something went wrong.
Oops, something went wrong.