summaryrefslogtreecommitdiff
path: root/Master/texmf-dist/scripts/context/lua/mtx-tools.lua
blob: bf4add16840720114709a1d84a9b835c3c869767 (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
if not modules then modules = { } end modules ['mtx-tools'] = {
    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"
}

local find, format, sub, rep, gsub, lower = string.find, string.format, string.sub, string.rep, string.gsub, string.lower

scripts       = scripts       or { }
scripts.tools = scripts.tools or { }

local bomb_1, bomb_2 = "^\254\255", "^\239\187\191"

function scripts.tools.disarmutfbomb()
    local force, done = environment.argument("force"), false
    local files = environment.files
    for i=1,#files do
        local name = files[i]
        if lfs.isfile(name) then
            local data = io.loaddata(name)
            if not data then
                -- just skip
            elseif find(data,bomb_1) then
                logs.simple("file '%s' has a 2 character utf bomb",name)
                if force then
                    io.savedata(name,(gsub(data,bomb_1,"")))
                end
                done = true
            elseif find(data,bomb_2) then
                logs.simple("file '%s' has a 3 character utf bomb",name)
                if force then
                    io.savedata(name,(gsub(data,bomb_2,"")))
                end
                done = true
            else
            --  logs.simple("file '%s' has no utf bomb",name)
            end
        end
    end
    if done and not force then
        logs.simple("use --force to do a real disarming")
    end
end

function scripts.tools.downcase()
    local pattern = environment.argument('pattern') or "*"
    local recurse = environment.argument('recurse')
    local force   = environment.argument('force')
    local n = 0
    if recurse and not find(pattern,"^%*%*%/") then
        pattern = "**/*" .. pattern
    end
    dir.glob(pattern,function(name)
        local basename = file.basename(name)
        if lower(basename) ~= basename then
            n = n + 1
            if force then
                os.rename(name,lower(name))
            end
        end
    end)
    if n > 0 then
        if force then
            logs.simple("%s files renamed",n)
        else
            logs.simple("use --force to do a real rename (%s files involved)",n)
        end
    else
        logs.simple("nothing to do")
    end
end


function scripts.tools.dirtoxml()

    local join, removesuffix, extname, date = file.join, file.removesuffix, file.extname, os.date

    local xmlns      = "http://www.pragma-ade.com/rlg/xmldir.rng"
    local timestamp  = "%Y-%m-%d %H:%M"

    local pattern    = environment.argument('pattern') or ".*"
    local url        = environment.argument('url')     or "no-url"
    local root       = environment.argument('root')    or "."
    local outputfile = environment.argument('output')

    local recurse    = environment.argument('recurse')
    local stripname  = environment.argument('stripname')
    local longname   = environment.argument('longname')

    local function flush(list,result,n,path)
        n, result = n or 1, result or { }
        local d = rep("  ",n)
        for name, attr in table.sortedhash(list) do
            local mode = attr.mode
            if mode == "file" then
                result[#result+1] = format("%s<file name='%s'>",d,(longname and path and join(path,name)) or name)
                result[#result+1] = format("%s  <base>%s</base>",d,removesuffix(name))
                result[#result+1] = format("%s  <type>%s</type>",d,extname(name))
                result[#result+1] = format("%s  <size>%s</size>",d,attr.size)
                result[#result+1] = format("%s  <permissions>%s</permissions>",d,sub(attr.permissions,7,9))
                result[#result+1] = format("%s  <date>%s</date>",d,date(timestamp,attr.modification))
                result[#result+1] = format("%s</file>",d)
            elseif mode == "directory" then
                result[#result+1] = format("%s<directory name='%s'>",d,name)
                flush(attr.list,result,n+1,(path and join(path,name)) or name)
                result[#result+1] = format("%s</directory>",d)
            end
        end
    end

    if not pattern or pattern == ""  then
        logs.report('provide --pattern=')
        return
    end

    if stripname then
        pattern = file.dirname(pattern)
    end

    local luapattern = string.topattern(pattern,true)

    lfs.chdir(root)

    local list = dir.collect_pattern(root,luapattern,recurse)

    if list[outputfile] then
        list[outputfile] = nil
    end

    local result = { "<?xml version='1.0'?>" }
    result[#result+1] = format("<files url=%q root=%q pattern=%q luapattern=%q xmlns='%s' timestamp='%s'>",url,root,pattern,luapattern,xmlns,date(timestamp))
    flush(list,result)
    result[#result+1] = "</files>"

    result = table.concat(result,"\n")

    if not outputfile or outputfile == "" then
        texio.write_nl(result)
    else
        io.savedata(outputfile,result)
    end

end

logs.extendbanner("Some File Related Goodies 1.01",true)

messages.help = [[
--disarmutfbomb       remove utf bomb if present
    --force             remove indeed

--dirtoxml              glob directory into xml
    --pattern           glob pattern (default: *)
    --url               url attribute (no processing)
    --root              the root of the globbed path (default: .)
    --output            output filename (console by default)
    --recurse           recurse into subdirecories
    --stripname         take pathpart of given pattern
    --longname          set name attributes to full path name

--downcase
    --pattern           glob pattern (default: *)
    --recurse           recurse into subdirecories
    --force             downcase indeed
]]

if environment.argument("disarmutfbomb") then
    scripts.tools.disarmutfbomb()
elseif environment.argument("dirtoxml") then
    scripts.tools.dirtoxml()
elseif environment.argument("downcase") then
    scripts.tools.downcase()
else
    logs.help(messages.help)
end