Warning: this is an htmlized version!
The original is here, and the conversion rules are here. |
-- -*- coding: raw-text-unix -*- -- elisp.lua - convert elisp hyperlinks (in e-scripts) to html. -- This is part of blogme3. -- -- The ascii files at http://anggtwu.net/ are all e-scripts -- (see <http://anggtwu.net/eev-article.html#e-scripts>); the code in -- blogme3 that converts them to HTML is spread over three files: -- (find-blogme3 "escripts.lua") -- (find-blogme3 "elisp.lua") -- (find-blogme3 "angglisp.lua") -- and this one is the second of them. The files escripts.lua and -- elisp.lua can be loaded independently of one another, and -- escripts.lua needs lpeg; because of this I'm currently making -- blogme3.lua always load elisp.lua, even though I'm not using its -- functions elsewhere... At some point I will clean this. -- -- Author: Eduardo Ochs <eduardoochs@gmail.com> -- Version: 2014jan24 -- <http://anggtwu.net/blogme3/elisp.lua> -- <http://anggtwu.net/blogme3/elisp.lua.html> -- License: GPL. -- (find-es "lua5" "sheadsymbol-roberto") -- (find-angg "LUA/lua50init.lua") -- (find-angg "LUA/lua50init.lua" "loadlpeg") -- (find-lpegw3m "doc.html" "function anywhere (p)") -- (find-blogmefile "blogme2-outer.lua" "entities and quoting (Q)") -- (find-anggfile "TH/Generate") -- (find-anggfile "TH/Generate" "txt2html") -- Quick index: -- «.tools» (to "tools") -- «.makesexphtml» (to "makesexphtml") -- «.maketarget» (to "maketarget") -- «.relative-links» (to "relative-links") -- «._E» (to "_E") -- «._E_intro» (to "_E_intro") -- «.Tgt» (to "Tgt") -- «.TGT» (to "TGT") -- «.set_E4» (to "set_E4") -- «.set_EHELP» (to "set_EHELP") -- «.code_c_d_local» (to "code_c_d_local") -- «.code_c_d_remote» (to "code_c_d_remote") -- «._E4s_as_lua» (to "_E4s_as_lua") --------[ Some tools ]-------- -- «tools» (to ".tools") null = function (obj) return obj == nil or obj == "" end isdir = function (str) return str == "" or string.sub(str, -1, -1) == "/" end -- dequote = function (sstr) return sstr and string.sub(sstr, 2, -2) end dequote = function (qstr) return qstr and qstr:match "^\"(.*)\"$" end href = function (target, text) if target then return format("<a href=\"%s\">%s</a>", target, text) end return text -- if target is nil then return text unchanged, not an href end --------[ makesexphtml ]-------- -- «makesexphtml» (to ".makesexphtml") -- Sexp hyperlinks are usually htmlized like this: -- -- (find-eev "eev-mini.el") -- \------/ \/ -- this points this points to -- to help on the result of -- "find-eev" evaluating the sexp -- -- The html for them is produced by the function "makesexphtml". -- It receives four arguments: -- (name) (sample value or description) -- all [[(find-eev "eev-mini.el")]] -- funname "find-eev" -- help URL of the help link, or nil -- target URL of the "result" link, or nil makesexphtml = function (all, funname, help, target) if all == 1 then return help end -- hack, 2007apr20 (unused) if all == 2 then return target end -- hack, 2007apr20 (for Tgt) if help then help = pathto(help) end -- hack, 2019feb20 local raw0, raw1, raw2, raw3 = "(", funname if string.sub(all, -2, -1) == "\")" then raw2, raw3 = string.sub(all, 2 + #funname, -3), "\")" else raw2, raw3 = string.sub(all, 2 + #funname, -2), ")" end return raw0 .. href(help, raw1) .. Q(raw2) .. href(target, raw3) end --------[ maketarget, makelocaltarget ]-------- -- «maketarget» (to ".maketarget") -- "maketarget" and "makelocaltarget" add a suffix (usually ".html") -- when the base url that they receive is not a directory, and add a -- "#tag" when their "tag" argument is not nil. maketarget = function (baseurl, suffix, tag) local url = baseurl if suffix and not isdir(baseurl) then url = url .. suffix end if not null(tag) then url = url .. "#" .. tag end return url end makelocaltarget = function (base, fname, suffix, tag) if fname then return maketarget(pathto(base..fname), suffix, tag) end end --------[ Relative links ]-------- -- «relative-links» (to ".relative-links") -- A link from -- "http://anggtwu.net/foo/bar/plic.html" to -- "http://anggtwu.net/ploc/bletch.html" should be relative: -- "../../ploc/bletch.html". -- For simplicity, a link from -- "http://anggtwu.net/foo/bar/plic.html" to -- "http://anggtwu.net/foo/blop.html" is relativized as -- "../../foo/blop.html", not as -- "../blop.html". -- My current convention is that I always run blogme3.lua from the -- "root of the output tree"; to generate -- http://anggtwu.net/foo/bar/plic.html -- I run something like, say, -- blogme3.lua -o foo/bar/plic.html -i ~/PAGESRC/foo/bar/plic.blogme -- from the directory "~/PAGE" or "/var/www/"... -- The function "getpathtoroot" can be used to set pathtoroot from the -- argument to "-o" - see blogme3.lua. pathtoroot = "" pathto = function (path) return pathtoroot .. path end getpathtoroot = function (path) local _, nslashes = string.gsub(path, "/", "/") return string.rep("../", nslashes) end --------[ _E_localanchor and friends ]-------- -- «_E» (to "._E") -- The functions in the table "_E" have signatures like -- "all,funname,qarg1,qarg2|->html"; here we define some of these -- functions, using "makesexphtml" and "maketarget"/"makelocaltarget" -- to do most of the work. We avoid using closures in _E because the -- code with them would be a bit harder to debug (and to explain...) - -- instead we use three extra tables, _EHELP, _EBASE, and _ESUFFIX. -- The values in _EBASE are interpreted differently by different -- "_E_kindoflink" functions. -- -- An example: when I generate the pages at angg I have this: -- _E ["find-eev"] = _E_localanchor -- _EHELP ["find-eev"] = eevarticle.."#shorter-hyperlinks" -- _EBASE ["find-eev"] = "eev-current/" -- _ESUFFIX["find-eev"] = ".html" -- and to produce the html for a link like -- -- (find-eev "eev-mini.el" "ee-code-c-d") -- -- the function "_E_localanchor" first "dequotes" its arguments qarg1 -- and qarg2 - that are [["eev-mini.el"]] and [["ee-code-c-d"]] - to -- remove the outer double-quotes from them. The results of the -- dequoting become the "fname" and the "tag" in the diagram below; -- they would be nil if the function "dequote" had received arguments -- that were not double-quoted strings. The values of "help", "base", -- and "suffix" are obtained from the entries for the funname -- ("find-eev", in this case) in the tables _EHELP, _EBASE, and -- _ESUFFIX. The first "}->" with four inputs and one output is -- "makelocaltarget", the second is "makesexphtml". -- -- Diagram from "_E_localanchor": -- all \ -- funname |---> sexphtml -- funname --_HELP-------------------> help | -- funname --_EBASE-----> base \---> target / -- \ fname | -- --_ESUFFIX---> suffix | -- tag / -- -- The other "_E_kindoflink" functions are similar, but simpler. _E = _E or {} _EBASE = _EBASE or {} _ESUFFIX = _ESUFFIX or {} _EHELP = _EHELP or {} _Es = _Es or {} -- eevarticle = pathto("eev-article.html") _E_localanchor = function (all, funname, qfname, qtag) local fname, tag = dequote(qfname), dequote(qtag) return makesexphtml(all, funname, _EHELP[funname], makelocaltarget(_EBASE[funname], fname, _ESUFFIX[funname], tag)) end _E_localfile = function (all, funname, qfname) local fname = dequote(qfname) return makesexphtml(all, funname, _EHELP[funname], makelocaltarget(_EBASE[funname], fname, _ESUFFIX[funname])) end _E_remoteanchor = function (all, funname, qfname, qtag) local fname, tag = dequote(qfname), dequote(qtag) if fname == nil then PP(all, funname, qfname, qtag) end return makesexphtml(all, funname, _EHELP[funname], maketarget(_EBASE[funname]..fname, _ESUFFIX[funname], tag)) end _E_remotefile = function (all, funname, qfname) local fname = dequote(qfname) return makesexphtml(all, funname, _EHELP[funname], maketarget(_EBASE[funname]..fname, _ESUFFIX[funname])) end _E_helponly = function (all, funname) return makesexphtml(all, funname, _EHELP[funname], nil) end _E_info = function (all, funname) -- a stub: info links are not working return makesexphtml(all, funname, _EHELP[funname], nil) end -- «_E_intro» (to "._E_intro") -- Added in 2019feb28 _E_intro = function (all, funname, qarg1, qarg2) local intro = "eev-intros/"..funname..".html" local posspec = dequote(qarg1) local sec = posspec and posspec:match "^(%d[%d%.]*)%. " local introsec = sec and intro.."#"..sec or intro return makesexphtml(all, funname, introsec, pathto(introsec)) end --------[ Tgt ]-------- -- «Tgt» (to ".Tgt") -- A hack. An example of usage: this block in blogme, -- [Tgt find-angg ".zshrc" "an_anchor" etc etc] -- evaluates to the target link of this sexp: -- (find-angg ".zshrc" "an_anchor") _A["Tgt"] = _AA["4"] _G["Tgt"] = function (funname, qarg1, qarg2, rest) if not _E[funname] then error(format("Tgt: not in _E: %q", funname)) end return _E[funname](2, funname, qarg1, qarg2) or error(format("Tgt: empty target for (%s %s %s)", funname, qarg1 or "nil", qarg2 or "nil")) end -- «TGT» (to ".TGT") -- 2007jul24: TGT is more natural to use than Tgt... -- Example: [TGT (find-enode "M-x")] def [[ ONESPACE 1 body string.gsub(body, "%s+", " ") ]] -- def [[ TGT 1 sexp Tgt(string.match(ONESPACE(sexp), "^%(([^%s]+) (.*)%)$")) ]] -- 2007sep29: (find-es "blogme" "_TARGETS" "SexpLink:match") -- the definition of TGT above is a hack that will not work always... -- When we need a "full TGT" we need to replace it like this: require "escripts" def [[ TGT 1 sexp Tgt(SexpLink:match(sexp)) ]] --------[ code_c_d ]-------- -- «set_E4» (to ".set_E4") -- «set_EHELP» (to ".set_EHELP") -- Functions to set many entries in the _Exxx tables at once. -- The top-level syntax - code_c_d_anchor(c, d) - is similar to the -- one that I use to define many hyperlink functions at once in elisp. -- Example: -- code_c_d_anchor("eev", "eev-current/") -- works as this: -- _E ["find-eev"] = _E_localanchor -- _EHELP ["find-eev"] = eevarticle.."#anchors" -- _EBASE ["find-eev"] = "eev-current/" -- _ESUFFIX["find-eev"] = ".html" -- _E ["find-eevfile"] = _E_localfile -- _EHELP ["find-eevfile"] = eevarticle.."#long" -- _EBASE ["find-eevfile"] = "eev-current/" -- _ESUFFIX["find-eevfile"] = "" set_E4 = function (funname, _e, _ehelp, _ebase, _esuffix) _E [funname] = _e _EHELP [funname] = _ehelp _EBASE [funname] = _ebase _ESUFFIX[funname] = _esuffix table.insert(_Es, funname) end set_EHELP = function (funname, help) -- set only _E and _EHELP set_E4(funname, _E_helponly, help) -- base and suffix are nil end --------[ code_c_d_local and code_c_d_remote ]-------- -- «code_c_d_local» (to ".code_c_d_local") -- «code_c_d_remote» (to ".code_c_d_remote") -- (find-blogme3 "angglisp.lua" "code_c_d_angg") -- (find-eev-quick-intro "9. Shorter hyperlinks") code_c_d_local = function (c, d) -- local h = eevarticle.."#shorter-hyperlinks" -- local h = eevintro "code-c-d" local h = "eev-intros/find-eev-quick-intro.html#9" set_E4("find-"..c.."file", _E_localfile, h, d, "") set_E4("find-"..c, _E_localanchor, h, d, ".html") set_E4("find-"..c.."w3m", _E_localfile, h, d, "") end code_c_d_remote = function (c, d) -- local h = eevarticle.."#shorter-hyperlinks" -- local h = eevintro "code-c-d" local h = "eev-intros/find-eev-quick-intro.html#9" set_E4("find-"..c.."file", _E_remotefile, h, d, "") set_E4("find-"..c, _E_remoteanchor, h, d, ".html") set_E4("find-"..c.."w3m", _E_remotefile, h, d, "") end --------[ Dump the four _E tables ]-------- -- «_E4s_as_lua» (to "._E4s_as_lua") -- (find-blogme3file "definers.lua" "def_as_lua =") _E4_as_lua = function (funname) if not f2n then f2n = preparef2n() end local _e = _E [funname] local _ehelp = _EHELP [funname] local _ebase = _EBASE [funname] local _esuffix = _ESUFFIX[funname] local _ename = f2n and f2n[_e] or mytostring(_e) return format([[ _E [%q] = %s _EHELP [%q] = %q _EBASE [%q] = %q _ESUFFIX[%q] = %q ]], funname, _ename, funname, _ehelp, funname, _ebase, funname, _esuffix) end _E4s_as_lua = function () return table.concat(map(_E4_as_lua, _Es), "\n") end --------[ Elisp hyperlinks that are not angg-specific ]-------- -- _EHELP["to"] = eevarticle.."#anchors" -- _E ["to"] = function (all, funname, qtag) -- local tag = dequote(qtag) -- return makesexphtml(all, funname, eevarticle.."#anchors", tag and "#"..tag) -- end