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

sile-typesetter / sile / 6941442205

21 Nov 2023 08:56AM UTC coverage: 63.58% (+1.3%) from 62.266%
6941442205

Pull #1904

github

web-flow
Merge pull request #1891 from sile-typesetter/ot-tate
Pull Request #1904: Merge develop into master (commit to next release being breaking)

67 of 198 new or added lines in 20 files covered. (33.84%)

171 existing lines in 13 files now uncovered.

9907 of 15582 relevant lines covered (63.58%)

6710.82 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()
345✔
6

7
function settings:_init()
345✔
8

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

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

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

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

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

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

49
  self:declare({
345✔
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({
345✔
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({
345✔
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({
345✔
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)
690✔
78
    local parameter = SU.required(options, "parameter", "\\set command")
109✔
79
    local makedefault = SU.boolean(options.makedefault, false)
109✔
80
    local reset = SU.boolean(options.reset, false)
109✔
81
    local value = options.value
109✔
82
    if content and (type(content) == "function" or content[1]) then
109✔
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)
101✔
92
    end
93
  end, "Set a SILE parameter <parameter> to value <value> (restoring the value afterwards if <content> is provided)", nil, true)
454✔
94

95
end
96

97
function settings:pushState ()
345✔
98
  if not self then return deprecator() end
1,674✔
99
  table.insert(self.stateQueue, self.state)
1,674✔
100
  self.state = pl.tablex.copy(self.state)
3,348✔
101
end
102

103
function settings:popState ()
345✔
104
  if not self then return deprecator() end
1,678✔
105
  self.state = table.remove(self.stateQueue)
3,356✔
106
end
107

108
function settings:declare (spec)
345✔
109
  if not spec then return deprecator() end
17,123✔
110
  if spec.name then
17,123✔
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
17,123✔
114
    SU.debug("settings", "Attempt to re-declare setting: " .. spec.parameter)
1,350✔
115
    return
1,350✔
116
  end
117
  self.declarations[spec.parameter] = spec
15,773✔
118
  self:set(spec.parameter, spec.default, true)
15,773✔
119
end
120

121
--- Reset all settings to their default value.
122
function settings:reset ()
345✔
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 ()
345✔
133
  if not self then return deprecator() end
133✔
134
  if #self.stateQueue ~= 0 then
133✔
135
    for parameter, _ in pairs(self.state) do
6,314✔
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]
6,181✔
140
    end
141
  end
142
end
143

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

161
function settings:set (parameter, value, makedefault, reset)
345✔
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
27,464✔
181
    if SILE.typesetter and not SILE.typesetter.state.hmodeOnly then
1,321✔
182
      SILE.typesetter.state.parindent = SU.cast("glue or nil", value)
2,262✔
183
    end
184
    return
1,321✔
185
  end
186
  if type(self) ~= "table" then return deprecator() end
26,143✔
187
  if not self.declarations[parameter] then
26,143✔
188
    SU.error("Undefined setting '"..parameter.."'")
×
189
  end
190
  if reset then
26,143✔
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)
52,278✔
197
  end
198
  self.state[parameter] = value
26,143✔
199
  if makedefault then
26,143✔
200
    self.defaults[parameter] = value
15,627✔
201
  end
202
end
203

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

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

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