Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 2 additions & 9 deletions lua/opencode/ui/input_window.lua
Original file line number Diff line number Diff line change
Expand Up @@ -400,10 +400,8 @@ function M.toggle()
end

if M._hidden then
-- Show: recreate the input window
M._show()
else
-- Hide: close the input window
M._hide()
end
end
Expand All @@ -421,21 +419,18 @@ function M._hide()
M._hidden = true
M._toggling = true

-- Close the input window (but keep the buffer)
pcall(vim.api.nvim_win_close, windows.input_win, false)
windows.input_win = nil

-- Reset toggling flag after the WinClosed event has been processed
vim.schedule(function()
M._toggling = false
end)

-- Focus output window
output_window.focus_output(true)

if was_at_bottom then
vim.schedule(function()
require('opencode.ui.renderer').scroll_to_bottom()
require('opencode.ui.renderer').scroll_to_bottom(true)
end)
end
end
Expand All @@ -456,15 +451,13 @@ function M._show()
local output_window = require('opencode.ui.output_window')
local was_at_bottom = output_window.viewport_at_bottom

-- Create a new split for the input window
local output_win = windows.output_win
vim.api.nvim_set_current_win(output_win)

local input_position = config.ui.input_position or 'bottom'
vim.cmd((input_position == 'top' and 'aboveleft' or 'belowright') .. ' split')
local input_win = vim.api.nvim_get_current_win()

-- Set the buffer
vim.api.nvim_win_set_buf(input_win, windows.input_buf)
windows.input_win = input_win

Expand All @@ -478,7 +471,7 @@ function M._show()

if was_at_bottom then
vim.schedule(function()
require('opencode.ui.renderer').scroll_to_bottom()
require('opencode.ui.renderer').scroll_to_bottom(true)
end)
end
end
Expand Down
31 changes: 21 additions & 10 deletions lua/opencode/ui/renderer.lua
Original file line number Diff line number Diff line change
Expand Up @@ -215,13 +215,18 @@ end

---Auto-scroll to bottom if user was already at bottom
---Respects cursor position if user has scrolled up
function M.scroll_to_bottom()
---@param force? boolean If true, scroll regardless of current position
function M.scroll_to_bottom(force)
if not state.windows or not state.windows.output_buf or not state.windows.output_win then
return
end

if not vim.api.nvim_win_is_valid(state.windows.output_win) then
return
end

local ok, line_count = pcall(vim.api.nvim_buf_line_count, state.windows.output_buf)
if not ok then
if not ok or line_count == 0 then
return
end

Expand All @@ -233,18 +238,24 @@ function M.scroll_to_bottom()
trigger_on_data_rendered()

-- Determine if we should scroll to bottom
local should_scroll = false

-- Always scroll on initial render
if prev_line_count == 0 then
should_scroll = true
-- Scroll if user is at bottom (respects manual scroll position)
elseif output_window.viewport_at_bottom then
should_scroll = true
local should_scroll = force == true

if not should_scroll then
-- Always scroll on initial render
if prev_line_count == 0 then
should_scroll = true
-- Scroll if user is at bottom (respects manual scroll position)
elseif output_window.viewport_at_bottom then
should_scroll = true
end
end

if should_scroll then
vim.api.nvim_win_set_cursor(state.windows.output_win, { line_count, 0 })
-- Use zb to position the cursor line at the bottom of the visible window
vim.api.nvim_win_call(state.windows.output_win, function()
vim.cmd('normal! zb')
end)
output_window.viewport_at_bottom = true
else
-- User has scrolled up, don't scroll
Expand Down