summaryrefslogtreecommitdiff
path: root/tex/context/base/trac-lmx.lua
blob: a39e3fe4ece26eb35958abb56cfc84d1727bcac2 (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
if not modules then modules = { } end modules ['trac-lmx'] = {
    version   = 1.001,
    comment   = "companion to trac-lmx.mkiv",
    author    = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
    copyright = "PRAGMA ADE / ConTeXt Development Team",
    license   = "see context related readme files"
}

local gsub, format, concat = string.gsub, string.format, table.concat

-- we can now use l-xml, and we can also use lpeg

lmx = lmx or { }

lmx.escapes = {
    ['&'] = '&',
    ['<'] = '&lt;',
    ['>'] = '&gt;',
    ['"'] = '&quot;'
}

-- local function p -> ends up in lmx.p, so we need to cast

lmx.variables = { }

lmx.variables['title-default'] = 'LMX File'
lmx.variables['title']         = lmx.variables['title-default']

-- demonstrates: local, *all, gsub using tables, nil or value, loadstring

function lmx.loadedfile(filename)
    return io.loaddata(resolvers.find_file(filename))
end

lmx.converting = false

local templates = { }

function lmx.convert(template,result) -- todo: use lpeg instead
    if not lmx.converting then -- else, if error then again tex error and loop
        local data = templates[template]
        if not data then
            data = lmx.loadedfile(template)
            templates[template] = data
        end
        local text = { }
        function lmx.print(...)
            text[#text+1] = concat({...})
        end
        function lmx.variable(str)
            return lmx.variables[str] or ""
        end
        function lmx.escape(str)
            str = tostring(str)
            str = gsub(str,'&','&amp;')
            str = gsub(str,'[<>"]',lmx.escapes)
            return str
        end
        function lmx.type(str)
            if str then lmx.print("<tt>" .. lmx.escape(str) .. "</tt>") end
        end
        function lmx.pv(str)
            lmx.print(lmx.variable(str))
        end
        function lmx.tv(str)
            lmx.type(lmx.variable(str))
        end
        data = gsub(data,"<%?lmx%-include%s+(.-)%s-%?>", function(filename)
            return lmx.loadedfile(filename)
        end)
        local definitions =  { }
        data = gsub(data,"<%?lmx%-define%-begin%s+(%S-)%s-%?>(.-)<%?lmx%-define%-end%s-%?>", function(tag,content)
            definitions[tag] = content
            return ""
        end)
        data = gsub(data,"<%?lmx%-resolve%s+(%S-)%s-%?>", function(tag)
            return definitions[tag] or ""
        end)
        data = gsub(data,"%c%s-(<%?lua .-%?>)%s-%c", function(lua)
            return "\n" .. lua .. " "
        end)
        data = gsub(data .. "<?lua ?>","(.-)<%?lua%s+(.-)%?>", function(txt, lua)
            txt = gsub(txt,"%c+", "\\n")
            txt = gsub(txt,'"'  , '\\"')
            txt = gsub(txt,"'"  , "\\'")
         -- txt = gsub(txt,"([\'\"])", { ["'"] = '\\"', ['"'] = "\\'" } )
            return "p(\"" .. txt .. "\")\n" .. lua .. "\n"
        end)
        lmx.converting = true
        data = "local p,v,e,t,pv,tv = lmx.print,lmx.variable,lmx.escape,lmx.type,lmx.pv,lmx.tv " .. data
        assert(loadstring(data))()
        lmx.converting = false
        text = concat(text)
        if result then
            io.savedata(result,text)
        else
            return text
        end
    end
end

-- these can be overloaded; we assume that the os handles filename associations

lmx.lmxfile = function(filename) return filename end
lmx.htmfile = function(filename) return filename end

if os.platform == "windows" then
    lmx.popupfile = function(filename) os.execute("start " .. filename) end
else
    lmx.popupfile = function(filename) os.execute(filename) end
end

function lmx.make(name)
    local lmxfile = lmx.lmxfile(name)
    local htmfile = lmx.htmfile(name)
    if lmxfile == htmfile then
        htmfile = gsub(lmxfile, "%.%a+$", "html")
    end
    lmx.convert(lmxfile, htmfile)
    return htmfile
end

function lmx.show(name)
    local htmfile = lmx.make(name)
    lmx.popupfile(htmfile)
    return htmfile
end

-- kind of private

lmx.restorables = { }

function lmx.set(key, value)
    if not lmx.restorables[key] then
        table.insert(lmx.restorables, key)
        lmx.variables['@@' .. key] = lmx.variables[key]
    end
    lmx.variables[key] = value
end

function lmx.get(key)
    return lmx.variables[key] or ""
end

function lmx.restore()
    for _,key in pairs(lmx.restorables) do
        lmx.variables[key] = lmx.variables['@@' .. key]
    end
    lmx.restorables = { }
end

-- command line

if arg then
    if     arg[1] == "--show"    then if arg[2] then lmx.show   (arg[2])                        end
    elseif arg[1] == "--convert" then if arg[2] then lmx.convert(arg[2], arg[3] or "temp.html") end
    end
end