22-- A lightweight, feature-rich plugin manager with support for lazy loading,
33-- dependencies, and asynchronous operations.
44
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
66
77-- =====================================================================
88-- 1. Configuration and Constants
@@ -391,6 +391,7 @@ function Plugin.new(spec)
391391 local plugin_name = parts [# parts ]:gsub (' %.git$' , ' ' )
392392
393393 local self = setmetatable ({
394+ id = 0 ,
394395 -- Basic properties
395396 name = name , -- Full repo name (user/repo)
396397 plugin_name = plugin_name , -- Just the repo part (for loading)
@@ -443,16 +444,35 @@ function Plugin:is_installed()
443444 end )()
444445end
445446
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+
446468-- Load a plugin and its dependencies
447469function Plugin :load ()
448470 if self .loaded then
449471 return true
450472 end
451473
452- local path = self :get_path ()
453-
454474 -- Check if plugin exists
455- local stat = uv .fs_stat (path )
475+ local stat = uv .fs_stat (self : get_path () )
456476 if not stat or stat .type ~= ' directory' then
457477 return false
458478 end
@@ -462,26 +482,15 @@ function Plugin:load()
462482 self .loaded = true
463483 vim .g .pm_loaded = vim .g .pm_loaded + 1
464484
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 ()
472488 end
473- end
489+ end )
474490
475491 load_opts (self .init_opts )
476492
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 ()
485494
486495 self :call_setup ()
487496 load_opts (self .config_opts )
@@ -701,6 +710,20 @@ function Plugin:build(action)
701710 return self
702711end
703712
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+
704727-- Install the plugin
705728function Plugin :install ()
706729 if self .is_dev or not self .is_remote then
@@ -710,7 +733,6 @@ function Plugin:install()
710733 end
711734
712735 return Async .wrap (function (callback )
713- print (callback )
714736 -- Check if already installed
715737 local installed = Async .await (self :is_installed ())
716738 if installed then
@@ -737,18 +759,17 @@ function Plugin:install()
737759 end
738760 end ,
739761 }, 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 )
741765 vim .schedule (function ()
742766 if obj .code == 0 then
743- self .status = STATUS .INSTALLED
744767 ui :update_entry (self .name , self .status , ' Installation complete' )
745-
746768 -- Apply colorscheme if this is a theme
747769 -- Make sure the plugin is loaded first
748770 if self .colorscheme then
749771 self :theme (self .colorscheme )
750772 end
751-
752773 if self .build_action then
753774 self :load_rtp (function ()
754775 vim .cmd (self .build_action )
@@ -762,6 +783,7 @@ function Plugin:install()
762783 ' Failed: ' .. (obj .stderr or ' Unknown error' ) .. ' code: ' .. obj .code
763784 )
764785 end
786+ callback (ok )
765787 end )
766788 end )
767789
@@ -914,7 +936,7 @@ function M.use(spec)
914936 M .log (' warn' , string.format (' Plugin %s is already registered, skipping duplicate' , plugin .name ))
915937 return plugin_map [plugin .name ]
916938 end
917-
939+ plugin . id = # plugins + 1
918940 -- Add to collections
919941 table.insert (plugins , plugin )
920942 plugin_map [plugin .name ] = plugin
@@ -927,47 +949,6 @@ function M.get_plugin(name)
927949 return plugin_map [name ]
928950end
929951
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-
971952-- Set up auto-install
972953local function setup_auto_install ()
973954 api .nvim_create_autocmd (' UIEnter' , {
986967
987968-- Install all plugins
988969function M .install ()
989- resolve_dependencies ()
990-
991970 local plugins_to_install = {}
992971
993972 -- Create installation tasks
@@ -1032,8 +1011,6 @@ end
10321011
10331012-- Update all plugins with concurrent operations
10341013function M .update ()
1035- resolve_dependencies ()
1036-
10371014 M .log (' info' , ' Checking for updates...' )
10381015 local plugins_to_update = {}
10391016
0 commit comments