@@ -2,6 +2,11 @@ local state = require('opencode.state')
22local config = require (' opencode.config' )
33local M = {}
44
5+ -- Track hidden state
6+ M ._hidden = false
7+ -- Flag to prevent WinClosed autocmd from closing all windows during toggle
8+ M ._toggling = false
9+
510function M .create_buf ()
611 local input_buf = vim .api .nvim_create_buf (false , true )
712 vim .api .nvim_set_option_value (' filetype' , ' opencode' , { buf = input_buf })
@@ -48,10 +53,12 @@ function M.close()
4853 pcall (vim .api .nvim_buf_delete , state .windows .input_buf , { force = true })
4954end
5055
56+ --- Handle submit action from input window
57+ --- @return boolean true if a message was sent to the AI , false otherwise
5158function M .handle_submit ()
5259 local windows = state .windows
5360 if not windows or not M .mounted (windows ) then
54- return
61+ return false
5562 end
5663 --- @cast windows { input_buf : integer }
5764
@@ -63,21 +70,22 @@ function M.handle_submit()
6370 })
6471
6572 if input_content == ' ' then
66- return
73+ return false
6774 end
6875
6976 if input_content :match (' ^!' ) then
7077 M ._execute_shell_command (input_content :sub (2 ))
71- return
78+ return false
7279 end
7380
7481 local key = config .get_key_for_function (' input_window' , ' slash_commands' ) or ' /'
7582 if input_content :match (' ^' .. key ) then
7683 M ._execute_slash_command (input_content )
77- return
84+ return false
7885 end
7986
8087 require (' opencode.core' ).send_message (input_content )
88+ return true
8189end
8290
8391M ._execute_shell_command = function (command )
@@ -267,6 +275,11 @@ function M.recover_input(windows)
267275end
268276
269277function M .focus_input ()
278+ if M ._hidden then
279+ M ._show ()
280+ return
281+ end
282+
270283 if not M .mounted () then
271284 return
272285 end
@@ -350,6 +363,18 @@ function M.setup_autocmds(windows, group)
350363 end ,
351364 })
352365
366+ vim .api .nvim_create_autocmd (' WinLeave' , {
367+ group = group ,
368+ buffer = windows .input_buf ,
369+ callback = function ()
370+ -- Auto-hide input window when auto_hide is enabled and focus leaves
371+ -- Don't hide if displaying a route (slash command output like /help)
372+ if config .ui .input .auto_hide and not M .is_hidden () and not state .display_route then
373+ M ._hide ()
374+ end
375+ end ,
376+ })
377+
353378 vim .api .nvim_create_autocmd ({ ' TextChanged' , ' TextChangedI' }, {
354379 buffer = windows .input_buf ,
355380 callback = function ()
@@ -365,4 +390,96 @@ function M.setup_autocmds(windows, group)
365390 end )
366391end
367392
393+ --- Toggle the input window visibility (hide/show)
394+ --- When hidden, the input window is closed entirely
395+ --- When shown, the input window is recreated
396+ function M .toggle ()
397+ local windows = state .windows
398+ if not windows then
399+ return
400+ end
401+
402+ if M ._hidden then
403+ M ._show ()
404+ else
405+ M ._hide ()
406+ end
407+ end
408+
409+ --- Hide the input window by closing it
410+ function M ._hide ()
411+ local windows = state .windows
412+ if not M .mounted (windows ) then
413+ return
414+ end
415+
416+ local output_window = require (' opencode.ui.output_window' )
417+ local was_at_bottom = output_window .viewport_at_bottom
418+
419+ M ._hidden = true
420+ M ._toggling = true
421+
422+ pcall (vim .api .nvim_win_close , windows .input_win , false )
423+ windows .input_win = nil
424+
425+ vim .schedule (function ()
426+ M ._toggling = false
427+ end )
428+
429+ output_window .focus_output (true )
430+
431+ if was_at_bottom then
432+ vim .schedule (function ()
433+ require (' opencode.ui.renderer' ).scroll_to_bottom (true )
434+ end )
435+ end
436+ end
437+
438+ --- Show the input window by recreating it
439+ function M ._show ()
440+ local windows = state .windows
441+ if not windows or not windows .input_buf or not windows .output_win then
442+ return
443+ end
444+
445+ -- Don't recreate if already visible
446+ if windows .input_win and vim .api .nvim_win_is_valid (windows .input_win ) then
447+ M ._hidden = false
448+ return
449+ end
450+
451+ local output_window = require (' opencode.ui.output_window' )
452+ local was_at_bottom = output_window .viewport_at_bottom
453+
454+ local output_win = windows .output_win
455+ vim .api .nvim_set_current_win (output_win )
456+
457+ local input_position = config .ui .input_position or ' bottom'
458+ vim .cmd ((input_position == ' top' and ' aboveleft' or ' belowright' ) .. ' split' )
459+ local input_win = vim .api .nvim_get_current_win ()
460+
461+ vim .api .nvim_win_set_buf (input_win , windows .input_buf )
462+ windows .input_win = input_win
463+
464+ -- Re-apply window settings
465+ M .setup (windows )
466+
467+ M ._hidden = false
468+
469+ -- Focus the input window
470+ M .focus_input ()
471+
472+ if was_at_bottom then
473+ vim .schedule (function ()
474+ require (' opencode.ui.renderer' ).scroll_to_bottom (true )
475+ end )
476+ end
477+ end
478+
479+ --- Check if the input window is currently hidden
480+ --- @return boolean
481+ function M .is_hidden ()
482+ return M ._hidden
483+ end
484+
368485return M
0 commit comments