summaryrefslogtreecommitdiff
path: root/scripts/context/lua/mtx-modules.lua
blob: 696e4767f3dde0dc415bde6b13fb05a061cb4958 (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
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 { }

-- 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.

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

local function source_to_ted(inpname,outname,filetype)
    local inp = io.open(inpname)
    if not inp then
        logs.simple("unable to open '%s'",inpname)
        return
    end
    local out = io.open(outname,"w")
    if not out then
        logs.simple("unable to open '%s'",outname)
        return
    end
    logs.simple("converting '%s' to '%s'",inpname,outname)
    local skiplevel, indocument, indefinition = 0, false, false
    out:write(format("\\startmodule[type=%s]\n",filetype or file.suffix(inpname)))
    for line in inp:lines() do
--~         line = strip(line)
        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
                    out:write(format("%s\n",someline))
                else
                    if indefinition then
                        out:write("\\stopdefinition\n")
                        indefinition = false
                    end
                    if not indocument then
                        out:write("\n\\startdocumentation\n")
                    end
                    out:write(format("%s\n",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)
                out:write(format("%s\n",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
                out:write("\\stopdocumentation\n")
                indocument = false
            end
            if indefinition then
                if is_empty(someline) then
                    out:write("\\stopdefinition\n")
                    indefinition = false
                else
                    out:write(format("%s\n",someline))
                end
            elseif not is_empty(someline) then
                out:write("\n\\startdefinition\n")
                indefinition = true
                if inlocaldocument then
                    -- nothing
                else
                    out:write(format("%s\n",someline))
                end
            end
        end
    end
    if indocument then
        out:write("\\stopdocumentation\n")
    end
    if indefinition then
        out:write("\\stopdefinition\n")
    end
    out:write("\\stopmodule\n")
    out:close()
    inp:close()
    return true
end

local suffixes = table.tohash { 'tex','mkii','mkiv','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 %s",longname))
                processed[#processed+1] = longname
            end
        end
    end
    for i=1,#processed do
        local name = processed[i]
        logs.simple("modules","processed: %s",name)
    end
end

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


logs.extendbanner("ConTeXt Module Documentation Generators 1.00")

messages.help = [[
--convert             convert source files (tex, mkii, mkiv, mp) to 'ted' files
--process             process source files (tex, mkii, mkiv, mp) to 'pdf' files
--prep                use original name with suffix 'prep' appended
]]

if environment.argument("process") then
    scripts.modules.process(true)
elseif environment.argument("convert") then
    scripts.modules.process(false)
else
    logs.help(messages.help)
end