Warning: this is an htmlized version!
The original is here, and the conversion rules are here. |
-- This file: -- http://anggtwu.net/blogme3/cruft-jan2024.lua.html -- http://anggtwu.net/blogme3/cruft-jan2024.lua -- (find-angg "blogme3/cruft-jan2024.lua") -- Author: Eduardo Ochs <eduardoochs@gmail.com> -- -- (defun e () (interactive) (find-angg "blogme3/cruft-jan2024.lua")) -- Code removed from ~/LUA/lua50init.lua in 2024jan23. -- See: (find-angg "LUA/lua50init.lua" ".EevIntro") -- (find-blogme3 "anggdefs.lua" "cruft-jan2024") -- (find-blogme3 "angglisp.lua" "cruft-jan2024") -- «.EevIntro» (to "EevIntro") -- «.youtube_make_url» (to "youtube_make_url") -- «.youtube_split» (to "youtube_split") -- «.getsexp» (to "getsexp") -- «.ELispHF» (to "ELispHF") -- «.SexpSkel» (to "SexpSkel") -- «.ELispH» (to "ELispH") -- «.Sexp» (to "Sexp") -- «.to_youtube_hash» (to "to_youtube_hash") -- Commented out: ---------- «.cruft-begins» (to "cruft-begins") -- «.url_split» (to "url_split") -- «.Blogme» (to "Blogme") -- «.code_video» (to "code_video") -- «.ELispInfo» (to "ELispInfo") -- «.getsexpskel» (to "getsexpskel") -- «.SexpLine» (to "SexpLine") -- --------«.cruft-ends» (to "cruft-ends") -- «EevIntro» (to ".EevIntro") -- (find-es "lua5" "EevIntro") -- Superseded by sandwiches: -- (find-blogme3file "sandwiches.lua") -- TODO: check which .blogme files still use this. -- EevIntro = Class { type = "EevIntro", from = function (stem, sec) return EevIntro {stem=stem, sec=sec} end, fromshort = function (short) if short:match"#" then return EevIntro.from(short:match"^(.-)#(.*)") else return EevIntro.from(short) end end, fromheadposspec = function (head, posspec) local stem = head:match "^find%-(.*)%-intro$" local sec = posspec and posspec:match "^(%d[%d%.]*)%. " return EevIntro.from(stem, sec) end, fromsexp = function (li) local head, rest = li:match "^%s*%(([!-~]+)(.*)%)%s*$" local posspec = rest:match "^%s+\"(.*)\"$" return EevIntro.fromheadposspec(head, posspec) end, __tostring = function (ei) return mytostring(ei) end, __index = { url = function (ei) return format("eev-intros/find-%s-intro.html%s", ei.stem, ei.sec and "#"..ei.sec or "") end, short = function (ei) return ei.stem .. (ei.sec and "#"..ei.sec or "") end, }, } introhtml = function (stem, sec) return EevIntro.from(stem, sec):url() end -- «youtube_make_url» (to ".youtube_make_url") -- (find-es "youtube" "time-syntax") youtube_make_url = function (hash, time) return "http://www.youtube.com/watch?v=" .. hash .. youtube_time(time) end youtube_time = function (time) if type(time) ~= "string" then return "" end local mm,ss = time:match("^(%d?%d):(%d%d)$") if ss then return "&t="..(mm*60+ss) end local hh,mm,ss = time:match("^(%d?%d):(%d%d):(%d%d)$") if ss then return "&t="..(hh*3600+mm*60+ss) end return "" end youtube_time_hhmmss = function (time) if type(time) ~= "string" then return "" end local mm,ss = time:match("^(%d?%d):(%d%d)$") if ss then return format("&t=%sm%ss", mm, ss) end local hh,mm,ss = time:match("^(%d?%d):(%d%d):(%d%d)$") if ss then return format("&t=%sh%sm%ss", hh, mm, ss) end return "" end -- «youtube_split» (to ".youtube_split") -- I was using this at too many places - including one-shot programs... -- (find-angg "LUA/youtube-tags.lua") -- (find-angg "LUA/youtube.lua") -- (find-blogme3 "youtube.lua") youtube_split_url0 = function (li) local a, url, b, title, c = li:match "^(.-)(https?://%S*)(%s*)(.-)(%s*)$" if not url then return end local hash, time for key,value in url:gmatch "[?&](%w*)=([^?&#'()]*)" do if key == "v" then hash = value end if key == "t" then time = value end -- not being used now end if not hash then return end return a, hash, b, title, c end youtube_split_url = function (li) local a, hash, b, title, c = youtube_split_url0(li) if a then return hash, youtube_make_url(hash), title end end -- «getsexp» (to ".getsexp") -- Superseded by sandwiches: -- (find-blogme3file "sandwiches.lua") -- TODO: check which .blogme files still use this. -- -- New version: (find-angg "LUA/SexpAtEol1.lua" "SexpAtEol-tests") -- (find-es "lua5" "getsexp") -- (find-blogme3 "sexp.lua" "getsexp") -- Version: 2019jan08. -- A low-level function that splits a line into a sexp, a skel, and other stuff. -- If str = 'Hello (find-xpdfpage "~/LATEX/foo.pdf" (+ 2 3))' -- then sexp = '(find-xpdfpage "~/LATEX/foo.pdf" (+ 2 3))', -- skel = '(find-xpdfpage "_______________" (_____))', -- head = 'find-xpdfpage', -- left = 'Hello '. getsexp = function (str) if str:sub(-1) ~= ")" then return end local rep = string.rep local simpq = function (s) return '"'..rep("_", #s-2)..'"' end -- simplify '"'s local simpp = function (s) return '('..rep("_", #s-2)..')' end -- simplify parens local leks = str:gsub("\\.", "__"):reverse():gsub('"[^"]*"', simpq):match("^%b)(") if not leks then return end local skel = leks:reverse() local sexp = str:sub(-#skel) local head = sexp:match("^%(([^ ()\"]+)") local skel = "(" .. skel:sub(2):gsub("%b()", simpp) local left = str:sub(1, -1-#skel) return sexp, head, skel, left end -- «ELispHF» (to ".ELispHF") -- Superseded by sandwiches: -- (find-blogme3file "sandwiches.lua") -- TODO: check which .blogme files still use this. -- -- (find-es "lua5" "ELispHF") -- (find-es "lua5" "ELispHF-tests") -- An ELispHF object holds an "elisp hyperlink function", that when -- called produces an ElispH object. -- ELispHF = Class { type = "ELispHF", newangg = function (head, d, suffix) return ELispHF {head=head, d=d, suffix=suffix, f="angg"} end, newintro = function (head) return ELispHF {head=head, f="intro"} end, newnode = function (head, c, manual) return ELispHF {head=head, c=c, manual=manual, f="node"} end, newyoutube = function (head, hash) return ELispHF {head=head, hash=hash, f="youtube"} end, __tostring = function (ehf) return mytabletostring(ehf) end, __call = function (ehf, ...) return ehf[ehf.f](ehf, ...) end, __index = { angg = function (ehf, a, b, c) local target = suffixing(ehf.d..(a or ""), ehf.suffix, b) return ELispH {intro="eev-quick#9", target=target} end, intro = function (ehf, a) local ei = EevIntro.fromheadposspec(ehf.head, a) return ELispH {intro=ei.stem, target=ei:url()} -- return ELispH {intro=ei:short(), target=ei:url()} end, node = function (ehf, a) local manual, section = ehf.manual, a local target = ELispInfo{}:mstohtml(manual, section) return ELispH {intro="eev-quick#9.2", target=target} end, youtube = function (ehf, a) local hash, time = ehf.hash, a local target = youtube_make_url(hash, time) return ELispH {intro="audiovideo#4.3", target=target} end, codevideo = function (ehf, c, urlorfnameorhash) if c and urlorfnameorhash then code_video(c, urlorfnameorhash) end return ELispH {intro="audiovideo#4.3"} end, }, } _EHF = VerticalTable {} -- «SexpSkel» (to ".SexpSkel") -- (find-es "lua5" "SexpSkel") -- (find-es "lua5" "SexpSkel-test") -- A user-friendly class based on getsexp with a nice printing function. SexpSkel = Class { type = "SexpSkel", fromline = function (line) local str,right = line:match("^(.-%))([%s]*)$") if not str then return SexpSkel {line=line} end local sexp,head,skel,left = getsexp(str) if not sexp then return SexpSkel {line=line} end return SexpSkel {line=line, left=left, sexp=sexp, right=right, skel=skel, head=head} end, __tostring = function (ss) if not ss.sexp then return ss.line.."\n[no sexp]" end local spacify = function (s, c) return string.rep(c or " ", #s) end local left0 = spacify(ss.left) local right0 = spacify(ss.right, ".") return ss.line .."\n".. left0..ss.sexp..right0 .."\n".. left0..ss.skel .."\n".. left0.." "..ss.head end, __index = { splitsexp = function (ss) local sexpmid = ss.sexp:sub(2, -2) -- without the '(' and the ')' local skelmid = ss.skel:sub(2, -2) -- without the '(' and the ')' local A = {} local f = function (p0, p1) -- positions from skelmid table.insert(A, sexpmid:sub(p0, p1-1)) -- substring from sexpmid -- PP(sexpmid:sub(p0, p1-1), skelmid:sub(p0, p1-1)) end skelmid:gsub("()[^%s]+()", f) return A end, parsestrargs = function (ss) local A = ss:splitsexp() local f = function (str) return str and str:match("^\"(.*)\"$") end return f(A[2]), f(A[3]), f(A[4]) end, parseq = function (ss) local headpat = "("..string.rep(".", #ss.head)..")" local qppat = "(\"?%))" -- optional last quote, closing parenthesis local a,head,b,qp = ss.sexp:match("^(.)"..headpat.."(.-)"..qppat.."$") -- print(table.concat({a,head,b,qp}, "|")) return a,head,b,qp end, -- -- (find-es "lua5" "SexpSkel") -- Interface with ELispH and ELispHF: ehtosexphtml = function (ss, eh, hzer) return eh:sexphtml(hzer, ss:parseq()) end, ehftoeh = function (ss, ehf) return ehf(ss:parsestrargs()) end, toehf = function (ss) return _EHF[ss.head] end, toeh = function (ss) local ehf = ss:toehf(); return ehf and ss:ehftoeh(ehf) end, totarget = function (ss) local eh = ss:toeh(); return eh and eh:gettarget() end, tohelp = function (ss) local eh = ss:toeh(); return eh and eh:gethelp() end, tosexphtml = function (ss, hzer) local eh = ss:toeh(); return eh and ss:ehtosexphtml(eh, hzer) end, }, } -- «ELispH» (to ".ELispH") -- Superseded by sandwiches: -- (find-blogme3file "sandwiches.lua") -- TODO: check which .blogme files still use this. -- -- See: (find-es "lua5" "ELispH") -- (find-es "lua5" "ELispH-tests") -- An ELispH object holds data that can generate a "help url" and -- a "target url". For example: -- -- eh = ELispH({intro="eev-quick", target="index.html", anchor="eev"}) -- eh:gethelp() --> "eev-intros/find-eev-quick-intro.html" -- eh:gettarget() --> "index.html#eev" -- -- The :sexphtml(...) method connects this to SexpSkel. -- ELispH = Class { type = "ELispH", __tostring = function (eh) return mytabletostring(eh) end, __index = { gethelp = function (eh) if eh.intro then local stem,section = eh.intro:match("^(.-)#(.*)") if section then return introhtml(stem, section) end return introhtml(eh.intro) end return eh.help end, gettarget = function (eh) return eh.target and (eh.target .. (eh.anchor and "#"..eh.anchor or "")) end, sexphtml = function (eh, hzer, a, head, b, qp) hzer = hzer or id local help = eh:gethelp() local target = eh:gettarget() return hzer(a) .. HREF1(help, hzer(head)) .. hzer(b) .. HREF1(target, hzer(qp)) end, -- test = function (eh) local outt = {help=eh:gethelp(), target=eh:gettarget()} return tostring(eh) .. " ->\n" .. mytabletostring(outt) end, }, } elispSPECIAL = {} -- «Sexp» (to ".Sexp") -- Used here: (find-blogme3 "anggdefs.lua" "Sexp") elisp = {} elisp["find-angg"] = meta_find_angg("") elisp["find-es"] = meta_find_angg("e/", ".e.html") Sexp = Class { type = "Sexp", __index = { getsexp = function (sexp) local line = sexp.line if line:sub(#line) ~= ")" then return end local len = #line local skel = line:gsub("\\.", "__") -- backslash+c -> __ skel = skel:revgsub("\"[^\"]*\"", underlinify) -- "abc" -> "___" skel = skel:sub(1, len-1):revgsub("%b)(", underlinify)..skel:sub(len) local revsexp = line:reverse():match("^%b)(") if not revsexp then return end sexp.sexp = revsexp:reverse() sexp.pre = line:sub(1, len-#sexp.sexp) -- sexp.sexpskel = skel:sub(#sexp.pre+1) sexp.midskel = skel:sub(#sexp.pre+2, len-1) sexp.head = sexp.midskel:match("^%S*") return sexp.head end, getsexpargs = function (sexp) local n = 0 sexp.ranges = {} for i,j in sexp.midskel:gmatch("()%S+()") do n = n + 1 sexp[n] = sexp.sexp:sub(i+1, j) sexp.ranges[n] = {i+1, j+1} end end, string = function (sexp, n) return sexp[n] and sexp[n]:match '^"(.*)"$' end, -- Q = function (text) return text end, hrefto = function (sexp, url) return function (text) return '<a href="'..url..'">'..sexp.Q(text)..'</a>' end end, setrange = function (sexp, a, b, s_or_f) table.insert(sexp.htmlranges, {a, b, s_or_f}) end, sethelp = function (sexp, url) local r = sexp.ranges[1] if url then sexp:setrange(r[1], r[2], sexp:hrefto(url)) end -- table.insert(sexp.htmlranges, {r[1], r[2], sexp:hrefto(url)}) -- end end, settarget = function (sexp, url) local len = #sexp.sexp if url then sexp:setrange(len-1, len+1, sexp:hrefto(url)) end -- table.insert(sexp.htmlranges, {len-1, len+1, sexp:hrefto(url)}) -- end end, tohtml0 = function (sexp) return replaceranges(sexp.sexp, sexp.htmlranges or {}, sexp.Q) end, getsexphtml = function (sexp) sexp.htmlranges = {} if not sexp.head then return end if elispSPECIAL[sexp.head] then -- for all kinds of special hacks elispSPECIAL[sexp.head](sexp) return end local find_aaa = elisp[sexp.head] if not find_aaa then return end sexp:getsexpargs() sexp.target, sexp.help = find_aaa(sexp:string(2), sexp:string(3)) sexp:sethelp(sexp.help) sexp:settarget(sexp.target) sexp.sexphtml = sexp:tohtml0() end, getlinehtml = function (sexp) if sexp:getsexp() then sexp:getsexphtml() end if sexp.sexphtml then sexp.linehtml = sexp.Q(sexp.pre)..sexp.sexphtml else sexp.linehtml = sexp.Q(sexp.line) end return sexp.linehtml end, }, } -- (find-blogme3 "anggdefs.lua" "basic-words-for-html" "HREF") HREF = function (url, str) return format('<a href="%s">%s</a>', url, str) end HREF1 = function (url, str) return url and HREF(url, str) or str end -- «to_youtube_hash» (to ".to_youtube_hash") to_youtube_hash = function (str) str = str:gsub("%.%w%w%w$", "") str = str:sub(-11) return str end -- «url_split» (to ".url_split") -- Used here: (find-angg "LUA/redirect.lua") url_percent_decode = function (str) local f = function (hh) return string.char(tonumber(hh, 16)) end return (str:gsub("%%(%x%x)", f)) end url_query_split = function (query) local Q = {} for key,value in query:gmatch "[?&](%w*)=([^?&#'()]*)" do Q[key] = url_percent_decode(value) end return Q end -- url_split_re = nil url_split_re0 = function () userocks() require "re" -- (find-es "lua5" "lpeg-re") return re.compile [=[ {| {:scheme: [a-z]+ :} "://" {:host: [^/]+ :} ( "/" {:path: [^?#]* :} ) ? ( "?" {:query: [^#]* :} ) ? ( "#" {:anchor: [^#]* :} ) ? |} ]=] end url_split = function (url) url_split_re = url_split_re or url_split_re0() local parts = url_split_re:match(url) if parts and parts.query then parts.q = url_query_split("?" .. parts.query) end return parts end ------------------------------------------------------------ -- «cruft-begins» (to ".cruft-begins") --[====[ -- «Blogme» (to ".Blogme") -- Deleted! Superseded by: (find-anggfile "LUA/BlogMe3.lua") code_c_d_angg = function (c, d, suffix) local find_c = "find-"..c local find_cfile = "find-"..c.."file" _EHF[find_c ] = ELispHF.newangg(find_c, d, suffix or ".html") _EHF[find_cfile] = ELispHF.newangg(find_c, d, ".html") end -- (find-blogme3 "angglisp.lua" "code_c_m_b_s") -- (find-angg "LUA/lua50init.lua" "ELispHF") -- (find-es "blogme" "code_c_m_b") infomanual_basedir = VerticalTable {} code_c_m_b = function (c, manual, basedir) infomanual_basedir[manual] = basedir local find_cnode = "find-"..c.."node" _EHF[find_cnode] = ELispHF.newnode(find_cnode, c, manual) end -- «code_video» (to ".code_video") -- Superseded by sandwiches: -- (find-blogme3file "sandwiches.lua") -- TODO: check which .blogme files still use this. -- -- Run this to make blogme3 process `(code-video "c" "fname")' sexps: -- _EHF["code-video"] = ELispHF {f="codevideo"} -- code_video = function (c, urlorfnameorhash) local find_c = "find-"..c local hash = to_youtube_hash(urlorfnameorhash) _EHF[find_c] = ELispHF.newyoutube(find_c, hash) end -- «ELispInfo» (to ".ELispInfo") -- (find-es "lua5" "ELispInfo") -- (find-blogme3 "sexp.lua" "find-xxxnodes") -- Superseded by sandwiches: -- (find-blogme3file "sandwiches.lua") -- TODO: check which .blogme files still use this. -- ELispInfo = Class { type = "ELispInfo", new = function (c, manual, basedir) infomanual_basedir[manual] = basedir return ELispInfo {c=c, manual=manual} end, __index = { -- convert [s]ection name to [h]tml shre = "([-'/ &])", shtable = {["-"] = "_002d", ["'"] = "_0027", ["/"] = "_002f", [" "] = "-", ["&"] = "-"}, shexpand = function (eli, section) return section:gsub("%s+", " "):gsub(eli.shre, eli.shtable) end, -- -- convert a pair (manual, section) to html mstohtml = function (eli, manual, section) if not manual or not section then return end local basedir = infomanual_basedir[manual] if not basedir then return end local sectionh = eli:shexpand(section) return basedir..sectionh..".html" end, -- a "nodename" is a string like "(libc)I/O Overview" nodenametohtml = function (eli, nodename) if not nodename then return end local manual, section = string.match(nodename, "^%(([^()]+)%)(.*)$") return eli:mstohtml(manual, section) end, -- -- -- convert a section name to html -- stohtml = function (eli, section) -- return eli:mstohtml(eli.manual, section) -- end, -- -- convert a (manual, section) pair or a section to an ELispH -- mstoeh = function (eli, manual, section) -- return ELispH {intro="eev-quick#3", target=eli:mstohtml(manual, section)} -- end, -- stoeh = function (eli, section) -- return ELispH {intro="eev-quick#9.2", target=eli:stohtml(section)} -- end, -- }, } -- _E = {} -- _E["to"] = ElispHF {intro="anchors", calctarget=calctarget_to} -- _E["find-angg"] = ElispHF {intro="anchors", d=""} -- «getsexpskel» (to ".getsexpskel") -- Olbsolete. -- Algorithm and tests: (find-es "lua5" "getsexpskel") -- -- getsexpskel = function (str) -- if str:sub(-1) ~= ")" then return end -- local f = function (s) return '"'..string.rep("_", #s-2)..'"' end -- local g = function (s) return ')'..string.rep("_", #s-2)..'(' end -- local str2 = str:gsub("\\.", "__") -- backslash+c -> __ -- local str3 = str2:reverse() -- local str4 = str3:gsub('"[^"]*"', f) -- local skel1 = str4:match("%b)("); if not skel1 then return end -- local skel2 = skel1:sub(2, -2):gsub("%b)(", g) -- local skel3 = skel2:reverse() -- return skel3 -- end -- «SexpLine» (to ".SexpLine") -- Obsolete. See: (find-es "lua5" "SexpLine") -- This was intended to replace some parts of: (find-blogme3 "escripts.lua") -- -- SexpLine = Class { -- type = "SexpLine", -- from = function (src) -- return SexpLine {src=src, skel=getsexpskel(src)} -- end, -- __tostring = function (sl) return mytabletostring(sl) end, -- __index = { -- skelf = function (sl) return sl.skel:match"^(%S+)" end, -- split = function (sl) -- local f = sl:skelf() -- local len = #sl.src -- local lensexp = #sl.skel + 2 -- local lena = len - lensexp -- local lenb = 1 -- local lenc = #f -- local lene = (sl.src:sub(-2, -2) == "\"") and 2 or 1 -- local lend = len - lena - lenb - lenc - lene -- sl.a = sl.src:sub(1, lena) -- sl.b = "(" -- sl.c = f -- sl.d = sl.src:sub(lena + lenb + lenc + 1, lena + lenb + lenc + lend) -- sl.e = sl.src:sub(-lene) -- local p1, p2 = sl.skel:match"^%S+%s+()%S+()" -- if p1 then -- local offset = lena + 1 -- sl.arg1 = sl.src:sub(offset + p1, offset + p2):match"^\"(.*)\"$" -- end -- return sl -- end, -- splitt = function (sl) -- for tests -- return sl.a.."|"..sl.b.."|"..sl.c.."|"..sl.d.."|"..sl.e -- end, -- splitsexp = function (sl) -- sl.nth = {} -- for p1,p2 in sl.skel:gmatch("()%S+()") do -- local b, e = #sl.a + 1 + p1, #sl.a + p2 -- local raw = sl.src:sub(b, e) -- local str = raw:match"^\"(.*)\"$" -- table.insert(sl.nth, {b=b, e=e, raw=raw, str=str}) -- end -- return sl -- end, -- n = function (sl) return #sl.nth end, -- rawarg = function (sl, n) return (sl.nth[n] or {}).raw end, -- arg = function (sl, n) return (sl.nth[n] or {}).str end, -- -- -- q = function (sl, body) return body end, -- r = function (sl, url, body) -- return url and format('<a href="%s">%s</a>', url, body) or body -- end, -- sethtml = function (sl) -- sl.f = sl.skel and sl:skelf() -- sl.ef = sl.f and _E[sl.f] -- if not sl.ef then -- sl.html = sl:q(sl.src) -- else -- sl:split() -- sl:splitsexp() -- sl.help = sl.ef:calchelp() -- sl.target = sl.ef:calctarget(sl:arg(2), sl:arg(3)) -- sl.sexphtml = sl.b.. -- sl:r(sl.help, sl.c).. -- sl:q(sl.d).. -- sl:r(sl.target, sl.e) -- sl.html = sl:q(sl.a) .. sl.sexphtml -- end -- return sl -- end, -- }, -- } --]====] -- «cruft-ends» (to ".cruft-ends") -- Local Variables: -- coding: utf-8-unix -- End: