Skip to content
This repository was archived by the owner on Dec 7, 2025. It is now read-only.

Commit 2093296

Browse files
committed
update
1 parent 53956b0 commit 2093296

File tree

1 file changed

+68
-50
lines changed

1 file changed

+68
-50
lines changed

lua/strive/init.lua

Lines changed: 68 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
-- A lightweight, feature-rich plugin manager with support for lazy loading,
33
-- dependencies, and asynchronous operations.
44

5-
local api, uv, if_nil, Iter, ffi = vim.api, vim.uv, vim.F.if_nil, vim.iter, require('ffi')
5+
local api, uv, if_nil, ffi = vim.api, vim.uv, vim.F.if_nil, require('ffi')
66

77
-- =====================================================================
88
-- 1. Configuration and Constants
@@ -41,6 +41,10 @@ local STATUS = {
4141
ERROR = 'error',
4242
}
4343

44+
local function isdir(dir)
45+
return (uv.fs_stat(dir) or {}).type == 'directory'
46+
end
47+
4448
-- =====================================================================
4549
-- 2. Async Utilities
4650
-- =====================================================================
@@ -146,7 +150,7 @@ function Async.await(promise)
146150
end
147151

148152
promise(function(result)
149-
vim.schedule(function()
153+
Async.safe_schedule(function()
150154
local ok = coroutine.resume(co, result)
151155
if not ok then
152156
vim.notify(debug.traceback(co), vim.log.levels.ERROR)
@@ -172,7 +176,7 @@ function Async.try_await(promise)
172176
end
173177

174178
promise(function(result)
175-
vim.schedule(function()
179+
Async.safe_schedule(function()
176180
local ok = coroutine.resume(co, result)
177181
if not ok then
178182
vim.notify(debug.traceback(co), vim.log.levels.ERROR)
@@ -193,7 +197,7 @@ function Async.async(func)
193197
end)
194198

195199
if not status then
196-
vim.schedule(function()
200+
Async.safe_schedule(function()
197201
vim.notify('Async error: ' .. tostring(result), vim.log.levels.ERROR)
198202
end)
199203
end
@@ -204,7 +208,7 @@ function Async.async(func)
204208
local function step(...)
205209
local ok, err = coroutine.resume(co, ...)
206210
if not ok then
207-
vim.schedule(function()
211+
Async.safe_schedule(function()
208212
vim.notify('Coroutine error: ' .. debug.traceback(co, err), vim.log.levels.ERROR)
209213
end)
210214
end
@@ -301,6 +305,14 @@ function Async.scandir(dir)
301305
end
302306
end
303307

308+
function Async.safe_schedule(callback)
309+
if not vim.in_fast_event() then
310+
callback()
311+
return
312+
end
313+
vim.schedule(callback)
314+
end
315+
304316
-- =====================================================================
305317
-- 3. Task Queue
306318
-- =====================================================================
@@ -483,7 +495,7 @@ function ProgressWindow:update_entry(plugin_name, status, message)
483495

484496
if self.visible then
485497
-- Schedule UI updates to run in the main event loop
486-
vim.schedule(function()
498+
Async.safe_schedule(function()
487499
self:refresh()
488500
end)
489501
end
@@ -630,12 +642,10 @@ function Plugin:is_installed()
630642
end
631643

632644
local function load_opts(opt)
633-
if opt then
634-
if type(opt) == 'string' then
635-
vim.cmd(opt)
636-
elseif type(opt) == 'function' then
637-
opt()
638-
end
645+
if type(opt) == 'string' then
646+
vim.cmd(opt)
647+
elseif type(opt) == 'function' then
648+
opt()
639649
end
640650
end
641651

@@ -651,7 +661,7 @@ function Plugin:packadd()
651661
end
652662

653663
-- Load a plugin and its dependencies
654-
function Plugin:load()
664+
function Plugin:load(opts)
655665
if self.loaded then
656666
return true
657667
end
@@ -667,30 +677,37 @@ function Plugin:load()
667677
self.loaded = true
668678
vim.g.strive_loaded = vim.g.strive_loaded + 1
669679

670-
load_opts(self.init_opts)
680+
if self.init_opts then
681+
load_opts(self.init_opts)
682+
end
671683

672684
self:packadd()
673-
self:load_scripts()
685+
self:load_scripts(opts and opts.script_cb or nil)
674686

675687
self:call_setup()
676688

677-
Iter(self.dependencies):map(function(d)
678-
if not d.loaded then
679-
d:load()
689+
if #self.dependencies > 0 then
690+
for _, dep in ipairs(self.dependencies) do
691+
if not dep.loaded then
692+
dep:load()
693+
end
680694
end
681-
end)
682-
683-
load_opts(self.config_opts)
695+
end
696+
if self.config_opts then
697+
load_opts(self.config_opts)
698+
end
684699
-- Update status
685700
self.status = STATUS.LOADED
686701

702+
pcall(api.nvim_del_augroup_by_name, 'strive_' .. self.plugin_name)
687703
return true
688704
end
689705

690706
-- Set up lazy loading on specific events
691707
function Plugin:on(events)
692708
self.is_lazy = true
693709
self.events = type(events) ~= 'table' and { events } or events
710+
local group = api.nvim_create_augroup('strive_' .. self.plugin_name, { clear = true })
694711

695712
-- Create autocmds for each event
696713
for _, event in ipairs(self.events) do
@@ -700,10 +717,7 @@ function Plugin:on(events)
700717
event, pattern = t[1], t[2]
701718
end
702719
api.nvim_create_autocmd(event, {
703-
group = api.nvim_create_augroup(
704-
'strive_' .. self.plugin_name .. '_' .. event,
705-
{ clear = true }
706-
),
720+
group = group,
707721
pattern = pattern,
708722
once = true,
709723
callback = function(args)
@@ -714,12 +728,10 @@ function Plugin:on(events)
714728
local event_data = args.data and vim.deepcopy(args.data) or {}
715729

716730
-- Schedule the event emission to avoid nesting too deep
717-
-- vim.schedule(function()
718731
api.nvim_exec_autocmds(event, {
719732
modeline = false,
720733
data = event_data,
721734
})
722-
-- end)
723735
end
724736
end,
725737
})
@@ -733,7 +745,7 @@ function Plugin:ft(filetypes)
733745
self.is_lazy = true
734746
self.filetypes = type(filetypes) ~= 'table' and { filetypes } or filetypes
735747
api.nvim_create_autocmd('FileType', {
736-
group = api.nvim_create_augroup('strive_' .. self.plugin_name .. '_ft', { clear = true }),
748+
group = api.nvim_create_augroup('strive_' .. self.plugin_name, { clear = true }),
737749
pattern = self.filetypes,
738750
once = true,
739751
callback = function(args)
@@ -750,25 +762,33 @@ function Plugin:ft(filetypes)
750762
return self
751763
end
752764

753-
function Plugin:load_scripts()
765+
function Plugin:load_scripts(callback)
754766
Async.async(function()
755767
local plugin_path = self:get_path()
756768
local plugin_dir = vim.fs.joinpath(plugin_path, 'plugin')
769+
if not isdir(plugin_dir) then
770+
return
771+
end
757772

758773
local result = Async.try_await(Async.scandir(plugin_dir))
759-
if not result.success or not result.value or not result.value[2] then
774+
if not result.success or not result.value then
760775
M.log('debug', string.format('Plugin directory not found: %s', plugin_dir))
761776
return
762777
end
763778

764779
while true do
765-
local name, type = uv.fs_scandir_next(result.value[2])
780+
local name, type = uv.fs_scandir_next(result.value)
766781
if not name then
767782
break
768783
end
769784
if type == 'file' and (name:match('%.lua$') or name:match('%.vim$')) then
770785
local file_path = vim.fs.joinpath(plugin_dir, name)
771-
vim.cmd('source ' .. vim.fn.fnameescape(file_path))
786+
Async.safe_schedule(function()
787+
vim.cmd('source ' .. vim.fn.fnameescape(file_path))
788+
if callback then
789+
callback()
790+
end
791+
end)
772792
end
773793
end
774794
end)()
@@ -784,16 +804,17 @@ function Plugin:cmd(commands)
784804
pcall(api.nvim_del_user_command, cmd_name)
785805
local args = cmd_args.args ~= '' and ' ' .. cmd_args.args or ''
786806
local bang = cmd_args.bang and '!' or ''
787-
self:load()
788-
vim.schedule(function()
789-
if vim.fn.exists(':' .. cmd_name) == 2 then
790-
---@diagnostic disable-next-line: param-type-mismatch
791-
local ok, err = pcall(vim.cmd, cmd_name .. bang .. args)
792-
if not ok then
793-
vim.notify(string.format('execute %s wrong: %s', cmd_name, err), vim.log.levels.ERROR)
807+
self:load({
808+
script_cb = function()
809+
if vim.fn.exists(':' .. cmd_name) == 2 then
810+
---@diagnostic disable-next-line: param-type-mismatch
811+
local ok, err = pcall(vim.cmd, cmd_name .. bang .. args)
812+
if not ok then
813+
vim.notify(string.format('execute %s wrong: %s', cmd_name, err), vim.log.levels.ERROR)
814+
end
794815
end
795-
end
796-
end)
816+
end,
817+
})
797818
end, {
798819
nargs = '*',
799820
bang = true,
@@ -898,7 +919,7 @@ function Plugin:theme(name)
898919
Async.async(function()
899920
local installed = Async.await(self:is_installed())
900921
if installed then
901-
vim.schedule(function()
922+
Async.safe_schedule(function()
902923
vim.opt.rtp:append(vim.fs.joinpath(START_DIR, self.plugin_name))
903924
vim.cmd.colorscheme(self.colorscheme)
904925
end)
@@ -974,7 +995,7 @@ function Plugin:install()
974995
lines = vim.split(lines, '\n', { trimempty = true })
975996

976997
if #lines > 0 then
977-
vim.schedule(function()
998+
Async.safe_schedule(function()
978999
ui:update_entry(self.name, self.status, lines[#lines])
9791000
end)
9801001
end
@@ -1105,7 +1126,7 @@ function Plugin:update()
11051126
lines = vim.split(lines, '\n', { trimempty = true })
11061127

11071128
if #lines > 0 then
1108-
vim.schedule(function()
1129+
Async.safe_schedule(function()
11091130
ui:update_entry(self.name, self.status, lines[#lines])
11101131
end)
11111132
end
@@ -1149,9 +1170,6 @@ function Plugin:install_with_retry()
11491170
local url = ('https://github.com/%s'):format(self.name)
11501171
local cmd = { 'git', 'clone', '--progress', url, path }
11511172

1152-
-- Ensure parent directory exists
1153-
vim.fn.mkdir(vim.fs.dirname(path), 'p')
1154-
11551173
-- Use retry with the system command (3 retries with exponential backoff)
11561174
local result = Async.try_await(Async.retry(function()
11571175
return Async.system(cmd, {
@@ -1163,7 +1181,7 @@ function Plugin:install_with_retry()
11631181
lines = vim.split(lines, '\n', { trimempty = true })
11641182

11651183
if #lines > 0 then
1166-
vim.schedule(function()
1184+
Async.safe_schedule(function()
11671185
ui:update_entry(self.name, self.status, lines[#lines])
11681186
end)
11691187
end
@@ -1522,7 +1540,7 @@ local function setup_auto_install()
15221540
-- When using strive in plugin folder
15231541
if vim.v.vim_did_enter == 1 then
15241542
-- UI has already initialized, schedule installation directly
1525-
vim.schedule(function()
1543+
Async.safe_schedule(function()
15261544
M.log('debug', 'UI already initialized, installing plugins now')
15271545
M.install()
15281546
end)
@@ -1534,7 +1552,7 @@ local function setup_auto_install()
15341552
api.nvim_create_autocmd('UIEnter', {
15351553
group = api.nvim_create_augroup('strive_auto_install', { clear = true }),
15361554
callback = function()
1537-
vim.schedule(function()
1555+
Async.safe_schedule(function()
15381556
M.log('debug', 'UIEnter triggered, installing plugins')
15391557
M.install()
15401558
end)

0 commit comments

Comments
 (0)