Warning: this is an htmlized version!
The original is here, and the conversion rules are here. |
#!/usr/bin/env lua5.1 ---- This is a one-file version of blogme4, generated ---- automatically by build.lua on 2011Oct03 2:19 BRT. See: ---- http://angg.twu.net/blogme4/build.lua.html ---- (find-blogme4 "build.lua") ---- This file: ---- http://angg.twu.net/blogme4/blogme4.lua.html ---- (find-blogme4 "blogme4.lua") ---- Index to the modules: -- «.common.lua» (to "common.lua") -- «.eoo.lua» (to "eoo.lua") -- «.def.lua» (to "def.lua") -- «.eval.lua» (to "eval.lua") -- «.brackets.lua» (to "brackets.lua") -- «.elisp.lua» (to "elisp.lua") -- «.angglisp.lua» (to "angglisp.lua") -- «.anggdefs.lua» (to "anggdefs.lua") -- «.anggdefs.lua» (to "anggdefs.lua") -- «.texinfo.lua» (to "texinfo.lua") -- «.options.lua» (to "options.lua") ---- «common.lua» (to ".common.lua") ---- This block is from: (find-blogme4 "common.lua") -- common.lua: functions from my LUA_INIT file. -- This file: -- http://angg.twu.net/blogme4/common.lua.html -- http://angg.twu.net/blogme4/common.lua -- (find-blogme4 "common.lua") -- Author: Eduardo Ochs <eduardoochs@gmail.com> -- Version: 2011aug04 -- License: GPL3 -- -- «.pathto» (to "pathto") -- (find-angg "LUA/lua50init.lua" "readfile") -- (find-angg "LUA/lua50init.lua" "writefile") readfile = function (fname) local f = assert(io.open(fname, "r")) local bigstr = f:read("*a") f:close() return bigstr end writefile = function (fname, bigstr) local f = assert(io.open(fname, "w+")) f:write(bigstr) f:close() end -- (find-angg "LUA/lua50init.lua" "printf") printf = function (...) io.write(string.format(...)) end -- (find-angg "LUA/lua50init.lua" "pack-and-unpack") pack = table.pack or function (...) return {n=select("#", ...), ...} end unpack = function (T) return table.unpack(T, 1, T.n) end -- (find-angg "LUA/lua50init.lua" "mapconcat") map = function (f, arr, n) local brr = {} for i=1,(n or #arr) do table.insert(brr, f(arr[i])) end return brr end mapconcat = function (f, tbl, sep) return table.concat(map(f, tbl), sep) end nop = function () end id = function (...) return ... end -- (find-angg "LUA/lua50init.lua" "gformat") -- Examples: gformat "<%1_%1>" "foo" --> "<foo_foo>" -- mapconcat(gformat "<%1_%1>", split "foo ba", ", ") --> "<foo_foo>, <ba_ba>" gformat = function (fmt, pat) return function (str) return (str:gsub((pat or "^.*$"), fmt)) end end -- (find-angg "LUA/lua50init.lua" "split") split = function (str, pat) local T = {} string.gsub(str, pat or "([^%s]+)", function (word) T[#T+1] = word end) return T end -- (find-angg "LUA/lua50init.lua" "splitlines") splitlines = function (bigstr) local lines = split(bigstr, "([^\n]*)\n?") table.remove(lines) return lines end maplines = function (f, bigstr) return mapconcat(f, splitlines(bigstr), "\n") end -- (find-angg "LUA/lua50init.lua" "mytostring") tos_compare_pairs = function (pair1, pair2) local key1, key2 = pair1.key, pair2.key local type1, type2 = type(key1), type(key2) if type1 == type2 then if type1 == "number" then return key1 < key2 end if type1 == "string" then return key1 < key2 end return tostring(key1) < tostring(key2) -- fast else return type1 < type2 -- numbers before strings before tables, etc end end tos_sorted_pairs = function (T) local Tpairs = {} for key,val in pairs(T) do table.insert(Tpairs, {key=key, val=val}) end return sorted(Tpairs, tos_compare_pairs) end tos_table_orig = function (T, sep) return "{"..mapconcat(tos_pair, tos_sorted_pairs(T), sep or ", ").."}" end tos_table = tos_table_orig tos = function (o) local t = type(o) if t=="number" then return tostring(o) end if t=="string" then return string.format("%q", o) end if t=="table" then return tos_table(o) end return "<"..tostring(o)..">" end tos_key = tos -- change this to print string keys differently tos_pair = function (pair) return tos_key(pair.key).."="..tos(pair.val) end mysort = tos_sorted_pairs -- compatibility mytostring = tos -- compatibility mytostring_arg = function (T, sep) return mapconcat(tos, T, sep or " ", T.n) end -- Tools for building extensions tos_good_string_key = function (key) return type(key) == "string" and key:match("^[A-Za-z_][A-Za-z_0-9]*$") end tos_has_tostring = function (o) return getmetatable(T) and getmetatable(T).__tostring end tos_has_eootype = function (o) return type(o) == "table" and getmetatable(o) and getmetatable(o).type end -- (find-angg "LUA/lua50init.lua" "PP") PP = function (...) local arg = pack(...) for i=1,arg.n do printf(" %s", tos(arg[i])) end printf("\n") return ... end -- (find-angg "LUA/lua50init.lua" "translatechars") translatechars = function (str, re, tbl) return (str:gsub(re, function (c) return tbl[c] or c end)) end -- (find-angg "LUA/lua50init.lua" "each2") each2 = function (T) local i = 1 return function () if i <= #T then i = i+2; return T[i-2], T[i-1] end end end -- (find-blogme3 "blogme3.lua" "blogmedir") fnamedirectory = function (fname) return fname:match"^(.*/)[^/]*$" end fnamenondirectory = function (fname) return fname:match "([^/]*)$" end -- «pathto» (to ".pathto") -- (find-blogme4 "options.lua" "dooption_o") pathtoroot = "" pathtoroot_ = function (path) local _, nslashes = path:gsub("/", "/") return ("../"):rep(nslashes) end pathto = function (path) return pathtoroot..path end ---- «eoo.lua» (to ".eoo.lua") ---- This block is from: (find-blogme4 "eoo.lua") -- eoo.lua: Edrx'x simple OO scheme. -- This file: -- http://angg.twu.net/blogme4/eoo.lua.html -- http://angg.twu.net/blogme4/eoo.lua -- (find-blogme4file "eoo.lua") -- Author: Eduardo Ochs <eduardoochs@gmail.com> -- Version: 2011jan12 -- License: GPL3 -- -- A very simple object system. -- The metatable of each object points to its class, -- and classes are callable, and act as creators. -- New classes can be created with, e.g.: -- Circle = Class { type = "Circle", __index = {...} } -- then: -- Circle {size = 1} -- sets the metatable of the table {size = 1} to Circle, -- and returns the table {size = 1} (with its mt modified). -- -- Originally from: (find-angg "LUA/canvas2.lua" "Class") -- A tool: (find-angg ".emacs.templates" "class") -- Inheritance: (find-dn5 "eoo.lua") -- Announcement: http://lua-users.org/lists/lua-l/2011-03/msg00975.html -- «.test-eoo» (to "test-eoo") Class = { type = "Class", __call = function (class, o) return setmetatable(o, class) end, } setmetatable(Class, Class) otype = function (o) -- works like type, except on my "objects" local mt = getmetatable(o) return mt and mt.type or type(o) end ---- «def.lua» (to ".def.lua") ---- This block is from: (find-blogme4 "def.lua") -- definers.lua: blogme3's def, DEF and friends, rewritten. -- This file: -- http://angg.twu.net/blogme4/definers.lua.html -- http://angg.twu.net/blogme4/definers.lua -- (find-blogme4 "definers.lua") -- Author: Eduardo Ochs <eduardoochs@gmail.com> -- Version: 2011feb17 -- License: GPL3 -- -- See: (find-angg "LUA/canvas2.lua" "Class") -- (find-blogme3 "definers.lua") -- (find-blogme3 "definers.lua" "def") -- «.undollar» (to "undollar") -- «.BlogmeWord» (to "BlogmeWord") -- «.def» (to "def") -- «.test-def» (to "test-def") -- require "eoo" -- (find-blogme4 "eoo.lua") -- «undollar» (to ".undollar") -- undollar: apply three kinds of "string interpolations" on code. -- This is very hard to understand without examples, so: -- -- undollar [[ "foo $bar plic" ]] --> [[ "foo "..bar.." plic" ]] -- undollar [[ "foo$(bar)plic" ]] --> [[ "foo"..(bar).."plic" ]] -- undollar " [[foo$[1+2]bar]] " --> " [[foo]]..(1+2)..[[bar]] " -- undollar = function (code) code = code:gsub("%$([a-z]+)", "\"..%1..\"") code = code:gsub("%$(%b())", "\"..%1..\"") code = code:gsub("%$(%b[])", function (s) return "]]..("..s:sub(2, -2)..")..[[" end) return code end wrap_f = function (arglist, statements) return "function ("..arglist..")\n"..statements.."\nend" end wrap_fr = function (arglist, expr) return "function ("..arglist..")\nreturn "..expr.."\nend" end wrap_rf = function (arglist, statements) return "return function ("..arglist..")\n"..statements.."\nend" end wrap_rfr = function (arglist, expr) return "return function ("..arglist..")\nreturn "..expr.."\nend" end -- wrap_fu = function (argl, body) return wrap_f (argl, undollar(body)) end -- wrap_fru = function (argl, body) return wrap_fr(argl, undollar(body)) end -- «BlogmeWord» (to ".BlogmeWord") -- The class of blogme words, -- and a way to create a bword from a string. -- See: (find-blogme4 "eoo.lua") -- BlogmeWord = Class { type = "BlogmeWord", __index = { fu = function (bw) return wrap_f (bw.arglist, undollar(bw.body)) end, fru = function (bw) return wrap_fr(bw.arglist, undollar(bw.body)) end, }, __call = function (bw, ...) return bw.fun(...) end, } BlogmeWordFrom = function (defspec) local name, argp, arglist, body = string.match(defspec, "^%s*(%S+)%s+(%S+)%s+(%S+)%s(.*)") assert(name, "defspec is not of the form \"name argp arglist body\"") local bw = BlogmeWord {name=name, argp=argp, arglist=arglist, body=body} return bw end -- «def» (to ".def") -- Old version: (find-blogme3 "definers.lua" "def") -- Examples of usage: (find-blogme4 "anggdefs.lua") -- Here we define Def_, Def, def_ and def, where: -- Def_ and def_ store a BW in _B, -- Def and def store a BW in _B and in _G. -- Def_ and Def expect a series of statements, -- def_ and def expect an expression. -- and: -- _G is the table of global symbols (usually lua functions), -- _B is the table of blogme words (instances of BlogmeWord). -- Here's the trick for remembering which function does what. -- In "Def_" and "Def" everything is bigger: they start with an -- uppercase letter (yeah!) and they expect a longer, more serious -- piece of code, made of several statements, possibly even starting -- with declarations of local variables, and usually ending with a -- "return". In contrast, "def_" and "def" are for smaller things, -- and they expect an expression (because internally they prepend a -- "return " to their code). -- An "_" always suggests "low-level", so "Def_" and "def_" do less -- than "Def" and "def". "Def_" and "def_" install the newly-defined -- word only in _B, while "Def" and "def" also copy it to _G. _B = {} Def_ = function (defspec, prefix) local bw = BlogmeWordFrom(defspec) local arglist = bw.arglist local body = bw.body local code = wrap_rf(arglist, (prefix or "")..undollar(body)) -- PP(bw.name, code) bw.fun = assert(loadstring(code, bw.name))() _B[bw.name] = bw return bw end Def = function (defspec, prefix) local bw = Def_(defspec, prefix) _G[bw.name] = bw return bw end def_ = function (defspec) return Def_(defspec, "return ") end def = function (defspec) return Def (defspec, "return ") end ---- «eval.lua» (to ".eval.lua") ---- This block is from: (find-blogme4 "eval.lua") -- eval.lua: functions for parsing and evaluating blogme code. -- This file: -- http://angg.twu.net/blogme4/eval.lua.html -- http://angg.twu.net/blogme4/eval.lua -- (find-blogme4file "eval.lua") -- Author: Eduardo Ochs <eduardoochs@gmail.com> -- Version: 2011feb17 -- License: GPL3 -- -- «.control-flow» (to "control-flow") -- «.parse_pattern» (to "parse_pattern") -- «.tlongwords» (to "tlongwords") -- «.qlongwords» (to "qlongwords") -- «.tlongword_mapconcat» (to "tlongword_mapconcat") -- «.longwords» (to "longwords") -- «.readvword» (to "readvword") -- «.readvrest» (to "readvrest") -- «.readqword» (to "readqword") -- «.readqrest» (to "readqrest") -- «._A» (to "_A") -- «.with_subj» (to "with_subj") -- «.blogme_eval» (to "blogme_eval") -- «.test-tlongword» (to "test-tlongword") -- «.test-parse» (to "test-parse") -- «.test-read» (to "test-read") -- «control-flow» (to ".control-flow") -- The difficult part of evaluation is dealing with the [] "blocks". -- The execution flow involves this very nasty recursion: -- -- blogme_eval(subj) -- v -- with_subj(subj, readverylongword) -- v -- readverylongword() <--------------------------\ -- v | -- parse_verylongword(blogme_evalblock) | -- v | -- /-> tlongword_mapconcat(blogme_evalblock, T, "") | -- | : | -- | v | -- | blogme_evalblock(s, e) | -- | v | -- | with_pos_endpos(s+1, e-1, blogme__eval) | -- | v | -- | blogme__eval() | -- | v | -- | _A[argp]() | -- | : | -- | v | -- | readvvvrest() | -- | | | \ | -- | v v v | -- | readvword() readvrest() | -- | v | | -- | readlongword() \------------------------/ -- | v -- \-- parse_longword(blogme_evalblock) -- «parse_pattern» (to ".parse_pattern") -- Conventions for the "parse*" functions -- ====================================== -- They operate on these three globals: -- subj (read-only), -- pos (advanced when parsing succeeds, unchanged when not), -- oldpos (gets the old value of pos on success, garbage on failure), -- result (discussed below; relevant on success, garbage on failure), -- and they return true if they succed, nil if they fail. -- They are all called either "parse__blah" or "parse_blah". -- The "parse__blah" functions just store "oldpos" in "result". -- The "parse_blah" functions are more complex, and they produce less -- trivial "result"s. In most cases - mainly the cases implemented -- with "parse_pattern" - their results are the substring of subj -- between oldpos and pos; the cases involving "longwords" will be -- described below. -- -- The "blah" in the names of the "parse__blah" and "parse_blah" -- function indicate what those functions try to parse, and -- (sometimes) how the result is calculated from the parsed region: -- "spaces": one or more whitespace chars -- "block": a region enclosed in balanced "[]"s -- "wchars": one or more "word chars", i.e., which are neither -- whitespace nor "[]"s -- "rchars": one or more "regular chars", i.e., those which are -- not "[]"s. -- parse_pattern = function (pat) oldpos, result, pos = pos, subj:match(pat, pos) if not pos then pos = oldpos else return true end end parse__spaces = function () return parse_pattern("^()[ \t\n]+()") end parse_spaces = function () return parse_pattern("^([ \t\n]+)()") end parse__wchars = function () return parse_pattern("^()[^ \t\n%[%]]+()") end parse_wchars = function () return parse_pattern("^([^ \t\n%[%]]+)()") end parse__rchars = function () return parse_pattern("^()[^%[%]]+()") end parse_rchars = function () return parse_pattern("^([^%[%]]+)()") end parse__block = function () return parse_pattern("^()%b[]()") end -- slow parse_block = function () return parse_pattern("^(%b[])()") end -- slow -- «tlongwords» (to ".tlongwords") -- A "longword" is something of the form "(wchars | block)+", and a -- "verylongword" is something of the form "(rchars | block)+". A -- string like "a[+ 1 2][+ 3 4]b c[+ 5 6]d" is two longwords, -- separated by a space, and is a single verylongword; verylongwords -- end at "]"s or the end of the string, while longwords can also end -- at whitespace. -- Usually we want the "value" of a longword/verylongword; the "value" -- is calculated by replacing each "[]" in the {very}longword by its -- result - for example, the "value" of "a[+ 1 2][+ 3 4]b" is "a37b". -- To calculate these "values" we need a nasty recursion, so here we -- start with something simpler. -- -- A "tlongword" is an array of strings and {begpos, endpos} pairs. -- For example, the value "as a tlongword" of the string -- -- 11111111112222 -- -- 12345678901234567890123 -- subj = "e[+ 1 [+ 2 3]]f[+ 4 5]" -- is: -- {"e", {2, 15}, "f", {16, 22}} -- Note that: -- subj:sub(2, 15) == "[+ 1 [+ 2 3]]" -- parse__xcharsandblocks = function (parse_xchars) local origpos = pos local T = {} -- a table of strings and {begpos, endpos} pairs local push = function (r) table.insert(T, r) end while parse__block() do push({oldpos, pos}) end -- push pair while parse_xchars() do push(result) -- push string while parse__block() do push({oldpos, pos}) end -- push pair end result = T -- the result is a table of strings and pairs oldpos = origpos return #T > 0 end parse_tlongword = function () return parse__xcharsandblocks(parse_wchars) end parse_tverylongword = function () return parse__xcharsandblocks(parse_rchars) end -- «qlongwords» (to ".qlongwords") -- Quoted longwords. -- These are used by blogme words like "#" and "lua:". parse__qlongword = function () if parse_tlongword() then result = oldpos return true end end parse_qlongword = function () if parse_tlongword() then result = subj:sub(oldpos, pos-1) return true end end parse__qverylongword = function () if pos < endpos then oldpos, pos, result = pos, endpos, pos return true end end parse_qverylongword = function () if pos < endpos then oldpos, pos, result = pos, endpos, subj:sub(pos, endpos-1) return true end end -- «tlongword_mapconcat» (to ".tlongword_mapconcat") -- This is the function that we use to evaluate tlongwords. -- The function "f" is usually "blogme_evalblock", so this ends up -- being recursive. -- See: (find-blogme4 "eval.lua" "blogme_eval") -- (find-elnode "Mapping Functions" "Function: mapconcat") -- In blogme3 I implemented a special behavior for tlongwords of -- length 1 - I skipped the concatenation step. This should be done -- here too, I think (for HLIST and friends?). -- tlongword_mapconcat = function (f, T, sep) if not T then return nil end for i=1,#T do if type(T[i]) == "table" then T[i] = f(T[i][1], T[i][2]) or "" end -- Note that *we change the table T*!!! end if #T == 1 then return T[1] end return table.concat(T, sep) end -- «longwords» (to ".longwords") -- These functions are similar to the ones that return tlongwords, but -- here we run tlongword_mapconcat to return the "values" of these -- tlongwords. -- (I think that they destroy endpos... is that important?) parse_longword = function (eval_block) if not parse_tlongword() then return nil end result = tlongword_mapconcat(eval_block, result, "") return true end parse_verylongword = function (eval_block) if not parse_tverylongword() then return nil end result = tlongword_mapconcat(eval_block, result, "") return true end -- «readvword» (to ".readvword") -- «readvrest» (to ".readvrest") -- The "read*" functions are high-level functions used to parse -- arguments for blogme "calls"; they follow conventions that are -- quite different from the "parse*" functions. -- For example, the argparser for "HREF" has to parse a longword -- and a verylongword; in the evaluation process for -- "[HREF http://foo/ bar plic]" -- we get: -- HREF(readvvrest()) -- that becomes: -- HREF("http://foo/", "bar plic") -- but -- "[HREF http://foo/ bar plic]" -- becomes: -- HREF("http://foo/", "") -- -- Shorthands: a "vword" is the value of a longword; a "vrest" (used -- to obtain the "rest of the arguments", as &rest in Lisp) is the -- value of a verylongword. Additional "v"s in the prefix mean vwords; -- for example, a "vvvrest" is a vword, then another vword, then a -- vrest. -- -- Remember that the "parse*" functions returned a flag, and stored -- the "result" of the parsed region in the global variable "result". -- The "read*" functions return their "results" straight away, and in -- the case of failure (i.e., of parsing nothing) they return the -- empty string. Also, they parse (and discard) spaces before each -- vword and vrest. readlongword = function () if parse_longword(blogme_evalblock) then return result end return "" end readverylongword = function () if parse_verylongword(blogme_evalblock) then return result end return "" end readvword = function () parse__spaces(); return readlongword() end readvrest = function () parse__spaces(); return readverylongword() end readvvrest = function () return readvword(), readvrest() end readvvvrest = function () return readvword(), readvvrest() end readvvvvrest = function () return readvword(), readvvvrest() end readvvvvvrest = function () return readvword(), readvvvvrest() end -- «readqword» (to ".readqword") -- «readqrest» (to ".readqrest") readqlongword = function () if parse_qlongword() then return result end return "" end readqverylongword = function () if parse_qverylongword() then return result end return "" end readqword = function () parse__spaces(); return readqlongword() end readqrest = function () parse__spaces(); return readqverylongword() end readqqrest = function () return readqword(), readqrest() end readqqqrest = function () return readqword(), readqqrest() end readqqqqrest = function () return readqword(), readqqqrest() end readqqqqqrest = function () return readqword(), readqqqqrest() end -- «_A» (to "._A") -- (find-blogme3 "definers.lua" "_AA") -- (find-blogme3 "brackets.lua" "readvword") -- (find-blogme3 "anggdefs.lua" "basic-special-words" "lua:") _A = _A or {} _A["0"] = nop _A["1"] = readvrest _A["2"] = readvvrest _A["3"] = readvvvrest _A["4"] = readvvvvrest _A["5"] = readvvvvvrest _A["1Q"] = readqrest _A["2Q"] = readqqrest _A["3Q"] = readqqqrest _A["4Q"] = readqqqqrest _A["5Q"] = readqqqqqrest -- «with_subj» (to ".with_subj") with_pos_endpos = function (pos_, endpos_, f) local backups = {pos=pos, endpos=endpos} pos, endpos = pos_, endpos_ local r = f(pos, endpos) pos, endpos = backups.pos, backups.endpos return r end with_subj = function (subj_, f) local backups = {subj=subj, pos=pos, endpos=endpos} subj, pos, endpos = subj_, 1, #subj_+1 local r = f(pos, endpos) subj, pos, endpos = backups.subj, backups.pos, backups.endpos return r end -- «blogme_eval» (to ".blogme_eval") -- "blogme__eval" (with a double "__") is a very low-level function, -- that does the heavy work for both "blogme_evalblock" and -- "blogme_eval". It takes as its "input" the global variables subj, -- pos and endpos, parses a word, and then returns the result of -- wordf(argpf()). Here is a typical example of how it runs. If: -- subj = "ab [HREF http://foo/ bar] cd" -- pos = 5 -- endpos = 25 -- then "word" is "HREF", "argp" is "2", and the result of argpf() -- is the sequence "http://foo/", "bar"; then blogme__eval will -- return the result of HREF("http://foo/", "bar"). -- Note that blogme__eval uses the table _B of blogmewords and -- the table _A or argparser codes. See: -- (find-blogme4 "def.lua" "BlogmeWord") -- -- "blogme_evalblock" is used to run a blogme "call" inside "[]s" (as -- in the example above). -- -- "blogme_eval" is used to evaluate all the blogme calls inside a -- string, replacing each one by its result; for example, -- blogme_eval "ab [HREF http://foo/ bar] cd" -- returns -- "ab " .. HREF("http://foo/", "bar") .. " cd". -- blogme__eval = function () parse__spaces() if not parse_wchars() then error("Empty word!") end local word = result local bword = _B[word] or error("Unknown blogme word: "..word) local wordf = bword.fun local argp = bword.argp local argpf = (type(argp) == "string" and (_A[argp] or _G[argp])) or argp or error("Unknow arglist parser: "..argp) return wordf(argpf()) end blogme_evalblock = function (s, e) return with_pos_endpos(s+1, e-1, blogme__eval) -- skip the '[' and the ']' end blogme_eval = function (subj_) return with_subj(subj_, readverylongword) end ---- «brackets.lua» (to ".brackets.lua") ---- This block is from: (find-blogme4 "brackets.lua") -- brackets.lua, rewritten for blogme4. -- This file: -- http://angg.twu.net/blogme4/brackets.lua.html -- http://angg.twu.net/blogme4/brackets.lua -- (find-blogme4file "brackets.lua") -- Author: Eduardo Ochs <eduardoochs@gmail.com> -- Version: 2011jan06 -- License: GPL3 -- -- See: (find-blogme3 "brackets.lua" "brackstructure") -- «.bracketstructure» (to "bracketstructure") -- «.test-brackets» (to "test-brackets") -- «bracketstructure» (to ".bracketstructure") -- Sometimes (actually, VERY often) we will have to jump over pairs of -- matching brackets in blogme source files... So let's implement a -- very efficient way to do that. -- -- Note that these functions are optional, and if they are loaded they -- are only used by the replacements for parse__block and parse_block, -- below. -- bracketstructure = function (subj) local pos2pos, stack = {}, {} local f = function (pos, c) if c == "[" then stack[#stack + 1] = pos else if #stack == 0 then error("Extra ']' at "..pos) end local openpos = stack[#stack] stack[#stack] = nil pos2pos[openpos], pos2pos[pos] = pos, openpos end end subj:gsub("()([%[%]])", f) if #stack > 0 then error("Extra '[' at "..stack[#stack]) end return pos2pos end bracketstructures = {} -- the cache afterclosing = function (subj, pos) local bs = bracketstructures[subj] or bracketstructure(subj) bracketstructures[subj] = bs -- store the resulting table into the cache if bs[pos] and bs[pos] > pos then return bs[pos] + 1 end end printbracketstructure = function (subj) local pos2pos = bracketstructure(subj) for _,pos in ipairs(sorted(keys(pos2pos))) do local otherpos = pos2pos[pos] if pos < otherpos then print(subj:sub(pos, otherpos)) end end end -- Override two functions from argparsers.lua with faster versions. -- The original parse__block and parse_block use string.match with the -- %b[]" pattern: -- (find-blogme4 "argparsers.lua" "parse_pattern" "parse__block") -- (find-blogme4 "argparsers.lua" "parse_pattern" "parse_block") -- (find-luamanualw3m "#5.4.1" "Patterns" "%b()") -- parse__block = function () oldpos, pos = pos, afterclosing(subj, pos) if not pos then pos = oldpos else return true end end parse_block = function () if parse__block() then result = subj:sub(oldpos, pos) return true end end ---- «elisp.lua» (to ".elisp.lua") ---- This block is from: (find-blogme4 "elisp.lua") -- elisp.lua: parse and interpret sexp hyperlinks. -- This file: -- http://angg.twu.net/blogme4/elisp.lua.html -- http://angg.twu.net/blogme4/elisp.lua -- (find-blogme4 "elisp.lua") -- Author: Eduardo Ochs <eduardoochs@gmail.com> -- Version: 2011aug01 -- License: GPL3 -- -- The docs below are a mess!!! -- -- Let me start by supposing that you know what a sexp is. Then you -- know what a "sexp one-liner" is, and I will say that a line "has an -- elink" if it is made of some "prefix characters" (possibly zero), -- then a sexp (a list), then optional spaces. -- The "sexp hyperlinks" used by eev are elinks. -- See: (find-eevarticlesection "hyperlinks") -- http://en.wikipedia.org/wiki/S-expression -- -- One of the hardest parts of htmlzing the material in -- http://angg.twu.net/ is that many of the files there require -- htmlizing "sexp hyperlinks", like this one: -- -- (find-blogme4 "def.lua" "undollar") -- -- the htmlization makes the "find-blogme4" into a link to a section -- of the documentation about eev, and makes the two last chars of the -- sexp, '")', behave somehow like what the sexp would do when run in -- Emacs... -- (find-blogme4 "hyperlinks") -- Here is a rough sketch of what we need to do on each line that may -- end with a sexp ("rough sketch" means "the details are below, -- scattered around")... We need to: -- -- 1) detect whether that line ends with a sexp, -- 2) split each line that ends with a sexp into what comes before -- the sexp (we call that the "pre"), the hyperlink itself (the -- "sexp") and the optional spaces after the sexp ("the spaces"), -- 3) split the sexp into its "elements", -- 4) check whether the first "element" (the "head") is a symbol, -- 5) check whether the "head" has an entry in the table "ewords", -- 6) if it has, we need to run sexp:sexphtml(), that usually: -- 7) splits the sexp into an "opening parenthesis" (the "o"), -- the "word" (the "w"), the "rest" ("r") and the "close" -- (usually the two last chars - '")'), -- 8) determines the "help url" that will be associated to the -- "word" and the "target url" that will be associated to the -- "close", -- 9) compose "o", "w", "r", "c" and the help url and the target -- url to build an htmlization of the sexp, -- -- I found a nice hackish way to detect if a line "has an elink". -- The algorithm is non-recursive, does not backtrack, runs very -- quickly, and can be implemented in Lua using just string.gsub, -- string.reverse and string.match. And it doesn't need Lpeg!... -- -- The rough idea is: -- 1) first simplify all literal strings - like "foo bar" - by: -- 1a) replacing all backslash-char pairs by "__"s, and then -- 1b) replacing all chars inside double-quotes by "_"s; -- 2) then, starting from the right, use Lua's "%b" pattern to find -- matching "()"s. -- -- Part of the trick is that we use string.reverse judiciously at the -- right points of the algorithm to perform pattern matches "starting -- from the right". Also, we produce a "simplified string" and work on -- it, but we keep the original string (that has the same length as -- the simplified one), and after doing all the parsing and -- discovering where the sexp and all its "elements" start and end we -- go back to the original string. -- -- Here's an example that illustrates how the algorithm works. -- line = [[ # (foo "a") (bar "plic: \"ploc\"") ]] -- -- skel = [[ # (foo "a") (bar "plic: __ploc__") ]] -- leks = [[ # (foo "_") (bar "______________") ]]:reverse() -- secaps = [[ ]]:reverse() -- lekspxes = [[(bar "______________")]]:reverse() -- sexpskel = [[(bar "______________")]] -- erp = [[ # (foo "_") ]]:reverse() -- -- pre = [[ # (foo "a") ]] -- sexp = [[(bar "plic: \"ploc\"")]] -- spaces = [[ ]] -- 1 = {0=[[bar]], 2, 5}, -- 2 = {0=[["plic: \"ploc\""]], 6, 22} -- -- o = [[(]] -- w = [[bar]] -- r = [[ "plic: \"ploc\"]] -- c = [[")]] -- require "eoo" -- (find-blogme4 "eoo.lua") -- require "common" -- (find-blogme4 "common.lua") Q = Q or id -- (find-blogme4 "anggdefs.lua" "Q") -- Some utility functions notdir = function (str) return str:match "[^/]$" end -- "" is a directory addfileext = function (fname, ext) if fname and ext and notdir(fname) then return fname..ext end return fname end addanchor = function (url, anchor) if url and anchor then return url.."#"..anchor end return url end addextanchor = function (fname, ext, anchor) return addanchor(addfileext(fname, ext), anchor) end href_ = function (url, text) if url then return "<a href=\""..url.."\">"..text.."</a>" end return text end buildurl_ = function (base, offset, ext, anchor) if not offset then return end local url = base..offset if notdir(url) and ext then url = url..ext end if anchor then url = url.."#"..anchor end return url end Sexpline = Class { type = "Sexpline", __index = { -- Two functions to split fields, calculating new fields. -- This one splits "line" into "pre", "sexp", and "spaces", -- and, as a bonus, it obtain the "elements" of the sexp -- (stored in integer-indexed positions). presexpspaces_ = function (sexpline) local line = sexpline.line local skel = line:gsub("\\.", "__") local leks = skel:reverse() local f = function (s) return '"'..("_"):rep(#s)..'"' end local leks = leks:gsub('"([^"]-)"', f) local secaps, lekspxes, erp = leks:match("^([ \t]*)(%b)()(.*)") if not erp then return end local pre = line:sub(1, #erp) local sexpskel = lekspxes:reverse() local sexp = line:sub(1+#pre, #pre+#sexpskel) local spaces = secaps:reverse() -- bonus: split the "sexp" into its "elements" and store them -- as tables in integer-indexed fields in the sexpline structure. local n, pos = 0, 2 local parseelement = function (pat) local s, e = sexpskel:match(pat, pos) if s then n = n + 1 sexpline[n] = {s, e, [0]=sexp:sub(s, e-1)} pos = e return true end end while parseelement "^[ \t]*()[^ \t\"()]+()" -- symbol or number or parseelement "^[ \t]*()\"_*\"()" -- string or parseelement "^[ \t]*()%b()()" do -- list end sexpline.pre = pre sexpline.sexp = sexp sexpline.spaces = spaces return true end, -- This one splits the "sexp" field into "o", "w", "r", "c" -- (for the standard way of htmlizing sexp hyperlinks). owrc_ = function (sexpline) if sexpline.sexp then local pat = "^(%()([-!$%&*+,/:<=>?@^_0-9A-Za-z]+)(.-)(\"?%))$" local o, w, r, c = sexpline.sexp:match(pat) -- open, word, rest, close sexpline.o = o sexpline.w = w sexpline.r = r sexpline.c = c return true end end, -- Notice the logical gap here! "sexphtml__" uses the fields -- "helpurl" and "targeturl", that are set by "sexpurls_" (below). -- About specials (like images): they're not supported yet! sexphtml__ = function (sexpline) if sexpline.helpurl or sexpline.targeturl then sexpline.sexphtml = sexpline.o .. href_(sexpline.helpurl, Q(sexpline.w)) .. Q(sexpline.r) .. href_(sexpline.targeturl, sexpline.c ) return true end end, linehtml__ = function (sexpline, htmlizer) htmlizer = htmlizer or Q if sexpline.sexphtml then sexpline.linehtml = htmlizer(sexpline.pre) .. sexpline.sexphtml .. sexpline.spaces else sexpline.linehtml = htmlizer(sexpline.line) end return sexpline end, -- sexphtml_ = function (sexpline, htmlizer) return sexpline:presexpspaces_() and sexpline:eword_() and sexpline:sexpurls_() -- defined below and sexpline:owrc_() and sexpline:sexphtml__(htmlizer) end, linehtml_ = function (sexpline, htmlizer) sexpline:sexphtml_() sexpline:linehtml__() return sexpline end, -- -- Two functions to extract the "elements" of the sexp, as strings. -- Like this, but 1-based and typed: (find-elnode "List Elements" "nth") symbol = function (sexpline, n) return sexpline[n] and sexpline[n][0]:match"^([^()\"].*)$" end, string = function (sexpline, n) return sexpline[n] and sexpline[n][0]:match"^\"(.*)\"$" end, -- eword_ = function (sexpline) sexpline.word = sexpline:symbol(1) sexpline.eword = ewords[sexpline.word] return sexpline.eword end, sexpurls_ = function (sexpline) local eword = sexpline.eword if eword then local a, b = sexpline:string(2), sexpline:string(3) -- no specials yet sexpline.helpurl = eword:helpurl_() sexpline.targeturl = eword:targeturl_(a, b) -- return sexpline.helpurl, sexpline.targeturl return true end end, }, } Eword = Class { type = "Eword", __index = { helpurl_ = function (eword) return eword.help end, targeturl_ = function (eword, a, b) return eword.base and eword:f(a, b) end, f = function (eword, a, b) return addextanchor(a and eword.base..a, eword.ext, b) end, }, } ewords = {} htmlizeline_ = function (line, htmlizer) return (Sexpline {line=line}):linehtml_(htmlizer) end htmlizeline = function (line, htmlizer) return (Sexpline {line=line}):linehtml_(htmlizer).linehtml end htmlizelines = function (bigstr, htmlizer) local f = function (line) return htmlizeline(line, htmlizer) end return bigstr:gsub("[^\n]*", f) end -- -- __ _ _ __ __ _ __ _ -- / _` | '_ \ / _` |/ _` | -- | (_| | | | | (_| | (_| | -- \__,_|_| |_|\__, |\__, | -- |___/ |___/ targeturl_base_a = function (eword, a, b) return a and eword.base..a -- use just the a end targeturl_to = function (eword, a, b) return a and "#"..a end eevarticle = eevarticle or "http://angg.twu.net/eev-article.html" --[[ ewords["to"] = Eword { help = eevarticle.."#anchors", -- base = "", -- targeturl = function (eword, sexp) -- local anchor = sexp:string(2) -- if anchor then return "#"..anchor end -- end, } --]] Ew = function (ew) ew.help = ew.help or eevarticle.."#shorter-hyperlinks" return Eword(ew) end Ewa = function (ew) ew.targeturl = targeturl_base_a return Ew(ew) end ewords["to"] = Ew { help = eevarticle.."#anchors", targeturl_ = targeturl_to, } code_c_d_angg = function (c, d) code_c_d_remote(c, pathto(d)) end code_c_d_remote = function (c, d) ewords["find-"..c.."file"] = Ewa {base = d} ewords["find-"..c] = Ew {base = d, ext = ".html"} ewords["find-"..c.."w3m"] = Ewa {base = d} end code_c_d_angg("angg", "") -- (find-angg "blogme4/") code_c_d_angg("es", "e/") -- (find-es "lua5") code_c_d_angg("dednat4", "dednat4/") -- (find-dednat4 "") code_c_d_angg("dn4", "dednat4/") code_c_d_angg("dn4ex", "dednat4/examples/") code_c_d_angg("dn5", "dednat5/") code_c_d_angg("blogme", "blogme/") code_c_d_angg("blogme3", "blogme3/") code_c_d_angg("blogme4", "blogme4/") code_c_d_angg("eev", "eev-current/") code_c_d_angg("flua", "flua/") code_c_d_angg("rubyforth", "rubyforth/") code_c_d_angg("vtutil", "vtutil/") code_c_d_angg("vtutil4", "vtutil4/") code_c_d_angg("RETRO", "RETRO/") ewords["find-es"].ext = ".e.html" ---- «angglisp.lua» (to ".angglisp.lua") ---- This block is from: (find-blogme4 "angglisp.lua") -- angglisp.lua: -- This file: -- http://angg.twu.net/blogme4/angglisp.lua.html -- http://angg.twu.net/blogme4/angglisp.lua -- (find-blogme4 "angglisp.lua") -- Author: Eduardo Ochs <eduardoochs@gmail.com> -- Version: 2011aug03 -- License: GPL3 -- -- require "elisp" -- (find-blogme4 "elisp.lua") ewords["find-angg"] = Eword { help = eevarticle.."#shorter-hyperlinks", base = "http://angg.twu.net/", ext = ".html", } ewords["find-image"] = Eword { sexphtml = function (eword, sexp) return "[image]" end, } -- These functions will be moved to somewhere else at some point... -- This is a port of: (find-blogme3 "angglisp.lua") -- See also: (find-blogme3 "anggdefs.lua" "-anggat") -- (find-blogme3 "angglisp.lua" "code_c_d_angg") code_c_d_angg = function (c, d) ewords["find-"..c.."file"] = Eword { help = eevarticle.."#shorter-hyperlinks", base = pathto(d), ext = "", -- wrong; the correct would be no anchor } ewords["find-"..c] = Eword { help = eevarticle.."#shorter-hyperlinks", base = pathto(d), ext = ".html", } ewords["find-"..c.."w3m"] = Eword { help = eevarticle.."#shorter-hyperlinks", base = pathto(d), ext = "", -- wrong; the correct would be no anchor } end code_c_d_angg("angg", "") -- (find-angg "blogme4/") code_c_d_angg("es", "e/") -- (find-es "lua5") code_c_d_angg("dednat4", "dednat4/") -- (find-dednat4 "") code_c_d_angg("dn4", "dednat4/") code_c_d_angg("dn4ex", "dednat4/examples/") code_c_d_angg("dn5", "dednat5/") code_c_d_angg("blogme", "blogme/") code_c_d_angg("blogme3", "blogme3/") code_c_d_angg("blogme4", "blogme4/") code_c_d_angg("eev", "eev-current/") code_c_d_angg("flua", "flua/") code_c_d_angg("rubyforth", "rubyforth/") code_c_d_angg("vtutil", "vtutil/") code_c_d_angg("vtutil4", "vtutil4/") code_c_d_angg("RETRO", "RETRO/") ewords["find-es"].ext = ".e.html" ---- «anggdefs.lua» (to ".anggdefs.lua") ---- This block is from: (find-blogme4 "anggdefs.lua") -- anggdefs.lua: some "def"s from blogme3, ported to blogme4. -- This file: -- http://angg.twu.net/blogme4/anggdefs.lua.html -- http://angg.twu.net/blogme4/anggdefs.lua -- (find-blogme4file "anggdefs.lua") -- Author: Eduardo Ochs <eduardoochs@gmail.com> -- Version: 2011feb17 -- License: GPL3 -- «.chars» (to "chars") -- «.Q» (to "Q") -- «.htmlize» (to "htmlize") -- «.htmlization_warning» (to "htmlization_warning") -- «.htmlizefile» (to "htmlizefile") -- require "common" -- (find-blogme4 "common.lua") -- require "def" -- (find-blogme4 "def.lua") -- require "elisp" -- (find-blogme4 "elisp.lua") -- require "angglisp" -- (find-blogme4 "angglisp.lua") -- Blogme words whose argparser is 1Q (or 2Q, 3Q...) quote their -- arguments - i.e., the [] blocks in it are not evaluated. -- (find-blogme4 "eval.lua" "qlongwords") -- (find-blogme4 "eval.lua" "readqword") -- (find-blogme4 "eval.lua" "_A") eval_statements = function (str) return assert(loadstring(str, str))() end eval_expr = function (str) return assert(loadstring("return "..str, str))() end def [[ ' 1Q body body ]] -- for lua-mode.el: ' def [[ lua: 1Q code eval_statements(code) ]] def [[ expr: 1Q code eval_expr(code) ]] def [[ # 0 _ "" ]] -- Remember that "def" & friends use "undollar", which expands all -- substrings of the form "$varname" in the body code. -- (find-blogme4 "def.lua" "undollar") -- (find-blogme3 "anggdefs.lua" "basic-words-for-html") def [[ J 1 text text ]] def [[ HREF 2 url,str "<a href=\"$url\">$str</a>" ]] def [[ H1 1 str "<h1>$str</h1>\n" ]] def [[ H2 1 str "<h2>$str</h2>\n" ]] def [[ H3 1 str "<h3>$str</h3>\n" ]] def [[ H4 1 str "<h4>$str</h4>\n" ]] def [[ H5 1 str "<h5>$str</h5>\n" ]] def [[ H6 1 str "<h6>$str</h6>\n" ]] def [[ BF 1 str "<strong>$str</strong>" ]] def [[ IT 1 str "<i>$str</i>" ]] def [[ RM 1 str "</i>$str<i>" ]] def [[ TT 1 str "<code>$str</code>" ]] def [[ EM 1 str "<em>$str</em>" ]] def [[ PRE 1 str "<pre>$str</pre>" ]] def [[ SMALL 1 body "<small>$body</small>" ]] def [[ NAME 2 tag,str "<a name=\"$tag\">$str</a>" ]] def [[ COLOR 2 color,str "<font color=\"$color\">$str</font>" ]] def [[ IMG 2 url,alt "<img src=\"$url\" alt=\"$alt\" border=0>\n" ]] def [[ IMAGE 2 url,alt HREF(url, "<br>"..IMG(url,alt)) ]] def [[ SCALEDIMAGE 2 perc,image "<a href=\"$image\">" .. "<img src=\"$image\" width=\"$perc\" height=\"$perc\" border=0>" .. "</a>" ]] def_ [[ P 1 str "\n\n<p>$str</p>" ]] -- (find-blogme3 "anggdefs.lua" "headers") def [[ TITLE 1 str "<title>$str</title>\n" ]] def [[ HEAD 1 str "<head>\n$str</head>\n" ]] def [[ BODY 1 str "<body>\n$str\n</body>\n" ]] def [[ HTML 1 str "<html>\n$str</html>\n" ]] html_dtd =[[ <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> ]] -- (find-wdg40w3m "html/doctype.html") html_style = "" -- (find-wdg40w3m "head/head.html" "STYLE") html_meta = "" -- (find-wdg40w3m "head/head.html" "META") html_favicon = "" -- http://www.favicon.cc/ html_speedbar = "" -- (find-TH "speedbar") -- (find-THfile "speedbar.blogme") def [[ TITLEDHTML 2 title,body html_dtd.. HTML(HEAD(TITLE(title)..html_meta..html_style).."\n".. BODY(body)) ]] -- «chars» (to ".chars") -- (find-blogme3 "charset.lua") -- (find-equailfile "sgml-input.el") latin1_pairs = [[ Æ AElig Á Aacute  Acirc À Agrave Å Aring à Atilde Ä Auml Ç Ccedil É Eacute Ê Ecirc È Egrave Ë Euml Í Iacute Ï Iuml Ó Oacute Ô Ocirc Ò Ograve Õ Otilde Ö Ouml Ú Uacute Û Ucirc Ù Ugrave Ü Uuml á aacute â acirc æ aelig à agrave å aring ã atilde ä auml ç ccedil é eacute ê ecirc è egrave ë euml í iacute î icirc ì igrave ï iuml ó oacute ô ocirc ò ograve õ otilde ö ouml ß szlig ú uacute û ucirc ù ugrave ü uuml ª ordf « laquo ° deg º ordm » raquo Ñ Ntilde ñ ntilde × times ]] -- «Q» (to ".Q") -- (find-blogme3 "anggdefs.lua" "Q") -- Q_re = "([&<>])" Q_re = "([\001-\008\011-\031&<>\127-\255])" Q_table = { ["&"]="&", ["<"]="<", [">"]=">" } Q_table["\15"] = "<font color=\"red\"><strong>*</strong></font>" Q_table["\171"] = "<font color=\"green\"><i>«</i></font>" Q_table["\187"] = "<font color=\"green\"><i>»</i></font>" for c,cname in each2(split(latin1_pairs)) do Q_table[c] = "&"..cname..";" end -- (find-angg "LUA/lua50init.lua" "translatechars") def [[ Q 1 text translatechars(text, Q_re, Q_table) ]] -- «htmlize» (to ".htmlize") -- (find-blogme4 "options.lua" "dooption_i") Def [[ htmlize 2 title,body blogme_output = TITLEDHTML(title, H2(title)..body) ]] -- «htmlization_warning» (to ".htmlization_warning") -- (find-blogme3 "options.lua" "htmlization_warning") def [=[ htmlization_head 1 fname [[ <head> <title>$[fname] (htmlized) </title> </head> ]] ]=] def [=[ htmlization_warning_ 2 original,htmlizer [[ <table><tr><td bgcolor="#CC0000"><font color="#FFCC00" size=-1> Warning: this is an htmlized version! <br>The original is across <a href="$[original]">this link</a>, <br>and the conversion rules are <a href="$[htmlizer]">here</a>. </font></td></tr></table> ]] ]=] def [[ htmlization_warning 1 fname htmlization_warning_( fnamenondirectory(fname), pathto "blogme3/escripts.lua.html" ) ]] -- (find-blogme3 "options.lua" "htmlization_head") -- htmlizeline = function (line) return htmlizeline_(Q, line) end -- htmlizelines = function (bigstr) -- -- local htmlizeline = function (line) htmlizeline_(Q, line) end -- -- return maplines(htmlizeline, bigstr) -- return bigstr:gsub("[^\n]*", htmlizeline) -- end --------[ htmlizefile ]-------- -- «htmlizefile» (to ".htmlizefile") -- (find-blogme4 "options.lua" "dooption_a2html") -- (find-blogme3 "options.lua" "htmlizefile") htmlizefile_ = function (fname, fcontents, htmlizer) htmlizer = htmlizer or htmlizelines local fnamestem = fnamenondirectory(fname) local warning = htmlization_warning(fname) local head = htmlization_head(fname) local body = BODY(warning .. PRE(htmlizer(fcontents))) return HTML(head .. body) end htmlizefile = function (fname, outfname, htmlizer) local fcontents = readfile(fname) outfname = outfname or fname..".html" writefile(outfname, htmlizefile_(fname, fcontents, htmlizer)) end -- The "new way" to define "htmlize" flexibly in blogme3 (allowing for -- a speedbar, a favicon, CSS, META, etc, with less headaches than in -- the "previous way") uses something like the messy chunk of code -- below... I am not using it in demo.lua at the moment (note that -- htmlize is redefined there, to something simpler). --[=[ def [[ html_head 1 title HEAD(TITLE(title)..html_meta.. html_favicon..html_style) ]] def [[ html_body_0 2 title,body H3(Q(title)).."\n"..body ]] def [[ html_body_1 2 title,body DIV(BORDERLESSBOX(html_body_0(title,body))) ]] def [[ html_body_2 2 title,body html_speedbar..html_body_1(title,body) ]] def [[ html_body 2 title,body html_body_0(title, body) ]] def [[ html_all 2 title,body html_dtd.. HTML(html_head(title).."\n".. BODY(html_body(title,body))) ]] def [[ htmlize 2 title,body set("blogme_output", html_all(title, body)) ]] def [[ htmlize 2 title,body set("blogme_output", sgmlify(html_all(title, body))) ]] -- sgmlify can be found here: (find-blogme3 "charset.lua") -- Example: [SETHEADSTYLE h3 { background-color: orange; }] def [[ HEADSTYLE 1 styles "<style type=\"text/css\"><!--\n$styles -->\n</style>\n" ]] Def [[ SETHEADSTYLE 1 styles html_style = HEADSTYLE(styles) ]] Def [[ SETFAVICON 1 url html_favicon = "<link rel=\"shortcut icon\" href=\"$url\" />\n" ]] --]=] ---- «anggdefs.lua» (to ".anggdefs.lua") ---- This block is from: (find-blogme4 "anggdefs.lua") -- anggdefs.lua: some "def"s from blogme3, ported to blogme4. -- This file: -- http://angg.twu.net/blogme4/anggdefs.lua.html -- http://angg.twu.net/blogme4/anggdefs.lua -- (find-blogme4file "anggdefs.lua") -- Author: Eduardo Ochs <eduardoochs@gmail.com> -- Version: 2011feb17 -- License: GPL3 -- «.chars» (to "chars") -- «.Q» (to "Q") -- «.htmlize» (to "htmlize") -- «.htmlization_warning» (to "htmlization_warning") -- «.htmlizefile» (to "htmlizefile") -- require "common" -- (find-blogme4 "common.lua") -- require "def" -- (find-blogme4 "def.lua") -- require "elisp" -- (find-blogme4 "elisp.lua") -- require "angglisp" -- (find-blogme4 "angglisp.lua") -- Blogme words whose argparser is 1Q (or 2Q, 3Q...) quote their -- arguments - i.e., the [] blocks in it are not evaluated. -- (find-blogme4 "eval.lua" "qlongwords") -- (find-blogme4 "eval.lua" "readqword") -- (find-blogme4 "eval.lua" "_A") eval_statements = function (str) return assert(loadstring(str, str))() end eval_expr = function (str) return assert(loadstring("return "..str, str))() end def [[ ' 1Q body body ]] -- for lua-mode.el: ' def [[ lua: 1Q code eval_statements(code) ]] def [[ expr: 1Q code eval_expr(code) ]] def [[ # 0 _ "" ]] -- Remember that "def" & friends use "undollar", which expands all -- substrings of the form "$varname" in the body code. -- (find-blogme4 "def.lua" "undollar") -- (find-blogme3 "anggdefs.lua" "basic-words-for-html") def [[ J 1 text text ]] def [[ HREF 2 url,str "<a href=\"$url\">$str</a>" ]] def [[ H1 1 str "<h1>$str</h1>\n" ]] def [[ H2 1 str "<h2>$str</h2>\n" ]] def [[ H3 1 str "<h3>$str</h3>\n" ]] def [[ H4 1 str "<h4>$str</h4>\n" ]] def [[ H5 1 str "<h5>$str</h5>\n" ]] def [[ H6 1 str "<h6>$str</h6>\n" ]] def [[ BF 1 str "<strong>$str</strong>" ]] def [[ IT 1 str "<i>$str</i>" ]] def [[ RM 1 str "</i>$str<i>" ]] def [[ TT 1 str "<code>$str</code>" ]] def [[ EM 1 str "<em>$str</em>" ]] def [[ PRE 1 str "<pre>$str</pre>" ]] def [[ SMALL 1 body "<small>$body</small>" ]] def [[ NAME 2 tag,str "<a name=\"$tag\">$str</a>" ]] def [[ COLOR 2 color,str "<font color=\"$color\">$str</font>" ]] def [[ IMG 2 url,alt "<img src=\"$url\" alt=\"$alt\" border=0>\n" ]] def [[ IMAGE 2 url,alt HREF(url, "<br>"..IMG(url,alt)) ]] def [[ SCALEDIMAGE 2 perc,image "<a href=\"$image\">" .. "<img src=\"$image\" width=\"$perc\" height=\"$perc\" border=0>" .. "</a>" ]] def_ [[ P 1 str "\n\n<p>$str</p>" ]] -- (find-blogme3 "anggdefs.lua" "headers") def [[ TITLE 1 str "<title>$str</title>\n" ]] def [[ HEAD 1 str "<head>\n$str</head>\n" ]] def [[ BODY 1 str "<body>\n$str\n</body>\n" ]] def [[ HTML 1 str "<html>\n$str</html>\n" ]] html_dtd =[[ <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> ]] -- (find-wdg40w3m "html/doctype.html") html_style = "" -- (find-wdg40w3m "head/head.html" "STYLE") html_meta = "" -- (find-wdg40w3m "head/head.html" "META") html_favicon = "" -- http://www.favicon.cc/ html_speedbar = "" -- (find-TH "speedbar") -- (find-THfile "speedbar.blogme") def [[ TITLEDHTML 2 title,body html_dtd.. HTML(HEAD(TITLE(title)..html_meta..html_style).."\n".. BODY(body)) ]] -- «chars» (to ".chars") -- (find-blogme3 "charset.lua") -- (find-equailfile "sgml-input.el") latin1_pairs = [[ Æ AElig Á Aacute  Acirc À Agrave Å Aring à Atilde Ä Auml Ç Ccedil É Eacute Ê Ecirc È Egrave Ë Euml Í Iacute Ï Iuml Ó Oacute Ô Ocirc Ò Ograve Õ Otilde Ö Ouml Ú Uacute Û Ucirc Ù Ugrave Ü Uuml á aacute â acirc æ aelig à agrave å aring ã atilde ä auml ç ccedil é eacute ê ecirc è egrave ë euml í iacute î icirc ì igrave ï iuml ó oacute ô ocirc ò ograve õ otilde ö ouml ß szlig ú uacute û ucirc ù ugrave ü uuml ª ordf « laquo ° deg º ordm » raquo Ñ Ntilde ñ ntilde × times ]] -- «Q» (to ".Q") -- (find-blogme3 "anggdefs.lua" "Q") -- Q_re = "([&<>])" Q_re = "([\001-\008\011-\031&<>\127-\255])" Q_table = { ["&"]="&", ["<"]="<", [">"]=">" } Q_table["\15"] = "<font color=\"red\"><strong>*</strong></font>" Q_table["\171"] = "<font color=\"green\"><i>«</i></font>" Q_table["\187"] = "<font color=\"green\"><i>»</i></font>" for c,cname in each2(split(latin1_pairs)) do Q_table[c] = "&"..cname..";" end -- (find-angg "LUA/lua50init.lua" "translatechars") def [[ Q 1 text translatechars(text, Q_re, Q_table) ]] -- «htmlize» (to ".htmlize") -- (find-blogme4 "options.lua" "dooption_i") Def [[ htmlize 2 title,body blogme_output = TITLEDHTML(title, H2(title)..body) ]] -- «htmlization_warning» (to ".htmlization_warning") -- (find-blogme3 "options.lua" "htmlization_warning") def [=[ htmlization_head 1 fname [[ <head> <title>$[fname] (htmlized) </title> </head> ]] ]=] def [=[ htmlization_warning_ 2 original,htmlizer [[ <table><tr><td bgcolor="#CC0000"><font color="#FFCC00" size=-1> Warning: this is an htmlized version! <br>The original is across <a href="$[original]">this link</a>, <br>and the conversion rules are <a href="$[htmlizer]">here</a>. </font></td></tr></table> ]] ]=] def [[ htmlization_warning 1 fname htmlization_warning_( fnamenondirectory(fname), pathto "blogme3/escripts.lua.html" ) ]] -- (find-blogme3 "options.lua" "htmlization_head") -- htmlizeline = function (line) return htmlizeline_(Q, line) end -- htmlizelines = function (bigstr) -- -- local htmlizeline = function (line) htmlizeline_(Q, line) end -- -- return maplines(htmlizeline, bigstr) -- return bigstr:gsub("[^\n]*", htmlizeline) -- end --------[ htmlizefile ]-------- -- «htmlizefile» (to ".htmlizefile") -- (find-blogme4 "options.lua" "dooption_a2html") -- (find-blogme3 "options.lua" "htmlizefile") htmlizefile_ = function (fname, fcontents, htmlizer) htmlizer = htmlizer or htmlizelines local fnamestem = fnamenondirectory(fname) local warning = htmlization_warning(fname) local head = htmlization_head(fname) local body = BODY(warning .. PRE(htmlizer(fcontents))) return HTML(head .. body) end htmlizefile = function (fname, outfname, htmlizer) local fcontents = readfile(fname) outfname = outfname or fname..".html" writefile(outfname, htmlizefile_(fname, fcontents, htmlizer)) end -- The "new way" to define "htmlize" flexibly in blogme3 (allowing for -- a speedbar, a favicon, CSS, META, etc, with less headaches than in -- the "previous way") uses something like the messy chunk of code -- below... I am not using it in demo.lua at the moment (note that -- htmlize is redefined there, to something simpler). --[=[ def [[ html_head 1 title HEAD(TITLE(title)..html_meta.. html_favicon..html_style) ]] def [[ html_body_0 2 title,body H3(Q(title)).."\n"..body ]] def [[ html_body_1 2 title,body DIV(BORDERLESSBOX(html_body_0(title,body))) ]] def [[ html_body_2 2 title,body html_speedbar..html_body_1(title,body) ]] def [[ html_body 2 title,body html_body_0(title, body) ]] def [[ html_all 2 title,body html_dtd.. HTML(html_head(title).."\n".. BODY(html_body(title,body))) ]] def [[ htmlize 2 title,body set("blogme_output", html_all(title, body)) ]] def [[ htmlize 2 title,body set("blogme_output", sgmlify(html_all(title, body))) ]] -- sgmlify can be found here: (find-blogme3 "charset.lua") -- Example: [SETHEADSTYLE h3 { background-color: orange; }] def [[ HEADSTYLE 1 styles "<style type=\"text/css\"><!--\n$styles -->\n</style>\n" ]] Def [[ SETHEADSTYLE 1 styles html_style = HEADSTYLE(styles) ]] Def [[ SETFAVICON 1 url html_favicon = "<link rel=\"shortcut icon\" href=\"$url\" />\n" ]] --]=] ---- «texinfo.lua» (to ".texinfo.lua") ---- This block is from: (find-blogme4 "texinfo.lua") -- texinfo.lua: -- This file: -- http://angg.twu.net/blogme4/texinfo.lua.html -- http://angg.twu.net/blogme4/texinfo.lua -- (find-blogme4 "texinfo.lua") -- Author: Eduardo Ochs <eduardoochs@gmail.com> -- Version: 2011sep27 -- License: GPL3 -- -- (find-es "texinfo") -- (find-angg "LUA/texinfo.lua") -- (find-dn5 "treesegs.lua") -- -- This does very little at the moment. -- «.TexiTree» (to "TexiTree") -- «.TOP-NODE-SUBNODES» (to "TOP-NODE-SUBNODES") -- «.MYNODE» (to "MYNODE") -- «.ANODE» (to "ANODE") -- require "eoo" -- (find-blogme4 "eoo.lua") -- require "def" -- (find-blogme4 "def.lua") -- «TexiTree» (to ".TexiTree") TexiTree = Class { type = "TexiTree", __index = { addnode_ = function (texitree, treepos, node) node.treepos = treepos table.insert(texitree.structure, treepos) texitree.nodes[treepos] = node end, addnode_at = function (texitree, level, node) local structure = texitree.structure local last_pos = structure[#structure] local last_level = #last_pos if last_level + 1 == level then return texitree:addnode_(last_pos.."A", node) else if last_level + 1 < level then error("Going too deep too fast") end local prev_pos = last_pos:sub(1, level) local prev_up = prev_pos:sub(1, -2) local prev_cb = prev_pos:sub(-1):byte() local node_pos = prev_up .. string.char(prev_cb + 1) return texitree:addnode_(node_pos, node) end end, add_at = function (texitree, level, node) if level == 1 then texitree:addnode_("_", node) else texitree:addnode_at(level, node) end end, add_top = function (texitree, node) texitree:add_at(1, node) end, add_chapter = function (texitree, node) texitree:add_at(2, node) end, add_section = function (texitree, node) texitree:add_at(3, node) end, add_subsection = function (texitree, node) texitree:add_at(4, node) end, -- menubody = function (texitree, pos) local items = {} for ascii=65,126 do local subpos = pos..string.char(ascii) local node = texitree.nodes[subpos] if not node then break end local short, long = node.short, node.long local left = "* "..short.."::" local line = string.format("%-32s%s\n", left, long) table.insert(items, line) end return table.concat(items) end, menufor = function (texitree, pos) local body = texitree:menubody(pos) if body ~= "" then return "\n\n@menu\n"..body.."@end menu\n" end end, -- up_prev_next = function (texitree, node) local pos_this = node.treepos local pos_up = pos_this:sub(1, -2) local pos_cb = pos_this:sub(-1):byte() local pos_prev = pos_up .. string.char(pos_cb - 1) local pos_next = pos_up .. string.char(pos_cb + 1) local up = texitree.nodes[pos_up] local prev = texitree.nodes[pos_prev] local next = texitree.nodes[pos_next] return up, prev, next end, node_head = function (texitree, node) local up, prev, next = texitree:up_prev_next(node) local up_short = (up and up.short) or "(dir)" local prev_short = (prev and prev.short) or "" local next_short = (next and next.short) or "" local short = node.short local long = node.long local command = ({"@top", "@chapter", "@section", "@subsection", "@subsubsection"})[#node.treepos] return string.format( "@node %s, %s, %s, %s\n" .. "@comment node-name, next, previous, up\n" .. "%s %s", short, next_short, prev_short, up_short, command, long) end, node_texi = function (texitree, node) local header = texitree:node_head(node) local body = node.body or "" return string.format("%s\n%s\n", header, body) end, nodes_texi = function (texitree) local f = function (pos) return texitree:node_texi(texitree.nodes[pos]) .. (texitree:menufor(pos) or "") end return mapconcat(f, texitree.structure, "\n") end, head_texi = function (texitree) local stem = texitree.stem or "foo" local title = texitree.title or "Foo" return "\\input texinfo\n" .. "@setfilename "..stem..".info\n" .. "@settitle "..title.."\n\n" end, foot_texi = function (texitree) return "\n@bye\n" end, full_texi = function (texitree) return texitree:head_texi() .. texitree:nodes_texi() .. texitree:foot_texi() end, print = function (texitree) print(texitree:nodes_texi()) end, print = function (texitree) print(texitree:full_texi()) end, writefile = function (texitree, fname) writefile(fname, texitree:full_texi()) end, -- srclink_fmt = '(find-blogme4 "doc/blogme4.b4texi" "%s")', infolink_fmt = '(find-node "(blogme4)%s")', srclink = function (texitree, anchor) return texitree.srclink_fmt:format(anchor) end, infolink = function (texitree, short) return texitree.infolink_fmt:format(short) end, }, } -- «TOP-NODE-SUBNODES» (to ".TOP-NODE-SUBNODES") Def [[ TOP 3 stem,title,body tt = TexiTree {structure={}, nodes={}, stem=stem, title=title} tt:add_at(1, {short="Top", long="Top", body=body}) tt.level = 2 ]] Def [[ NODE 3 short,long,body tt:add_at(tt.level, {short=short, long=long, body=body}) ]] Def [[ SUBNODES nop _ local oldlevel = tt.level tt.level = tt.level + 1 readvrest() -- process the body with level=level+1 tt.level = oldlevel ]] -- «MYNODE» (to ".MYNODE") -- (find-texinode "exampleindent") -- (find-texinode "Quotations and Examples") -- (find-texinode "Block Enclosing Commands") -- (find-texinode "example") -- (find-texinode "verbatim") -- (find-texinode "noindent") trim = function (str) return str:match("^(.-)[ \n\t]*$") end tquote = function (str) return (str:gsub("[{}@]", "@%1")) end def [[ IE 1 body "\n@example\n" ..tquote(trim(body)).."\n@end example\n" ]] def [[ LE 1 body "\n@verbatim\n"..tquote(trim(body)).."\n@end verbatim\n" ]] def [[ IE' 1Q body IE(body) ]] def [[ LE' 1Q body LE(body) ]] def [[ NI nop _ "@noindent " ]] def [[ PRELINK 1 anchor "" ]] def [[ PRELINK 1 anchor IE("src: "..tt:srclink(anchor).."\n") ]] Def [[ MYNODE 4 anchor,short,long,body print(tt:infolink(short)) return NODE(short, long, PRELINK(anchor)..body) ]] -- «ANODE» (to ".ANODE") -- (find-blogme4 "eval.lua" "parse_pattern") read_pattern = function (pat) if not parse_pattern(pat) then print("Failed pattern: "..pat) error() end return result end read_line = function () return read_pattern("^([^\n]+)\n?()") end read_line_pat = function (pat) return read_line():match(pat) end read_anchor = function () return read_line_pat("«([!-~]+)»") end read_qstr = function () return read_line_pat("\"([^\"]*)\"") end _A["A3"] = function () return read_anchor(), read_qstr(), readvvrest() end def [[ ANODE A3 anchor,short,long,body MYNODE(anchor,short,long,body) ]] ---- «options.lua» (to ".options.lua") ---- This block is from: (find-blogme4 "options.lua") -- options.lua: process command-line options. -- This file: -- http://angg.twu.net/blogme4/options.lua.html -- http://angg.twu.net/blogme4/options.lua -- (find-blogme4 "options.lua") -- Author: Eduardo Ochs <eduardoochs@gmail.com> -- Version: 2011aug07 -- License: GPL3 -- -- Based on: (find-blogme3 "options.lua") -- «.dooption_o» (to "dooption_o") -- «.dooption_i» (to "dooption_i") -- «.dooption_a2html» (to "dooption_a2html") -- «.dooption_e» (to "dooption_e") -- «.dooptions» (to "dooptions") -- require "eoo" -- (find-blogme4 "eoo.lua") -- «dooption_o» (to ".dooption_o") -- (find-blogme4 "common.lua" "pathto") -- Example: in blogme4.lua -o e/lua5.e.html ... -- the "-o" does: outputfile = "e/lua5.e.html" -- pathtoroot = "../" -- to cancel the "e/" -- and so: pathto("foo/bar/plic.html") -- yields: "../foo/bar/plic.html" dooption_o = function (fname) outputfile = fname pathtoroot = pathtoroot_(fname) eevarticle = pathto("eev-article.html") end -- «dooption_i» (to ".dooption_i") -- (find-blogme4 "eval.lua" "blogme_eval") -- Example: in blogme4.lua ... -i TH/emacs.blogme -- the "-i" evals the contents of the file "TH/emacs.blogme" -- using blogme_eval, discards the result of the expansion (!!!), -- then writes the contents of the variable "blogme_output" into -- the file whose filename is stored in the variable "outputfile". -- Usually blogme_output is set by htmlize - see: -- (find-blogme4 "anggdefs.lua" "htmlize") -- and outputfile is set by the command-line option "-o" (see above). dooption_i = function (fname) blogme_eval(readfile(fname)) writefile(outputfile, blogme_output) end -- «dooption_a2html» (to ".dooption_a2html") -- (find-blogme4 "anggdefs.lua" "htmlizefile") -- Example: in blogme4.lua -o README.html -a2html README -- the "-a2html" htmlizes the ascii file "README" in the standard way -- and stores the result in "README.html". dooption_a2html = function (fname) htmlizefile(fname, outputfile) end -- «dooption_e» (to ".dooption_e") -- Example: blogme4.lua -e 'PP(sorted(keys(_B)))' dooption_e = function (luacode) assert(loadstring(luacode))() end -- «dooptions» (to ".dooptions") -- Process all command-line arguments (by recursion). -- Example: dooptions("-o", "foo.html", "-i", "foo.blogme") -- calls: dooption_o("foo.html") -- dooptions("-i", "foo.blogme") -- dooption_i("foo.blogme") -- dooptions() _O = _O or {} _O["-o"] = function (fname, ...) dooption_o(fname); dooptions(...) end _O["-i"] = function (fname, ...) dooption_i(fname); dooptions(...) end _O["-a2html"] = function (fname, ...) dooption_a2html(fname);dooptions(...) end _O["-e"] = function (code, ...) dooption_e(code); dooptions(...) end dooptions = function (optionname, ...) if not optionname then return end if not _O[optionname] then error(format("Not in _O (for dooptions): %q", optionname)) end _O[optionname](...) end -- Here is a subtle but important point. -- (find-lua51manualw3m "#pdf-require" "argument" "modname") -- (find-lua51manualw3m "#6" "Lua Stand-alone" "'...'") -- blogme4.lua -e 'PP(B_)' --> dooptions("-e", "PP(B_)") -- blogme4.lua --> dooptions() -- no output! -- dofile "blogme4.lua" --> dooptions() -- load as a library -- require "blogme4" --> dooptions("blogme4") -- yuck! -- so 'dofile "blogme4.lua"' is a good way to load this as a library, -- but 'require "blogme4"' wouldn't even work - because it would call -- the non-existent command-line option "blogme4" - if it weren't by -- this hack: _O["blogme4"] = function () end -- Process all command-line options, -- or do nothing if this is being loaded as a library. dooptions(...) -- Local Variables: -- coding: raw-text-unix -- ee-anchor-format: "«%s»" -- End: