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

sile-typesetter / sile / 6932773445

20 Nov 2023 04:11PM UTC coverage: 60.703% (-1.6%) from 62.266%
6932773445

Pull #1904

github

alerque
feat(utilities): Add Greek alphabetical (non-arithmetic) numbering

Useful in some context such as biblical annotations etc. where greek
characters are used orderly for numbering.
Pull Request #1904: Merge develop into master (commit to next release being breaking)

66 of 193 new or added lines in 19 files covered. (34.2%)

321 existing lines in 26 files now uncovered.

9452 of 15571 relevant lines covered (60.7%)

2104.43 hits per line

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

82.86
/core/settings.lua
1
local deprecator = function ()
2
  SU.deprecated("SILE.settings.*", "SILE.settings:*", "0.13.0", "0.15.0")
×
3
end
4

5
local settings = pl.class()
53✔
6

7
function settings:_init()
53✔
8

9
  self.state = {}
53✔
10
  self.declarations = {}
53✔
11
  self.stateQueue = {}
53✔
12
  self.defaults = {}
53✔
13

14
  self:declare({
53✔
15
    parameter = "document.language",
16
    type = "string",
17
    default = "en",
18
    help = "Locale for localized language support"
×
19
  })
20

21
  self:declare({
106✔
22
    parameter = "document.parindent",
23
    type = "glue",
24
    default = SILE.nodefactory.glue("20pt"),
106✔
25
    help = "Glue at start of paragraph"
×
26
  })
27

28
  self:declare({
106✔
29
    parameter = "document.baselineskip",
30
    type = "vglue",
31
    default = SILE.nodefactory.vglue("1.2em plus 1pt"),
106✔
32
    help = "Leading"
×
33
  })
34

35
  self:declare({
106✔
36
    parameter = "document.lineskip",
37
    type = "vglue",
38
    default = SILE.nodefactory.vglue("1pt"),
106✔
39
    help = "Leading"
×
40
  })
41

42
  self:declare({
106✔
43
    parameter = "document.parskip",
44
    type = "vglue",
45
    default = SILE.nodefactory.vglue("0pt plus 1pt"),
106✔
46
    help = "Leading"
×
47
  })
48

49
  self:declare({
53✔
50
    parameter = "document.spaceskip",
51
    type = "length or nil",
52
    default = nil,
53
    help = "The length of a space (if nil, then measured from the font)"
×
54
  })
55

56
  self:declare({
53✔
57
    parameter = "document.rskip",
58
    type = "glue or nil",
59
    default = nil,
60
    help = "Skip to be added to right side of line"
×
61
  })
62

63
  self:declare({
53✔
64
    parameter = "document.lskip",
65
    type = "glue or nil",
66
    default = nil,
67
    help = "Skip to be added to left side of line"
×
68
  })
69

70
  self:declare({
53✔
71
    parameter = "document.zenkakuchar",
72
    default = "あ",
73
    type = "string",
74
    help = "The character measured to determine the length of a zenkaku width (全角幅)"
×
75
  })
76

77
  SILE.registerCommand("set", function(options, content)
106✔
78
    local parameter = SU.required(options, "parameter", "\\set command")
24✔
79
    local makedefault = SU.boolean(options.makedefault, false)
24✔
80
    local reset = SU.boolean(options.reset, false)
24✔
81
    local value = options.value
24✔
82
    if content and (type(content) == "function" or content[1]) then
24✔
83
      if makedefault then
8✔
84
        SU.warn("Are you sure meant to set default settings *and* pass content to ostensibly apply them to temporarily?")
×
85
      end
86
      self:temporarily(function()
16✔
87
        self:set(parameter, value, makedefault, reset)
8✔
88
        SILE.process(content)
8✔
89
      end)
90
    else
91
      self:set(parameter, value, makedefault, reset)
16✔
92
    end
93
  end, "Set a SILE parameter <parameter> to value <value> (restoring the value afterwards if <content> is provided)", nil, true)
77✔
94

95
end
96

97
function settings:pushState ()
53✔
98
  if not self then return deprecator() end
195✔
99
  table.insert(self.stateQueue, self.state)
195✔
100
  self.state = pl.tablex.copy(self.state)
390✔
101
end
102

103
function settings:popState ()
53✔
104
  if not self then return deprecator() end
196✔
105
  self.state = table.remove(self.stateQueue)
392✔
106
end
107

108
function settings:declare (spec)
53✔
109
  if not spec then return deprecator() end
2,824✔
110
  if spec.name then
2,824✔
111
    SU.deprecated("'name' argument of SILE.settings:declare", "'parameter' argument of SILE.settings:declare", "0.10.10", "0.11.0")
×
112
  end
113
  if self.declarations[spec.parameter] then
2,824✔
114
    SU.debug("settings", "Attempt to re-declare setting: " .. spec.parameter)
340✔
115
    return
340✔
116
  end
117
  self.declarations[spec.parameter] = spec
2,484✔
118
  self:set(spec.parameter, spec.default, true)
2,484✔
119
end
120

121
--- Reset all settings to their default value.
122
function settings:reset ()
53✔
NEW
123
  if not self then return deprecator() end
×
124
  for k,_ in pairs(self.state) do
×
125
    self:set(k, self.defaults[k])
×
126
  end
127
end
128

129
--- Restore all settings to the value they had in the top-level state,
130
-- that is at the head of the settings stack (normally the document
131
-- level).
132
function settings:toplevelState ()
53✔
133
  if not self then return deprecator() end
30✔
134
  if #self.stateQueue ~= 0 then
30✔
135
    for parameter, _ in pairs(self.state) do
1,453✔
136
      -- Bypass self:set() as the latter performs some tests and a cast,
137
      -- but the setting might not have been defined in the top level state
138
      -- (in which case, assume the default value).
139
      self.state[parameter] = self.stateQueue[1][parameter] or self.defaults[parameter]
1,423✔
140
    end
141
  end
142
end
143

144
function settings:get (parameter)
53✔
145
  -- HACK FIXME https://github.com/sile-typesetter/sile/issues/1699
146
  -- See comment on set() below.
147
  if parameter == "current.parindent" then
52,283✔
148
    return SILE.typesetter and SILE.typesetter.state.parindent
177✔
149
  end
150
  if not parameter then return deprecator() end
52,106✔
151
  if not self.declarations[parameter] then
52,106✔
152
    SU.error("Undefined setting '"..parameter.."'")
×
153
  end
154
  if type(self.state[parameter]) ~= "nil" then
52,106✔
155
    return self.state[parameter]
41,511✔
156
  else
157
    return self.defaults[parameter]
10,595✔
158
  end
159
end
160

161
function settings:set (parameter, value, makedefault, reset)
53✔
162
  -- HACK FIXME https://github.com/sile-typesetter/sile/issues/1699
163
  -- Anything dubbed current.xxx should likely NOT be a "setting" (subject
164
  -- to being pushed/popped via temporary stacking) and actually has its
165
  -- own lifecycle (e.g. reset for the next paragraph).
166
  -- These should be rather typesetter states, or something to that extent
167
  -- yet to clarify. Notably, current.parindent falls in that category,
168
  -- BUT probably current.hangAfter and current.hangIndent too.
169
  -- To avoid breaking too much code yet without being sure of the solution,
170
  -- we implement a hack of sorts for current.parindent only.
171
  -- Note moreover that current.parindent is currently probably a bad concept
172
  -- anyway:
173
  --   - It can be nil (= document.parindent applies)
174
  --   - It can be a zero-glue (\noindent, ragged environments, etc.)
175
  --   - It can be a valued glue set to document.parindent
176
  --     (e.g. from \indent, and document.parindent thus applies)
177
  --   - It could be another valued glue (uh, use case to ascertain)
178
  -- What we would _likely_ only need to track is whether document.parindent
179
  -- applies or not on the paragraph just composed afterwards...
180
  if parameter == "current.parindent" then
3,229✔
181
    if SILE.typesetter and not SILE.typesetter.state.hmodeOnly then
265✔
182
      SILE.typesetter.state.parindent = SU.cast("glue or nil", value)
474✔
183
    end
184
    return
265✔
185
  end
186
  if type(self) ~= "table" then return deprecator() end
2,964✔
187
  if not self.declarations[parameter] then
2,964✔
188
    SU.error("Undefined setting '"..parameter.."'")
×
189
  end
190
  if reset then
2,964✔
191
    if makedefault then
4✔
192
      SU.error("Can't set a new default and revert to and old default setting at the same time!")
×
193
    end
194
    value = self.defaults[parameter]
4✔
195
  else
196
    value = SU.cast(self.declarations[parameter].type, value)
5,920✔
197
  end
198
  self.state[parameter] = value
2,964✔
199
  if makedefault then
2,964✔
200
    self.defaults[parameter] = value
2,461✔
201
  end
202
end
203

204
function settings:temporarily (func)
53✔
205
  if not func then return deprecator() end
151✔
206
  self:pushState()
151✔
207
  func()
151✔
208
  self:popState()
151✔
209
end
210

211
function settings:wrap () -- Returns a closure which applies the current state, later
53✔
212
  if not self then return deprecator() end
2✔
213
  local clSettings = pl.tablex.copy(self.state)
2✔
214
  return function(content)
215
    table.insert(self.stateQueue, self.state)
1✔
216
    self.state = clSettings
1✔
217
    SILE.process(content)
1✔
218
    self:popState()
1✔
219
  end
220
end
221

222
return settings
53✔
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