Compose
Compose divides the workarea into regions, each with its own layout. Create IDE-style layouts, presentation modes, or any custom arrangement.
Horizontal split
Divide left to right:
local Compose = require("layouts.combinators.compose")local Tall = require("layouts.tall")local Column = require("layouts.column")
local devLayout = Compose.horizontal({ { ratio = 0.65, layout = Tall, count = 1 }, { ratio = 0.35, layout = Column },}, { name = "developer", displayName = "Developer",})This creates:
- Left 65%: First window in tall layout
- Right 35%: Remaining windows stacked in column
Vertical split
Divide top to bottom:
local Compose = require("layouts.combinators.compose")local Fullscreen = require("layouts.fullscreen")local Column = require("layouts.column")
local presentLayout = Compose.vertical({ { ratio = 0.85, layout = Fullscreen, count = 1 }, { ratio = 0.15, layout = Column },}, { name = "presentation", displayName = "Presentation",})This creates:
- Top 85%: Main presentation window
- Bottom 15%: Speaker notes in column
Window assignment
Each split specifies how many windows it receives:
count = N: Assign exactly N windows to this regioncountomitted: Assign all remaining windows
Windows are assigned in order. The first split gets its count, then the next,
and so on. The last split (or any without count) receives whatever remains.
Compose.horizontal({ { ratio = 0.5, layout = Tall, count = 2 }, -- First 2 windows { ratio = 0.5, layout = Grid }, -- All remaining windows})Nested composition
Compose layouts can contain other Compose layouts:
local Compose = require("layouts.combinators.compose")local Tall = require("layouts.tall")local Grid = require("layouts.grid")local Fullscreen = require("layouts.fullscreen")
local ideLayout = Compose.horizontal({ { ratio = 0.6, layout = Tall, count = 2 }, { ratio = 0.4, layout = Compose.vertical({ { ratio = 0.5, layout = Grid, count = 2 }, { ratio = 0.5, layout = Fullscreen }, })},}, { name = "ide", displayName = "IDE Layout",})This creates:
- Left 60%: 2 master windows (tall layout)
- Right top 20%: 2 windows in grid
- Right bottom 20%: Remaining windows fullscreen
Ratio normalization
Ratios are normalized to sum to 1.0. These are equivalent:
-- Explicit fractions{ ratio = 0.6 }, { ratio = 0.4 }
-- Any proportional values{ ratio = 3 }, { ratio = 2 } -- Same as 0.6, 0.4{ ratio = 60 }, { ratio = 40 } -- Same as 0.6, 0.4Error handling
Compose returns nil and an error string on invalid input:
-- Compose requires valid splitslocal layout, err = Compose.horizontal({ { ratio = 0, layout = Tall }, -- ratio must be positive})-- err = "ratio at index 1 must be a positive number"State management
Compose maintains state for child layouts. Stateful layouts (like BSP with custom splits) preserve their state when wrapped in Compose. State persists across layout cycles and Hammerspoon restarts.