• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

sile-typesetter / sile / 9474085178

11 Jun 2024 10:59PM UTC coverage: 69.177% (+13.9%) from 55.259%
9474085178

push

github

alerque
style(classes): Restyle with stylua

1 of 1 new or added line in 1 file covered. (100.0%)

104 existing lines in 9 files now uncovered.

11978 of 17315 relevant lines covered (69.18%)

4307.68 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

80.67
/classes/plain.lua
1
--- plain document class.
2
-- @use classes.plain
3

4
local base = require("classes.base")
92✔
5

6
local class = pl.class(base)
92✔
7
class._name = "plain"
92✔
8

9
class.defaultFrameset = {
92✔
10
   content = {
92✔
11
      left = "5%pw",
12
      right = "95%pw",
13
      top = "5%ph",
14
      bottom = "top(footnotes)",
15
   },
92✔
16
   folio = {
92✔
17
      left = "left(content)",
18
      right = "right(content)",
19
      top = "bottom(footnotes)+2%ph",
20
      bottom = "97%ph",
21
   },
92✔
22
   footnotes = {
92✔
23
      left = "left(content)",
24
      right = "right(content)",
25
      height = "0",
26
      bottom = "90%ph",
27
   },
92✔
28
}
92✔
29
class.firstContentFrame = "content"
92✔
30

31
local skips = {
92✔
32
   small = "3pt plus 1pt minus 1pt",
33
   med = "6pt plus 2pt minus 2pt",
34
   big = "12pt plus 4pt minus 4pt",
35
}
36

37
function class:_init (options)
92✔
38
   base._init(self, options)
92✔
39
   self:loadPackage("bidi")
92✔
40
   self:loadPackage("folio")
92✔
41
end
42

43
function class:declareOptions ()
92✔
44
   base.declareOptions(self)
92✔
45
   self:declareOption("direction", function (_, value)
184✔
46
      if value then
3✔
47
         SILE.documentState.direction = value
3✔
48
         SILE.settings:set("font.direction", value, true)
3✔
49
         for _, frame in pairs(self.defaultFrameset) do
12✔
50
            if not frame.direction then
9✔
51
               frame.direction = value
9✔
52
            end
53
         end
54
      end
55
      return SILE.documentState.direction
3✔
56
   end)
57
end
58

59
function class:setOptions (options)
92✔
60
   -- TODO: set a default direction here?
61
   base.setOptions(self, options)
92✔
62
end
63

64
function class:declareSettings ()
92✔
65
   base.declareSettings(self)
92✔
66
   for k, v in pairs(skips) do
368✔
67
      SILE.settings:declare({
552✔
68
         parameter = "plain." .. k .. "skipamount",
276✔
69
         type = "vglue",
70
         default = SILE.types.node.vglue(v),
552✔
71
         help = "The amount of a \\" .. k .. "skip",
276✔
72
      })
73
   end
74
end
75

76
function class:registerCommands ()
92✔
77
   SILE.classes.base.registerCommands(self)
92✔
78

79
   self:registerCommand("noindent", function (_, content)
184✔
80
      if #SILE.typesetter.state.nodes ~= 0 then
46✔
81
         SU.warn([[\noindent was called after paragraph content has already been procesed.
2✔
82

83
  This will not result in avoiding the current paragraph being indented.
84
  This function must be called before any content belonging to the
85
  paragraph is processed. If the intent was to suppress indentation of a
86
  following paragraph, first explicitly close the current paragraph. From
87
  an input document this is typically done with an empty line between
88
  paragraphs, but calling the \par command explicitly or from Lua code
89
  running SILE.call("par") will end the current paragraph.
90
]])
1✔
91
      end
92
      SILE.settings:set("current.parindent", SILE.types.node.glue())
92✔
93
      SILE.process(content)
46✔
94
   end, "Do not add an indent to the start of this paragraph")
138✔
95

96
   self:registerCommand("neverindent", function (_, content)
184✔
97
      SILE.settings:set("current.parindent", SILE.types.node.glue())
62✔
98
      SILE.settings:set("document.parindent", SILE.types.node.glue())
62✔
99
      SILE.process(content)
31✔
100
   end, "Turn off all indentation")
123✔
101

102
   self:registerCommand("indent", function (_, content)
184✔
103
      SILE.settings:set("current.parindent", SILE.settings:get("document.parindent"))
6✔
104
      SILE.process(content)
3✔
105
   end, "Do add an indent to the start of this paragraph, even if previously told otherwise")
95✔
106

107
   for k, _ in pairs(skips) do
368✔
108
      self:registerCommand(k .. "skip", function (_, _)
552✔
109
         SILE.typesetter:leaveHmode()
30✔
110
         SILE.typesetter:pushExplicitVglue(SILE.settings:get("plain." .. k .. "skipamount"))
60✔
111
      end, "Skip vertically by a " .. k .. " amount")
582✔
112
   end
113

114
   self:registerCommand("hfill", function (_, _)
184✔
115
      SILE.typesetter:pushExplicitGlue(SILE.types.node.hfillglue())
22✔
116
   end, "Add a huge horizontal glue")
103✔
117

118
   self:registerCommand("vfill", function (_, _)
184✔
119
      SILE.typesetter:leaveHmode()
197✔
120
      SILE.typesetter:pushExplicitVglue(SILE.types.node.vfillglue())
394✔
121
   end, "Add huge vertical glue")
289✔
122

123
   self:registerCommand("hss", function (_, _)
184✔
124
      SILE.typesetter:pushGlue(SILE.types.node.hssglue())
×
125
      table.insert(SILE.typesetter.state.nodes, SILE.types.node.zerohbox())
×
126
   end, "Add glue which stretches and shrinks horizontally (good for centering)")
92✔
127

128
   self:registerCommand("vss", function (_, _)
184✔
129
      SILE.typesetter:pushExplicitVglue(SILE.types.node.vssglue())
×
130
   end, "Add glue which stretches and shrinks vertically")
92✔
131

132
   local _thinspacewidth = SILE.types.measurement(0.16667, "em")
92✔
133

134
   self:registerCommand("thinspace", function (_, _)
184✔
135
      SILE.call("glue", { width = _thinspacewidth })
×
136
   end)
137

138
   self:registerCommand("negthinspace", function (_, _)
184✔
139
      SILE.call("glue", { width = -_thinspacewidth })
×
140
   end)
141

142
   self:registerCommand("enspace", function (_, _)
184✔
143
      SILE.call("glue", { width = SILE.types.measurement(1, "en") })
×
144
   end)
145

146
   self:registerCommand("relax", function (_, _) end)
92✔
147

148
   self:registerCommand("enskip", function (_, _)
184✔
149
      SILE.call("enspace")
×
150
   end)
151

152
   local _quadwidth = SILE.types.measurement(1, "em")
92✔
153

154
   self:registerCommand("quad", function (_, _)
184✔
UNCOV
155
      SILE.call("glue", { width = _quadwidth })
×
156
   end)
157

158
   self:registerCommand("qquad", function (_, _)
184✔
159
      SILE.call("glue", { width = _quadwidth * 2 })
24✔
160
   end)
161

162
   self:registerCommand("slash", function (_, _)
184✔
163
      SILE.typesetter:typeset("/")
×
164
      SILE.call("penalty", { penalty = 50 })
×
165
   end)
166

167
   self:registerCommand("break", function (_, _)
184✔
168
      SILE.call("penalty", { penalty = -10000 })
13✔
169
   end, "Requests a frame break (if in vertical mode) or a line break (if in horizontal mode)")
105✔
170

171
   self:registerCommand("cr", function (_, _)
184✔
172
      SILE.call("hfill")
2✔
173
      SILE.call("break")
2✔
174
   end, "Fills a line with a stretchable glue and then requests a line break")
94✔
175

176
   -- Despite their name, in older versions, \framebreak and \pagebreak worked badly in horizontal
177
   -- mode. The former was a linebreak, and the latter did nothing. That was surely not intended.
178
   -- There are many ways, though to assume what's wrong or what the user's intent ought to be.
179
   -- We now warn, and terminate the paragraph, but to all extents this might be a wrong approach to
180
   -- reconsider at some point.
181

182
   self:registerCommand("framebreak", function (_, _)
184✔
183
      if not SILE.typesetter:vmode() then
8✔
184
         SU.warn("framebreak was not intended to work in horizontal mode. Behaviour may change in future versions")
×
185
      end
186
      SILE.call("penalty", { penalty = -10000, vertical = true })
4✔
187
   end, "Requests a frame break (switching to vertical mode if needed)")
96✔
188

189
   self:registerCommand("pagebreak", function (_, _)
184✔
190
      if not SILE.typesetter:vmode() then
8✔
191
         SU.warn("pagebreak was not intended to work in horizontal mode. Behaviour may change in future versions")
×
192
      end
193
      SILE.call("penalty", { penalty = -20000, vertical = true })
4✔
194
   end, "Requests a non-negotiable page break (switching to vertical mode if needed)")
96✔
195

196
   self:registerCommand("nobreak", function (_, _)
184✔
197
      SILE.call("penalty", { penalty = 10000 })
×
198
   end, "Inhibits a frame break (if in vertical mode) or a line break (if in horizontal mode)")
92✔
199

200
   self:registerCommand("novbreak", function (_, _)
184✔
201
      SILE.call("penalty", { penalty = 10000, vertical = true })
18✔
202
   end, "Inhibits a frame break (switching to vertical mode if needed)")
110✔
203

204
   self:registerCommand(
184✔
205
      "allowbreak",
92✔
206
      function (_, _)
207
         SILE.call("penalty", { penalty = 0 })
×
208
      end,
209
      "Allows a page break (if in vertical mode) or a line break (if in horizontal mode) at a point would not be considered as suitable for breaking"
210
   )
92✔
211

212
   -- THIS SEEMS BROKEN BUT THE COMMAND NOT MENTIONED IN THE SILE MANUAL
213
   -- In TeX, "\filbreak" compensates the vertical fill if no break actually occurs
214
   -- (\def\filbreak{\par\vfil\penalty-200\vfilneg)
215
   self:registerCommand("filbreak", function (_, _)
184✔
216
      SILE.call("vfill")
×
217
      SILE.call("penalty", { penalty = -200 })
×
218
   end, "I HAVE THE SAME NAME AS A TEX COMMAND BUT DON'T SEEM TO BE THE SAME")
92✔
219

220
   -- NOTE: TeX's "\goodbreak" does a \par first, so always switches to vertical mode.
221
   -- SILE differs here, allowing it both within a paragraph (line breaking) and between
222
   -- paragraphs (page breaking).
223
   self:registerCommand("goodbreak", function (_, _)
184✔
224
      SILE.call("penalty", { penalty = -500 })
3✔
225
   end, "Indicates a good potential point to break a frame (if in vertical mode) or a line (if in horizontal mode")
95✔
226

227
   self:registerCommand("eject", function (_, _)
184✔
228
      SILE.call("vfill")
3✔
229
      SILE.call("break")
3✔
230
   end, "Fills the page with stretchable vglue and then request a page break")
95✔
231

232
   self:registerCommand("supereject", function (_, _)
184✔
233
      SILE.call("vfill")
102✔
234
      SILE.call("penalty", { penalty = -20000 })
102✔
235
   end, "Fills the page with stretchable vglue and then requests a non-negotiable page break")
194✔
236

237
   self:registerCommand("em", function (_, content)
184✔
238
      local style = SILE.settings:get("font.style")
62✔
239
      local toggle = (style and style:lower() == "italic") and "Regular" or "Italic"
124✔
240
      SILE.call("font", { style = toggle }, content)
62✔
241
   end, "Emphasizes its contents by switching the font style to italic (or back to regular if already italic)")
154✔
242

243
   self:registerCommand("strong", function (_, content)
184✔
244
      SILE.call("font", { weight = 700 }, content)
×
245
   end, "Sets the font weight to bold (700)")
92✔
246

247
   self:registerCommand("code", function (options, content)
184✔
248
      -- IMPLEMENTATION NOTE:
249
      -- The \code command came from the url package, though used in plenty of
250
      -- places. It was referring to the verbatim:font from the verbatim
251
      -- package, which _should_ be sort of unrelated.
252
      -- Trying to untangle the things here, by introducing the
253
      -- definition from the former, but it's of sub-quality...
254
      -- The ugly -3 size is a HACK of sorts.
255
      options.family = options.family or "Hack"
1✔
256
      options.size = options.size or SILE.settings:get("font.size") - 3
2✔
257
      SILE.call("font", options, content)
1✔
258
   end)
259

260
   self:registerCommand("nohyphenation", function (_, content)
184✔
261
      SILE.call("font", { language = "und" }, content)
×
262
   end)
263

264
   self:registerCommand("center", function (_, content)
184✔
265
      if #SILE.typesetter.state.nodes ~= 0 then
20✔
266
         SU.warn("\\center environment started after other nodes in a paragraph, may not center as expected")
×
267
      end
268
      SILE.settings:temporarily(function ()
40✔
269
         local lskip = SILE.settings:get("document.lskip") or SILE.types.node.glue()
40✔
270
         local rskip = SILE.settings:get("document.rskip") or SILE.types.node.glue()
40✔
271
         SILE.settings:set("document.parindent", SILE.types.node.glue())
40✔
272
         SILE.settings:set("current.parindent", SILE.types.node.glue())
40✔
273
         SILE.settings:set("document.lskip", SILE.types.node.hfillglue(lskip.width.length))
40✔
274
         SILE.settings:set("document.rskip", SILE.types.node.hfillglue(rskip.width.length))
40✔
275
         SILE.settings:set("typesetter.parfillskip", SILE.types.node.glue())
40✔
276
         SILE.settings:set("document.spaceskip", SILE.types.length("1spc", 0, 0))
40✔
277
         SILE.process(content)
20✔
278
         SILE.call("par")
20✔
279
      end)
280
   end, "Typeset its contents in a centered block (keeping margins).")
112✔
281

282
   self:registerCommand("raggedright", function (_, content)
184✔
283
      SILE.settings:temporarily(function ()
8✔
284
         local lskip = SILE.settings:get("document.lskip") or SILE.types.node.glue()
8✔
285
         local rskip = SILE.settings:get("document.rskip") or SILE.types.node.glue()
8✔
286
         SILE.settings:set("document.lskip", SILE.types.node.glue(lskip.width.length))
8✔
287
         SILE.settings:set("document.rskip", SILE.types.node.hfillglue(rskip.width.length))
8✔
288
         SILE.settings:set("typesetter.parfillskip", SILE.types.node.glue())
8✔
289
         SILE.settings:set("document.spaceskip", SILE.types.length("1spc", 0, 0))
8✔
290
         SILE.process(content)
4✔
291
         SILE.call("par")
4✔
292
      end)
293
   end, "Typeset its contents in a left aligned block (keeping margins).")
96✔
294

295
   self:registerCommand("raggedleft", function (_, content)
184✔
296
      SILE.settings:temporarily(function ()
10✔
297
         local lskip = SILE.settings:get("document.lskip") or SILE.types.node.glue()
10✔
298
         local rskip = SILE.settings:get("document.rskip") or SILE.types.node.glue()
10✔
299
         SILE.settings:set("document.lskip", SILE.types.node.hfillglue(lskip.width.length))
10✔
300
         SILE.settings:set("document.rskip", SILE.types.node.glue(rskip.width.length))
10✔
301
         SILE.settings:set("typesetter.parfillskip", SILE.types.node.glue())
10✔
302
         SILE.settings:set("document.spaceskip", SILE.types.length("1spc", 0, 0))
10✔
303
         SILE.process(content)
5✔
304
         SILE.call("par")
5✔
305
      end)
306
   end, "Typeset its contents in a right aligned block (keeping margins).")
97✔
307

308
   self:registerCommand("justified", function (_, content)
184✔
309
      SILE.settings:temporarily(function ()
2✔
310
         local lskip = SILE.settings:get("document.lskip") or SILE.types.node.glue()
2✔
311
         local rskip = SILE.settings:get("document.rskip") or SILE.types.node.glue()
2✔
312
         -- Keep the fixed part of the margins for nesting but remove the stretchability.
313
         SILE.settings:set("document.lskip", SILE.types.node.glue(lskip.width.length))
2✔
314
         SILE.settings:set("document.rskip", SILE.types.node.glue(rskip.width.length))
2✔
315
         -- Reset parfillskip to its default value, in case the surrounding context
316
         -- is ragged and cancelled it.
317
         SILE.settings:set("typesetter.parfillskip", nil, false, true)
1✔
318
         SILE.settings:set("document.spaceskip", nil)
1✔
319
         SILE.process(content)
1✔
320
         SILE.call("par")
1✔
321
      end)
322
   end, "Typeset its contents in a justified block (keeping margins).")
93✔
323

324
   self:registerCommand("ragged", function (options, content)
184✔
325
      -- Fairly dubious command for compatibility
326
      local l = SU.boolean(options.left, false)
1✔
327
      local r = SU.boolean(options.right, false)
1✔
328
      if l and r then
1✔
329
         SILE.call("center", {}, content)
2✔
330
      elseif r then
×
331
         SILE.call("raggedleft", {}, content)
×
332
      elseif l then
×
333
         SILE.call("raggedright", {}, content)
×
334
      else
335
         SILE.call("justified", {}, content)
×
336
      end
337
   end)
338

339
   self:registerCommand("rightalign", function (_, content)
184✔
340
      SU.deprecated("\\rightalign", "\\raggedleft", "0.15.0", "0.17.0")
×
341
      SILE.call("raggedleft", {}, content)
×
342
   end)
343

344
   self:registerCommand("blockquote", function (_, content)
184✔
345
      SILE.call("smallskip")
1✔
346
      SILE.typesetter:leaveHmode()
1✔
347
      SILE.settings:temporarily(function ()
2✔
348
         local indent = SILE.types.measurement("2em"):absolute()
2✔
349
         local lskip = SILE.settings:get("document.lskip") or SILE.types.node.glue()
2✔
350
         local rskip = SILE.settings:get("document.rskip") or SILE.types.node.glue()
2✔
351
         -- We keep the stretcheability of the lskip and rskip: honoring text alignment
352
         -- from the parent context.
353
         SILE.settings:set("document.lskip", SILE.types.node.glue(lskip.width + indent))
3✔
354
         SILE.settings:set("document.rskip", SILE.types.node.glue(rskip.width + indent))
3✔
355
         SILE.settings:set("font.size", SILE.settings:get("font.size") * 0.95)
2✔
356
         SILE.process(content)
1✔
357
         SILE.typesetter:leaveHmode()
1✔
358
      end)
359
      SILE.call("smallskip")
1✔
360
   end, "A blockquote environment")
93✔
361

362
   self:registerCommand("quote", function (_, content)
184✔
363
      SU.deprecated(
×
364
         "\\quote",
365
         "\\pullquote or \\blockquote",
366
         "0.14.5",
367
         "0.16.0",
368
         [[
×
369
  The \quote command has *such* bad output it is being completely
370
  deprecated as unsuitable for general purpose use.
371
  The pullquote package (\use[module=packages.pullquote]) provides one
372
  alternative, and the blockquote environment provides another.
373
  But you can also copy and adapt the original source from the plain
374
  class if you need to maintain exact output past SILE v0.16.0.]]
×
375
      )
376
      SILE.call("smallskip")
×
377
      SILE.call("par")
×
378
      local margin = SILE.types.measurement(2.5, "em")
×
379
      SILE.settings:set("document.lskip", margin)
×
380
      SILE.settings:set("document.lskip", margin)
×
381
      SILE.call("font", { size = SILE.types.measurement(0.8, "em") }, function ()
×
382
         SILE.call("noindent")
×
383
         SILE.process(content)
×
384
      end)
385
      SILE.call("par")
×
386
      SILE.settings:set("document.lskip", nil)
×
387
      SILE.settings:set("document.rskip", nil)
×
388
      SILE.call("smallskip")
×
389
   end)
390

391
   self:registerCommand("listitem", function (_, content)
184✔
392
      SU.deprecated(
×
393
         "\\listitem",
394
         "\\item",
395
         "0.14.6",
396
         "0.16.0",
397
         [[
×
398
  The new list package (\use[module=packages.lists) has much better
399
  typography for lists. If you want to maintain the exact output of listitem
400
  past SILE v0.16.0 copy the source of \listitem from the plain class into
401
  your project.]]
×
402
      )
403
      SILE.call("medskip")
×
404
      SILE.typesetter:typeset("• ")
×
405
      SILE.process(content)
×
406
      SILE.call("medskip")
×
407
   end)
408

409
   self:registerCommand("sloppy", function (_, _)
184✔
410
      SILE.settings:set("linebreak.tolerance", 9999)
×
411
   end)
412

413
   self:registerCommand("awful", function (_, _)
184✔
414
      SILE.settings:set("linebreak.tolerance", 10000)
×
415
   end)
416

417
   self:registerCommand("hbox", function (_, content)
184✔
418
      local hbox, hlist = SILE.typesetter:makeHbox(content)
18✔
419
      SILE.typesetter:pushHbox(hbox)
18✔
420
      if #hlist > 0 then
18✔
421
         SU.warn("Hbox has migrating content (ignored for now, but likely to break in future versions)")
×
422
         -- Ugly shim:
423
         -- One day we ought to do SILE.typesetter:pushHlist(hlist) here, so as to push
424
         -- back the migrating contents from within the hbox'ed content.
425
         -- However, old Lua code assumed the hbox to be returned, and sometimes removed it
426
         -- from the typesetter queue (for measuring, etc.), assuming it was the last
427
         -- element in the queue...
428
      end
429
      return hbox
18✔
430
   end, "Compiles all the enclosed horizontal-mode material into a single hbox")
92✔
431

432
   self:registerCommand("vbox", function (options, content)
184✔
433
      local vbox
434
      SILE.settings:temporarily(function ()
26✔
435
         if options.width then
13✔
436
            SILE.settings:set("typesetter.breakwidth", SILE.types.length(options.width))
×
437
         end
438
         SILE.typesetter:pushState()
13✔
439
         SILE.process(content)
13✔
440
         SILE.typesetter:leaveHmode(1)
13✔
441
         vbox = SILE.pagebuilder:collateVboxes(SILE.typesetter.state.outputQueue)
26✔
442
         SILE.typesetter:popState()
13✔
443
      end)
444
      return vbox
13✔
445
   end, "Compiles all the enclosed material into a single vbox")
92✔
446
end
447

448
return class
92✔
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc