The agent_pane_min_width config value was accepted in the schema and passed as CapacityConfig.agentPaneWidth but never actually used — the underscore-prefixed _config parameter in decideSpawnActions was unused, and all split/capacity calculations used the hardcoded MIN_PANE_WIDTH. Now decideSpawnActions, canSplitPane, isSplittableAtCount, findMinimalEvictions, and calculateCapacity all accept and use the configured minimum pane width, falling back to the default (52) when not provided. Closes #1781
109 lines
2.4 KiB
TypeScript
109 lines
2.4 KiB
TypeScript
import { MIN_PANE_HEIGHT, MIN_PANE_WIDTH } from "./types"
|
|
import type { TmuxPaneInfo } from "./types"
|
|
import {
|
|
DIVIDER_SIZE,
|
|
MAIN_PANE_RATIO,
|
|
MAX_GRID_SIZE,
|
|
} from "./tmux-grid-constants"
|
|
|
|
export interface GridCapacity {
|
|
cols: number
|
|
rows: number
|
|
total: number
|
|
}
|
|
|
|
export interface GridSlot {
|
|
row: number
|
|
col: number
|
|
}
|
|
|
|
export interface GridPlan {
|
|
cols: number
|
|
rows: number
|
|
slotWidth: number
|
|
slotHeight: number
|
|
}
|
|
|
|
export function calculateCapacity(
|
|
windowWidth: number,
|
|
windowHeight: number,
|
|
minPaneWidth: number = MIN_PANE_WIDTH,
|
|
): GridCapacity {
|
|
const availableWidth = Math.floor(windowWidth * (1 - MAIN_PANE_RATIO))
|
|
const cols = Math.min(
|
|
MAX_GRID_SIZE,
|
|
Math.max(
|
|
0,
|
|
Math.floor(
|
|
(availableWidth + DIVIDER_SIZE) / (minPaneWidth + DIVIDER_SIZE),
|
|
),
|
|
),
|
|
)
|
|
const rows = Math.min(
|
|
MAX_GRID_SIZE,
|
|
Math.max(
|
|
0,
|
|
Math.floor(
|
|
(windowHeight + DIVIDER_SIZE) / (MIN_PANE_HEIGHT + DIVIDER_SIZE),
|
|
),
|
|
),
|
|
)
|
|
return { cols, rows, total: cols * rows }
|
|
}
|
|
|
|
export function computeGridPlan(
|
|
windowWidth: number,
|
|
windowHeight: number,
|
|
paneCount: number,
|
|
): GridPlan {
|
|
const capacity = calculateCapacity(windowWidth, windowHeight)
|
|
const { cols: maxCols, rows: maxRows } = capacity
|
|
|
|
if (maxCols === 0 || maxRows === 0 || paneCount === 0) {
|
|
return { cols: 1, rows: 1, slotWidth: 0, slotHeight: 0 }
|
|
}
|
|
|
|
let bestCols = 1
|
|
let bestRows = 1
|
|
let bestArea = Infinity
|
|
|
|
for (let rows = 1; rows <= maxRows; rows++) {
|
|
for (let cols = 1; cols <= maxCols; cols++) {
|
|
if (cols * rows < paneCount) continue
|
|
const area = cols * rows
|
|
if (area < bestArea || (area === bestArea && rows < bestRows)) {
|
|
bestCols = cols
|
|
bestRows = rows
|
|
bestArea = area
|
|
}
|
|
}
|
|
}
|
|
|
|
const availableWidth = Math.floor(windowWidth * (1 - MAIN_PANE_RATIO))
|
|
const slotWidth = Math.floor(availableWidth / bestCols)
|
|
const slotHeight = Math.floor(windowHeight / bestRows)
|
|
|
|
return { cols: bestCols, rows: bestRows, slotWidth, slotHeight }
|
|
}
|
|
|
|
export function mapPaneToSlot(
|
|
pane: TmuxPaneInfo,
|
|
plan: GridPlan,
|
|
mainPaneWidth: number,
|
|
): GridSlot {
|
|
const rightAreaX = mainPaneWidth
|
|
const relativeX = Math.max(0, pane.left - rightAreaX)
|
|
const relativeY = pane.top
|
|
|
|
const col =
|
|
plan.slotWidth > 0
|
|
? Math.min(plan.cols - 1, Math.floor(relativeX / plan.slotWidth))
|
|
: 0
|
|
const row =
|
|
plan.slotHeight > 0
|
|
? Math.min(plan.rows - 1, Math.floor(relativeY / plan.slotHeight))
|
|
: 0
|
|
|
|
return { row, col }
|
|
}
|