utils.lua (2753B)
1 local path = require "path" 2 3 function die(err, msg) 4 msg = tostring(msg or err) 5 if err then 6 io.stderr:write(msg .. "\n") 7 os.exit(1) 8 end 9 end 10 11 function yn(prompt) 12 local meaning = { 13 Y = true, 14 y = true, 15 yes = true, 16 Yes = true, 17 n = false, 18 N = false, 19 No = false, 20 no = false 21 } 22 local ans 23 while meaning[ans] == nil do 24 io.write(prompt) 25 io.flush() -- For some reason, prompt doesn't show up without this 26 ans = io.read() 27 end 28 return meaning[ans] 29 end 30 31 function decodewith(decoder, fn) 32 die(not path.exists(fn), fn.." does not exist.") 33 die(not path.isfile(fn), fn.." is not a file.") 34 local f, err = io.open(fn, "r") 35 die(err) 36 status, res = xpcall(decoder, die, f:read("a")) 37 f:close() 38 die(not status, res) 39 return res 40 end 41 42 function encodewith(encoder, fn, data) 43 local f, err = io.open(fn, "w") 44 die(not status, err) 45 status, err = f:write(encoder(data)) 46 die(not status, err) 47 end 48 49 function format(fmt, dict, sett) 50 -- A identifier is 51 -- > any string of Latin letters, Arabic-Indic digits, and 52 -- > underscores, not beginning with a digit and not being a reserved 53 -- > word 54 res = fmt 55 for s in string.gmatch(fmt, "%{([_a-zA-Z][._a-zA-Z0-9]*)%}") do 56 local value = dict 57 local pref = sett 58 for k in string.gmatch(s, "([_a-zA-Z][_a-zA-Z0-9]*)") do 59 if type(value) == "table" then value = value[k] end 60 if type(pref) == "table" then pref = pref[k] end 61 end 62 if pref and value then string.format(pref, value) end 63 res = fmt.gsub(res, "{"..s.."}", value or "nil") 64 end 65 return res 66 end 67 68 function m4flags(d) 69 flags = "" 70 for k, v in pairs(d) do 71 flags = flags .. string.format(" -D %s='%s'", k, v) 72 end 73 return flags 74 end 75 76 function table.query(t, q) 77 for _,i in ipairs(t) do 78 if q(i) then 79 return i 80 end 81 end 82 return nil 83 end 84 85 function table.filter(t, q) 86 local res = {} 87 for _,i in ipairs(t) do 88 if q(i) then 89 table.insert(res, i) 90 end 91 end 92 return res 93 end 94 95 function format_event(e) 96 local formats = { 97 deactivation = "Deactivated {who}", 98 deregister = "Deregistered {who}", 99 monthly = "Monthly report", 100 readdress = "Changed {who}'s address", 101 register = "Registered {who}", 102 rename = "Changed {whither}'s name from '{who}'", 103 weekly = "Weekly report", 104 activation = "Activated {who}", 105 writ = "Writ of FAGE for {who}" 106 } 107 die(not formats[e.what], string.format("No format for '%s'", e.what)) 108 return string.format("* %s %s\n", 109 os.date("%Y-%m-%d %H:%M %z", e.when), 110 format(formats[e.what], e) 111 ) 112 end 113 114 function ord(num) 115 if (num == 1) then 116 return "st" 117 elseif (num == 2) then 118 return "nd" 119 elseif (num == 3) then 120 return "rd" 121 else 122 return "th" 123 end 124 end 125 126 function jsonformat(fn) 127 os.execute(string.format('jq --sort-keys . %s > .tmp', fn)) 128 os.execute(string.format('mv .tmp %s', fn)) 129 end