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 local helpinfo = [[ mtx-tools Some File Related Goodies 1.01 remove utf bomb if present remove indeed glob directory into xml glob pattern (default: *) url attribute (no processing) the root of the globbed path (default: .) output filename (console by default) recurse into subdirecories take pathpart of given pattern set name attributes to full path name lowercase names show unicode characters in given string show unicode characters in given file glob pattern (default: *) recurse into subdirecories downcase indeed ]] local application = logs.application { name = "mtx-tools", banner = "Some File Related Goodies 1.01", helpinfo = helpinfo, } local report = application.report local writeln = (logs and logs.writer) or (texio and texio.write_nl) or print 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 report("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 report("file '%s' has a 3 character utf bomb",name) if force then io.savedata(name,(gsub(data,bomb_2,""))) end done = true else -- report("file '%s' has no utf bomb",name) end end end if done and not force then report("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 local low = lower(name) if n == 1 then report() end report("%a renamed to %a",name,low) if force then os.rename(name,low) end end end) if n > 0 then report() if force then report("%s files renamed",n) else report("use --force to do a real rename (%s files involved)",n) end else report("nothing to do") end end function scripts.tools.dirtoxml() local join, removesuffix, suffixonly, date = file.join, file.removesuffix, file.suffixonly, 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') or false 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",d,(longname and path and join(path,name)) or name) result[#result+1] = format("%s %s",d,removesuffix(name)) result[#result+1] = format("%s %s",d,suffixonly(name)) result[#result+1] = format("%s %s",d,attr.size) result[#result+1] = format("%s %s",d,sub(attr.permissions,7,9)) result[#result+1] = format("%s %s",d,date(timestamp,attr.modification)) result[#result+1] = format("%s",d) elseif mode == "directory" then result[#result+1] = format("%s",d,name) flush(attr.list,result,n+1,(path and join(path,name)) or name) result[#result+1] = format("%s",d) end end end if not pattern or pattern == "" then 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.collectpattern(root,luapattern,recurse) if list[outputfile] then list[outputfile] = nil end local result = { "" } result[#result+1] = format("",url,root,pattern,luapattern,xmlns,date(timestamp)) flush(list,result) result[#result+1] = "" result = table.concat(result,"\n") if not outputfile or outputfile == "" then writeln(result) else io.savedata(outputfile,result) end end local function showstring(s) if not characters or not characters.data then require("char-def") end local d = characters.data local f = string.formatters["%U %s %-30s %c"] for c in string.utfvalues(s) do local cs = d[c] print(f(c,cs.category or "",cs.description or "",c)) end end function scripts.tools.showstring() local files = environment.files for i=1,#files do showstring(files[i]) end end function scripts.tools.showfile() local files = environment.files for i=1,#files do showstring(io.loaddata(files[i]) or "") end end if environment.argument("disarmutfbomb") then scripts.tools.disarmutfbomb() elseif environment.argument("dirtoxml") then scripts.tools.dirtoxml() elseif environment.argument("downcase") then scripts.tools.downcase() elseif environment.argument("exporthelp") then application.export(environment.argument("exporthelp"),environment.files[1]) elseif environment.argument("showstring") then scripts.tools.showstring() elseif environment.argument("showfile") then scripts.tools.showfile() else application.help() end