summaryrefslogtreecommitdiff
path: root/Master/texmf-dist/scripts/context/lua/mtx-modules.lua
blob: f4003c1db12b2249e51f728a3620fc3d870378f5 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
if not modules then modules = { } end modules ['mtx-modules'] = {
    version   = 1.002,
    comment   = "companion to mtxrun.lua",
    author    = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
    copyright = "PRAGMA ADE / ConTeXt Development Team",
    license   = "see context related readme files"
}

scripts         = scripts         or { }
scripts.modules = scripts.modules or { }

local helpinfo = [[
<?xml version="1.0"?>
<application>
 <metadata>
  <entry name="name">mtx-modules</entry>
  <entry name="detail">ConTeXt Module Documentation Generators</entry>
  <entry name="version">1.00</entry>
 </metadata>
 <flags>
  <category name="basic">
   <subcategory>
    <flag name="convert"><short>convert source files (tex, mkii, mkiv, mp) to 'ted' files</short></flag>
    <flag name="process"><short>process source files (tex, mkii, mkiv, mp) to 'pdf' files</short></flag>
    <flag name="prep"><short>use original name with suffix 'prep' appended</short></flag>
   </subcategory>
  </category>
 </flags>
</application>
]]

local application = logs.application {
    name     = "mtx-modules",
    banner   = "ConTeXt Module Documentation Generators 1.00",
    helpinfo = helpinfo,
}

local report = application.report

-- Documentation can be woven into a source file. This script can generates
-- a file with the documentation and source fragments properly tagged. The
-- documentation is included as comment:
--
-- %D ......  some kind of documentation
-- %M ......  macros needed for documenation
-- %S B       begin skipping
-- %S E       end skipping
--
-- The generated file is structured as:
--
-- \starttypen
-- \startmodule[type=suffix]
-- \startdocumentation
-- \stopdocumentation
-- \startdefinition
-- \stopdefinition
-- \stopmodule
-- \stoptypen
--
-- Macro definitions specific to the documentation are not surrounded by
-- start-stop commands. The suffix specificaction can be overruled at runtime,
-- but defaults to the file extension. This specification can be used for language
-- depended verbatim typesetting.
--
-- In the mkiv variant we filter the \module settings so that we don't have
-- to mess with global document settings.

local find, format, sub, is_empty, strip, gsub = string.find, string.format, string.sub, string.is_empty, string.strip, string.gsub

local function source_to_ted(inpname,outname,filetype)
    local data = io.loaddata(inpname)
    if not data or data == "" then
        report("invalid module name '%s'",inpname)
        return
    end
    report("converting '%s' to '%s'",inpname,outname)
    local skiplevel, indocument, indefinition = 0, false, false
    local started = false
    local settings = format("type=%s",filetype or file.suffix(inpname))
    local preamble, n = lpeg.match(lpeg.Cs((1-lpeg.patterns.newline^2)^1) * lpeg.Cp(),data)
    if preamble then
        preamble = string.match(preamble,"\\module.-%[(.-)%]")
        if preamble then
            preamble = gsub(preamble,"%%D *","")
            preamble = gsub(preamble,"%%(.-)[\n\r]","")
            preamble = gsub(preamble,"[\n\r]","")
            preamble = strip(preamble)
            settings = format("%s,%s",settings,preamble)
            data = string.sub(data,n,#data)
        end
    end
    local lines = string.splitlines(data)
    local result = { }
    result[#result+1] = format("\\startmoduledocumentation[%s]",settings)
    for i=1,#lines do
        local line = lines[i]
        if find(line,"^%%D ") or find(line,"^%%D$") then
            if skiplevel == 0 then
                local someline = #line < 3 and "" or sub(line,4,#line)
                if indocument then
                    result[#result+1] = someline
                else
                    if indefinition then
                        result[#result+1] = "\\stopdefinition"
                        indefinition = false
                    end
                    if not indocument then
                        result[#result+1] = "\\startdocumentation"
                    end
                    result[#result+1] = someline
                    indocument = true
                end
            end
        elseif find(line,"^%%M ") or find(line,"^%%M$") then
            if skiplevel == 0 then
                local someline = (#line < 3 and "") or sub(line,4,#line)
                result[#result+1] = someline
            end
        elseif find(line,"^%%S B") then
            skiplevel = skiplevel + 1
        elseif find(line,"^%%S E") then
            skiplevel = skiplevel - 1
        elseif find(line,"^%%") then
            -- nothing
        elseif skiplevel == 0 then
            inlocaldocument = indocument
            inlocaldocument = false
            local someline = line
            if indocument then
                result[#result+1] = "\\stopdocumentation"
                indocument = false
            end
            if indefinition then
                if is_empty(someline) then
                    result[#result+1] = "\\stopdefinition"
                    indefinition = false
                else
                    result[#result+1] = someline
                end
            elseif not is_empty(someline) then
                result[#result+1] = "\n"
                result[#result+1] = "\\startdefinition"
                indefinition = true
                if inlocaldocument then
                    -- nothing
                else
                    result[#result+1] = someline
                end
            end
        end
    end
    if indocument then
        result[#result+1] = "\\stopdocumentation"
    end
    if indefinition then
        result[#result+1] = "\\stopdefinition"
    end
    result[#result+1] = "\\stopmoduledocumentation"
    io.savedata(outname,table.concat(result,"\n"))
    return true
end

local suffixes = table.tohash { 'tex','mkii','mkiv', 'mkvi', 'mp' }

function scripts.modules.process(runtex)
    local processed = { }
    local prep = environment.argument("prep")
    local files = environment.files
    for i=1,#files do
        local shortname = files[i]
        local suffix = file.suffix(shortname)
        if suffixes[suffix] then
            local longname
            if prep then
                longname = shortname .. ".prep"
            else
                longname = file.removesuffix(shortname) .. "-" .. suffix .. ".ted"
            end
            local done = source_to_ted(shortname,longname)
            if done and runtex then
                os.execute(format("mtxrun --script context --usemodule=mod-01 --purge %s",longname))
                processed[#processed+1] = longname
            end
        end
    end
    for i=1,#processed do
        local name = processed[i]
        report("modules","processed: %s",name)
    end
end

--  context --ctx=m-modules.ctx xxx.mkiv

if environment.argument("process") then
    scripts.modules.process(true)
elseif environment.argument("convert") then
    scripts.modules.process(false)
elseif environment.argument("exporthelp") then
    application.export(environment.argument("exporthelp"),environment.files[1])
else
    application.help()
end