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
|