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
3 changes: 2 additions & 1 deletion lua/opencode/ui/input_window.lua
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,8 @@ local function apply_dimensions(windows, height)
end

local total_width = vim.api.nvim_get_option_value('columns', {})
local width = math.floor(total_width * config.ui.window_width)
local width_ratio = state.pre_zoom_width and config.ui.zoom_width or config.ui.window_width
local width = math.floor(total_width * width_ratio)

vim.api.nvim_win_set_config(windows.input_win, { width = width, height = height })
end
Expand Down
3 changes: 2 additions & 1 deletion lua/opencode/ui/output_window.lua
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,8 @@ function M.update_dimensions(windows)
return
end
local total_width = vim.api.nvim_get_option_value('columns', {})
local width = math.floor(total_width * config.ui.window_width)
local width_ratio = state.pre_zoom_width and config.ui.zoom_width or config.ui.window_width
local width = math.floor(total_width * width_ratio)

vim.api.nvim_win_set_config(windows.output_win, { width = width })
end
Expand Down
197 changes: 197 additions & 0 deletions tests/unit/zoom_spec.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,197 @@
local state = require('opencode.state')
local config = require('opencode.config')
local input_window = require('opencode.ui.input_window')
local output_window = require('opencode.ui.output_window')
local ui = require('opencode.ui.ui')

describe('ui zoom state', function()
local windows
local original_columns

before_each(function()
original_columns = vim.o.columns
vim.o.columns = 200

config.setup({
ui = {
window_width = 0.4,
zoom_width = 0.8,
position = 'right',
},
})

local input_buf = vim.api.nvim_create_buf(false, true)
local output_buf = vim.api.nvim_create_buf(false, true)
local input_win = vim.api.nvim_open_win(input_buf, true, {
relative = 'editor',
width = 80,
height = 10,
row = 0,
col = 0,
})
local output_win = vim.api.nvim_open_win(output_buf, false, {
relative = 'editor',
width = 80,
height = 20,
row = 11,
col = 0,
})

windows = {
input_buf = input_buf,
input_win = input_win,
output_buf = output_buf,
output_win = output_win,
}
state.windows = windows
state.pre_zoom_width = nil
end)

after_each(function()
vim.o.columns = original_columns
state.pre_zoom_width = nil

if windows then
pcall(vim.api.nvim_win_close, windows.input_win, true)
pcall(vim.api.nvim_win_close, windows.output_win, true)
pcall(vim.api.nvim_buf_delete, windows.input_buf, { force = true })
pcall(vim.api.nvim_buf_delete, windows.output_buf, { force = true })
end
state.windows = nil
end)

describe('toggle_zoom', function()
it('sets zoom width when not zoomed', function()
local initial_width = vim.api.nvim_win_get_width(windows.output_win)

ui.toggle_zoom()

local expected_zoom_width = math.floor(config.ui.zoom_width * vim.o.columns)
local actual_width = vim.api.nvim_win_get_width(windows.output_win)

assert.is_not_nil(state.pre_zoom_width)
assert.equals(initial_width, state.pre_zoom_width)
assert.equals(expected_zoom_width, actual_width)
end)

it('restores original width when zoomed', function()
local initial_width = vim.api.nvim_win_get_width(windows.output_win)

ui.toggle_zoom()
ui.toggle_zoom()

local actual_width = vim.api.nvim_win_get_width(windows.output_win)

assert.is_nil(state.pre_zoom_width)
assert.equals(initial_width, actual_width)
end)

it('sets zoom width for both input and output windows', function()
ui.toggle_zoom()

local expected_zoom_width = math.floor(config.ui.zoom_width * vim.o.columns)
local input_width = vim.api.nvim_win_get_width(windows.input_win)
local output_width = vim.api.nvim_win_get_width(windows.output_win)

assert.equals(expected_zoom_width, input_width)
assert.equals(expected_zoom_width, output_width)
end)
end)

describe('input_window.update_dimensions', function()
it('uses default window_width when not zoomed', function()
input_window.update_dimensions(windows)

local expected_width = math.floor(config.ui.window_width * vim.o.columns)
local actual_width = vim.api.nvim_win_get_width(windows.input_win)

assert.equals(expected_width, actual_width)
end)

it('uses zoom_width when zoomed', function()
state.pre_zoom_width = 80

input_window.update_dimensions(windows)

local expected_width = math.floor(config.ui.zoom_width * vim.o.columns)
local actual_width = vim.api.nvim_win_get_width(windows.input_win)

assert.equals(expected_width, actual_width)
end)

it('preserves zoom state after update_dimensions', function()
state.pre_zoom_width = 80

input_window.update_dimensions(windows)

assert.equals(80, state.pre_zoom_width)
end)
end)

describe('output_window.update_dimensions', function()
it('uses default window_width when not zoomed', function()
output_window.update_dimensions(windows)

local expected_width = math.floor(config.ui.window_width * vim.o.columns)
local actual_width = vim.api.nvim_win_get_width(windows.output_win)

assert.equals(expected_width, actual_width)
end)

it('uses zoom_width when zoomed', function()
state.pre_zoom_width = 80

output_window.update_dimensions(windows)

local expected_width = math.floor(config.ui.zoom_width * vim.o.columns)
local actual_width = vim.api.nvim_win_get_width(windows.output_win)

assert.equals(expected_width, actual_width)
end)

it('preserves zoom state after update_dimensions', function()
state.pre_zoom_width = 80

output_window.update_dimensions(windows)

assert.equals(80, state.pre_zoom_width)
end)
end)

describe('zoom state persistence', function()
it('maintains zoom width after input window show/hide cycle', function()
ui.toggle_zoom()

local expected_zoom_width = math.floor(config.ui.zoom_width * vim.o.columns)

input_window.update_dimensions(windows)

local actual_width = vim.api.nvim_win_get_width(windows.input_win)
assert.equals(expected_zoom_width, actual_width)
assert.is_not_nil(state.pre_zoom_width)
end)

it('maintains zoom width after output window update_dimensions', function()
ui.toggle_zoom()

local expected_zoom_width = math.floor(config.ui.zoom_width * vim.o.columns)

output_window.update_dimensions(windows)

local actual_width = vim.api.nvim_win_get_width(windows.output_win)
assert.equals(expected_zoom_width, actual_width)
assert.is_not_nil(state.pre_zoom_width)
end)

it('correctly un-zooms after multiple update_dimensions calls', function()
ui.toggle_zoom()

input_window.update_dimensions(windows)
output_window.update_dimensions(windows)

ui.toggle_zoom()

assert.is_nil(state.pre_zoom_width)
end)
end)
end)