@@ -597,7 +597,8 @@ function Plugin.new(spec)
597597 is_remote = not name :find (vim .env .HOME ), -- Is it a remote or local plugin
598598 is_local = spec .is_local or false , -- Development mode flag
599599 is_lazy = spec .is_lazy or false , -- Whether to lazy load
600- local_path = nil , -- Loacal path to load
600+ local_path = nil , -- Local path to load
601+ branch = spec .branch , -- Git branch to use
601602
602603 -- States
603604 status = STATUS .PENDING , -- Current plugin status
@@ -765,7 +766,11 @@ function Plugin:load(do_action, callback)
765766 end
766767
767768 if do_action and self .run_action then
768- vim .cmd (self .run_action )
769+ if type (self .run_action ) == ' string' then
770+ vim .cmd (self .run_action )
771+ else
772+ self .run_action ()
773+ end
769774 end
770775
771776 if callback then
@@ -944,14 +949,17 @@ function Plugin:keys(mappings)
944949 if type (rhs ) == ' function' then
945950 self :load (nil , rhs )
946951 elseif type (rhs ) == ' string' then
947- self :load (nil , function () vim .cmd (rhs ) end )
952+ self :load (nil , function ()
953+ vim .cmd (rhs )
954+ end )
948955 elseif type (rhs ) == ' nil' then
949956 -- If rhs not specified, it should be defined in plugin config
950957 -- In this case, we need to pass a callback
951958 self :load (nil , function ()
952959 vim .schedule (function ()
953960 vim .fn .feedkeys (lhs )
954- end ) end )
961+ end )
962+ end )
955963 end
956964 end , opts )
957965 end
@@ -992,6 +1000,17 @@ function Plugin:after(fn)
9921000 return self
9931001end
9941002
1003+ function Plugin :branch (branch_name )
1004+ assert (
1005+ type (branch_name ) == ' string' and branch_name ~= ' ' ,
1006+ ' Branch name must be a non-empty string'
1007+ )
1008+ self .branch = branch_name
1009+ return self
1010+ end
1011+
1012+ function Plugin :bind () end
1013+
9951014-- Set plugin as a theme
9961015function Plugin :theme (name )
9971016 self .colorscheme = name or self .plugin_name
@@ -1026,7 +1045,7 @@ function Plugin:call_setup()
10261045end
10271046
10281047function Plugin :run (action )
1029- assert (type (action ) == ' string' )
1048+ assert (type (action ) == ' string' or type ( action ) == ' function ' )
10301049 self .run_action = action
10311050 return self
10321051end
@@ -1045,7 +1064,7 @@ function Plugin:depends(deps)
10451064 return self
10461065end
10471066
1048- -- Install the plugin
1067+ -- MODIFIED: Install the plugin with branch support
10491068function Plugin :install ()
10501069 if self .is_local or not self .is_remote then
10511070 return Async .wrap (function (cb )
@@ -1063,13 +1082,23 @@ function Plugin:install()
10631082 ' --depth=' .. DEFAULT_SETTINGS .git_depth ,
10641083 ' --single-branch' ,
10651084 ' --progress' ,
1066- url ,
1067- path ,
10681085 }
10691086
1087+ -- Add branch specification if provided
1088+ if self .branch then
1089+ table.insert (cmd , ' --branch=' .. self .branch )
1090+ M .log (' debug' , string.format (' Installing %s from branch: %s' , self .name , self .branch ))
1091+ end
1092+
1093+ -- Add URL and path at the end
1094+ table.insert (cmd , url )
1095+ table.insert (cmd , path )
1096+
10701097 -- Update status
10711098 self .status = STATUS .INSTALLING
1072- ui :update_entry (self .name , self .status , ' Starting installation...' )
1099+ local install_msg = self .branch and (' Installing from branch: ' .. self .branch )
1100+ or ' Starting installation...'
1101+ ui :update_entry (self .name , self .status , install_msg )
10731102
10741103 -- Use our new Async.system wrapper
10751104 local result = Async .try_await (Async .system (cmd , {
@@ -1091,7 +1120,9 @@ function Plugin:install()
10911120
10921121 if result .success then
10931122 self .status = STATUS .INSTALLED
1094- ui :update_entry (self .name , self .status , ' Installation complete' )
1123+ local success_msg = self .branch and (' Installed from branch: ' .. self .branch )
1124+ or ' Installation complete'
1125+ ui :update_entry (self .name , self .status , success_msg )
10951126
10961127 -- Apply colorscheme if this is a theme
10971128 if self .colorscheme then
@@ -1114,6 +1145,7 @@ function Plugin:install()
11141145 end )()
11151146end
11161147
1148+ -- MODIFIED: Check for updates with branch awareness
11171149function Plugin :has_updates ()
11181150 return Async .wrap (function (callback )
11191151 if self .is_local or not self .is_remote then
@@ -1131,19 +1163,26 @@ function Plugin:has_updates()
11311163 ' origin' ,
11321164 }
11331165
1166+ -- If a specific branch is set, fetch that branch
1167+ if self .branch then
1168+ table.insert (fetch_cmd , self .branch .. ' :refs/remotes/origin/' .. self .branch )
1169+ end
1170+
11341171 local result = Async .try_await (Async .system (fetch_cmd ))
11351172 if not result .success then
11361173 callback (false )
11371174 return
11381175 end
11391176
1177+ -- Compare with the appropriate upstream
1178+ local upstream_ref = self .branch and ' @{upstream}' or ' @{upstream}'
11401179 local rev_cmd = {
11411180 ' git' ,
11421181 ' -C' ,
11431182 path ,
11441183 ' rev-list' ,
11451184 ' --count' ,
1146- ' HEAD..@{upstream} ' ,
1185+ ' HEAD..' .. upstream_ref ,
11471186 }
11481187
11491188 result = Async .try_await (Async .system (rev_cmd ))
@@ -1159,6 +1198,7 @@ function Plugin:has_updates()
11591198 end )()
11601199end
11611200
1201+ -- MODIFIED: Update plugin with branch support
11621202function Plugin :update (skip_check )
11631203 if self .is_local or not self .is_remote then
11641204 return Async .wrap (function (cb )
@@ -1209,19 +1249,29 @@ function Plugin:update(skip_check)
12091249
12101250 if not has_updates then
12111251 self .status = STATUS .UPDATED
1212- ui :update_entry (self .name , self .status , ' Already up to date' )
1252+ local up_to_date_msg = self .branch and (' Up to date on branch: ' .. self .branch )
1253+ or ' Already up to date'
1254+ ui :update_entry (self .name , self .status , up_to_date_msg )
12131255 callback (true , ' up_to_date' )
12141256 return
12151257 end
12161258 end
12171259
12181260 -- Update the plugin
12191261 self .status = STATUS .UPDATING
1220- ui :update_entry (self .name , self .status , ' Starting update...' )
1262+ local updating_msg = self .branch and (' Updating branch: ' .. self .branch )
1263+ or ' Starting update...'
1264+ ui :update_entry (self .name , self .status , updating_msg )
12211265
12221266 local path = self :get_path ()
12231267 local cmd = { ' git' , ' -C' , path , ' pull' , ' --progress' }
12241268
1269+ -- If specific branch is set, pull from that branch
1270+ if self .branch then
1271+ table.insert (cmd , ' origin' )
1272+ table.insert (cmd , self .branch )
1273+ end
1274+
12251275 -- Use our new Async.system wrapper
12261276 local result = Async .try_await (Async .system (cmd , {
12271277 timeout = DEFAULT_SETTINGS .git_timeout ,
@@ -1246,10 +1296,15 @@ function Plugin:update(skip_check)
12461296 local stdout = result .value .stdout or ' '
12471297 local update_info = ' Update complete'
12481298 local commit_info = stdout :match (' ([a-f0-9]+)%.%.([a-f0-9]+)' )
1299+
12491300 if stdout :find (' Already up to date' ) then
1250- update_info = ' Already up to date'
1301+ update_info = self .branch and (' Already up to date on branch: ' .. self .branch )
1302+ or ' Already up to date'
12511303 elseif commit_info then
1252- update_info = string.format (' Updated to %s' , stdout :match (' ([a-f0-9]+)%.%.([a-f0-9]+)' ))
1304+ local branch_info = self .branch and (' on branch: ' .. self .branch ) or ' '
1305+ update_info = string.format (' Updated to %s%s' , commit_info , branch_info )
1306+ elseif self .branch then
1307+ update_info = ' Updated on branch: ' .. self .branch
12531308 end
12541309
12551310 ui :update_entry (self .name , self .status , update_info )
@@ -1263,6 +1318,7 @@ function Plugin:update(skip_check)
12631318 end )()
12641319end
12651320
1321+ -- MODIFIED: Install with retry and branch support
12661322function Plugin :install_with_retry ()
12671323 if self .is_local or not self .is_remote then
12681324 return Async .wrap (function (cb )
@@ -1279,11 +1335,21 @@ function Plugin:install_with_retry()
12791335 end
12801336
12811337 self .status = STATUS .INSTALLING
1282- ui :update_entry (self .name , self .status , ' Starting installation...' )
1338+ local install_msg = self .branch and (' Installing from branch: ' .. self .branch )
1339+ or ' Starting installation...'
1340+ ui :update_entry (self .name , self .status , install_msg )
12831341
12841342 local path = self :get_path ()
12851343 local url = (' https://github.com/%s' ):format (self .name )
1286- local cmd = { ' git' , ' clone' , ' --progress' , url , path }
1344+ local cmd = { ' git' , ' clone' , ' --progress' }
1345+
1346+ -- Add branch specification if provided
1347+ if self .branch then
1348+ table.insert (cmd , ' --branch=' .. self .branch )
1349+ end
1350+
1351+ table.insert (cmd , url )
1352+ table.insert (cmd , path )
12871353
12881354 -- Use retry with the system command (3 retries with exponential backoff)
12891355 local result = Async .try_await (Async .retry (function ()
@@ -1308,7 +1374,9 @@ function Plugin:install_with_retry()
13081374 -- Handle result
13091375 if result .success then
13101376 self .status = STATUS .INSTALLED
1311- ui :update_entry (self .name , self .status , ' Installation complete' )
1377+ local success_msg = self .branch and (' Installed from branch: ' .. self .branch )
1378+ or ' Installation complete'
1379+ ui :update_entry (self .name , self .status , success_msg )
13121380
13131381 -- Apply colorscheme if this is a theme
13141382 if self .colorscheme then
@@ -1418,7 +1486,7 @@ function M.install()
14181486 table.insert (install_tasks , function (done )
14191487 Async .async (function ()
14201488 local result = Async .try_await (
1421- DEFAULT_SETTINGS .install_retry and Plugin :install_with_retry () or plugin :install ()
1489+ DEFAULT_SETTINGS .install_retry and plugin :install_with_retry () or plugin :install ()
14221490 )
14231491 if not result .success then
14241492 M .log (
0 commit comments