typo-cln.lua /size: 3242 b    last modification: 2020-07-01 14:35
1if not modules then modules = { } end modules ['typo-cln'] = {
2    version   = 1.001,
3    comment   = "companion to typo-cln.mkiv",
4    author    = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
5    copyright = "PRAGMA ADE / ConTeXt Development Team",
6    license   = "see context related readme files"
7}
8
9-- This quick and dirty hack took less time than listening to a CD (In
10-- this case Dream Theaters' Octavium). Of course extensions will take
11-- more time.
12
13local tonumber = tonumber
14local utfbyte = utf.byte
15
16local trace_cleaners = false  trackers.register("typesetters.cleaners",         function(v) trace_cleaners = v end)
17local trace_autocase = false  trackers.register("typesetters.cleaners.autocase",function(v) trace_autocase = v end)
18
19local report_cleaners = logs.reporter("nodes","cleaners")
20local report_autocase = logs.reporter("nodes","autocase")
21
22typesetters.cleaners  = typesetters.cleaners or { }
23local cleaners        = typesetters.cleaners
24
25local variables       = interfaces.variables
26
27local nodecodes       = nodes.nodecodes
28
29local enableaction    = nodes.tasks.enableaction
30
31local texsetattribute = tex.setattribute
32
33local nuts            = nodes.nuts
34
35local getattr         = nuts.getattr
36local setattr         = nuts.setattr
37
38local setchar         = nuts.setchar
39
40local nextglyph       = nuts.traversers.glyph
41
42local unsetvalue      = attributes.unsetvalue
43
44local glyph_code      = nodecodes.glyph
45local uccodes         = characters.uccodes
46
47local a_cleaner       = attributes.private("cleaner")
48
49local resetter = { -- this will become an entry in char-def
50    [utfbyte(".")] = true
51}
52
53-- Contrary to the casing code we need to keep track of a state.
54-- We could extend the casing code with a status tracker but on
55-- the other hand we might want to apply casing afterwards. So,
56-- cleaning comes first.
57
58function cleaners.handler(head)
59    local inline = false
60    for n, char, font in nextglyph, head do
61        if resetter[char] then
62            inline = false
63        elseif not inline then
64            local a = getattr(n,a_cleaner)
65            if a == 1 then -- currently only one cleaner so no need to be fancy
66                local upper = uccodes[char]
67                if type(upper) == "table" then
68                    -- some day, not much change that \SS ends up here
69                else
70                    setchar(n,upper)
71                    if trace_autocase then
72                        report_autocase("")
73                    end
74                end
75            end
76            inline = true
77        end
78    end
79    return head
80end
81
82-- see typo-cap for a more advanced settings handler .. not needed now
83
84local enabled = false
85
86function cleaners.set(n)
87    if n == variables.reset or not tonumber(n) or n == 0 then
88        texsetattribute(a_cleaner,unsetvalue)
89    else
90        if not enabled then
91            enableaction("processors","typesetters.cleaners.handler")
92            if trace_cleaners then
93                report_cleaners("enabling cleaners")
94            end
95            enabled = true
96        end
97        texsetattribute(a_cleaner,tonumber(n))
98    end
99end
100
101-- interface
102
103interfaces.implement {
104    name      = "setcharactercleaning",
105    actions   = cleaners.set,
106    arguments = "string"
107}
108