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

sile-typesetter / sile / 9304060604

30 May 2024 02:07PM UTC coverage: 74.124% (-0.6%) from 74.707%
9304060604

push

github

alerque
style: Reformat Lua with stylua

8104 of 11995 new or added lines in 184 files covered. (67.56%)

15 existing lines in 11 files now uncovered.

12444 of 16788 relevant lines covered (74.12%)

7175.1 hits per line

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

96.48
/inputters/sil.lua
1
local base = require("inputters.base")
181✔
2

3
local epnf = require("epnf")
181✔
4

5
local inputter = pl.class(base)
181✔
6
inputter._name = "sil"
181✔
7

8
inputter.order = 50
181✔
9

10
inputter.appropriate = function (round, filename, doc)
11
   if round == 1 then
178✔
12
      return filename:match(".sil$")
175✔
13
   elseif round == 2 then
3✔
14
      local sniff = doc:sub(1, 100)
2✔
15
      local promising = sniff:match("\\begin") or sniff:match("\\document") or sniff:match("\\sile")
2✔
16
      return promising and inputter.appropriate(3, filename, doc) or false
3✔
17
   elseif round == 3 then
1✔
18
      local _parser = epnf.define(inputter._grammar)
1✔
19
      local status, _ = pcall(epnf.parsestring, _parser, doc)
1✔
20
      return status
1✔
21
   end
22
end
23

24
local bits = SILE.parserBits
181✔
25

26
inputter.passthroughCommands = {
181✔
27
   ftl = true,
28
   lua = true,
29
   math = true,
30
   raw = true,
31
   script = true,
32
   sil = true,
33
   use = true,
34
   xml = true,
35
}
181✔
36

37
function inputter:_init ()
181✔
38
   -- Save time when parsing strings by only setting up the grammar once per
39
   -- instantiation then re-using it on every use.
40
   self._parser = self:rebuildParser()
348✔
41
   base._init(self)
174✔
42
end
43

44
-- luacheck: push ignore
45
-- stylua: ignore start
46
---@diagnostic disable: undefined-global, unused-local, lowercase-global
47
function inputter._grammar (_ENV)
181✔
48
   local isPassthrough = function (_, _, command)
49
      return inputter.passthroughCommands[command] or false
4,031✔
50
   end
51
   local isNotPassthrough = function (...)
52
      return not isPassthrough(...)
3,958✔
53
   end
54
   local isMatchingEndEnv = function (a, b, thisCommand, lastCommand)
55
      return thisCommand == lastCommand
292✔
56
   end
57
   local _ = WS^0
175✔
58
   local eol = S"\r\n"
175✔
59
   local specials = S"{}%\\"
175✔
60
   local escaped_specials = P"\\" * specials
175✔
61
   local unescapeSpecials = function (str)
62
      return str:gsub('\\([{}%%\\])', '%1')
1,798✔
63
   end
64
   local myID = C(bits.silidentifier) / 1
175✔
65
   local cmdID = myID - P"beign" - P"end"
175✔
66
   local wrapper = function (a) return type(a)=="table" and a or {} end
1,847✔
67
   local parameters = (P"[" * bits.parameters * P"]")^-1 / wrapper
175✔
68
   local comment = (
69
         P"%" *
175✔
70
         P(1-eol)^0 *
175✔
71
         eol^-1
175✔
72
      ) / ""
175✔
73

74
   START "document"
175✔
75
   document = V"texlike_stuff" * EOF"Unexpected character at end of input"
350✔
76
   texlike_stuff = Cg(
350✔
77
         V"environment" +
175✔
78
         comment +
175✔
79
         V"texlike_text" +
175✔
80
         V"texlike_braced_stuff" +
175✔
81
         V"texlike_command"
175✔
82
      )^0
175✔
83
   passthrough_stuff = C(Cg(
525✔
84
         V"passthrough_text" +
175✔
85
         V"passthrough_debraced_stuff"
175✔
86
      )^0)
350✔
87
   passthrough_env_stuff = Cg(
350✔
88
         V"passthrough_env_text"
175✔
89
      )^0
175✔
90
   texlike_text = C((1 - specials + escaped_specials)^1) / unescapeSpecials
175✔
91
   passthrough_text = C((1-S("{}"))^1)
175✔
92
   passthrough_env_text = C((1 - (P"\\end{" * Cmt(cmdID * Cb"command", isMatchingEndEnv) * P"}"))^1)
175✔
93
   texlike_braced_stuff = P"{" * V"texlike_stuff" * ( P"}" + E("} expected") )
350✔
94
   passthrough_braced_stuff = P"{" * V"passthrough_stuff" * ( P"}" + E("} expected") )
350✔
95
   passthrough_debraced_stuff = C(V"passthrough_braced_stuff")
175✔
96
   texlike_command = (
×
97
         P"\\" *
175✔
98
         Cg(cmdID, "command") *
175✔
99
         Cg(parameters, "options") *
175✔
100
         (
×
101
         (Cmt(Cb"command", isPassthrough) * V"passthrough_braced_stuff") +
175✔
102
         (Cmt(Cb"command", isNotPassthrough) * V"texlike_braced_stuff")
175✔
103
         )^0
175✔
104
      )
175✔
105
   local notpass_end =
106
         P"\\end{" *
175✔
107
         ( Cmt(cmdID * Cb"command", isMatchingEndEnv) + E"Environment mismatch") *
350✔
108
         ( P"}" * _ ) + E"Environment begun but never ended"
350✔
109
   local pass_end =
110
         P"\\end{" *
175✔
111
         ( cmdID * Cb"command" ) *
175✔
112
         ( P"}" * _ ) + E"Environment begun but never ended"
350✔
113
   environment =
×
114
      P"\\begin" *
175✔
115
      Cg(parameters, "options") *
175✔
116
      P"{" *
175✔
117
      Cg(cmdID, "command") *
175✔
118
      P"}" *
175✔
119
      (
×
120
         (Cmt(Cb"command", isPassthrough) * V"passthrough_env_stuff" * pass_end) +
175✔
121
         (Cmt(Cb"command", isNotPassthrough) * V"texlike_stuff" * notpass_end)
175✔
122
      )
175✔
123
end
124
-- luacheck: pop
125
-- stylua: ignore end
126
---@diagnostic enable: undefined-global, unused-local, lowercase-global
127

128
local linecache = {}
181✔
129
local lno, col, lastpos
130
local function resetCache ()
131
   lno = 1
174✔
132
   col = 1
174✔
133
   lastpos = 0
174✔
134
   linecache = { { lno = 1, pos = 1 } }
174✔
135
end
136

137
local function getline (str, pos)
138
   local start = 1
6,840✔
139
   lno = 1
6,840✔
140
   if pos > lastpos then
6,840✔
141
      lno = linecache[#linecache].lno
4,508✔
142
      start = linecache[#linecache].pos + 1
4,508✔
143
      col = 1
4,508✔
144
   else
145
      for j = 1, #linecache - 1 do
30,885✔
146
         if linecache[j + 1].pos >= pos then
30,885✔
147
            lno = linecache[j].lno
2,332✔
148
            col = pos - linecache[j].pos
2,332✔
149
            return lno, col
2,332✔
150
         end
151
      end
152
   end
153
   for i = start, pos do
128,380✔
154
      if string.sub(str, i, i) == "\n" then
247,744✔
155
         lno = lno + 1
2,440✔
156
         col = 1
2,440✔
157
         linecache[#linecache + 1] = { pos = i, lno = lno }
2,440✔
158
         lastpos = i
2,440✔
159
      end
160
      col = col + 1
123,872✔
161
   end
162
   return lno, col
4,508✔
163
end
164

165
local function massage_ast (tree, doc)
166
   -- Sort out pos
167
   if type(tree) == "string" then
9,420✔
168
      return tree
2,580✔
169
   end
170
   if tree.pos then
6,840✔
171
      tree.lno, tree.col = getline(doc, tree.pos)
13,680✔
172
   end
173
   if
174
      tree.id == "document"
6,840✔
175
      or tree.id == "texlike_braced_stuff"
6,840✔
176
      or tree.id == "passthrough_stuff"
6,491✔
177
      or tree.id == "passthrough_braced_stuff"
6,452✔
178
      or tree.id == "passthrough_env_stuff"
6,413✔
179
   then
180
      return massage_ast(tree[1], doc)
461✔
181
   end
182
   if tree.id == "texlike_text" or tree.id == "passthrough_text" or tree.id == "passthrough_env_text" then
6,379✔
183
      return tree[1]
1,831✔
184
   end
185
   for key, val in ipairs(tree) do
13,333✔
186
      if val.id == "texlike_stuff" then
8,785✔
187
         SU.splice(tree, key, key, massage_ast(val, doc))
1,698✔
188
      else
189
         tree[key] = massage_ast(val, doc)
16,438✔
190
      end
191
   end
192
   return tree
4,548✔
193
end
194

195
function inputter:rebuildParser ()
181✔
196
   return epnf.define(self._grammar)
174✔
197
end
198

199
function inputter:parse (doc)
181✔
200
   local parsed = epnf.parsestring(self._parser, doc)[1]
348✔
201
   if not parsed then
174✔
NEW
202
      return SU.error("Unable to parse input document to an AST tree")
×
203
   end
204
   resetCache()
174✔
205
   local top = massage_ast(parsed, doc)
174✔
206
   local tree
207
   -- Content not part of a tagged command could either be part of a document
208
   -- fragment or junk (e.g. comments, whitespace) outside of a document tag. We
209
   -- need to either capture the document tag only or decide this is a fragment
210
   -- and wrap it in a document tag.
211
   for _, leaf in ipairs(top) do
181✔
212
      if leaf.command and (leaf.command == "document" or leaf.command == "sile") then
180✔
213
         tree = leaf
173✔
214
         break
173✔
215
      end
216
   end
217
   -- In the event we didn't isolate a top level document tag above, assume this
218
   -- is a fragment and wrap it in one.
219
   if not tree then
174✔
220
      tree = { top, command = "document" }
1✔
221
   end
222
   return { tree }
174✔
223
end
224

225
return inputter
181✔
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

© 2026 Coveralls, Inc