Overview
Comment: | add --version -V flag |
---|---|
Downloads: | Tarball | ZIP archive | SQL archive |
Timelines: | family | ancestors | descendants | both | trunk |
Files: | files | file ages | folders |
SHA3-256: |
0c6a7846785c6aa3dbf9875546d9c41d |
User & Date: | lexi on 2021-12-21 05:04:57 |
Other Links: | manifest | tags |
Context
2021-12-22
| ||
10:19 | add extension mechanism, move toc to extensions, update docs, fix bugs check-in: 330e1ecfdb user: lexi tags: trunk | |
2021-12-21
| ||
05:04 | add --version -V flag check-in: 0c6a784678 user: lexi tags: trunk | |
03:26 | fix embarassing typobug check-in: d5e8521d30 user: lexi tags: trunk | |
Changes
Modified cli.lua from [37b0a0a8ee] to [bdd85f20a4].
2 2 local ss = require 'sirsem' 3 3 4 4 local default_mode = { 5 5 ['render:format'] = 'html'; 6 6 ['html:gen-styles'] = true; 7 7 } 8 8 9 -local function 10 -kmap(fn, list) 11 - local new = {} 12 - for k, v in pairs(list) do 13 - local nk,nv = fn(k,v) 14 - new[nk or k] = nv or v 15 - end 16 - return new 17 -end 18 - 19 -local function 20 -kfilter(list, fn) 21 - local new = {} 22 - for k, v in pairs(list) do 23 - if fn(k,v) then new[k] = v end 24 - end 25 - return new 26 -end 27 - 28 9 local function 29 10 main(input, output, log, mode, suggestions, vars) 30 11 local doc = ct.parse(input.stream, input.src, mode) 31 12 input.stream:close() 32 13 if mode['parse:show-tree'] then 33 14 log:write(dump(doc)) 34 15 end ................................................................................ 43 24 error 'what output format should i translate the input to?' 44 25 end 45 26 if mode['render:format'] == 'none' then return 0 end 46 27 if not ct.render[mode['render:format']] then 47 28 ct.exns.unimpl('output format “%s” unsupported', mode['render:format']):throw() 48 29 end 49 30 50 - local render_opts = kmap(function(k,v) 31 + local render_opts = ss.kmap(function(k,v) 51 32 return k:sub(2+#mode['render:format']) 52 - end, kfilter(mode, function(m) 33 + end, ss.kfilter(mode, function(m) 53 34 return ss.str.begins(m, mode['render:format']..':') 54 35 end)) 55 36 56 37 doc.vars = vars 57 38 58 39 -- this is kind of gross but the context object belongs to the parser, 59 40 -- not the renderer, so that's not a suitable place for this information ................................................................................ 136 117 mode = function(key,value) mode[checkmodekey(key)] = value end; 137 118 ['mode-set'] = function(key) mode[checkmodekey(key)] = true end; 138 119 ['mode-clear'] = function(key) mode[checkmodekey(key)] = false end; 139 120 140 121 ['mode-weak'] = function(key,value) suggestions[checkmodekey(key)] = value end; 141 122 ['mode-set-weak'] = function(key) suggestions[checkmodekey(key)] = true end; 142 123 ['mode-clear-weak'] = function(key) suggestions[checkmodekey(key)] = false end; 124 + 125 + ['version'] = function() 126 + outp:write(ct.info:about()) 127 + if next(ct.ext.loaded) then 128 + outp:write('\nactive extensions:\n') 129 + for k,v in pairs(ct.ext.loaded) do 130 + outp:write(string.format(' * %s', v.id .. 131 + (v.version and (' ' .. v.version:string()) or ''))) 132 + if v.desc then 133 + outp:write(string.format(': %s', v.desc)) 134 + if v.contributors then 135 + outp:write(string.format(' [%s]', table.concat( 136 + ss.map(function(ctr) 137 + return ctr.name or ctr.handle 138 + end, v.contributors), ', '))) 139 + end 140 + else 141 + outp:write'\n' 142 + end 143 + end 144 + end 145 + os.exit(0) 146 + end 143 147 } 144 148 145 149 local args = {} 146 150 local keepParsing = true 147 151 do local i = 1 while i <= #arg do local v = arg[i] 148 152 local execLongOpt = function(longopt) 149 153 if not onswitch[longopt] then 150 154 ct.exns.cli('switch --%s unrecognized', longopt):throw() 151 155 end 152 156 local nargs = optnparams(longopt) 153 157 154 158 if nargs > 1 then 155 159 if i + nargs > #arg then 156 - ct.exns.cli('not enough arguments for switch --%s (%u expected)', longopt, nargs):throw() 160 + ct.exns.cli('not enough arguments for switch --%s (%s expected)', longopt, nargs):throw() 157 161 end 158 162 local nt = {} 159 163 for j = i+1, i+nargs do 160 164 table.insert(nt, arg[j]) 161 165 end 162 - onswitch[longopt](table.unpack(nt)) 166 + print('onsw') 163 167 elseif nargs == 1 then 164 168 onswitch[longopt](arg[i+1]) 169 + else 170 + onswitch[longopt]() 165 171 end 166 172 i = i + nargs 167 173 end 168 174 if v == '--' then 169 175 keepParsing = false 170 176 else 171 177 local longopt = v:match '^%-%-(.+)$' ................................................................................ 173 179 execLongOpt(longopt) 174 180 else 175 181 if keepParsing and v:sub(1,1) == '-' then 176 182 for c,p in ss.str.enc.utf8.each(v:sub(2)) do 177 183 if optmap[c] then 178 184 execLongOpt(optmap[c]) 179 185 else 180 - ct.exns.cli('switch -%i unrecognized', c):throw() 186 + ct.exns.cli('switch -%s unrecognized', c):throw() 181 187 end 182 188 end 183 189 else 184 190 table.insert(args, v) 185 191 end 186 192 end 187 193
Modified cortav.lua from [70cf5fbd0d] to [7d896a453b].
8 8 local startswith = ss.str.begins 9 9 local eachcode = ss.str.enc.utf8.each 10 10 local dump = ss.dump 11 11 local declare = ss.declare 12 12 13 13 -- make this module available to require() when linked into a lua bytecode program with luac 14 14 local ct = ss.namespace 'cortav' 15 +ct.info = { 16 + version = ss.version {0,1; 'devel'}; 17 + package_name = 'cortav'; 18 + contributors = { 19 + { name = 'lexi hale', handle = 'velartrill'; 20 + mail = 'lexi@hale.su', homepage = 'https://hale.su' }; 21 + }; 22 + ident_string = function(i) 23 + return string.format('%s %s', i.package_name, i.version) 24 + end; 25 + credits = function(i) 26 + local all = ss.copy(i.contributors) 27 + for i,who in pairs(all) do 28 + who.role = who.role or 'core functionality' 29 + end 30 + for name,ext in pairs(ct.ext.loaded) do 31 + if ext.contributors then 32 + for _,c in pairs(ext.contributors) do 33 + local ofs, ref = ss.find(all, function(a) 34 + return a.handle == c.handle 35 + end) 36 + if ofs then 37 + ref.role = string.format('%s; %s extension', ref.role, name) 38 + else 39 + local c = ss.clone(ext.author) 40 + c.role = name .. ' extension' 41 + end 42 + end 43 + end 44 + end 45 + return all 46 + end; 47 + credits_ascii = function(contributors) 48 + local body = '' 49 + for _, c in pairs(contributors) do 50 + local str 51 + if c.handle then 52 + str = string.format('%s “%s” <%s>', c.name, c.handle, c.mail) 53 + else 54 + str = string.format('%s <%s>', c.name, c.mail) 55 + end 56 + if c.homepage then 57 + str = string.format('%s (%s)', str, c.homepage) 58 + end 59 + if c.role then 60 + str = string.format('%s: %s', str, c.role) 61 + end 62 + body = body .. string.format(' ~ %s\n', str) 63 + end 64 + return body 65 + end; 66 + about = function(i) 67 + return i:ident_string() .. '\n' .. 68 + i.credits_ascii(i:credits()) 69 + end; 70 +} 71 + 72 + 15 73 ct.render = {} 16 74 17 75 ct.exns = { 18 76 tx = ss.exnkind('translation error', function(msg,...) 19 77 return string.format("(%s:%u) "..msg, ...) 20 78 end); 21 79 io = ss.exnkind('IO error', function(msg, ...)
Modified ext/toc.lua from [a3dcc0807f] to [ed743c91e7].
1 1 local ct = require 'cortav' 2 2 local ss = require 'sirsem' 3 3 4 4 ct.ext.install { 5 5 id = 'toc'; 6 6 desc = 'provides a table of contents for HTML renderer plus generic fallback'; 7 + version = ss.version {0,1; 'devel'}; 8 + contributors = {{name='lexi hale', handle='velartrill', mail='lexi@hale.su', homepage='https://hale.su'}}; 7 9 directive = function(words) 8 10 9 11 end; 10 12 }
Modified sirsem.lua from [a1f6282434] to [8f6ee343ec].
35 35 function ss.filter(list, fn) 36 36 local new = {} 37 37 for i, v in ipairs(list) do 38 38 if fn(v,i) then table.insert(new, v) end 39 39 end 40 40 return new 41 41 end 42 +function ss.kmap(fn, list) 43 + local new = {} 44 + for k, v in pairs(list) do 45 + local nk,nv = fn(k,v) 46 + new[nk or k] = nv or v 47 + end 48 + return new 49 +end 50 + 51 +function ss.kfilter(list, fn) 52 + local new = {} 53 + for k, v in pairs(list) do 54 + if fn(k,v) then new[k] = v end 55 + end 56 + return new 57 +end 58 + 59 +function ss.find(tbl, pred, ...) 60 + pred = pred or function(a,b) 61 + return a == b 62 + end 63 + for k,v in pairs(tbl) do 64 + if pred(v,k,...) then return k,v end 65 + end 66 + return nil 67 +end 68 + 69 +function ss.clone(tbl) -- performs a shallow copy 70 + if tbl.clone then return tbl:clone() end 71 + local new = {} 72 + for k,v in pairs(tbl) do 73 + new[k] = v 74 + end 75 + return new 76 +end 77 + 78 +function ss.copy(tbl) -- performs a deep copy 79 + local new = {} 80 + for k,v in pairs(tbl) do 81 + if type(v) == 'table' then 82 + if v.clone then 83 + new[k] = v:clone() -- this may or may not do a deep copy! 84 + else 85 + new[k] = ss.copy(v) 86 + end 87 + else 88 + new[k] = v 89 + end 90 + end 91 + return new 92 +end 93 + 94 +function ss.delegate(tbl,tpl) -- returns a table that looks up keys it lacks from 95 + -- tbl (lightweight alternative to shallow copies) 96 + tpl = tpl or {} 97 + return setmetatable({}, {__index=tbl}) 98 +end 42 99 43 100 ss.str = {} 44 101 45 102 function ss.str.begins(str, pfx) 46 103 return string.sub(str, 1, #pfx) == pfx 47 104 end 48 105 ................................................................................ 268 325 ss.str.exn('out of place token “%s”', stop):throw() 269 326 end 270 327 end 271 328 end 272 329 273 330 ss.str.exn('token “%s” expected before end of line', stop):throw() 274 331 end 332 + 333 +ss.version = ss.declare { 334 + name = 'version'; 335 + mk = function(tbl) return tbl end; 336 + fns = { 337 + pre = function(self,other) end; 338 + post = function(self,other) end; 339 + string = function(self) return tostring(self) end; 340 + }; 341 + cast = { 342 + string = function(vers) 343 + if not(next(vers)) then return '0.0' end 344 + local str = '' 345 + for _,v in pairs(vers) do 346 + if type(v) == 'string' then 347 + if str ~= '' then str = str .. '-' end 348 + str = str .. v 349 + else 350 + if str ~= '' then str = str .. '.' end 351 + str = str .. tostring(v) 352 + end 353 + end 354 + return str 355 + end 356 + }; 357 +} 358 + 359 +function ss.classinstance(o) 360 + local g = getmetatable(o) 361 + if not o then return nil end 362 + local mm = getmetatable(g) 363 + if not o then return nil end 364 + if mm.__name == 'class' then 365 + return g 366 + else 367 + return nil 368 + end 369 +end 370 +