|
Warning: this is an htmlized version!
The original is here, and the conversion rules are here. |
-- This file:
-- http://anggtwu.net/LUA/BlogMe3.lua.html
-- http://anggtwu.net/LUA/BlogMe3.lua
-- (find-angg "LUA/BlogMe3.lua")
-- Author: Eduardo Ochs <eduardoochs@gmail.com>
--
-- This is a rewrite of blogme3/brackets.lua.
-- The code is as similar to the original as possible,
-- but structured as classes, and with test blocks.
-- Version: 2023feb02
--
-- See: (find-blogme3 "brackets.lua")
-- (find-blogme4 "brackets.lua" "bracketstructure")
-- (find-blogme3 "definers.lua")
-- (find-blogme3 "definers.lua" "_AA")
--
-- (defun e () (interactive) (find-angg "LUA/BlogMe3.lua"))
-- «.BlogMe» (to "BlogMe")
-- «.BlogMe-tostring» (to "BlogMe-tostring")
-- «.BlogMe-lowlevel» (to "BlogMe-lowlevel")
-- «.BlogMe-mygather» (to "BlogMe-mygather")
-- «.BlogMe-midlevel» (to "BlogMe-midlevel")
-- «.BlogMe-highlevel» (to "BlogMe-highlevel")
-- «.BlogMe-evalblock» (to "BlogMe-evalblock")
-- «.BlogMe-runat» (to "BlogMe-runat")
-- «.BlogMe-run» (to "BlogMe-run")
-- «.BlogMe-highlevel-tests» (to "BlogMe-highlevel-tests")
-- «.BlogMe-lowlevel-tests» (to "BlogMe-lowlevel-tests")
-- «.BlogMe-midlevel-tests» (to "BlogMe-midlevel-tests")
-- «.parsers-and-evaluators» (to "parsers-and-evaluators")
-- «._A-and-_B» (to "_A-and-_B")
-- «._A-and-_B-tests» (to "_A-and-_B-tests")
-- «.BlogMeShort» (to "BlogMeShort")
-- «.BlogMeShort-tests» (to "BlogMeShort-tests")
-- «.BlogMeDef» (to "BlogMeDef")
-- «.BlogMeDef-dowords» (to "BlogMeDef-dowords")
-- «.BlogMeDef-tests» (to "BlogMeDef-tests")
-- «.def» (to "def")
-- «.def-tests» (to "def-tests")
-- ____ _ __ __
-- | __ )| | ___ __ _| \/ | ___
-- | _ \| |/ _ \ / _` | |\/| |/ _ \
-- | |_) | | (_) | (_| | | | | __/
-- |____/|_|\___/ \__, |_| |_|\___|
-- |___/
--
-- «BlogMe» (to ".BlogMe")
BlogMe = Class {
type = "BlogMe",
from = function (subj)
local n2pos,pos2pos,pos2n = BlogMe.bracketstructure(subj)
return BlogMe {
subj = subj,
pos = 1,
n2pos = HTable(n2pos),
pos2n = HTable(pos2n),
pos2pos = HTable(pos2pos),
}
end,
--
-- See: (find-blogme3 "brackets.lua" "bracketstructure")
bracketstructure = function (subj)
local pos2n, n2pos, pos2pos = {}, {}, {}
local opens = {}
local n = 0
for pos,bracket in string.gmatch(subj, "()([%[%]])") do
n = n + 1
pos2n[pos] = n
n2pos[n] = pos
if bracket == "[" then
table.insert(opens, pos)
pos2pos[pos] = "?"
else -- bracket == "]"
if #opens > 0 then
local openpos = table.remove(opens)
pos2pos[openpos] = pos
pos2pos[pos] = openpos
else
error("Extra closing bracket at pos " .. pos)
end
end
end
if #opens > 0 then
error("Extra opening bracket at pos " .. opens[#opens])
end
return n2pos, pos2pos, pos2n
end,
__tostring = function (b) return b:tostring() end,
__index = {
--
-- See: (find-es "lua5" "posnumbers")
-- «BlogMe-tostring» (to ".BlogMe-tostring")
tostring = function(b)
local line2,line1 = b:posnumbers(1, #b.subj)
local caret = b.pos and (string.rep(" ", b.pos-1).."^") or ""
local fmt = " %s\n" ..
" %s\n" ..
"subj = %s\n" ..
" %s\n" ..
"pos = %s\n" ..
"n2pos = %s\n" ..
"pos2n = %s\n" ..
"pos2pos = %s\n"
return format(fmt, line1, line2, b.subj,
caret, tostring(b.pos),
tostring(b.n2pos), tostring(b.pos2n),
tostring(b.pos2pos))
end,
posnumbers = function (b,i,j)
local fmt = "%2d"
local hnum = function (k) return format(fmt, k) end
local digit = function (k, pos) return hnum(k):sub(pos,pos) end
local line = function (pos)
local f = function (k) return digit(k, pos) end
return mapconcat(f, seq(i,j), "")
end
return line(2), line(1)
end,
--
-- «BlogMe-lowlevel» (to ".BlogMe-lowlevel")
-- See: (find-blogme3 "brackets.lua" "parsers")
-- "wchars" means "word chars",
-- "rchars" means "regular chars".
parsebypattern = function (b, pat)
local capture, newpos = string.match(b.subj, pat, b.pos)
if newpos then b.pos = newpos; return capture end
end,
parsespaces = function (b) return b:parsebypattern("^([ \t\n]+)()") end,
parsewchars = function (b) return b:parsebypattern("^([^ \t\n%[%]]+)()") end,
parserchars = function (b) return b:parsebypattern("^([^%[%]]+)()") end,
parseblock = function (b)
if b.pos2pos[b.pos] and b.pos < b.pos2pos[b.pos] then
local inside = b.pos + 1
b.pos = b.pos2pos[b.pos] + 1
return inside
end
end,
--
-- «BlogMe-mygather» (to ".BlogMe-mygather")
-- From: (find-blogme3 "brackets.lua" "myconcat")
-- (find-blogme3 "brackets.lua" "mygather")
mygather = function (b, methodname)
local T = {}
while true do
local val = b[methodname](b)
if val then table.insert(T, val) else return T end
end
end,
myconcat = function (b, T)
if #T > 1 then return table.concat(T, "") end
if #T == 1 then return T[1] end
end,
myconcatgather = function (b, methodname)
return b:myconcat(b:mygather(methodname))
end,
--
-- «BlogMe-midlevel» (to ".BlogMe-midlevel")
-- See: (find-blogme3 "brackets.lua" "parsers_")
-- "q" means "quoted".
-- "v" means "value", or "evaluated".
-- The method evalblock is defined at the end of the class.
--
readvblock_ = function (b)
local blockstart = b:parseblock()
if blockstart then return b:evalblock(blockstart) or "" end
end,
readqblock_ = function (b)
local blockstart = b:parseblock()
if blockstart then return b.subj:sub(blockstart - 1, b.pos - 1) end
end,
readwcharsorqblock_ = function (b) return b:parsewchars() or b:readqblock_() end,
readwcharsorvblock_ = function (b) return b:parsewchars() or b:readvblock_() end,
readrcharsorqblock_ = function (b) return b:parserchars() or b:readqblock_() end,
readrcharsorvblock_ = function (b) return b:parserchars() or b:readvblock_() end,
readqword__ = function (b) return b:myconcatgather("readwcharsorqblock_") end,
readvword__ = function (b) return b:myconcatgather("readwcharsorvblock_") end,
readqrest__ = function (b) return b:myconcatgather("readrcharsorqblock_") end,
readvrest__ = function (b) return b:myconcatgather("readrcharsorvblock_") end,
readqword_ = function (b) b:parsespaces(); return b:readqword__() end,
readvword_ = function (b) b:parsespaces(); return b:readvword__() end,
readqrest_ = function (b) b:parsespaces(); return b:readqrest__() end,
readvrest_ = function (b) b:parsespaces(); return b:readvrest__() end,
--
-- «BlogMe-highlevel» (to ".BlogMe-highlevel")
-- See: (find-blogme3 "brackets.lua" "readvword")
readqword = function (b) return b:readqword_() or "" end,
readvword = function (b) return b:readvword_() or "" end,
readqrest = function (b) return b:readqrest_() or "" end,
readvrest = function (b) return b:readvrest_() or "" end,
readqlist = function (b) return b:mygather("readqword_") end,
readvlist = function (b) return b:mygather("readvword_") end,
readqargs = function (b) return unpack(b:readqlist()) end,
readvargs = function (b) return unpack(b:readvlist()) end,
--
readqqrest = function (b) return b:readqword(), b:readqrest() end,
readqqqrest = function (b) return b:readqword(), b:readqqrest() end,
readqqqqrest = function (b) return b:readqword(), b:readqqqrest() end,
readqqqqqrest = function (b) return b:readqword(), b:readqqqqrest() end,
readvvrest = function (b) return b:readvword(), b:readvrest() end,
readvvvrest = function (b) return b:readvword(), b:readvvrest() end,
readvvvvrest = function (b) return b:readvword(), b:readvvvrest() end,
readvvvvvrest = function (b) return b:readvword(), b:readvvvvrest() end,
--
readqqlist = function (b) return b:readqword(), b:readqlist() end,
readqqqlist = function (b) return b:readqword(), b:readqqlist() end,
readqqqqlist = function (b) return b:readqword(), b:readqqqlist() end,
readqqqqqlist = function (b) return b:readqword(), b:readqqqqlist() end,
readvvlist = function (b) return b:readvword(), b:readvlist() end,
readvvvlist = function (b) return b:readvword(), b:readvvlist() end,
readvvvvlist = function (b) return b:readvword(), b:readvvvlist() end,
readvvvvvlist = function (b) return b:readvword(), b:readvvvvlist() end,
--
nop = function (b) return end,
--
-- «BlogMe-evalblock» (to ".BlogMe-evalblock")
-- See: (find-blogme3 "brackets.lua" "evalblock")
readeval = function (b)
b:parsespaces()
local word = b:parsewchars() -- should this be global (for debugging)?
local headfun = _B[word] or _G[word] or error("Not in _B or _G: " .. word)
local argsfun = _A[word] or error("Not in _A: " .. word)
return headfun(b[argsfun](b))
end,
evalblock = function (b, start)
local oldpos = b.pos
b.pos = start
local result = b:readeval()
b.pos = oldpos
return result
end,
--
-- «BlogMe-runat» (to ".BlogMe-runat")
-- ":runat()" and ":runats()" are debugging functions that run an
-- argument parser at a certain position, or several argument
-- parser at the same position, and print the result of each
-- argument parser.
runat = function (b, pos, parsername)
if pos then b.pos = pos end
PP(b[parsername](b))
end,
runats = function (b, pos, parsernames)
for _,parsername in ipairs(split(parsernames)) do
b.pos = pos
printf("%-21s", parsername..":")
PP(b[parsername](b))
end
end,
--
-- «BlogMe-run» (to ".BlogMe-run")
-- The ":run()" method is what we use to evaluate a blogme file.
-- The ":readvrest()" argument parser reads "everything" - or,
-- more precisely: everything up to the next closing bracket or to
-- the end - as a string, and evaluates the "[]"s in it and
-- replaces them by their results; ":run()" is implemented as a
-- call to ":readvrest()".
--
run = function (b)
b.pos = 1
return b["readvrest"](b)
end,
},
}
-- «BlogMe-highlevel-tests» (to ".BlogMe-highlevel-tests")
--[==[
* (eepitch-lua51)
* (eepitch-kill)
* (eepitch-lua51)
dofile "BlogMe3.lua"
def [[ IT 1 str "<i>$str</i>" ]]
def [[ EM 1 str "<em>$str</em>" ]]
= IT("foo")
bm = BlogMe.from [[ abc[IT de]fg hi ]]
bm:runats(1, [[ readqlist
readqrest
readqqrest
readqqqrest
readqword ]])
bm:runats(1, [[ readvlist
readvrest
readvvrest
readvvvrest
readvword ]])
--]==]
-- «BlogMe-lowlevel-tests» (to ".BlogMe-lowlevel-tests")
--[==[
* (eepitch-lua51)
* (eepitch-kill)
* (eepitch-lua51)
dofile "BlogMe.lua"
b = BlogMe.from [=[ a[b[c]d[e]]f ]=]
= b
PP(b:parsespaces(),
b:parsewchars(),
b:parseblock(),
b:parsewchars(),
b.pos)
-- «BlogMe-midlevel-tests» (to ".BlogMe-midlevel-tests")
* (eepitch-lua51)
* (eepitch-kill)
* (eepitch-lua51)
dofile "BlogMe.lua"
prb = function () print(b) end
b = BlogMe.from [=[ a b[c]d e[f [g h]][i j]k l m ]=]
b.pos = 12
= b
= b:readqblock_()
b.pos = 12
= b
PP(b:readqblock_(),
b:readqblock_(),
b:readqblock_())
b.pos = 11
= b
PP(b:readwcharsorqblock_(),
b:readwcharsorqblock_(),
b:readwcharsorqblock_(),
b:readwcharsorqblock_(),
b:readwcharsorqblock_())
b.pos = 12
= b
PP(b:mygather("readqblock_"))
b.pos = 12
PP(b:myconcatgather("readqblock_"))
b.pos = 11
= b
PP(b:readqword_())
b.pos = 11; PP(b:readqrest_())
b.pos = 11; PP(b:readqword())
b.pos = 11; PP(b:readqrest())
b.pos = 11; PP(b:readqqrest())
b.pos = 11; PP(b:readqqqrest())
b.pos = 11; PP(b:readqqqqrest())
b.pos = 11; PP(b:readqlist())
b.pos = 11; PP(b:readqqlist())
b.pos = 11; PP(b:readqqqlist())
b.pos = 11; PP(b:readqqqqlist())
--]==]
--------[ Parsers and Evaluators ]--------
-- «parsers-and-evaluators» (to ".parsers-and-evaluators")
--
-- This is the most twisted part of blogme3...
-- That's because it involves some recursions.
-- The problem: evaluating a "block" usually involve "reading vwords",
-- where a vword is the "value of a (big) word"; and to obtain the
-- value of a big word we need to evaluate all the blocks in it.
--
-- Something like "[print foo[+ 22 33]bar]" is a "block", and parsing
-- it with parseblock() just returns the position of the "[" (as a
-- number!) and advances pos past the "]"... But that's just the
-- "syntactical level", and that's the easy part; above that there's a
-- "semantical level", where blocks can have "values", obtained by
-- evaluation. To understand how evaluation works we need to
-- understand a function, "evalblock(start)" - the argument "start" is
-- the position of a "[", as a number -, and two tables, _A and _B,
-- whose keys are strings and whose values are functions:
--
-- _A["print"] is the "argument parser" for "print";
-- _B["print"] is the "blogme code" for "print".
--
-- They are similar to Lua's "_G": _G["print"] is the "Lua code" for
-- "print".
--
-- So: if we run "evalblock(start)" after the "parseblock()" then
-- blogme tries to execute the "print": it first parses "print", then
-- uses the function in _A["print"] to parse the argument list, then
-- runs the code in _B["print"] with those arguments:
-- _B["print"]("foo55bar").
--
-- _A["print"] knows that the arguments are a series of "vwords" -
-- "values of (big) words". A similar idea is that of "qwords" -
-- "quoted (big) words". Parsing "foo[+ 22 33]bar" as a qword (by
-- calling getqword() with pos at the "f") would return this, as a
-- string: "foo[+ 22 33]bar"; but parsing "foo[+ 22 33]bar" as vword
-- (by calling readqword() with pos at the "f") involves evaluating the
-- blocks in the way - and "[+ 22 33]" evaluates to 55 (a number), and
-- myconcat {"foo", 55, "bar"} returns "foo55bar".
--
-- _A["print"] is set to `readvargs' - a function that returns a
-- variable number of results. In "[HREF http://foo/bar Foo bar]" the
-- function in _A["HREF"] is `readvvrest', that returns exactly two
-- results: first a vword, then a "vrest" - and "vrests" are like
-- vwords, but whitespace chars are treated as regular chars, not as
-- separators; the result of running readvrest() with pos at the "F"
-- is "Foo bar".
--
-- "readvrest" returns the "rest of the arguments" as a string;
-- "readvlist" returns it as an array of vwords; and "readvargs" is
-- like "readvlist" but varargs-ish - it returns the vwords that it
-- can read as several values, like in "return v1, v2, v3". (Note: the
-- choice of terms is not very good - "list" could become "array", and
-- maybe "args" should become "list"...)
--
-- "Parsers" return positions, as numbers; "readers" return "values",
-- that are usually strings. Readers are divided into two classes:
-- "quoters", that don't call evalblock and always return strings, and
-- "evaluators", that call evalblock on blocks; all readers use
-- myconcat and mygather to build their results.
--
-- "Parsers" return nil - and don't advance pos - when they "fail";
-- that is, when they can't parse what they expected. "Readers" return
-- the empty string.
--
-- Readers whose names have the suffix "_" (meaning "low-level") don't
-- advance pos when they fail; readers without the "_" in their names
-- are higher-level versions that call "parsespaces" at some places -
-- high-level readers may advance pos past some whitespace then fail,
-- and when that happens pos is not returned to before the whitespace.
--
-- Char classes: Basic parsers: Quoters: Evaluators:
-- wordchar parsewchars evalblock
-- regularchar parserchars readqblock readvblock
-- spacechar parsespaces readqword readvword
-- parseblock readqrest readvrest
-- readqqrest readvvrest
-- readqqqrest readvvvrest
-- readqlist readvlist
-- readqqlist readvvlist
-- readqqqlist readvvvlist
-- readqargs readvargs
-- (find-blogmefile "blogme2-inner.lua" "-- run_head:")
-- (find-blogmefile "blogme2-middle.lua")
-- _ _ ____
-- / \ __ _ _ __ __| | | __ )
-- / _ \ / _` | '_ \ / _` | | _ \
-- / ___ \ | (_| | | | | (_| | | |_) |
-- ___/_/ \_\ \__,_|_| |_|\__,_| ___|____/
-- |____| |____|
--
-- «_A-and-_B» (to "._A-and-_B")
-- The low-level way to define blogme words is with _A and _B.
-- The high-level way is
-- See: (find-blogme3 "brackets.lua" "evalblock")
_A = VTable {} -- arglist parser functions for blogme words
_B = VTable {} -- like _G, but for blogme words
_A["PP"] = "readvlist"
_B["PP"] = PP
_A["lua"] = "readqrest"
_B["lua"] = expr
-- «_A-and-_B-tests» (to "._A-and-_B-tests")
--[==[
* (eepitch-lua51)
* (eepitch-kill)
* (eepitch-lua51)
dofile "BlogMe.lua"
b = BlogMe.from [=[ a[lua 2+3]b ]=]
b.pos = 1
= b
= b:readqword()
b.pos = 1
= b
= b:readvword()
--]==]
-- ____ _ ____ _ _
-- | __ )| | ___ __ _ _ __ ___ ___/ ___|| |__ ___ _ __| |_ ___
-- | _ \| |/ _ \ / _` | '_ ` _ \ / _ \___ \| '_ \ / _ \| '__| __/ __|
-- | |_) | | (_) | (_| | | | | | | __/___) | | | | (_) | | | |_\__ \
-- |____/|_|\___/ \__, |_| |_| |_|\___|____/|_| |_|\___/|_| \__|___/
-- |___/
--
-- «BlogMeShort» (to ".BlogMeShort")
-- Sorthands for argument parsers.
-- For example, this def
--
-- def [[ R 2 url,body HREF(url, nilify(body) or url) ]]
--
-- tells blogme that the argument parser for R is "2", that is a
-- shorthand for "readvvrest".
--
-- The global variable "_AA" holds a list of shorthands for "_A". This
-- class helps me to initialize and maintain _AA and to avoid certain
-- common errors. See: (find-blogme3 "definers.lua" "_AA")
--
BlogMeShort = Class {
type = "BlogMeShort",
--
isshort = function (short)
if not _AA[short] then error("Not in _AA: %S", short) end
return short
end,
islong = function (long)
local method = BlogMe.__index[long]
if not method then error(format("%q: argparser method not found", long)) end
return long
end,
expand = function (short)
return BlogMeShort.isshort(short) and _AA[short]
end,
defshort = function (short, long)
_AA[short] = BlogMeShort.islong(long)
end,
defshorts = function (bigstr)
for short,long in bigstr:gmatch("(%S+)%s+(%S+)") do
BlogMeShort.defshort(short, long)
end
end,
--
shorthands = [[
1 readvrest 1L readvlist 1Q readqrest 0 nop
2 readvvrest 2L readvvlist 2Q readqqrest * readvargs
3 readvvvrest 3L readvvvlist 3Q readqqqrest
4 readvvvvrest 4L readvvvvlist 4Q readqqqqrest
5 readvvvvvrest 5L readvvvvvlist 5Q readqqqqqrest
]],
init = function ()
local bigstr = BlogMeShort.shorthands
BlogMeShort.defshorts(bigstr)
end,
}
_AA = VTable {}
BlogMeShort.init()
-- «BlogMeShort-tests» (to ".BlogMeShort-tests")
--[[
* (eepitch-lua51)
* (eepitch-kill)
* (eepitch-lua51)
dofile "BlogMe3.lua"
= _AA
= BlogMeShort.expand ("1L")
= BlogMeShort.expand ("99") -- err
= BlogMeShort.defshort("99", "readqrest")
= BlogMeShort.expand ("99")
= BlogMeShort.defshort("99", "foo") -- err
= _AA
--]]
-- ____ _ __ __ ____ __
-- | __ )| | ___ __ _| \/ | ___| _ \ ___ / _|
-- | _ \| |/ _ \ / _` | |\/| |/ _ \ | | |/ _ \ |_
-- | |_) | | (_) | (_| | | | | __/ |_| | __/ _|
-- |____/|_|\___/ \__, |_| |_|\___|____/ \___|_|
-- |___/
--
-- «BlogMeDef» (to ".BlogMeDef")
-- The function "def" is defined using this class.
-- The variants "def_", "bdef", and "bdef_" too,
-- and new variants are easy to define.
-- The suffix "_" means: don't add a "return".
-- The prefix "b" means: store in _B, not in _G.
--
-- See: (find-blogme3 "anggdefs.lua" "basic-html")
-- (find-blogme3 "definers.lua" "undollar")
-- (find-blogme3 "definers.lua" "def")
--
BlogMeDef = Class {
type = "BlogMeDef",
fromsplit = function (defstr)
local pat = "^%s*(%S+)%s+(%S+)%s+(%S+)%s(.*)"
local name,short,arglist,body0 = defstr:match(pat)
return BlogMeDef { name=name, short=short, arglist=arglist,
body0=body0, body1=body0 }
end,
run0 = function (definer, defstr)
local bd = BlogMeDef.fromsplit(defstr)
bd:doword(definer)
return bd
end,
run = function (definer, defstr)
local bd = BlogMeDef.run0(definer, defstr)
eval(bd.body1)
return bd
end,
--
__tostring = function (bd)
return bd:tostring()
end,
--
__index = {
tostring = function (bd)
local f = function (o) return tostring(o) end
local f = function (o) return "[=[ "..tostring(o).." ]=]" end
local F = function (o) return "[=[ "..tostring(o).."\n]=]" end
local q = function (o) return mytostring(o) end
return " Name:"
.."\n name: " .. q(bd.name)
.."\n storein: " .. q(bd.storein)
.."\n"
.."\n Argument parser:"
.."\n short: " .. q(bd.short)
.."\n long: " .. q(bd.long)
.."\n arglist: " .. q(bd.arglist)
.."\n"
.."\n Body:"
.."\n body0: " .. f(bd.body0)
.."\n body1: " .. F(bd.body1)
--.."\n"
--..f(bd.body1)
.."\n"
end,
--
-- «BlogMeDef-dowords» (to ".BlogMeDef-dowords")
-- A little language for transforming the fields of a BlogMeDef object.
-- For example, in:
--
-- bd:dowords("undollar ret f _B set _A")
--
-- "undollar" expands each '$var' in bd.body1 to '..var..',
-- "ret" prepends a 'return ' to bd.body1,
-- "f" wraps bd.body1 in a 'function(...) ... end',
-- "_B" sets bd.storein to "_B" instead of "_G",
-- "set" prepends a '_B[...]=...' or '_G[...]=...' to bd.body1,
-- "_A" prepends a '_A[...]=...' to bd.body1.
--
doword = function (bd, word) bd["do_"..word](bd) end,
dowords = function (bd, words)
for _,word in ipairs(split(words)) do bd:doword(word) end
end,
--
do_def = function (bd) bd:dowords("undollar ret f _G set _A") end,
do_def_ = function (bd) bd:dowords("undollar f _G set _A") end,
do_bdef = function (bd) bd:dowords("undollar ret f _B set _A") end,
do_bdef_ = function (bd) bd:dowords("undollar f _B set _A") end,
--
do__G = function (bd) bd.storein = "_G" end,
do__B = function (bd) bd.storein = "_B" end,
do_ret = function (bd) bd.body1 = "return "..bd.body1 end,
--
do_set = function (bd)
local fmt = "%s[%q] = %s"
bd.body1 = format(fmt, bd.storein, bd.name, bd.body1)
end,
do_f = function (bd)
local fmt = "function (%s)\n %s\n end"
bd.body1 = format(fmt, bd.arglist, bd.body1)
end,
do__A = function (bd)
local fmt = '\n_A["%s"] = "%s"\n%s'
bd.long = BlogMeShort.expand(bd.short)
bd.body1 = format(fmt, bd.name, bd.long, bd.body1)
end,
do_undollar = function (bd)
bd.body1 = bd.body1:gsub("%$([a-z]+)", "\"..%1..\"")
bd.body1 = bd.body1:gsub("%$(%b())", "\"..%1..\"")
bd.body1 = bd.body1:gsub("%$(%b[])", function (s)
return "]]..("..strsub(s, 2, -2)..")..[["
end)
return bd.body1
end,
},
}
-- «BlogMeDef-tests» (to ".BlogMeDef-tests")
-- See: (find-blogme3 "anggdefs.lua" "basic-html")
-- The tests for "def"
--[==[
* (eepitch-lua51)
* (eepitch-kill)
* (eepitch-lua51)
dofile "BlogMe3.lua"
bd = BlogMeDef.fromsplit [[ H1 1 str "<h1>$str</h1>\n" ]]
= bd
bd:do_def()
= bd
= BlogMeDef.run0("def", [[ foo 2 a,b "<foo>$a:$b</foo>" ]])
= BlogMeDef.run0("def_", [[ foo 2 a,b return "<foo>$a:$b</foo>" ]])
= BlogMeDef.run0("bdef", [[ foo 2 a,b "<foo>$a:$b</foo>" ]])
= BlogMeDef.run0("bdef_", [[ foo 2 a,b return "<foo>$a:$b</foo>" ]])
BlogMeDef.run ("def", [[ foo 2 a,b "<foo>$a:$b</foo>" ]])
= foo("aaa", "bbb")
--]==]
-- _ __
-- __| | ___ / _|
-- / _` |/ _ \ |_
-- | (_| | __/ _|
-- \__,_|\___|_|
--
-- «def» (to ".def")
-- "def" and friends.
-- See: (to "BlogMeDef-dowords")
def = function (defstr) return BlogMeDef.run("def", defstr) end
def_ = function (defstr) return BlogMeDef.run("def_", defstr) end
bdef = function (defstr) return BlogMeDef.run("bdef", defstr) end
bdef_ = function (defstr) return BlogMeDef.run("bdef_", defstr) end
-- «def-tests» (to ".def-tests")
--[==[
* (eepitch-lua51)
* (eepitch-kill)
* (eepitch-lua51)
dofile "BlogMe3.lua"
= def [[ FOO 2 a,b "($a:$b)" ]]
= def [[ HREF 2 tgt,body "<a href=\"$tgt\">$body</a>" ]]
= def [[ lua: 1Q code eval(code) ]]
= bdef [[ P 1Q code P(code) ]]
PP(FOO("xy","zw"))
bm = BlogMe.from [[ ab[FOO c d e]fg ]]
PP(bm:run())
--]==]
-- Local Variables:
-- coding: utf-8-unix
-- End: