Complete examples
These examples demonstrate how to combine Shoji’s building blocks for practical workflows.
Developer setup
Section titled “Developer setup”A complete configuration for software development with multiple layout options.
-- ~/.hammerspoon/init.luahs.loadSpoon("Shoji")
local shoji = spoon.Shoji
-- Access building blockslocal Modifiers = shoji.Modifierslocal Partition = shoji.Combinators.Partition
local Tall = shoji.Layouts.Talllocal Wide = shoji.Layouts.Widelocal Grid = shoji.Layouts.Gridlocal BSP = shoji.Layouts.BSPlocal Column = shoji.Layouts.Columnlocal Monocle = shoji.Layouts.Monocle
-------------------------------------------------------------------------- Modified layouts------------------------------------------------------------------------
-- Mirrored tall: main area on right instead of leftlocal TallRight = Modifiers.wrap( Tall, Modifiers.Mirror.horizontal(), { name = "tall-right", displayName = "Tall (Right)" })
-- Centered tall: 80% of screen, centeredlocal CenteredTall = Modifiers.wrap( Tall, Modifiers.Centered.ratio(0.8), { name = "tall-centered", displayName = "Tall (Centered)" })
-------------------------------------------------------------------------- Partitioned layouts------------------------------------------------------------------------
-- Developer: main editor (65%), reference stack (35%)local Developer = Partition.horizontal({ { ratio = 0.65, layout = Tall, count = 1 }, { ratio = 0.35, layout = Column },}, { name = "developer", displayName = "Developer",})
-- IDE: editor (60%), grid + terminal (40%)local IDE = Partition.horizontal({ { ratio = 0.6, layout = Tall, count = 2 }, { ratio = 0.4, layout = Partition.vertical({ { ratio = 0.5, layout = Grid, count = 2 }, { ratio = 0.5, layout = Monocle }, })},}, { name = "ide", displayName = "IDE Layout",})
-- Presentation: main content (85%), notes strip (15%)local Presentation = Partition.vertical({ { ratio = 0.85, layout = Monocle, count = 1 }, { ratio = 0.15, layout = Column },}, { name = "presentation", displayName = "Presentation",})
-------------------------------------------------------------------------- Configuration------------------------------------------------------------------------
shoji:configure({ layouts = { TallRight, CenteredTall, Developer, IDE, Presentation, }, enabled_layouts = { "tall", "tall-right", "developer", "ide", "monocle", }, gap_outer = 8, gap_inner = 8,})shoji:start()
shoji:bindHotkeys({ -- Layout cycling cycle_layout_forward = { { "cmd", "ctrl", "alt" }, "space" },
-- Window focus focus_next = { { "ctrl", "alt" }, "'" }, focus_prev = { { "ctrl", "alt" }, ";" },
-- Window swapping swap_main = { { "cmd", "ctrl", "alt" }, "return" },
-- Layout adjustments increase_main_ratio = { { "ctrl", "alt" }, "." }, decrease_main_ratio = { { "ctrl", "alt" }, "," },
-- Float toggle toggle_float = { { "ctrl", "alt", "shift" }, "t" },})Keybindings summary
Section titled “Keybindings summary”| Keys | Action |
|---|---|
cmd+ctrl+alt+space |
Cycle layouts |
ctrl+alt+' |
Focus next window |
ctrl+alt+; |
Focus previous window |
cmd+ctrl+alt+return |
Swap with main |
ctrl+alt+. |
Expand main area |
ctrl+alt+, |
Shrink main area |
ctrl+alt+shift+t |
Toggle floating |
Ultrawide monitor setup
Section titled “Ultrawide monitor setup”Extra gaps and centered layouts work well on ultrawide displays.
hs.loadSpoon("Shoji")
local shoji = spoon.Shojilocal Modifiers = shoji.Modifierslocal Tall = shoji.Layouts.Talllocal BSP = shoji.Layouts.BSP
-- Centered at 85% with extra gapslocal CenteredTall = Modifiers.chain(Tall, { Modifiers.Centered.ratio(0.85), Modifiers.Gaps.create({ outer = 20, inner = 12 }),}, { name = "centered-tall", displayName = "Centered Tall",})
-- BSP with breathing roomlocal SpacedBSP = Modifiers.chain(BSP, { Modifiers.Gaps.create({ outer = 24, inner = 8 }),}, { name = "spaced-bsp", displayName = "Spaced BSP", preserveActions = true, -- Keep BSP resize actions})
shoji:configure({ layouts = { CenteredTall, SpacedBSP }, enabled_layouts = { "centered-tall", "spaced-bsp" }, gap_outer = 16, gap_inner = 8,})shoji:start()Minimal configuration
Section titled “Minimal configuration”A simple setup with just the essentials.
hs.loadSpoon("Shoji")
local shoji = spoon.Shojilocal Modifiers = shoji.Modifierslocal Tall = shoji.Layouts.Tall
-- Tall with main area on rightlocal TallRight = Modifiers.wrap( Tall, Modifiers.Mirror.horizontal(), { name = "tall-right", displayName = "Tall (Right)" })
shoji:configure({ layouts = { TallRight }, enabled_layouts = { "tall", "tall-right", "monocle" }, gap_outer = 8, gap_inner = 8,})shoji:start()
shoji:bindHotkeys({ cycle_layout_forward = { { "cmd", "ctrl", "alt" }, "space" }, swap_main = { { "cmd", "ctrl", "alt" }, "return" }, toggle_float = { { "ctrl", "alt", "shift" }, "t" },})Building blocks reference
Section titled “Building blocks reference”Modifiers
Section titled “Modifiers”| Modifier | Purpose |
|---|---|
Mirror.horizontal() |
Flip left/right |
Mirror.vertical() |
Flip top/bottom |
Gaps.create() |
Extra spacing (uniform or per-edge) |
Centered.ratio() |
Scale and center |
Combinators
Section titled “Combinators”| Combinator | Purpose |
|---|---|
Partition.horizontal() |
Split screen left-to-right |
Partition.vertical() |
Split screen top-to-bottom |
Functions
Section titled “Functions”| Function | Purpose |
|---|---|
Modifiers.wrap() |
Apply one modifier |
Modifiers.chain() |
Apply multiple modifiers |