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

sile-typesetter / sile / 6915746301

18 Nov 2023 07:02PM UTC coverage: 56.433% (-12.3%) from 68.751%
6915746301

push

github

web-flow
Merge 8b3fdc301 into f64e235fa

8729 of 15468 relevant lines covered (56.43%)

932.75 hits per line

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

77.63
/classes/plain.lua
1
local base = require("classes.base")
171✔
2

3
local class = pl.class(base)
171✔
4
class._name = "plain"
171✔
5

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

28
local skips = {
171✔
29
  small = "3pt plus 1pt minus 1pt",
30
  med = "6pt plus 2pt minus 2pt",
31
  big = "12pt plus 4pt minus 4pt"
×
32
}
33

34
function class:_init (options)
171✔
35
  base._init(self, options)
171✔
36
  self:loadPackage("bidi")
171✔
37
  self:loadPackage("folio")
171✔
38
end
39

40
function class:declareOptions ()
171✔
41
  base.declareOptions(self)
171✔
42
  self:declareOption("direction", function (_, value)
342✔
43
    if value then
6✔
44
      SILE.documentState.direction = value
6✔
45
      SILE.settings:set("font.direction", value, true)
6✔
46
      for _, frame in pairs(self.defaultFrameset) do
24✔
47
        if not frame.direction then
18✔
48
          frame.direction = value
18✔
49
        end
50
      end
51
    end
52
    return SILE.documentState.direction
6✔
53
  end)
54
end
55

56
function class:setOptions (options)
171✔
57
  -- TODO: set a default direction here?
58
  base.setOptions(self, options)
171✔
59
end
60

61
function class:declareSettings ()
171✔
62
  base.declareSettings(self)
171✔
63
  for k, v in pairs(skips) do
684✔
64
    SILE.settings:declare({
1,026✔
65
        parameter = "plain." .. k .. "skipamount",
513✔
66
        type = "vglue",
67
        default = SILE.nodefactory.vglue(v),
1,026✔
68
        help = "The amount of a \\" .. k .. "skip"
513✔
69
      })
70
  end
71
end
72

73
function class:registerCommands ()
171✔
74

75
  SILE.classes.base.registerCommands(self)
171✔
76

77
  self:registerCommand("noindent", function (_, content)
342✔
78
    if #SILE.typesetter.state.nodes ~= 0 then
103✔
79
      SU.warn("\\noindent called after nodes already received in a paragraph, the setting will have no effect because the parindent (if any) has already been output")
14✔
80
    end
81
    SILE.settings:set("current.parindent", SILE.nodefactory.glue())
206✔
82
    SILE.process(content)
103✔
83
  end, "Do not add an indent to the start of this paragraph")
274✔
84

85
  self:registerCommand("neverindent", function (_, content)
342✔
86
    SILE.settings:set("current.parindent", SILE.nodefactory.glue())
104✔
87
    SILE.settings:set("document.parindent", SILE.nodefactory.glue())
104✔
88
    SILE.process(content)
52✔
89
  end, "Turn off all indentation")
223✔
90

91
  self:registerCommand("indent", function (_, content)
342✔
92
    SILE.settings:set("current.parindent", SILE.settings:get("document.parindent"))
8✔
93
    SILE.process(content)
4✔
94
  end, "Do add an indent to the start of this paragraph, even if previously told otherwise")
175✔
95

96
  for k, _ in pairs(skips) do
684✔
97
    self:registerCommand(k .. "skip", function (_, _)
1,026✔
98
      SILE.typesetter:leaveHmode()
51✔
99
      SILE.typesetter:pushExplicitVglue(SILE.settings:get("plain." .. k .. "skipamount"))
102✔
100
    end, "Skip vertically by a " .. k .. " amount")
1,077✔
101
  end
102

103
  self:registerCommand("hfill", function (_, _)
342✔
104
    SILE.typesetter:pushExplicitGlue(SILE.nodefactory.hfillglue())
50✔
105
  end, "Add a huge horizontal glue")
196✔
106

107
  self:registerCommand("vfill", function (_, _)
342✔
108
    SILE.typesetter:leaveHmode()
359✔
109
    SILE.typesetter:pushExplicitVglue(SILE.nodefactory.vfillglue())
718✔
110
  end, "Add huge vertical glue")
530✔
111

112
  self:registerCommand("hss", function (_, _)
342✔
113
    SILE.typesetter:initline()
×
114
    SILE.typesetter:pushGlue(SILE.nodefactory.hssglue())
×
115
    table.insert(SILE.typesetter.state.nodes, SILE.nodefactory.zerohbox())
×
116
  end, "Add glue which stretches and shrinks horizontally (good for centering)")
171✔
117

118
  self:registerCommand("vss", function (_, _)
342✔
119
    SILE.typesetter:pushExplicitVglue(SILE.nodefactory.vssglue())
×
120
  end, "Add glue which stretches and shrinks vertically")
171✔
121

122
  local _thinspacewidth = SILE.measurement(0.16667, "em")
171✔
123

124
  self:registerCommand("thinspace", function (_, _)
342✔
125
    SILE.call("glue", { width = _thinspacewidth })
×
126
  end)
127

128
  self:registerCommand("negthinspace", function (_, _)
342✔
129
    SILE.call("glue", { width = -_thinspacewidth })
×
130
  end)
131

132
  self:registerCommand("enspace", function (_, _)
342✔
133
    SILE.call("glue", { width = SILE.measurement(1, "en") })
×
134
  end)
135

136
  self:registerCommand("relax", function (_, _)
342✔
137
  end)
138

139
  self:registerCommand("enskip", function (_, _)
342✔
140
    SILE.call("enspace")
×
141
  end)
142

143
  local _quadwidth = SILE.measurement(1, "em")
171✔
144

145
  self:registerCommand("quad", function (_, _)
342✔
146
    SILE.call("glue", { width = _quadwidth })
1✔
147
  end)
148

149
  self:registerCommand("qquad", function (_, _)
342✔
150
    SILE.call("glue", { width = _quadwidth * 2 })
90✔
151
  end)
152

153
  self:registerCommand("slash", function (_, _)
342✔
154
    SILE.typesetter:typeset("/")
×
155
    SILE.call("penalty", { penalty = 50 })
×
156
  end)
157

158
  self:registerCommand("break", function (_, _)
342✔
159
    SILE.call("penalty", { penalty = -10000 })
44✔
160
  end, "Requests a frame break (if in vertical mode) or a line break (if in horizontal mode)")
215✔
161

162
  self:registerCommand("cr", function (_, _)
342✔
163
    SILE.call("hfill")
3✔
164
    SILE.call("break")
3✔
165
  end, "Fills a line with a stretchable glue and then requests a line break")
174✔
166

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

173
  self:registerCommand("framebreak", function (_, _)
342✔
174
    if not SILE.typesetter:vmode() then
22✔
175
      SU.warn("framebreak was not intended to work in horizontal mode. Behaviour may change in future versions")
×
176
    end
177
    SILE.call("penalty", { penalty = -10000, vertical = true })
11✔
178
  end, "Requests a frame break (switching to vertical mode if needed)")
182✔
179

180
  self:registerCommand("pagebreak", function (_, _)
342✔
181
    if not SILE.typesetter:vmode() then
14✔
182
      SU.warn("pagebreak was not intended to work in horizontal mode. Behaviour may change in future versions")
×
183
    end
184
    SILE.call("penalty", { penalty = -20000, vertical = true })
7✔
185
  end, "Requests a non-negotiable page break (switching to vertical mode if needed)")
178✔
186

187
  self:registerCommand("nobreak", function (_, _)
342✔
188
    SILE.call("penalty", { penalty = 10000 })
×
189
  end, "Inhibits a frame break (if in vertical mode) or a line break (if in horizontal mode)")
171✔
190

191
  self:registerCommand("novbreak", function (_, _)
342✔
192
    SILE.call("penalty", { penalty = 10000, vertical = true })
7✔
193
  end, "Inhibits a frame break (switching to vertical mode if needed)")
178✔
194

195
  self:registerCommand("allowbreak", function (_, _)
342✔
196
    SILE.call("penalty", { penalty = 0 })
×
197
  end, "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")
171✔
198

199
  -- THIS SEEMS BROKEN BUT THE COMMAND NOT MENTIONED IN THE SILE MANUAL
200
  -- In TeX, "\filbreak" compensates the vertical fill if no break actually occurs
201
  -- (\def\filbreak{\par\vfil\penalty-200\vfilneg)
202
  self:registerCommand("filbreak", function (_, _)
342✔
203
    SILE.call("vfill")
×
204
    SILE.call("penalty", { penalty = -200 })
×
205
  end, "I HAVE THE SAME NAME AS A TEX COMMAND BUT DON'T SEEM TO BE THE SAME")
171✔
206

207
  -- NOTE: TeX's "\goodbreak" does a \par first, so always switches to vertical mode.
208
  -- SILE differs here, allowing it both within a paragraph (line breaking) and between
209
  -- paragraphs (page breaking).
210
  self:registerCommand("goodbreak", function (_, _)
342✔
211
    SILE.call("penalty", { penalty = -500 })
4✔
212
  end, "Indicates a good potential point to break a frame (if in vertical mode) or a line (if in horizontal mode")
175✔
213

214
  self:registerCommand("eject", function (_, _)
342✔
215
    SILE.call("vfill")
3✔
216
    SILE.call("break")
3✔
217
  end, "Fills the page with stretchable vglue and then request a page break")
174✔
218

219
  self:registerCommand("supereject", function (_, _)
342✔
220
    SILE.call("vfill")
181✔
221
    SILE.call("penalty", { penalty = -20000 })
181✔
222
  end, "Fills the page with stretchable vglue and then requests a non-negotiable page break")
352✔
223

224
  self:registerCommand("justified", function (_, content)
342✔
225
    SILE.settings:set("document.rskip", nil)
1✔
226
    SILE.settings:set("document.spaceskip", nil)
1✔
227
    SILE.process(content)
1✔
228
    SILE.call("par")
1✔
229
  end)
230

231
  self:registerCommand("rightalign", function (_, content)
342✔
232
    SILE.call("raggedleft", {}, function ()
8✔
233
      SILE.process(content)
4✔
234
      SILE.call("par")
4✔
235
    end)
236
  end)
237

238
  self:registerCommand("em", function (_, content)
342✔
239
    SILE.call("font", { style = "Italic" }, content)
38✔
240
  end)
241

242
  self:registerCommand("strong", function (_, content)
342✔
243
    SILE.call("font", { weight = 700 }, content)
×
244
  end)
245

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

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

263
  self:registerCommand("raggedright", function (_, content)
36✔
264
    SILE.call("ragged", { right = true }, content)
1✔
265
  end)
266

267
  self:registerCommand("raggedleft", function (_, content)
36✔
268
    SILE.call("ragged", { left = true }, content)
2✔
269
  end)
270

271
  self:registerCommand("quote", function (_, content)
36✔
272
    SU.deprecated("\\quote", "\\pullquote", "0.14.5", "0.16.0", [[
×
273
  The \quote command has *such* bad output it is being completely
274
  deprecated as unsuitable for general purpose use. The pullquote
275
  package (\use[module=packages.pullquote]) provides one alternative,
276
  but you can also copy and adapt the original source from the plain
277
  class if you need to maintain exact output past SILE v0.16.0.]])
×
278
    SILE.call("smallskip")
×
279
    SILE.call("par")
×
280
    local margin = SILE.measurement(2.5, "em")
×
281
    SILE.settings:set("document.lskip", margin)
×
282
    SILE.settings:set("document.lskip", margin)
×
283
    SILE.call("font", { size = SILE.measurement(0.8, "em") }, function ()
×
284
      SILE.call("noindent")
×
285
      SILE.process(content)
×
286
    end)
287
    SILE.call("par")
×
288
    SILE.settings:set("document.lskip", nil)
×
289
    SILE.settings:set("document.rskip", nil)
×
290
    SILE.call("smallskip")
×
291
  end)
292

293
  self:registerCommand("listitem", function (_, content)
36✔
294
    SU.deprecated("\\listitem", "\\item", "0.14.6", "0.16.0", [[
×
295
  The new list package (\use[module=packages.lists) has much better
296
  typography for lists. If you want to maintain the exact output of listitem
297
  past SILE v0.16.0 copy the source of \listitem from the plain class into
298
  your project.]])
×
299
    SILE.call("medskip")
×
300
    SILE.typesetter:typeset("• ")
×
301
    SILE.process(content)
×
302
    SILE.call("medskip")
×
303
  end)
304

305
  self:registerCommand("sloppy", function (_, _)
36✔
306
    SILE.settings:set("linebreak.tolerance", 9999)
×
307
  end)
308

309
  self:registerCommand("awful", function (_, _)
36✔
310
    SILE.settings:set("linebreak.tolerance", 10000)
×
311
  end)
312

313
  self:registerCommand("center", function (_, content)
36✔
314
    if #SILE.typesetter.state.nodes ~= 0 then
41✔
315
      SU.warn("\\center environment started after other nodes in a paragraph, may not center as expected")
×
316
    end
317
    SILE.settings:temporarily(function()
82✔
318
      SILE.settings:set("current.parindent", 0)
41✔
319
      SILE.settings:set("document.parindent", 0)
41✔
320
      SILE.call("ragged", { left = true, right = true }, content)
41✔
321
    end)
322
  end)
323

324
  self:registerCommand("ragged", function (options, content)
36✔
325
    SILE.settings:temporarily(function ()
88✔
326
      if SU.boolean(options.left, false) then SILE.settings:set("document.lskip", SILE.nodefactory.hfillglue()) end
131✔
327
      if SU.boolean(options.right, false) then SILE.settings:set("document.rskip", SILE.nodefactory.hfillglue()) end
130✔
328
      SILE.settings:set("typesetter.parfillskip", SILE.nodefactory.glue())
88✔
329
      SILE.settings:set("document.parindent", SILE.nodefactory.glue())
88✔
330
      SILE.settings:set("document.spaceskip", SILE.length("1spc", 0, 0))
88✔
331
      SILE.process(content)
44✔
332
      SILE.call("par")
44✔
333
    end)
334
  end)
335

336
  self:registerCommand("hbox", function (_, content)
36✔
337
    local hbox, hlist = SILE.typesetter:makeHbox(content)
12✔
338
    SILE.typesetter:pushHbox(hbox)
12✔
339
    if #hlist > 0 then
12✔
340
      SU.warn("Hbox has migrating content (ignored for now, but likely to break in future versions)")
×
341
      -- Ugly shim:
342
      -- One day we ought to do SILE.typesetter:pushHlist(hlist) here, so as to push
343
      -- back the migrating contents from within the hbox'ed content.
344
      -- However, old Lua code assumed the hbox to be returned, and sometimes removed it
345
      -- from the typesetter queue (for measuring, etc.), assuming it was the last
346
      -- element in the queue...
347
    end
348
    return hbox
12✔
349
  end, "Compiles all the enclosed horizontal-mode material into a single hbox")
18✔
350

351
  self:registerCommand("vbox", function (options, content)
36✔
352
    local vbox
353
    SILE.settings:temporarily(function ()
2✔
354
      if options.width then SILE.settings:set("typesetter.breakwidth", SILE.length(options.width)) end
1✔
355
      SILE.typesetter:pushState()
1✔
356
      SILE.process(content)
1✔
357
      SILE.typesetter:leaveHmode(1)
1✔
358
      vbox = SILE.pagebuilder:collateVboxes(SILE.typesetter.state.outputQueue)
2✔
359
      SILE.typesetter:popState()
1✔
360
    end)
361
    return vbox
1✔
362
  end, "Compiles all the enclosed material into a single vbox")
18✔
363

364
end
365

366
return class
18✔
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