|
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: