3232local M = {}
3333M .__index = M
3434
35+ -- Height calculation constants
36+ local MIN_CHAT_HEIGHT = 10 -- Minimum lines for chat container to remain usable
37+ local WINDOW_MARGIN = 3 -- Additional margin for window borders and spacing
38+ local UI_ELEMENTS_HEIGHT = 2 -- Reserve space for statusline and tabline
39+ local SAFETY_MARGIN = 2 -- Extra margin to prevent "Not enough room" errors
40+
3541--- @param id integer Tab ID
3642--- @return eca.Sidebar
3743function M :new (id )
@@ -210,7 +216,21 @@ function M:_create_containers()
210216 local contexts_height = self :get_contexts_height ()
211217 local selected_code_height = self :get_selected_code_height ()
212218 local todos_height = self :get_todos_height ()
213- local chat_height = self :get_chat_height ()
219+ local original_chat_height = self :get_chat_height ()
220+ local chat_height = original_chat_height
221+
222+ -- Validate total height to prevent "Not enough room" error
223+ local total_height = chat_height + selected_code_height + todos_height + status_height + contexts_height + input_height + usage_height
224+
225+ -- Always calculate from total screen minus UI elements (more accurate than current window)
226+ local available_height = vim .o .lines - UI_ELEMENTS_HEIGHT
227+
228+ if total_height > available_height then
229+ Utils .debug (string.format (" Total height (%d) exceeds available height (%d), adjusting chat height" , total_height , available_height ))
230+ local extra_height = total_height - (available_height - SAFETY_MARGIN )
231+ chat_height = math.max (MIN_CHAT_HEIGHT , chat_height - extra_height )
232+ Utils .debug (string.format (" Adjusted chat height from %d to %d" , original_chat_height , chat_height ))
233+ end
214234
215235 -- Base options for all containers
216236 local base_buf_options = {
@@ -247,16 +267,16 @@ function M:_create_containers()
247267 self .containers .chat :mount ()
248268 self :_setup_container_events (self .containers .chat , " chat" )
249269
250- -- Track the last mounted container winid for relative positioning
251- local last_winid = self .containers .chat .winid
252- Utils .debug (" Mounted container: chat (winid: " .. last_winid .. " )" )
270+ -- Track the current container for hierarchical mounting with proper space management
271+ local current_winid = self .containers .chat .winid
272+ Utils .debug (" Mounted container: chat (winid: " .. current_winid .. " )" )
253273
254274 -- 2. Create selected_code container (conditional)
255275 if selected_code_height > 0 then
256276 self .containers .selected_code = Split ({
257277 relative = {
258278 type = " win" ,
259- winid = last_winid ,
279+ winid = current_winid ,
260280 },
261281 position = " bottom" ,
262282 size = { height = selected_code_height },
@@ -270,16 +290,16 @@ function M:_create_containers()
270290 })
271291 self .containers .selected_code :mount ()
272292 self :_setup_container_events (self .containers .selected_code , " selected_code" )
273- last_winid = self .containers .selected_code .winid
274- Utils .debug (" Mounted container: selected_code (winid: " .. last_winid .. " )" )
293+ current_winid = self .containers .selected_code .winid
294+ Utils .debug (" Mounted container: selected_code (winid: " .. current_winid .. " )" )
275295 end
276296
277297 -- 3. Create todos container (conditional)
278298 if todos_height > 0 then
279299 self .containers .todos = Split ({
280300 relative = {
281301 type = " win" ,
282- winid = last_winid ,
302+ winid = current_winid ,
283303 },
284304 position = " bottom" ,
285305 size = { height = todos_height },
@@ -292,15 +312,15 @@ function M:_create_containers()
292312 })
293313 self .containers .todos :mount ()
294314 self :_setup_container_events (self .containers .todos , " todos" )
295- last_winid = self .containers .todos .winid
296- Utils .debug (" Mounted container: todos (winid: " .. last_winid .. " )" )
315+ current_winid = self .containers .todos .winid
316+ Utils .debug (" Mounted container: todos (winid: " .. current_winid .. " )" )
297317 end
298318
299319 -- 4. Create status container (always present) - for processing messages
300320 self .containers .status = Split ({
301321 relative = {
302322 type = " win" ,
303- winid = last_winid ,
323+ winid = current_winid ,
304324 },
305325 position = " bottom" ,
306326 size = { height = status_height },
@@ -313,14 +333,14 @@ function M:_create_containers()
313333 })
314334 self .containers .status :mount ()
315335 self :_setup_container_events (self .containers .status , " status" )
316- last_winid = self .containers .status .winid
317- Utils .debug (" Mounted container: status (winid: " .. last_winid .. " )" )
336+ current_winid = self .containers .status .winid
337+ Utils .debug (" Mounted container: status (winid: " .. current_winid .. " )" )
318338
319339 -- 5. Create contexts container between status and input
320340 self .containers .contexts = Split ({
321341 relative = {
322342 type = " win" ,
323- winid = last_winid ,
343+ winid = current_winid ,
324344 },
325345 position = " bottom" ,
326346 size = { height = contexts_height },
@@ -333,14 +353,14 @@ function M:_create_containers()
333353 })
334354 self .containers .contexts :mount ()
335355 self :_setup_container_events (self .containers .contexts , " contexts" )
336- last_winid = self .containers .contexts .winid
337- Utils .debug (" Mounted container: contexts (winid: " .. last_winid .. " )" )
356+ current_winid = self .containers .contexts .winid
357+ Utils .debug (" Mounted container: contexts (winid: " .. current_winid .. " )" )
338358
339359 -- 6. Create input container (always present)
340360 self .containers .input = Split ({
341361 relative = {
342362 type = " win" ,
343- winid = last_winid ,
363+ winid = current_winid ,
344364 },
345365 position = " bottom" ,
346366 size = { height = input_height },
@@ -353,14 +373,14 @@ function M:_create_containers()
353373 })
354374 self .containers .input :mount ()
355375 self :_setup_container_events (self .containers .input , " input" )
356- last_winid = self .containers .input .winid
357- Utils .debug (" Mounted container: input (winid: " .. last_winid .. " )" )
376+ current_winid = self .containers .input .winid
377+ Utils .debug (" Mounted container: input (winid: " .. current_winid .. " )" )
358378
359379 -- 7. Create usage container (always present) - moved to bottom
360380 self .containers .usage = Split ({
361381 relative = {
362382 type = " win" ,
363- winid = last_winid ,
383+ winid = current_winid ,
364384 },
365385 position = " bottom" ,
366386 size = { height = usage_height },
@@ -537,9 +557,9 @@ function M:get_chat_height()
537557 local selected_code_height = self :get_selected_code_height ()
538558 local todos_height = self :get_todos_height ()
539559
540- return math.max (10 ,
560+ return math.max (MIN_CHAT_HEIGHT ,
541561 total_height - input_height - usage_height - status_height - contexts_height
542- - selected_code_height - todos_height - 3
562+ - selected_code_height - todos_height - WINDOW_MARGIN
543563 )
544564end
545565
0 commit comments