2
2
-- A lightweight, feature-rich plugin manager with support for lazy loading,
3
3
-- dependencies, and asynchronous operations.
4
4
5
- local api , uv , if_nil = vim .api , vim .uv , vim .F .if_nil
5
+ local api , uv , if_nil , Iter = vim .api , vim .uv , vim .F .if_nil , vim . iter
6
6
7
7
-- =====================================================================
8
8
-- 1. Configuration and Constants
@@ -391,6 +391,7 @@ function Plugin.new(spec)
391
391
local plugin_name = parts [# parts ]:gsub (' %.git$' , ' ' )
392
392
393
393
local self = setmetatable ({
394
+ id = 0 ,
394
395
-- Basic properties
395
396
name = name , -- Full repo name (user/repo)
396
397
plugin_name = plugin_name , -- Just the repo part (for loading)
@@ -443,16 +444,35 @@ function Plugin:is_installed()
443
444
end )()
444
445
end
445
446
447
+ local function load_opts (opt )
448
+ if opt then
449
+ if type (opt ) == ' string' then
450
+ vim .cmd (opt )
451
+ elseif type (opt ) == ' function' then
452
+ opt ()
453
+ end
454
+ end
455
+ end
456
+
457
+ function Plugin :packadd ()
458
+ -- If it's a lazy-loaded plugin, add it
459
+ if self .is_lazy then
460
+ if not self .is_dev then
461
+ vim .cmd .packadd (self .plugin_name )
462
+ else
463
+ vim .opt .rtp :append (self :get_path ())
464
+ end
465
+ end
466
+ end
467
+
446
468
-- Load a plugin and its dependencies
447
469
function Plugin :load ()
448
470
if self .loaded then
449
471
return true
450
472
end
451
473
452
- local path = self :get_path ()
453
-
454
474
-- Check if plugin exists
455
- local stat = uv .fs_stat (path )
475
+ local stat = uv .fs_stat (self : get_path () )
456
476
if not stat or stat .type ~= ' directory' then
457
477
return false
458
478
end
@@ -462,26 +482,15 @@ function Plugin:load()
462
482
self .loaded = true
463
483
vim .g .pm_loaded = vim .g .pm_loaded + 1
464
484
465
- local function load_opts (opt )
466
- if opt then
467
- if type (opt ) == ' string' then
468
- vim .cmd (opt )
469
- elseif type (opt ) == ' function' then
470
- opt ()
471
- end
485
+ Iter (self .dependencies ):map (function (d )
486
+ if not d .loaded then
487
+ d :load ()
472
488
end
473
- end
489
+ end )
474
490
475
491
load_opts (self .init_opts )
476
492
477
- -- If it's a lazy-loaded plugin, add it
478
- if self .is_lazy then
479
- if not self .is_dev then
480
- vim .cmd .packadd (self .plugin_name )
481
- else
482
- vim .opt .rtp :append (path )
483
- end
484
- end
493
+ self :packadd ()
485
494
486
495
self :call_setup ()
487
496
load_opts (self .config_opts )
@@ -701,6 +710,20 @@ function Plugin:build(action)
701
710
return self
702
711
end
703
712
713
+ -- Add dependency to a plugin
714
+ function Plugin :depends (deps )
715
+ deps = type (deps ) == ' string' and { deps } or deps
716
+ -- Extend the current dependencies
717
+ for _ , dep in ipairs (deps ) do
718
+ if not plugins [dep ] then
719
+ local d = M .use (dep )
720
+ d .is_lazy = true
721
+ table.insert (self .dependencies , d )
722
+ end
723
+ end
724
+ return self
725
+ end
726
+
704
727
-- Install the plugin
705
728
function Plugin :install ()
706
729
if self .is_dev or not self .is_remote then
@@ -710,7 +733,6 @@ function Plugin:install()
710
733
end
711
734
712
735
return Async .wrap (function (callback )
713
- print (callback )
714
736
-- Check if already installed
715
737
local installed = Async .await (self :is_installed ())
716
738
if installed then
@@ -737,18 +759,17 @@ function Plugin:install()
737
759
end
738
760
end ,
739
761
}, function (obj )
740
- callback (obj .code == 0 )
762
+ local ok = obj .code == 0
763
+ self .status = ok and STATUS .INSTALLED or STATUS .ERROR
764
+ callback (ok )
741
765
vim .schedule (function ()
742
766
if obj .code == 0 then
743
- self .status = STATUS .INSTALLED
744
767
ui :update_entry (self .name , self .status , ' Installation complete' )
745
-
746
768
-- Apply colorscheme if this is a theme
747
769
-- Make sure the plugin is loaded first
748
770
if self .colorscheme then
749
771
self :theme (self .colorscheme )
750
772
end
751
-
752
773
if self .build_action then
753
774
self :load_rtp (function ()
754
775
vim .cmd (self .build_action )
@@ -762,6 +783,7 @@ function Plugin:install()
762
783
' Failed: ' .. (obj .stderr or ' Unknown error' ) .. ' code: ' .. obj .code
763
784
)
764
785
end
786
+ callback (ok )
765
787
end )
766
788
end )
767
789
@@ -914,7 +936,7 @@ function M.use(spec)
914
936
M .log (' warn' , string.format (' Plugin %s is already registered, skipping duplicate' , plugin .name ))
915
937
return plugin_map [plugin .name ]
916
938
end
917
-
939
+ plugin . id = # plugins + 1
918
940
-- Add to collections
919
941
table.insert (plugins , plugin )
920
942
plugin_map [plugin .name ] = plugin
@@ -927,47 +949,6 @@ function M.get_plugin(name)
927
949
return plugin_map [name ]
928
950
end
929
951
930
- -- Process dependencies for all plugins
931
- local function resolve_dependencies ()
932
- local resolved = {}
933
- local function resolve_plugin (name , chain )
934
- if resolved [name ] then
935
- return true
936
- end
937
-
938
- -- Detect circular dependencies
939
- chain = chain or {}
940
- if vim .tbl_contains (chain , name ) then
941
- local cycle = table.concat (chain , ' -> ' ) .. ' -> ' .. name
942
- M .log (' error' , ' Circular dependency detected: ' .. cycle )
943
- return false
944
- end
945
-
946
- -- Get the plugin
947
- local plugin = plugin_map [name ]
948
- if not plugin then
949
- -- Auto-register missing dependency
950
- plugin = M .use (name )
951
- end
952
-
953
- -- Resolve dependencies first
954
- local new_chain = vim .list_extend ({}, chain )
955
- table.insert (new_chain , name )
956
-
957
- for _ , dep_name in ipairs (plugin .dependencies ) do
958
- resolve_plugin (dep_name , new_chain )
959
- end
960
-
961
- resolved [name ] = true
962
- return true
963
- end
964
-
965
- -- Resolve each plugin
966
- for name , _ in pairs (plugin_map ) do
967
- resolve_plugin (name )
968
- end
969
- end
970
-
971
952
-- Set up auto-install
972
953
local function setup_auto_install ()
973
954
api .nvim_create_autocmd (' UIEnter' , {
986
967
987
968
-- Install all plugins
988
969
function M .install ()
989
- resolve_dependencies ()
990
-
991
970
local plugins_to_install = {}
992
971
993
972
-- Create installation tasks
@@ -1032,8 +1011,6 @@ end
1032
1011
1033
1012
-- Update all plugins with concurrent operations
1034
1013
function M .update ()
1035
- resolve_dependencies ()
1036
-
1037
1014
M .log (' info' , ' Checking for updates...' )
1038
1015
local plugins_to_update = {}
1039
1016
0 commit comments