Complete examples
These examples demonstrate how to combine Shoji’s building blocks for practical workflows.
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
| 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
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
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
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
| Combinator | Purpose |
|---|---|
Partition.horizontal() | Split screen left-to-right |
Partition.vertical() | Split screen top-to-bottom |
Functions
| Function | Purpose |
|---|---|
Modifiers.wrap() | Apply one modifier |
Modifiers.chain() | Apply multiple modifiers |