Overview
Comment: | add remote fetch via curl, shim native bindings |
---|---|
Downloads: | Tarball | ZIP archive | SQL archive |
Timelines: | family | ancestors | descendants | both | trunk |
Files: | files | file ages | folders |
SHA3-256: |
ee086767f3c7d8e499c9a4a91ffe77f6 |
User & Date: | lexi on 2022-09-10 17:28:05 |
Other Links: | manifest | tags |
Context
2022-09-10
| ||
19:14 | tweak docs check-in: 5a78370f0f user: lexi tags: trunk | |
17:28 | add remote fetch via curl, shim native bindings check-in: ee086767f3 user: lexi tags: trunk | |
13:31 | better footnotes, update syntax def, delete broken old span check-in: a8358d587d user: lexi tags: trunk | |
Changes
Modified cli.lua from [2aa6072a5d] to [6b3b695c7e].
1 1 -- [ส] cli.lua 2 2 -- ~ lexi hale <lexi@hale.su> 3 3 -- ๐ฏ AGPLv3 4 4 -- ? simple command line driver for the cortav library 5 5 local ct = require 'cortav' 6 6 local ss = require 'sirsem' 7 7 8 +local native = _G.native 9 + 8 10 local default_mode = { 9 11 ['render:format'] = 'html'; 10 12 ['html:gen-styles'] = true; 11 13 ['groff:color'] = true; 12 14 } 13 15 14 16 local function ................................................................................ 223 225 local ok, e = true, entry_cli() 224 226 if not ok then 225 227 local str = 'translation failure' 226 228 if ss.exn.is(e) then 227 229 str = e.kind.desc 228 230 end 229 231 local color = false 230 - if log:seek() == nil then 231 - -- this is not a very reliable heuristic for detecting 232 - -- attachment to a tty but it's better than nothing 233 - if os.getenv('COLORTERM') then 232 + if native then 233 + if native.posix.isatty(log) then 234 234 color = true 235 - else 236 - local term = os.getenv('TERM') 237 - if term:find 'color' then color = true end 235 + end 236 + else 237 + if log:seek() == nil then 238 + -- this is not a very reliable heuristic for detecting 239 + -- attachment to a tty but it's better than nothing 240 + if os.getenv('COLORTERM') then 241 + color = true 242 + else 243 + local term = os.getenv('TERM') 244 + if term:find 'color' then color = true end 245 + end 238 246 end 239 247 end 240 248 if color then 241 249 str = string.format('\27[1;31m%s\27[m', str) 242 250 end 243 251 log:write(string.format('%s: %s\n', str, e)) 244 252 os.exit(1) 245 253 end 246 254 os.exit(e)
Modified cortav.lua from [648cf1722d] to [940c3efd41].
794 794 } 795 795 end}; 796 796 {seq = '>', parse = insert_link}; 797 797 {seq = 'โ', parse = insert_link}; 798 798 {seq = '๐', parse = insert_link}; 799 799 {seq = '##', parse = insert_var_ref(true)}; 800 800 {seq = '#', parse = insert_var_ref(false)}; 801 - {seq = '%%', parse = function() --[[NOP]] end}; 801 + {seq = '%%', parse = function (s,c) 802 + local com = s:match '^%%%%%s*(.*)$' 803 + return { 804 + kind = 'comment'; 805 + comment = com; 806 + } 807 + end}; 802 808 {seq = '%!', parse = insert_span_directive(true,false)}; 803 809 {seq = '%:', parse = insert_span_directive(false,true)}; 804 810 {seq = '%', parse = insert_span_directive(false,false)}; 805 811 } 806 812 end 807 813 808 814 function ct.parse_span(str,ctx)
Modified makefile from [fbd94cf6db] to [10a67640c2].
37 37 luac != which luac 38 38 sh != which sh 39 39 40 40 extens = $(wildcard ext/*.lua) 41 41 extens-names ?= $(basename $(notdir $(extens))) 42 42 rendrs = $(wildcard render/*.lua) 43 43 rendrs-names ?= $(basename $(notdir $(rendrs))) 44 +binds = $(wildcard bind/*.c) 45 +binds-names ?= $(basename $(notdir $(binds))) 44 46 45 47 build = build 46 48 executable = cortav 47 49 default-format-flags = -m html:width 40em 48 50 49 51 prefix = $(HOME)/.local 50 52 bin-prefix = $(prefix)/bin 51 53 52 54 lua-standalone = $(if $(lua-lib-prefix),$(lua-lib-prefix)/liblua.a,-llua) 53 55 lua-bindeps = -lm -ldl 56 + 57 +ifneq ($(filter net,$(binds-names)),) 58 + lua-bindeps += -lcurl 59 +endif 54 60 55 61 dbg-flags-luac = $(if $(debug),,-s) 56 62 dbg-flags-cc = $(if $(debug),-g,-s) 57 63 58 64 # sterilize the operating theatre 59 65 export LUA_PATH=./?.lua;./?.lc 60 66 export LUA_PATH_5_3=./?.lc;./?.lua ................................................................................ 84 90 # raw bytecode without shebang header, must be run as `lua cortav.lc` 85 91 $(build)/$(executable).lc: sirsem.lua $(encoding-files) cortav.lua $(rendrs) $(extens) cli.lua | $(build)/ 86 92 @echo ' ยป building with extensions $(extens-names)' 87 93 @echo ' ยป building with renderers $(rendrs-names)' 88 94 $(luac) $(dbg-flags-luac) -o $@ $^ 89 95 90 96 # true standalone binary, wraps bytecode file and (optionally) lua 91 -$(build)/$(executable).bin: $(build)/$(executable).lc tool/makeshim.lua 92 - $(lua) tool/makeshim.lua $< |\ 93 - $(CC) -s -o$@ -xc - -xnone $(lua-standalone) $(lua-bindeps) 97 +$(build)/$(executable).bin: $(build)/$(executable).lc tool/makeshim.lua $(binds) 98 + $(lua) tool/makeshim.lua $< "" $(binds-names) |\ 99 + $(CC) -s -o$@ -xc - -xnone $(binds) $(lua-standalone) $(lua-bindeps) 100 + 101 +# loadable lua modules for binds, mainly useful for testing 102 +$(build)/bind/%.so: bind/%.c bind/bind.h | $(build)/bind/ 103 + $(CC) -fPIC -shared -g -o$@ $< 94 104 95 105 $(build)/cortav.html: cortav.ct $(build)/$(executable) | $(build)/ 96 106 $(build)/$(executable) $< -o $@ -m render:format html -y html:fossil-uv 97 107 98 108 .PHONY: syncdoc 99 109 syncdoc: $(build)/cortav.html 100 110 fossil uv add $< --as cortav.html ................................................................................ 104 114 # just in case it ever gets invoked in a bad way 105 115 .PHONY: clean 106 116 clean: 107 117 rm -f $(build)/*.{html,lc,sh,txt,desktop} \ 108 118 $(build)/$(executable){,.bin} 109 119 rmdir $(build) 110 120 111 -$(build)/%.sh: desk/%.sh 121 +$(build)/%.sh: desk/%.sh | $(build)/ 112 122 echo >$@ "#!$(sh)" 113 123 echo >>$@ 'cortav_exec="$(bin-prefix)/$(executable)"' 114 124 echo >>$@ 'cortav_flags="$${ct_format_flags-$(default-format-flags)}"' 115 125 cat $< >> $@ 116 126 chmod +x $@ 117 127 118 128 $(build)/velartrill-cortav-view.desktop: desk/cortav-view.desktop
Modified render/html.lua from [e235e554e3] to [28584fb71a].
173 173 overflow-y: auto; 174 174 margin-top: 0; 175 175 } 176 176 aside.footnote > .text > :first-child { 177 177 margin-top: 0; 178 178 } 179 179 ]]; 180 + docmeta = [[ 181 + .render-warn { 182 + border: 1px solid @tone(0.1 20); 183 + background: @tone(0.4 20); 184 + padding: 1em; 185 + margin: 5em 1em; 186 + } 187 + ]]; 188 + embed = [[ 189 + embed, .embed { 190 + width: 100%; 191 + height: fit-content; 192 + max-height: 80vh; 193 + overflow: scroll; 194 + } 195 + embed {height: 20em;} 196 + ]]; 180 197 header = [[ 181 198 body { padding: 0 2.5em !important } 182 199 h1,h2,h3,h4,h5,h6 { border-bottom: 1px solid @tone(0.7); } 183 200 h1 { font-size: 200%; border-bottom-style: double !important; border-bottom-width: 3px !important; margin: 0em -1em; } 184 201 h2 { font-size: 130%; margin: 0em -0.7em; } 185 202 h3 { font-size: 110%; margin: 0em -0.5em; } 186 203 h4 { font-size: 100%; font-weight: normal; margin: 0em -0.2em; } ................................................................................ 505 522 506 523 local renderJob = doc:job('render_html', nil, render_state_handle) 507 524 doc.stage.job = renderJob; 508 525 509 526 local runhook = function(h, ...) 510 527 return renderJob:hook(h, render_state_handle, ...) 511 528 end 529 + 530 + local function htmlentities(v) 531 + return v:gsub('[<>&"]', function(x) 532 + return string.format('&#%02u;', string.byte(x)) 533 + end) 534 + end 512 535 513 536 local function htmlURI(uri) 514 537 local family = uri:canfetch() 515 538 if family == 'file' then 516 539 if uri.namespace == 'localhost' then 517 540 -- emit an actual file url 518 541 return 'file://' .. uri:construct('path','frag') ................................................................................ 629 652 tag('body', nil, body or '')) 630 653 end 631 654 632 655 local function htmlSpan(spans, block, sec) 633 656 local text = {} 634 657 for k,v in pairs(spans) do 635 658 if type(v) == 'string' then 636 - v=v:gsub('[<>&"]', function(x) 637 - return string.format('&#%02u;', string.byte(x)) 638 - end) 659 + v=htmlentities(v) 639 660 for fn, ext in renderJob:each('hook','render_html_sanitize') do 640 661 v = fn(renderJob:delegate(ext), v) 641 662 end 642 663 table.insert(text,v) 643 664 else 644 665 table.insert(text, (span_renderers[v.kind](v, block, sec))) 645 666 end ................................................................................ 997 1018 end 998 1019 end}; 999 1020 {ss.mime'text/x.cortav', function(s,ctr) 1000 1021 if s == nil then 1001 1022 return {} 1002 1023 elseif next(ctr) == nil then 1003 1024 if (s.mode == 'embed' or s.mode == 'auto') and s.doc then 1025 + addStyle 'embed' 1004 1026 ctr.tag = 'div'; -- kinda hacky, maybe fix 1027 + ctr.attrs = {class='embed'} 1005 1028 ctr.nodes = renderSubdoc(s.doc) 1006 1029 elseif s.mode == 'link' then 1007 1030 -- yeah this is not gonna work my dude 1031 + addStyle 'embed' 1008 1032 ctr.elt = 'embed'; 1009 1033 ctr.attrs = { 1010 1034 type = 'text/x.cortav'; 1011 1035 src = htmlURI(s.uri); 1012 1036 } 1013 1037 end 1014 1038 end 1015 1039 end}; 1016 1040 {ss.mime'text/html', function(s,ctr) 1017 1041 if s == nil then 1018 1042 return {} 1019 1043 elseif next(ctr) == nil then 1020 1044 if (s.mode == 'embed' or s.mode == 'auto') and s.raw then 1045 + addStyle 'embed' 1021 1046 ctr.tag = 'div' 1047 + ctr.attrs = {class='embed'} 1022 1048 ctr.nodes = s.raw 1023 1049 elseif s.mode == 'link' then 1050 + addStyle 'embed' 1024 1051 ctr.elt = 'embed'; 1025 1052 ctr.attrs = { 1026 1053 type = 'text/html'; 1027 1054 src = htmlURI(s.uri); 1028 1055 } 1029 1056 end 1030 1057 end ................................................................................ 1032 1059 {ss.mime'text/*', function(s,ctr) 1033 1060 if s == nil then 1034 1061 return {} 1035 1062 elseif next(ctr) == nil then 1036 1063 local mime = s.mime:clone() 1037 1064 mime.opts={} 1038 1065 if (s.mode == 'embed' or s.mode == 'auto') and s.raw then 1066 + addStyle 'embed' 1039 1067 ctr.tag = 'pre'; 1040 - ctr.nodes = s.raw 1068 + ctr.attrs = {class='embed'} 1069 + ctr.nodes = htmlentities(s.raw); 1041 1070 elseif s.mode == 'link' then 1071 + addStyle 'embed' 1042 1072 ctr.elt = 'embed'; 1043 1073 ctr.attrs = { 1044 1074 type = tostring(mime); 1045 1075 src = htmlURI(s.uri); 1046 1076 } 1047 1077 end 1048 1078 end
Modified sirsem.lua from [9b28e1fde4] to [2b64c7033a].
17 17 end 18 18 return pkg 19 19 end 20 20 ss = namespace 'sirsem' 21 21 ss.namespace = namespace 22 22 end 23 23 24 +local native = _G.native 25 + 24 26 function ss.map(fn, lst) 25 27 local new = {} 26 28 for k,v in pairs(lst) do 27 29 table.insert(new, fn(v,k)) 28 30 end 29 31 return new 30 32 end ................................................................................ 112 114 -- tbl (lightweight alternative to shallow copies) 113 115 tpl = tpl or {} 114 116 return setmetatable({}, {__index=tbl}) 115 117 end 116 118 117 119 ss.str = {} 118 120 119 -function ss.str.begins(str, pfx) 120 - -- appallingly, this is actually ~2/5ths faster than either 121 - -- of the below. i hate scripting languages so much 122 - return string.find(str, pfx, 1, true) == 1 123 - -- to my shock, disgust, and horror, even writing my own 124 - -- string scanning library for lua IN C only sped this up by 125 - -- a tiny fraction. i am just speechless. 126 --- return string.sub(str, 1, #pfx) == pfx 127 - 128 --- local pl = string.len(pfx) 129 --- local sl = string.len(str) 130 --- if sl < pl then return false end 131 --- for i=1,pl do 132 --- if string.byte(str,i) ~= string.byte(pfx,i) then 133 --- return false 134 --- end 135 --- end 136 --- return true 121 +if native then 122 + function ss.str.begins(str, pfx) 123 + return native.strutils.rangematch(str,1,pfx) 124 + end 125 +else 126 + function ss.str.begins(str, pfx) 127 + -- appallingly, this is actually ~2/5ths faster than either 128 + -- of the below. i hate scripting languages so much 129 + return string.find(str, pfx, 1, true) == 1 130 + -- to my shock, disgust, and horror, even writing my own 131 + -- string scanning library for lua IN C only sped this up by 132 + -- a tiny fraction. i am just speechless. 133 + -- return string.sub(str, 1, #pfx) == pfx 134 + 135 + -- local pl = string.len(pfx) 136 + -- local sl = string.len(str) 137 + -- if sl < pl then return false end 138 + -- for i=1,pl do 139 + -- if string.byte(str,i) ~= string.byte(pfx,i) then 140 + -- return false 141 + -- end 142 + -- end 143 + -- return true 144 + end 137 145 end 138 146 139 147 function ss.enum(syms) 140 148 local e = {} 141 149 for i,v in pairs(syms) do 142 150 e[v] = i 143 151 e[i] = v ................................................................................ 1170 1178 local fetchableProtocols = { 1171 1179 http = { 1172 1180 proto = { 1173 1181 {'http'}; 1174 1182 {'https'}; 1175 1183 {'http', 'tls'}; 1176 1184 }; 1177 - fetch = function(uri) 1185 + fetch = native and native.net and function(uri) 1186 + -- translate to a curl-compatible URI 1187 + if uri.path and uri.path ~= '' and uri.path:sub(1,1) ~= '/' then 1188 + fetchexn('relative HTTP URIs like โ%sโ are not fetchable', uri):throw() 1189 + end 1190 + uri = uri:clone() 1191 + if uri.class[2] == 'tls' then 1192 + uri.class = {'https'} 1193 + end 1194 + if not uri.namespace then 1195 + uri.namespace = 'localhost' 1196 + end 1197 + local body, e = native.net.fetchURI(tostring(uri)) 1198 + if e then 1199 + fetchexn('could not fetch URI โ%sโ: %s',uri,e):throw() 1200 + end 1201 + return body 1202 + end or function(uri) 1178 1203 fetchexn('cortav must be compiled with the C shim and libcurl support to use http fetch'):throw() 1179 1204 end; 1180 1205 }; 1181 1206 file = { 1182 1207 proto = { 1183 1208 {'file'}; 1184 1209 {'file', 'txt'}; ................................................................................ 1336 1361 class = nil; 1337 1362 namespace = nil; 1338 1363 path = nil; 1339 1364 query = nil; 1340 1365 frag = nil; 1341 1366 auth = nil; 1342 1367 } end; 1368 + clonesetup = function(me) 1369 + me.class = ss.clone(me.class) 1370 + end; 1343 1371 construct = function(me, str) 1344 1372 local enc = ss.str.enc.utf8 1345 1373 -- URIs must be either ASCII or utf8, so we read and 1346 1374 -- store as UTF8. to use a URI in another encoding, it 1347 1375 -- must be manually converted to and fro using the 1348 1376 -- appropriate functions, such as encodeUCS 1349 1377 if not str then return end
Modified tool/makeshim.lua from [cea771ab78] to [f7d9ea5be8].
31 31 32 32 // load and run our payload 33 33 int e = luaL_loadbufferx(l, ct_bytecode, sizeof(ct_bytecode), "cortav", "b"); 34 34 if (e != LUA_OK) { 35 35 printf("some kind of error idk fam\n"); 36 36 return -1; 37 37 } 38 + 39 + // create the native interface table, if nothing 40 + // else to signal that cortav is running under a 41 + // binary shim 42 + lua_pushglobaltable(l); 43 + lua_newtable(l); 44 + _lua_env_setup 45 + lua_setfield(l, -2, "native"); 46 + lua_pop(l, 1); 38 47 39 48 if (lua_pcall(l, 0, 0, 0) != LUA_OK) { 40 49 size_t len; 41 50 const char* msg = luaL_tolstring(l, -1, &len); 42 51 if (isatty(2)) { 43 52 fprintf(stderr, "\33[31;1m(fatal)\33[m %.*s\n", (int)len, msg); 44 53 } else { ................................................................................ 60 69 io.stderr:write('(' .. arg[0]..' fatal) cannot open file '..arg[i]) 61 70 end 62 71 return dflt 63 72 end 64 73 65 74 local src = setfile(1, io.stdin, "rb") 66 75 local dest = setfile(2, io.stdout, "w") 76 +local binds = {} 77 +for i=3,#arg do 78 + io.stderr:write(string.format("(%s info) including loader for bind %s\n", arg[0], arg[i])) 79 + table.insert(binds, arg[i]) 80 +end 67 81 68 82 local cstr = {} 69 83 local strtpl = [[static char ct_bytecode [%u] = { 70 84 %s 71 85 };]] 86 + 87 +local bindfn = [[#define _lua_env_setup]] 88 + 89 +if next(binds) then 90 + -- make cpp do our interpolation for us 91 + bindfn = [[#define _lua_env_setup init_binds(l);]] 92 + local calls = {} 93 + local decls = {} 94 + local ctpl = [[ 95 + luaopen_bind_%s(l); 96 + lua_setfield(l, -2, "%s"); 97 +]] 98 + for n,b in ipairs(binds) do 99 + table.insert(decls, string.format('extern int luaopen_bind_%s(lua_State* l);\n', b)) 100 + table.insert(calls, string.format(ctpl, b, b)) 101 + end 102 + local hdr = [[ 103 +static void init_binds(lua_State* l) { 104 +]] 105 + local foot = [[ 106 +} 107 +]] 108 + bindfn = bindfn .. '\n' 109 + .. table.concat(decls) 110 + .. hdr 111 + .. table.concat(calls) 112 + .. foot 113 +end 72 114 73 115 local bytes = {} 74 116 75 117 local bn = 1 76 118 local len = 0 77 119 while true do 78 120 local byte = src:read(1) ................................................................................ 90 132 bytes[bn] = str 91 133 bn = bn + 1 92 134 end 93 135 94 136 local lines = { 95 137 includes; 96 138 strtpl:format(#bytes, table.concat(bytes)); 139 + bindfn; 97 140 main; 98 141 } 99 142 100 143 dest:write(table.concat(lines, '\n'))