From 05594b617517430a75e34973879663f89690f9d8 Mon Sep 17 00:00:00 2001
From: Omikhleia <didier.willis@gmail.com>
Date: Sun, 25 Jun 2023 19:48:08 +0200
Subject: [PATCH] feat: add the `\layout` command for changing the page layout

---
 classes/resilient/book.lua          | 31 +++++++++++++++++++++++++++--
 examples/manual-classes/classes.sil |  8 ++++++++
 2 files changed, 37 insertions(+), 2 deletions(-)

diff --git a/classes/resilient/book.lua b/classes/resilient/book.lua
index 7f5b2f1..c88d961 100644
--- a/classes/resilient/book.lua
+++ b/classes/resilient/book.lua
@@ -573,8 +573,7 @@ function class:registerCommands ()
     local spec = SU.required(options, "layout", "layout")
     local papersize = SU.required(options, "papersize", "layout")
     local offset = SU.cast("measurement", options.offset or "0")
-    local parser = require("resilient.layoutparser")
-    local layout = parser:match(spec)
+    local layout = layoutParser:match(spec)
     if not layout then
       SU.error("Unrecognized layout '" .. spec .. "'")
     end
@@ -585,6 +584,34 @@ function class:registerCommands ()
     layout:setPaperHack(W, H)
     layout:draw(W, H, { ratio = options.ratio, rough = options.rough })
   end, "Show a graphical representation of a page layout")
+
+  self:registerCommand("layout", function (options, _)
+    local spec = SU.required(options, "layout", "layout")
+    local layout = layoutParser:match(spec)
+    if not layout then
+      SU.error("Unknown page layout '".. spec .. "'")
+    end
+    local offset = SU.cast("measurement", self.options["offset"])
+    layout:setOffset(offset)
+    -- Kind of a hack dues to restrictions with frame parsers.
+    layout:setPaperHack(SILE.documentState.paperSize[1], SILE.documentState.paperSize[2])
+
+    SILE.call("supereject")
+    SILE.typesetter:leaveHmode()
+
+    local oddFrameset, evenFrameset = layout:frameset()
+    self:defineMaster({
+      id = "right",
+      firstContentFrame = self.firstContentFrame,
+      frames = oddFrameset
+    })
+    self:defineMaster({
+      id = "left",
+      firstContentFrame = self.firstContentFrame,
+      frames = evenFrameset
+    })
+    self:switchMaster(self:oddPage() and "right" or "left")
+  end, "Set the page layout")
 end
 
 return class
diff --git a/examples/manual-classes/classes.sil b/examples/manual-classes/classes.sil
index 09d4031..d87cb06 100644
--- a/examples/manual-classes/classes.sil
+++ b/examples/manual-classes/classes.sil
@@ -261,6 +261,14 @@ Cross-references are supported via the \autodoc:package{labelrefs} package, henc
 the \autodoc:command{\label}, \autodoc:command{\ref} and \autodoc:command{\pageref} commands are
 available.
 
+\medskip
+A few layout-related commands are also provided.
+
+The \autodoc:command{\layout[layout=<layout spec>]} command inserts a page break and changes the page layout from that point. An optional \autodoc:parameter{offset=<dimen>} may be specified to also alter the binding offset. By default, the global offset (that is, as possibly defined via the corresponding class option) is used.
+
+Mostly intended for documentation, the \autodoc:command{\showlayout[layout=<layout spec>, papersize=<paper spec>]} command outputs an image representing the selected page layout and paper size.
+Optional parameters are \autodoc:parameter{offset=<dimen>} for the binding offset (0, that is no offset, by default), \autodoc:parameter{ratio=<number>} for the image down-scaling (dividing the paper size by the specified amount, 6.5 by default), and \autodoc:parameter{rough=<boolean>} (false by default).
+
 \chapter{A \em{curriculum vitae} class}
 
 The \strong{resilient.resume} class provides a minimalist (read, naive) way to make a modern \em{résumé} (CV) with SILE.