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

sile-typesetter / sile / 12179665938

05 Dec 2024 12:23PM CUT coverage: 44.129% (-16.6%) from 60.747%
12179665938

push

github

web-flow
Merge pull request #2188 from alerque/snafu

Properly format errors, avoid erroring after already triggering an error

6 of 9 new or added lines in 3 files covered. (66.67%)

3720 existing lines in 16 files now uncovered.

8790 of 19919 relevant lines covered (44.13%)

4433.46 hits per line

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

0.0
/packages/math/init.lua
UNCOV
1
local base = require("packages.base")
×
2

UNCOV
3
local package = pl.class(base)
×
UNCOV
4
package._name = "math"
×
5

UNCOV
6
function package:_init ()
×
UNCOV
7
   base._init(self)
×
UNCOV
8
   local typesetter = require("packages.math.typesetter")
×
UNCOV
9
   self.ConvertMathML, self.handleMath = typesetter[1], typesetter[2]
×
UNCOV
10
   local texlike = require("packages.math.texlike")
×
UNCOV
11
   self.convertTexlike, self.compileToMathML = texlike[1], texlike[2]
×
12
   -- Register a new unit that is 1/18th of the current math font size
UNCOV
13
   SILE.registerUnit("mu", {
×
14
      relative = true,
15
      definition = function (value)
UNCOV
16
         return value * SILE.settings:get("math.font.size") / 18
×
17
      end,
18
   })
UNCOV
19
   self:loadPackage("counters")
×
20
end
21

UNCOV
22
function package.declareSettings (_)
×
UNCOV
23
   SILE.settings:declare({
×
24
      parameter = "math.font.family",
25
      type = "string",
26
      default = "Libertinus Math",
27
   })
UNCOV
28
   SILE.settings:declare({
×
29
      parameter = "math.font.style",
30
      type = "string",
31
      default = "Regular",
32
   })
UNCOV
33
   SILE.settings:declare({
×
34
      parameter = "math.font.weight",
35
      type = "integer",
36
      default = 400,
37
   })
UNCOV
38
   SILE.settings:declare({
×
39
      parameter = "math.font.script.feature",
40
      type = "string or nil",
41
      default = "ssty",
42
      help = "OpenType feature for the math script-style alternates (esp. primes), theoretically ssty",
43
   })
UNCOV
44
   SILE.settings:declare({
×
45
      parameter = "math.font.filename",
46
      type = "string",
47
      default = "",
48
   })
UNCOV
49
   SILE.settings:declare({
×
50
      parameter = "math.font.size",
51
      type = "integer",
52
      default = 10,
53
   })
54
   -- Whether to show debug boxes around mboxes
UNCOV
55
   SILE.settings:declare({
×
56
      parameter = "math.debug.boxes",
57
      type = "boolean",
58
      default = false,
59
   })
UNCOV
60
   SILE.settings:declare({
×
61
      parameter = "math.displayskip",
62
      type = "VGlue",
63
      default = SILE.types.node.vglue("2ex plus 1pt"),
64
   })
65

66
   -- Penalties for breaking before and after a display math formula
67
   -- See TeX's \predisplaypenalty and \postdisplaypenalty
UNCOV
68
   SILE.settings:declare({
×
69
      parameter = "math.predisplaypenalty",
70
      type = "integer",
71
      default = 10000, -- strict no break by default as in (La)TeX
72
      help = "Penalty for breaking before a display math formula",
73
   })
UNCOV
74
   SILE.settings:declare({
×
75
      parameter = "math.postdisplaypenalty",
76
      type = "integer",
77
      -- (La)TeX's default is 0 (a normal line break penalty allowing a break
78
      -- after a display math formula)
79
      -- See https://github.com/sile-typesetter/sile/issues/2160
80
      --    And see implementation in handleMath(): we are not yet doing the right
81
      --    things with respect to paragraphing, so setting a lower value for now
82
      --    to ease breaking after a display math formula rather than before
83
      --    when the formula is in the middle of a paragraph.
84
      --    (In TeX, these penalties would apply in horizontal mode, with a display
85
      --    math formula being a horizontal full-width box, our implementation
86
      --    currently use them as vertical penalties).
87
      default = -50,
88
      help = "Penalty for breaking after a display math formula",
89
   })
90
end
91

UNCOV
92
function package:registerCommands ()
×
UNCOV
93
   self:registerCommand("mathml", function (options, content)
×
94
      local mbox
UNCOV
95
      xpcall(function ()
×
UNCOV
96
         mbox = self:ConvertMathML(content)
×
UNCOV
97
      end, function (err)
×
98
         print(err)
×
99
         print(debug.traceback())
×
100
      end)
UNCOV
101
      self:handleMath(mbox, options)
×
102
   end)
103

UNCOV
104
   self:registerCommand("math", function (options, content)
×
105
      local mbox
UNCOV
106
      xpcall(function ()
×
UNCOV
107
         mbox = self:ConvertMathML(self:compileToMathML({}, self:convertTexlike(content)))
×
UNCOV
108
      end, function (err)
×
109
         print(err)
×
110
         print(debug.traceback())
×
111
      end)
UNCOV
112
      self:handleMath(mbox, options)
×
113
   end)
114

UNCOV
115
   self:registerCommand("math:numberingstyle", function (options, _)
×
116
      SILE.typesetter:typeset("(")
×
117
      if options.counter then
×
118
         SILE.call("show-counter", { id = options.counter })
×
119
      elseif options.number then
×
120
         SILE.typesetter:typeset(options.number)
×
121
      end
122
      SILE.typesetter:typeset(")")
×
123
   end)
124
end
125

126
package.documentation = [[
127
\begin{document}
128
\use[module=packages.math]
129
\set[parameter=math.font.family, value=Libertinus Math]
130
\set[parameter=math.font.size, value=11]
131
% Default verbatim font (Hack) is missing a few math symbols
132
\use[module=packages.font-fallback]
133
\font:add-fallback[family=Symbola]
134
\define[command=paragraph]{\smallskip\em{\process.}\novbreak\par}
135
The \autodoc:package{math} package provides typesetting of formulas directly in a SILE document.
136

137
\autodoc:note{Mathematical typesetting in SILE is still in its infancy.
138
As such, it lacks some features and may contain bugs.
139
Feedback and contributions are always welcome.}
140

141
\noindent To typeset mathematics, you will need an OpenType math font installed on your system.
142
By default, this package uses Libertinus Math, so it will fail if Libertinus Math can’t be found.
143
Another font may be specified via the setting \autodoc:setting{math.font.family}.
144
If required, you can set the font style and weight via \autodoc:setting{math.font.style} and \autodoc:setting{math.font.weight}.
145
The font size can be set via \autodoc:setting{math.font.size}.
146
The \autodoc:setting{math.font.script.feature} setting can be used to specify OpenType features for the math font, which are applied to the smaller script styles.
147
It defaults to \code{ssty} (script style alternates), notably to ensure that some symbols such as the prime, double prime, etc. are displayed correctly.
148
The default setting applies to Libertinus Math and well-designed math fonts, but some fonts may require different features.
149
(The STIX Two Math font has a stylitic set \code{ss04} from primes only, but also supports, according to its documentation, \code{ssty}, which provides other optical adjustments.)
150

151
\paragraph{MathML}
152
The first way to typeset math formulas is to enter them in the MathML format.
153
MathML is a standard for encoding mathematical notation for the Web and for other types of digital documents.
154
It is supported by a wide range of tools and represents the most promising format for unifying the encoding of mathematical notation, as well as improving its accessibility (e.g., to blind users).
155

156
To render an equation encoded in MathML, simply put it in a \code{mathml} command.
157
For example, the formula \mathml{\mrow{\msup{\mi{a}\mn{2}} \mo{+} \msup{\mi{b}\mn{2}} \mo{=} \msup{\mi{c}\mn{2}}}} was typeset by the following command:
158

159
\begin[type=autodoc:codeblock]{raw}
160
\mathml{
161
    \mrow{
162
        \msup{\mi{a}\mn{2}}
163
        \mo{+}
164
        \msup{\mi{b}\mn{2}}
165
        \mo{=}
166
        \msup{\mi{c}\mn{2}}
167
    }
168
}
169
\end{raw}
170

171
\noindent In an XML document, we could use the more classical XML syntax:
172

173
\begin[type=autodoc:codeblock]{raw}
174
<mathml>
175
    <mrow>
176
        <msup> <mi>a</mi> <mn>2</mn> </msup>
177
        <mo>+</mo>
178
        <msup> <mi>b</mi> <mn>2</mn> </msup>
179
        <mo>=</mo>
180
        <msup> <mi>c</mi> <mn>2</mn> </msup>
181
    </mrow>
182
</mathml>
183
\end{raw}
184

185
\noindent By default, formulas are integrated into the flow of text.
186
To typeset them on their own line, use the \autodoc:parameter{mode=display} option:
187

188
\mathml[mode=display]{
189
    \mrow{
190
        \msup{\mi{a}\mn{2}}
191
        \mo{+}
192
        \msup{\mi{b}\mn{2}}
193
        \mo{=}
194
        \msup{\mi{c}\mn{2}}
195
    }
196
}
197

198
\paragraph{TeX-like syntax}
199
As the previous examples illustrate, MathML is not really intended to be written by humans and quickly becomes very verbose.
200
That is why this package also provides a \code{math} command, which understands a syntax similar to the math syntax of TeX.
201
To typeset the above equation, one only has to type \code{\\math\{a^2 + b^2 = c^2\}}.
202

203
Here is a slightly more involved equation:
204

205
\begin[type=autodoc:codeblock]{raw}
206
\begin[mode=display]{math}
207
    \sum_{n=1}^\infty \frac{1}{n^2} = \frac{\pi^2}{6}
208
\end{math}
209
\end{raw}
210

211
\noindent This renders as:
212

213
\begin[mode=display]{math}
214
    \sum_{n=1}^\infty \frac{1}{n^2} = \frac{\pi^2}{6}
215
\end{math}
216

217
The general philosophy of the TeX-like syntax is to be a simple layer on top of MathML, and not to mimic perfectly the syntax of the LaTeX tool.
218
Its main difference from the SILE syntax is that \code{\\mycommand\{arg1\}\{arg2\}\{arg3\}} is translated into MathML as \code{<mycommand> arg1 arg2 arg3 </mycommand>} whereas in normal SILE syntax, the XML equivalent would be \code{<mycommand>arg1</mycommand> arg2 arg3}.
219

220
\code{\\sum}, \code{\\infty}, and \code{\\pi} are only shorthands for the Unicode characters \math{\sum}, \math{\infty} and \math{\pi}.
221
If it’s more convenient, you can use these Unicode characters directly.
222
The symbol shorthands are the same as in the TeX package \href[src=https://www.ctan.org/pkg/unicode-math]{\code{unicode-math}}.
223

224
The TeX-like syntax also supports several familiar constructs, pre-defined with appropriate spacing, movable limits and other properties, such as \code{\\sin}, \code{\\cos}, \code{\\lim}, etc.
225
These are just macro-definitions (see further below); for instance, \code{\\lim} is a shorthand for \code{\\mo[atom=op, movablelimits=true]\{lim\}}.
226
\begin[mode=display]{math}
227
    \sin 2\theta = 2\sin \theta \cos \theta
228
\end{math}
229
\begin[mode=display]{math}
230
    \math{\lim_{n\to\infty} F(n) = 0}
231
\end{math}
232

233
\code{\{formula\}} is a shorthand for \code{\\mrow\{formula\}}.
234
Delimiters—among other glyphs—stretch vertically to the size of their englobing \code{mrow}, which is useful for their size to adapt to the content.
235
SILE automatically wraps paired delimiters in such a construct, so these adapt to their inner content only.
236

237
\begin[type=autodoc:codeblock]{raw}
238
\Gamma (\frac{\zeta}{2}) + x^2(x+1)
239
\end{raw}
240

241
\noindent directly renders as
242

243
\begin[mode=display]{math}
244
    \Gamma (\frac{\zeta}{2}) + x^2(x+1)
245
\end{math}
246

247
\noindent which is neat.
248
But for cases when stretchy delimiters are not paired in an obvious way, these can end up too large.
249
To keep them small, you should put braces around the expression:
250

251
\begin[type=autodoc:codeblock]{raw}
252
\Vert v \Vert = \sqrt{x^2 + y^2} \text{ vs. } {\Vert v \Vert} = \sqrt{x^2 + y^2}
253
\end{raw}
254

255
\begin[mode=display]{math}
256
\Vert v \Vert = \sqrt{x^2 + y^2} \text{ vs. } {\Vert v \Vert} = \sqrt{x^2 + y^2}
257
\end{math}
258

259
Alternatively, you can use the \code{\\left} and \code{\\right} commands to automatically adjust the size of the delimiters to the inner content.
260
Since SILE does it automatically for paired delimiters, it only really useful if you took a TeX formula using these commands and want to keep it as is, or if you want to use delimiters that are not paired in an obvious way.
261
In this construct, the period is also supported for a null delimiter, as with TeX.
262

263
\begin[type=autodoc:codeblock]{raw}
264
\left\rangle \frac{\zeta}{2} \right\langle \quad \left\}\frac{\zeta}{2} \right.
265
\end{raw}
266

267
\begin[mode=display]{math}
268
\left\rangle \frac{\zeta}{2} \right\langle \quad \left\}\frac{\zeta}{2} \right.
269
\end{math}
270

271
\noindent To print a brace in a formula, you need to escape it with a backslash.
272

273
\paragraph{Token kinds}
274
In the \code{math} syntax, every individual letter is an identifier (MathML tag \code{mi}), every number is a… number (tag \code{mn}) and all other characters are operators (tag \code{mo}).
275
If this does not suit you, you can explicitly use the \code{\\mi}, \code{\\mn}, or \code{\\mo} tags.
276
For instance, \code{sin(x)} will be rendered as \math{sin(x)}, because SILE considers the letters s, i and n to be individual identifiers, and identifiers made of one character are italicized by default.
277
To avoid that, you can specify that \math{\mi{sin}} is an identifier by writing \code{\\mi\{sin\}(x)} and get: \math{\mi{sin}(x)}.
278
If you prefer it in “double struck” style, this is permitted by the \code{mathvariant} attribute: \code{\\mi[mathvariant=double-struck]\{sin\}(x)} renders as \math{\mi[mathvariant=double-struck]{sin}(x)}.
279

280
\paragraph{Atom types and spacing}
281
The current implementation does not follow the MathML rules for spacing, but rather the rules defined in the TeXbook, based on atom types.
282
Each token automatically gets assigned an atom type from the list below:
283
\begin{itemize}
284
  \item{\code{ord}: \code{mi} and \code{mn} tokens, as well as unclassified operators}
285
  \item{\code{op}: large operators like ‘\math{\sum}’ or ‘\math{\prod}’}
286
  \item{\code{bin}: binary operators like ‘\math{+}’ or ‘\math{\%}’}
287
  \item{\code{rel}: relation operators like ‘\math{=}’ or ‘\math{<}’}
288
  \item{\code{open}: opening operators like ‘\math{(}’ or ‘\math{[}’}
289
  \item{\code{close}: closing operators like ‘\math{)}’ or ‘\math{]}’}
290
  \item{\code{punct}: punctuation operators like ‘\math{,}’}
291
  % TODO: Those are defined in the 'math' package but appear to be unused
292
  %\item{\code{inner}}
293
  %\item{\code{over}}
294
  %\item{\code{under}}
295
  %\item{\code{accent}}
296
  %\item{\code{bothaccent}}
297
\end{itemize}
298
\noindent The spacing between any two successive tokens is set automatically based on their atom types, and hence may not reflect the actual spacing used in the input.
299
To make an operator behave like it has a certain atom type, you can use the \code{atom} attribute. For example, \code{a \\mo[atom=bin]\{div\} b} renders as \math[mode=display]{a \mo[atom=bin]{div} b.}
300

301
Spaces in math mode are defined in “math units” (mu), which are 1/18 of an em of the current \em{math} font (and are independent of the current text font size).
302
Standard spaces inserted automatically between tokens come in three varieties: thin (3 mu), medium (4 mu) and thick (5 mu).
303
If needed, you can insert them manually with the \code{\\thinspace} (or \code{\\,}), \code{\\medspace} (or \code{\\>}), and \code{\\thickspace} (or \code{\\;}) commands.
304
Negative space counterparts are available as \code{\\negthinspace} (or \code{\\!}), \code{\\negmedspace}, and \code{\\negthickspace}.
305
The \code{\\enspace}, \code{\\quad}, and \code{\\qquad} commands from normal text mode are also available, but the spaces they insert scale relative to the text font size.
306
Finally, you can add a space of any size using the \code{\\mspace[width=<dimension>]} command.
307

308
\paragraph{Macros}
309
To save you some typing, the math syntax lets you define macros with the following syntax:
310

311
\begin[type=autodoc:codeblock]{raw}
312
\def{macro-name}{macro-body}
313
\end{raw}
314

315
\noindent where in the macro’s body \code{#1}, \code{#2}, etc. will be replaced by the macro’s arguments.
316
For instance:
317

318
\begin[type=autodoc:codeblock]{raw}
319
\begin[mode=display]{math}
320
    \def{diff}{\mfrac{\mo{d}#1}{\mo{d}#2}}
321
    \def{bi}{\mi[mathvariant=bold-italic]{#1}}
322

323
    \diff{\bi{p}}{t} = ∑_i \bi{F}_i
324
\end{math}
325
\end{raw}
326

327
\noindent results in:
328

329
\begin[mode=display]{math}
330
  \def{diff}{\mfrac{\mo{d}#1}{\mo{d}#2}}
331
  \def{bi}{\mi[mathvariant=bold-italic]{#1}}
332
  \diff{\bi{p}}{t} = ∑_i \bi{F}_i
333
\end{math}
334

335
When macros are not enough, creating new mathematical elements is quite simple: one only needs to create a new class deriving from \code{mbox} (defined in \code{packages/math/base-elements.lua}) and define the \code{shape} and \code{output} methods.
336
\code{shape} must define the \code{width}, \code{height} and \code{depth} attributes of the element, while \code{output} must draw the actual output.
337
An \code{mbox} may have one or more children (for instance, a fraction has two children—its numerator and denominator).
338
The \code{shape} and \code{output} methods of the children are called automatically.
339

340
\paragraph{Matrices, aligned equations, and other tables}
341
Tabular math can be typeset using the \code{table} command (or equivalently the \code{mtable} MathML tag).
342
For instance, to typeset a matrix:
343

344
\begin[type=autodoc:codeblock]{raw}
345
\begin[mode=display]{math}
346
    (
347
    \table{
348
        1 & 2 & 7 \\
349
        0 & 5 & 3 \\
350
        8 & 2 & 1 \\
351
    }
352
    )
353
\end{math}
354
\end{raw}
355

356
\noindent will yield:
357

358
\begin[mode=display]{math}
359
  (\table{
360
       1 & 2 & 7 \\
361
       0 & 5 & 3 \\
362
       8 & 2 & 1 \\
363
  })
364
\end{math}
365

366
\noindent Tables may also be used to control the alignment of formulas:
367

368
\begin[type=autodoc:codeblock]{raw}
369
\begin[mode=display]{math}
370
    \{
371
    \table[columnalign=right center left]{
372
        u_0 &=& 1 \\
373
        u_1 &=& 1 \\
374
        u_n &=& u_{n−1} + u_{n−2}, \forall n ⩾ 2 \\
375
    }
376
\end{math}
377
\end{raw}
378

379
\begin[mode=display]{math}
380
    \{
381
    \table[columnalign=right center left]{
382
        u_0 &=& 1 \\
383
        u_1 &=& 1 \\
384
        u_n &=& u_{n−1} + u_{n−2}, \forall n ⩾ 2 \\
385
    }
386
\end{math}
387

388
\noindent Tables currently do not support all attributes required by the MathML standard, but they do allow to control spacing using the \code{rowspacing} and \code{columnspacing} options.
389

390
Finally, here is a little secret. This notation:
391

392
\begin[type=autodoc:codeblock]{raw}
393
\table{
394
    1 & 2 & 7 \\
395
    0 & 5 & 3 \\
396
    8 & 2 & 1 \\
397
}
398
\end{raw}
399

400
\noindent is strictly equivalent to this one:
401

402
\begin[type=autodoc:codeblock]{raw}
403
\table{
404
        {1} {2} {7}
405
    }{
406
        {0} {5} {3}
407
    }{
408
        {8} {2} {1}
409
    }
410
}
411
\end{raw}
412

413
\noindent In other words, the notation using \code{&} and \code{\\\\} is only a syntactic sugar for a two-dimensional array constructed with braces.
414

415
\paragraph{Numbered equations}
416
Equations can be numbered in display mode.
417

418
When \autodoc:parameter{numbered=true}, equations are numbered using a default “equation” counter:
419
\math[mode=display, numbered=true]{e^{i\pi} = -1}
420

421
A different counter can be set by using the option \autodoc:parameter{counter=<id>}, and this setting will also enable numbering.
422

423
It is also possible to impose direct numbering using the \autodoc:parameter{number=<value>} option.
424

425
The default numbering format is \autodoc:example{(n)}, but this style may be overridden by defining a custom \autodoc:command{\math:numberingstyle} command.
426
The \code{counter} or the direct value \code{number} is passed as a parameter to this hook, as well as any other options.
427

428
\paragraph{Missing features}
429
This package still lacks support for some mathematical constructs, but hopefully we’ll get there.
430
Among unsupported constructs are: decorating symbols with so-called accents, such as arrows or hats, “over” or “under” braces, and line breaking inside a formula.
431

432
\font:remove-fallback
433
\end{document}
UNCOV
434
]]
×
435

UNCOV
436
return package
×
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

© 2024 Coveralls, Inc