@@ -210,6 +210,74 @@ function MarketplaceView:before_leave()
210210end
211211
212212function MarketplaceView :setup_active_mode ()
213+ local function enter_detail_mode ()
214+ local cursor = vim .api .nvim_win_get_cursor (0 )
215+ local server = self :get_server_at_line (cursor [1 ])
216+ if server then
217+ self .cursor_positions .browse_mode = cursor
218+ self .selected_server = server
219+ self .active_mode = " details"
220+ self .active_installation_index = 1
221+ self :setup_active_mode ()
222+ self :draw ()
223+ local install_line = self .interactive_lines [1 ]
224+ vim .api .nvim_win_set_cursor (0 , { install_line and install_line .line or 7 , 0 })
225+ end
226+ end
227+ local function go_to_browse_mode ()
228+ self .cursor_positions .details_mode = vim .api .nvim_win_get_cursor (0 )
229+ self .active_mode = " browse"
230+ self .selected_server = nil
231+ self :setup_active_mode ()
232+ self :draw ()
233+ -- Restore browse mode position
234+ if self .cursor_positions .browse_mode then
235+ vim .api .nvim_win_set_cursor (0 , self .cursor_positions .browse_mode )
236+ end
237+ end
238+ local function install_server ()
239+ local cursor = vim .api .nvim_win_get_cursor (0 )
240+ local type , context = self :get_line_info (cursor [1 ])
241+
242+ if type == " install_with_method" and not State :is_server_installed (self .selected_server .id ) then
243+ -- Open installation editor directly
244+ self :handle_installation_selection (
245+ context --[[ @as { server: MarketplaceItem, installation: MarketplaceInstallation }]]
246+ )
247+ elseif type == " uninstall_server" and State :is_server_installed (self .selected_server .id ) then
248+ -- Show confirmation and uninstall
249+ if context then
250+ local server_id = context .server .id --[[ @as string]]
251+ utils .confirm_and_delete_server (server_id )
252+ end
253+ end
254+ end
255+ local function cycle_method (forward )
256+ if self .selected_server and self .selected_server .installations then
257+ local num_installations = # self .selected_server .installations
258+ if num_installations >= 1 then
259+ local is_installed = State :is_server_installed (self .selected_server .id )
260+ local max_index = is_installed and num_installations + 1 or num_installations
261+
262+ if forward then
263+ self .active_installation_index = (self .active_installation_index % max_index ) + 1
264+ else
265+ self .active_installation_index = ((self .active_installation_index - 2 ) % max_index ) + 1
266+ end
267+
268+ self :draw ()
269+ -- Keep cursor on install/uninstall line
270+ if self .interactive_lines and # self .interactive_lines > 0 then
271+ for _ , line_info in ipairs (self .interactive_lines ) do
272+ if line_info .type == " install_with_method" or line_info .type == " uninstall_server" then
273+ vim .api .nvim_win_set_cursor (0 , { line_info .line , 0 })
274+ break
275+ end
276+ end
277+ end
278+ end
279+ end
280+ end
213281 if self .active_mode == " browse" then
214282 self .keymaps = {
215283 [" /" ] = {
@@ -308,89 +376,34 @@ function MarketplaceView:setup_active_mode()
308376 desc = " Clear filters" ,
309377 },
310378 [" l" ] = {
311- action = function ()
312- local cursor = vim .api .nvim_win_get_cursor (0 )
313- local server = self :get_server_at_line (cursor [1 ])
314- if server then
315- self .cursor_positions .browse_mode = cursor
316- self .selected_server = server
317- self .active_mode = " details"
318- self .active_installation_index = 1
319- self :setup_active_mode ()
320- self :draw ()
321- local install_line = self .interactive_lines [1 ]
322- vim .api .nvim_win_set_cursor (0 , { install_line and install_line .line or 7 , 0 })
323- end
324- end ,
379+ action = enter_detail_mode ,
380+ desc = " View details" ,
381+ },
382+ [" <Cr>" ] = {
383+ action = enter_detail_mode ,
325384 desc = " View details" ,
326385 },
327386 }
328387 else
329388 self .keymaps = {
330- [" h" ] = {
331- action = function ()
332- self .cursor_positions .details_mode = vim .api .nvim_win_get_cursor (0 )
333- self .active_mode = " browse"
334- self .selected_server = nil
335- self :setup_active_mode ()
336- self :draw ()
337- -- Restore browse mode position
338- if self .cursor_positions .browse_mode then
339- vim .api .nvim_win_set_cursor (0 , self .cursor_positions .browse_mode )
340- end
341- end ,
389+ [" <Esc>" ] = {
390+ action = go_to_browse_mode ,
342391 desc = " Back to list" ,
343392 },
344- [" <Tab> " ] = {
393+ [" l " ] = {
345394 action = function ()
346- if self .selected_server and self .selected_server .installations then
347- local num_installations = # self .selected_server .installations
348- if num_installations >= 1 then
349- local is_installed = State :is_server_installed (self .selected_server .id )
350- -- For installed servers, we have 1 extra "Current" tab
351- self .active_installation_index = (
352- self .active_installation_index
353- % (is_installed and num_installations + 1 or num_installations )
354- ) + 1
355- self :draw ()
356- -- Keep cursor on install/uninstall line
357- if self .interactive_lines and # self .interactive_lines > 0 then
358- for _ , line_info in ipairs (self .interactive_lines ) do
359- if
360- line_info .type == " install_with_method"
361- or line_info .type == " uninstall_server"
362- then
363- vim .api .nvim_win_set_cursor (0 , { line_info .line , 0 })
364- break
365- end
366- end
367- end
368- end
369- end
395+ cycle_method (true )
370396 end ,
371- desc = " Switch installation method" ,
397+ desc = " Switch method" ,
372398 },
373- [" l " ] = {
399+ [" h " ] = {
374400 action = function ()
375- local cursor = vim .api .nvim_win_get_cursor (0 )
376- local type , context = self :get_line_info (cursor [1 ])
377-
378- if type == " install_with_method" and not State :is_server_installed (self .selected_server .id ) then
379- -- Open installation editor directly
380- self :handle_installation_selection (
381- context --[[ @as { server: MarketplaceItem, installation: MarketplaceInstallation }]]
382- )
383- elseif type == " uninstall_server" and State :is_server_installed (self .selected_server .id ) then
384- -- Show confirmation and uninstall
385- if context then
386- local server_id = context .server .id --[[ @as string]]
387- utils .confirm_and_delete_server (server_id )
388- end
389- else
390- -- Normal vim movement: move cursor right
391- vim .cmd (" normal! l" )
392- end
401+ cycle_method (false )
393402 end ,
403+ desc = " Switch method" ,
404+ },
405+ [" <Cr>" ] = {
406+ action = install_server ,
394407 desc = " Install/Uninstall" ,
395408 },
396409 }
@@ -416,8 +429,8 @@ function MarketplaceView:handle_installation_selection(context)
416429 start_insert = false ,
417430 go_to_placeholder = true , -- Position cursor at first ${} placeholder
418431 virtual_lines = {
419- { Text .icons .hint .. " ${VARIABLES} will be resolved from environment if not replaced" , " DiagnosticHint " },
420- { Text .icons .hint .. " ${cmd: echo 'secret'} will run command and replace ${}" , " DiagnosticHint " },
432+ { Text .icons .hint .. " ${VARIABLES} will be resolved from environment if not replaced" , " Comment " },
433+ { Text .icons .hint .. " ${cmd: echo 'secret'} will run command and replace ${}" , " Comment " },
421434 },
422435 on_success = function ()
423436 -- Switch to main view and browse mode after successful installation
@@ -666,6 +679,10 @@ function MarketplaceView:render_browse_mode(line_offset)
666679 end
667680 end
668681
682+ local info_line = NuiLine ()
683+ info_line :append (Text .icons .bug .. " Report issues or suggest changes: " , Text .highlights .title )
684+ info_line :append (" https://github.com/ravitemer/mcp-registry" , Text .highlights .link )
685+ table.insert (lines , Text .pad_line (info_line ))
669686 return lines
670687end
671688
@@ -772,13 +789,13 @@ function MarketplaceView:render_details_mode(line_offset)
772789 self :track_line (# lines + line_offset , " uninstall_server" , {
773790 type = " uninstall_server" ,
774791 server = server ,
775- hint = " [<l > Uninstall, <Tab > Switch Installation ]" ,
792+ hint = " [<Cr > Uninstall, <l > Switch Method ]" ,
776793 })
777794
778795 table.insert (lines , Text .pad_line (NuiLine ()))
779- local prereq_line = NuiLine ()
780- prereq_line :append (" PREVIEW " , Text .highlights .muted )
781- table.insert (lines , Text .pad_line (prereq_line ))
796+ -- local prereq_line = NuiLine()
797+ -- prereq_line:append("PREVIEW ", Text.highlights.muted)
798+ -- table.insert(lines, Text.pad_line(prereq_line))
782799 table.insert (lines , self :divider ())
783800
784801 -- Show details based on active tab
@@ -821,7 +838,7 @@ function MarketplaceView:render_details_mode(line_offset)
821838 type = " install_with_method" ,
822839 server = server ,
823840 installation = active_installation ,
824- hint = " [<l > Install, <Tab > Switch Method]" ,
841+ hint = " [<Cr > Install, <l > Switch Method]" ,
825842 })
826843
827844 table.insert (lines , Text .pad_line (NuiLine ()))
@@ -834,9 +851,9 @@ function MarketplaceView:render_details_mode(line_offset)
834851 -- table.insert(lines, Text.pad_line(prereq_line))
835852 -- end
836853
837- local prereq_line = NuiLine ()
838- prereq_line :append (" PREVIEW " , Text .highlights .muted )
839- table.insert (lines , Text .pad_line (prereq_line ))
854+ -- local prereq_line = NuiLine()
855+ -- prereq_line:append("PREVIEW ", Text.highlights.muted)
856+ -- table.insert(lines, Text.pad_line(prereq_line))
840857 table.insert (lines , self :divider ())
841858
842859 -- Show active installation details
0 commit comments