<commit_before>local _currentMaster

local function defineMaster (_, args)
  SU.required(args, "id", "defining master")
  SU.required(args, "frames", "defining master")
  SU.required(args, "firstContentFrame", "defining master")
  SILE.scratch.masters[args.id] = { frames = {}, firstContentFrame = nil }
  for frame, spec in pairs(args.frames) do
    spec.id = frame
    if spec.solve then
      SILE.scratch.masters[args.id].frames[frame] = spec
    else
      SILE.scratch.masters[args.id].frames[frame] = SILE.newFrame(spec)
    end
  end
  SILE.scratch.masters[args.id].firstContentFrame = SILE.scratch.masters[args.id].frames[args.firstContentFrame]
end

local function defineMasters (class, list)
  if list then
    for i = 1, #list do
      class:defineMaster(list[i])
    end
  end
end

local function doswitch (frames)
  SILE.frames = { page = SILE.frames.page }
  for id, frame in pairs(frames) do
    SILE.frames[id] = frame
    frame:invalidate()
  end
end

local function switchMasterOnePage (class, id)
  if not id then
    id = class
    SU.deprecated("class.switchMasterOnePage", "class:switchMasterOnePage", "0.13.0", "0.15.0")
  end
  if not SILE.scratch.masters[id] then
    SU.error("Can't find master "..id)
  end
  SILE.documentState.thisPageTemplate = SILE.scratch.masters[id]
  doswitch(SILE.scratch.masters[id].frames)
  SILE.typesetter:chuck()
  SILE.typesetter:initFrame(SILE.scratch.masters[id].firstContentFrame)
end

local function switchMaster (class, id)
  if not id then
    id, class = class, SILE.documentState.documentClass
    SU.deprecated("class.switchMaster", "class:switchMaster", "0.13.0", "0.15.0")
  end
  _currentMaster = id
  if not SILE.scratch.masters[id] then
    SU.error("Can't find master "..id)
  end
  class.pageTemplate = SILE.scratch.masters[id]
  SILE.documentState.thisPageTemplate = pl.tablex.deepcopy(class.pageTemplate)
  doswitch(SILE.scratch.masters[id].frames)
  SILE.typesetter:initFrame(SILE.scratch.masters[id].firstContentFrame)
end

local function currentMaster (_)
  return _currentMaster
end

local function init (class, args)

  if not SILE.scratch.masters then
    SILE.scratch.masters = {}
  end

  defineMasters(class, args)

end

local function registerCommands (class)

  class:registerCommand("define-master-template", function(options, content)
    SU.required(options, "id", "defining a master")
    SU.required(options, "first-content-frame", "defining a master")
    -- Subvert the <frame> functionality from baseclass
    local spare = SILE.documentState.thisPageTemplate.frames
    local sp2 = SILE.frames
    SILE.frames = { page = SILE.frames.page }
    SILE.documentState.thisPageTemplate.frames = {}
    SILE.process(content)
    SILE.scratch.masters[options.id] = {}
    SILE.scratch.masters[options.id].frames = SILE.documentState.thisPageTemplate.frames
    if not SILE.scratch.masters[options.id].frames[options["first-content-frame"]] then
      SU.error("first-content-frame "..options["first-content-frame"].." not found")
    end
    SILE.scratch.masters[options.id].firstContentFrame = SILE.scratch.masters[options.id].frames[options["first-content-frame"]]
    SILE.documentState.thisPageTemplate.frames = spare
    SILE.frames = sp2
  end)

  class:registerCommand("switch-master-one-page", function (options, _)
    SU.required(options, "id", "switching master")
    switchMasterOnePage(class, options.id)
    SILE.typesetter:leaveHmode()
  end, "Switches the master for the current page")

  class:registerCommand("switch-master", function (options, _)
    SU.required(options, "id", "switching master")
    switchMaster(class, options.id)
  end, "Switches the master for the current page")

end

return {
  init = init,
  registerCommands = registerCommands,
  exports = {
    switchMasterOnePage = switchMasterOnePage,
    switchMaster = switchMaster,
    defineMaster = defineMaster,
    defineMasters = defineMasters,
    currentMaster = currentMaster,
  },
  documentation = [[
\begin{document}

The masters functionality is also itself an add-on package. It allows a class to
define sets of frames and switch between them either temporarily or permanently.
It defines the commands \autodoc:command{\define-master-template} (which is pattern
on the \autodoc:command{\pagetemplate} function we will meet in chapter 8),
\autodoc:command{\switch-master} and \autodoc:command{\switch-master-one-page}.
See \code{tests/masters.sil} for more about this package.

\end{document}
]]
}<commit_msg>refactor(packages): Update masters package with new interface<commit_after>local base = require("packages.base")

local package = pl.class(base)
package._name = "masters"

local _currentMaster

local function defineMaster (_, args)
  SU.required(args, "id", "defining master")
  SU.required(args, "frames", "defining master")
  SU.required(args, "firstContentFrame", "defining master")
  SILE.scratch.masters[args.id] = { frames = {}, firstContentFrame = nil }
  for frame, spec in pairs(args.frames) do
    spec.id = frame
    if spec.solve then
      SILE.scratch.masters[args.id].frames[frame] = spec
    else
      SILE.scratch.masters[args.id].frames[frame] = SILE.newFrame(spec)
    end
  end
  SILE.scratch.masters[args.id].firstContentFrame = SILE.scratch.masters[args.id].frames[args.firstContentFrame]
end

local function defineMasters (class, list)
  if list then
    for i = 1, #list do
      defineMaster(class, list[i])
    end
  end
end

local function doswitch (frames)
  SILE.frames = { page = SILE.frames.page }
  for id, frame in pairs(frames) do
    SILE.frames[id] = frame
    frame:invalidate()
  end
end

local function switchMasterOnePage (class, id)
  if not id then
    id = class
    SU.deprecated("class.switchMasterOnePage", "class:switchMasterOnePage", "0.13.0", "0.15.0")
  end
  if not SILE.scratch.masters[id] then
    SU.error("Can't find master "..id)
  end
  SILE.documentState.thisPageTemplate = SILE.scratch.masters[id]
  doswitch(SILE.scratch.masters[id].frames)
  SILE.typesetter:chuck()
  SILE.typesetter:initFrame(SILE.scratch.masters[id].firstContentFrame)
end

local function switchMaster (class, id)
  if not id then
    id, class = class, SILE.documentState.documentClass
    SU.deprecated("class.switchMaster", "class:switchMaster", "0.13.0", "0.15.0")
  end
  _currentMaster = id
  if not SILE.scratch.masters[id] then
    SU.error("Can't find master "..id)
  end
  class.pageTemplate = SILE.scratch.masters[id]
  SILE.documentState.thisPageTemplate = pl.tablex.deepcopy(class.pageTemplate)
  doswitch(SILE.scratch.masters[id].frames)
  SILE.typesetter:initFrame(SILE.scratch.masters[id].firstContentFrame)
end

local function currentMaster (_)
  return _currentMaster
end

function package:_init (class, args)

  base._init(self, class)

  if not SILE.scratch.masters then
    SILE.scratch.masters = {}
  end

  defineMasters(class, args)

  -- exports
  class.switchMasterOnePage = switchMasterOnePage
  class.switchMaster = switchMaster
  class.defineMaster = defineMaster
  class.defineMasters = defineMasters
  class.currentMaster = currentMaster

end

function package:registerCommands ()

  local class = self.class

  class:registerCommand("define-master-template", function(options, content)
    SU.required(options, "id", "defining a master")
    SU.required(options, "first-content-frame", "defining a master")
    -- Subvert the <frame> functionality from baseclass
    local spare = SILE.documentState.thisPageTemplate.frames
    local sp2 = SILE.frames
    SILE.frames = { page = SILE.frames.page }
    SILE.documentState.thisPageTemplate.frames = {}
    SILE.process(content)
    SILE.scratch.masters[options.id] = {}
    SILE.scratch.masters[options.id].frames = SILE.documentState.thisPageTemplate.frames
    if not SILE.scratch.masters[options.id].frames[options["first-content-frame"]] then
      SU.error("first-content-frame "..options["first-content-frame"].." not found")
    end
    SILE.scratch.masters[options.id].firstContentFrame = SILE.scratch.masters[options.id].frames[options["first-content-frame"]]
    SILE.documentState.thisPageTemplate.frames = spare
    SILE.frames = sp2
  end)

  class:registerCommand("switch-master-one-page", function (options, _)
    SU.required(options, "id", "switching master")
    switchMasterOnePage(class, options.id)
    SILE.typesetter:leaveHmode()
  end, "Switches the master for the current page")

  class:registerCommand("switch-master", function (options, _)
    SU.required(options, "id", "switching master")
    switchMaster(class, options.id)
  end, "Switches the master for the current page")

end

package.documentation = [[
\begin{document}
The masters functionality is also itself an add-on package.
It allows a class to define sets of frames and switch between them either temporarily or permanently.
It defines the commands \autodoc:command{\define-master-template} (which is pattern on the \autodoc:command{\pagetemplate} function we will meet in chapter 8), \autodoc:command{\switch-master} and \autodoc:command{\switch-master-one-page}.
See \code{tests/masters.sil} for more about this package.
\end{document}
]]

return package
{'fraction_non_alphanumeric': 0.11863666156871314, 'fraction_numerical': 0.004369674459252786, 'mean_word_length': 4.325770796974986, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 5, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2728063', 'n_tokens_mistral': 2979, 'n_tokens_neox': 2947, 'n_words': 668}