@@ -413,4 +413,150 @@ function U.is_installed(plugin)
413413 end
414414end
415415
416+ --- Function to execute a shell command and return the output as a tabl
417+ --- @param command string | string[] The shell command (s ) to execute
418+ --- @return string[] output The output of the shell command
419+ function U .run_hidden_command (command )
420+ -- Convert the command to a string if it's a table
421+ if type (command ) == " table" then
422+ command = table.concat (command , " \n " )
423+ end
424+ -- Execute the command and capture the output
425+ local handle = io.popen (command )
426+
427+ -- Check if the handle is nil (command may have failed)
428+ if not handle then
429+ error (" Failed to run command: " .. command ) -- Raise an error if the command failed
430+ end
431+
432+ local output = handle :read (" *a" ) -- Read all output
433+ handle :close () -- Important to close the handle safely
434+
435+ -- Check if the output is nil to avoid issues with splitting
436+ if output == nil then
437+ return {} -- Return an empty table if there is no output
438+ end
439+
440+ -- Split output by newline into a table
441+ local lines = {}
442+ for line in output :gmatch (" [^\n ]+" ) do
443+ table.insert (lines , line ) -- Insert each line into the table
444+ end
445+
446+ return lines
447+ end
448+
449+ --- Function to draw a floating window to display data
450+ --- @param data string[] The data to display in the floating window
451+ --- @return boolean success True if the floating window was successfully drawn
452+ function U .draw_floating_window (data )
453+ -- Verify the data is not empty
454+ if not data or # data == 0 then
455+ U .notify (" No data to display" , vim .log .levels .WARN )
456+ return false
457+ end
458+
459+ -- Add a padding character to each line
460+ for i = 1 , # data do
461+ data [i ] = data [i ] .. " "
462+ end
463+
464+ local width = 0
465+ local height = # data - 2
466+
467+ -- Find the width of the longest line for proper sizing
468+ for _ , line in ipairs (data ) do
469+ width = math.max (width , # line )
470+ end
471+
472+ -- Determine padding and calculate window size
473+ local padded_width = width + 2
474+ local padded_height = height + 2
475+
476+ -- Get the current window's dimensions
477+ local win_id = vim .api .nvim_get_current_win ()
478+ local win_config = vim .api .nvim_win_get_config (win_id )
479+ local current_win_width = win_config .width
480+ local current_win_height = win_config .height
481+
482+ -- Calculate the center position for the floating window
483+ local col = math.floor ((current_win_width - padded_width ) / 2 )
484+ local row = math.floor ((current_win_height - padded_height ) / 2 )
485+
486+ local buf_id = vim .api .nvim_create_buf (false , true ) -- Create a new buffer (scratch)
487+
488+ -- Set buffer content to the output
489+ vim .api .nvim_buf_set_lines (buf_id , 0 , - 1 , false , data )
490+
491+ -- Set window options for floating window
492+ local opts = {
493+ relative = " win" ,
494+ win = win_id ,
495+ width = padded_width ,
496+ height = padded_height ,
497+ anchor = " NW" ,
498+ col = col ,
499+ row = row ,
500+ border = " rounded" , -- Rounded border
501+ }
502+
503+ -- Create floating window
504+ local float_win_id = vim .api .nvim_open_win (buf_id , true , opts )
505+
506+ -- Disable line numbers
507+ vim .api .nvim_set_option_value (" number" , false , { scope = " local" , win = float_win_id }) -- Disable line numbers
508+ vim .api .nvim_set_option_value (" relativenumber" , false , { scope = " local" , win = float_win_id }) -- Disable relative line numbers
509+
510+ -- Set additional options for the floating window
511+ vim .api .nvim_set_option_value (" wrap" , true , { scope = " local" , win = float_win_id }) -- Enable line wrapping
512+ vim .api .nvim_set_option_value (" scrolloff" , 0 , { scope = " local" , win = float_win_id }) -- Disable scrolloff for horizontal
513+ vim .api .nvim_set_option_value (" sidescrolloff" , 0 , { scope = " local" , win = float_win_id }) -- Disable scrolloff for vertical
514+ vim .api .nvim_set_option_value (" list" , false , { scope = " local" , win = float_win_id }) -- Disable whitespace characters
515+
516+ -- Helper function to close the floating window
517+ local function closing ()
518+ vim .api .nvim_win_close (float_win_id , true )
519+ end
520+
521+ -- Helper function to pick an item
522+ local function picking ()
523+ local line = vim .api .nvim_get_current_line ()
524+ local item = line :match (" %s*(.*)" ):gsub (" %s+$" , " " ) -- Remove trailing spaces
525+ -- Store item in register
526+ vim .fn .setreg (' "' , item )
527+ closing ()
528+ end
529+
530+ -- Bind keys for closing
531+ for _ , key in ipairs ({ " q" , " <Esc>" }) do
532+ vim .api .nvim_buf_set_keymap (buf_id , " n" , key , " " , {
533+ noremap = true ,
534+ silent = true ,
535+ callback = function ()
536+ closing ()
537+ end ,
538+ desc = " Close terminal window" ,
539+ })
540+ end
541+
542+ -- Bind keys for picking
543+ for _ , key in ipairs ({ " y" , " <CR>" , " <Space>" }) do
544+ vim .api .nvim_buf_set_keymap (buf_id , " n" , key , " " , {
545+ noremap = true ,
546+ silent = true ,
547+ callback = function ()
548+ picking ()
549+ end ,
550+ desc = " Select item" ,
551+ })
552+ end
553+
554+ -- Check for errors
555+ if float_win_id == 0 then
556+ U .notify (" Failed to create floating window" , vim .log .levels .ERROR )
557+ return false
558+ end
559+ return true
560+ end
561+
416562return U
0 commit comments