Repository navigation
Expand file tree
/
Copy pathfloat_layout.lua
More file actions
144 lines (124 loc) · 4.33 KB
/
Copy pathfloat_layout.lua
File metadata and controls
144 lines (124 loc) · 4.33 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
local config = require('opencode.config')
local state = require('opencode.state')
local M = {}
---@param value number|nil
---@param total integer
---@param fallback number
---@return integer
local function resolve_dimension(value, total, fallback)
local resolved = value or fallback
if resolved > 0 and resolved <= 1 then
return math.floor(total * resolved)
end
return math.floor(resolved)
end
---@param value number|nil
---@param total integer
---@param size integer
---@return integer
local function resolve_position(value, total, size)
if value == nil then
return math.floor((total - size) / 2)
end
if value > 0 and value <= 1 then
return math.floor(total * value)
end
return math.floor(value)
end
---@param value integer
---@param min_value integer
---@param max_value integer
---@return integer
local function clamp(value, min_value, max_value)
return math.min(max_value, math.max(min_value, value))
end
---@param windows OpencodeWindowState|nil
---@return integer
local function input_height(windows)
local line_count = 1
if windows and windows.input_buf and vim.api.nvim_buf_is_valid(windows.input_buf) then
line_count = vim.api.nvim_buf_line_count(windows.input_buf)
end
local min_height = math.max(1, math.floor(vim.o.lines * config.ui.input.min_height))
local max_height = math.max(min_height, math.floor(vim.o.lines * config.ui.input.max_height))
return clamp(line_count, min_height, max_height)
end
---@param windows OpencodeWindowState|nil
---@return vim.api.keyset.win_config
local function base_config(windows)
local float = config.ui.float or {}
local width
if windows and windows.saved_width_ratio then
width = math.floor(vim.o.columns * windows.saved_width_ratio)
windows.saved_width_ratio = nil
elseif state.pre_zoom_width then
width = math.floor(vim.o.columns * config.ui.zoom_width)
else
width = resolve_dimension(float.width, vim.o.columns, 0.95)
end
local height = resolve_dimension(float.height, vim.o.lines, 0.9)
return {
relative = 'editor',
width = width,
height = height,
row = resolve_position(float.row, vim.o.lines, height),
col = resolve_position(float.col, vim.o.columns, width),
border = float.border,
}
end
---@param windows OpencodeWindowState|nil
---@param show_input boolean
---@return vim.api.keyset.win_config output_config
function M.window_configs(windows, show_input)
local float = config.ui.float or {}
local base = base_config(windows)
local prompt_height = show_input and input_height(windows) or 0
local gap = show_input and (float.gap or 1) or 0
local output_height = math.max(1, base.height - prompt_height - gap)
local output_config = vim.tbl_deep_extend('force', base, {
height = output_height,
zindex = float.zindex or 40,
})
if not show_input then
return output_config, nil
end
local input_config = vim.tbl_deep_extend('force', base, {
height = prompt_height,
zindex = (float.zindex or 40) + 1,
})
if config.ui.input_position == 'top' then
output_config.row = base.row + prompt_height + gap
else
input_config.row = base.row + output_height + gap
end
return output_config, input_config
end
---@param buf integer
---@param enter boolean
---@param win_config vim.api.keyset.win_config
---@return integer
function M.open_win(buf, enter, win_config)
win_config = vim.tbl_deep_extend('force', win_config, { style = 'minimal' })
local win = vim.api.nvim_open_win(buf, enter, win_config)
local float = config.ui.float or {}
for opt, value in pairs(float.opts or {}) do
pcall(vim.api.nvim_set_option_value, opt, value, { win = win, scope = 'local' })
end
return win
end
---@param windows OpencodeWindowState|nil
---@param show_input boolean
function M.update(windows, show_input)
if not windows or not windows.output_win or not vim.api.nvim_win_is_valid(windows.output_win) then
return
end
local output_config, input_config = M.window_configs(windows, show_input)
pcall(vim.api.nvim_win_set_config, windows.output_win, output_config)
if show_input and input_config and windows.input_win and vim.api.nvim_win_is_valid(windows.input_win) then
pcall(vim.api.nvim_win_set_config, windows.input_win, input_config)
end
if windows.footer_win and vim.api.nvim_win_is_valid(windows.footer_win) then
require('opencode.ui.footer').update_window(windows)
end
end
return M