mtx-modules.lua /size: 7968 b    last modification: 2020-07-01 14:35
1if not modules then modules = { } end modules ['mtx-modules'] = {
2    version   = 1.002,
3    comment   = "companion to mtxrun.lua",
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-- should be an extra
10
11scripts         = scripts         or { }
12scripts.modules = scripts.modules or { }
13
14local helpinfo = [[
15<?xml version="1.0"?>
16<application>
17 <metadata>
18  <entry name="name">mtx-modules</entry>
19  <entry name="detail">ConTeXt Module Documentation Generators</entry>
20  <entry name="version">1.00</entry>
21 </metadata>
22 <flags>
23  <category name="basic">
24   <subcategory>
25    <flag name="convert"><short>convert source files (tex, mkii, mkiv, mp, etc.) to 'ted' files</short></flag>
26    <flag name="process"><short>process source files (tex, mkii, mkiv, mp, etc.) to 'pdf' files</short></flag>
27    <flag name="prep"><short>use original name with suffix 'prep' appended</short></flag>
28    <flag name="direct"><short>use old method instead of extra</short></flag>
29   </subcategory>
30  </category>
31 </flags>
32</application>
33]]
34
35local application = logs.application {
36    name     = "mtx-modules",
37    banner   = "ConTeXt Module Documentation Generators 1.00",
38    helpinfo = helpinfo,
39}
40
41local report = application.report
42
43-- Documentation can be woven into a source file. This script can generates
44-- a file with the documentation and source fragments properly tagged. The
45-- documentation is included as comment:
46--
47-- %D ......  some kind of documentation
48-- %M ......  macros needed for documenation
49-- %S B       begin skipping
50-- %S E       end skipping
51--
52-- The generated file is structured as:
53--
54-- \starttypen
55-- \startmodule[type=suffix]
56-- \startdocumentation
57-- \stopdocumentation
58-- \startdefinition
59-- \stopdefinition
60-- \stopmodule
61-- \stoptypen
62--
63-- Macro definitions specific to the documentation are not surrounded by
64-- start-stop commands. The suffix specification can be overruled at runtime,
65-- but defaults to the file extension. This specification can be used for language
66-- depended verbatim typesetting.
67--
68-- In the mkiv variant we filter the \module settings so that we don't have
69-- to mess with global document settings.
70
71local find, format, sub, is_empty, strip, gsub = string.find, string.format, string.sub, string.is_empty, string.strip, string.gsub
72
73local function source_to_ted(inpname,outname,filetype)
74    local data = io.loaddata(inpname)
75    if not data or data == "" then
76        report("invalid module name '%s'",inpname)
77        return
78    end
79    report("converting '%s' to '%s'",inpname,outname)
80    local skiplevel, indocument, indefinition = 0, false, false
81    local started = false
82    local settings = format("type=%s",filetype or file.suffix(inpname))
83    local preamble, n = lpeg.match(lpeg.Cs((1-lpeg.patterns.newline^2)^1) * lpeg.Cp(),data)
84    if preamble then
85        preamble = string.match(preamble,"\\module.-%[(.-)%]")
86        if preamble then
87            preamble = gsub(preamble,"%%D *","")
88            preamble = gsub(preamble,"%%(.-)[\n\r]","")
89            preamble = gsub(preamble,"[\n\r]","")
90            preamble = strip(preamble)
91            settings = format("%s,%s",settings,preamble)
92            data = string.sub(data,n,#data)
93        end
94    end
95    local lines = string.splitlines(data)
96    local result = { }
97    result[#result+1] = format("\\startmoduledocumentation[%s]",settings)
98    for i=1,#lines do
99        local line = lines[i]
100        if find(line,"^%%D ") or find(line,"^%%D$") then
101            if skiplevel == 0 then
102                local someline = #line < 3 and "" or sub(line,4,#line)
103                if indocument then
104                    result[#result+1] = someline
105                else
106                    if indefinition then
107                        result[#result+1] = "\\stopdefinition"
108                        indefinition = false
109                    end
110                    if not indocument then
111                        result[#result+1] = "\\startdocumentation"
112                    end
113                    result[#result+1] = someline
114                    indocument = true
115                end
116            end
117        elseif find(line,"^%%M ") or find(line,"^%%M$") then
118            if skiplevel == 0 then
119                local someline = (#line < 3 and "") or sub(line,4,#line)
120                result[#result+1] = someline
121            end
122        elseif find(line,"^%%S B") then
123            skiplevel = skiplevel + 1
124        elseif find(line,"^%%S E") then
125            skiplevel = skiplevel - 1
126        elseif find(line,"^%%") then
127            -- nothing
128        elseif skiplevel == 0 then
129            inlocaldocument = indocument
130            inlocaldocument = false
131            local someline = line
132            if indocument then
133                result[#result+1] = "\\stopdocumentation"
134                indocument = false
135            end
136            if indefinition then
137                if is_empty(someline) then
138                    result[#result+1] = "\\stopdefinition"
139                    indefinition = false
140                else
141                    result[#result+1] = someline
142                end
143            elseif not is_empty(someline) then
144                result[#result+1] = "\n"
145                result[#result+1] = "\\startdefinition"
146                indefinition = true
147                if inlocaldocument then
148                    -- nothing
149                else
150                    result[#result+1] = someline
151                end
152            end
153        end
154    end
155    if indocument then
156        result[#result+1] = "\\stopdocumentation"
157    end
158    if indefinition then
159        result[#result+1] = "\\stopdefinition"
160    end
161    result[#result+1] = "\\stopmoduledocumentation"
162    io.savedata(outname,table.concat(result,"\n"))
163    return true
164end
165
166local suffixes = table.tohash {
167    "tex",
168    "mkii",
169    "mkiv", "mkvi", "mkil", "mkli",
170    "mp", "mpii", "mpiv",
171}
172
173function scripts.modules.process(runtex)
174    local processed = { }
175    local files     = environment.files
176    if environment.arguments.direct then
177        local prep = environment.argument("prep")
178        for i=1,#files do
179            local shortname = files[i]
180            local suffix    = file.suffix(shortname)
181            if suffixes[suffix] then
182                local longname
183                if prep then
184                    longname = shortname .. ".prep"
185                else
186                    longname = file.removesuffix(shortname) .. "-" .. suffix .. ".ted"
187                end
188                local done = source_to_ted(shortname,longname)
189                if done and runtex then
190                    local command = format("mtxrun --script context --usemodule=module-basic --purge %s",longname)
191                    report()
192                    report("running: %s",command)
193                    report()
194                    os.execute(command)
195                    processed[#processed+1] = longname
196                end
197            end
198        end
199    else
200        for i=1,#files do
201            local name    = files[i]
202            local only    = file.nameonly(name)
203            local command = format("mtxrun --script context --extra=module --result=%s %s",only,name)
204            report()
205            report("running: %s",command)
206            report()
207            os.execute(command)
208            processed[#processed+1] = command
209        end
210    end
211    if #processed > 0 then
212        report()
213        for i=1,#processed do
214            report("processed: %s",processed[i])
215        end
216    end
217end
218
219--  context --ctx=m-modules.ctx xxx.mkiv
220
221if environment.argument("process") then
222    scripts.modules.process(true)
223elseif environment.argument("convert") then
224    scripts.modules.process(false)
225elseif environment.argument("exporthelp") then
226    application.export(environment.argument("exporthelp"),environment.files[1])
227else
228    application.help()
229end
230