Warning: this is an htmlized version!
The original is across this link,
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         = { ["&"]="&amp;", ["<"]="&lt;", [">"]="&gt;" }
Q_table["\15"]  = "<font color=\"red\"><strong>*</strong></font>"
Q_table["\171"] = "<font color=\"green\"><i>&laquo;</i></font>"
Q_table["\187"] = "<font color=\"green\"><i>&raquo;</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         = { ["&"]="&amp;", ["<"]="&lt;", [">"]="&gt;" }
Q_table["\15"]  = "<font color=\"red\"><strong>*</strong></font>"
Q_table["\171"] = "<font color=\"green\"><i>&laquo;</i></font>"
Q_table["\187"] = "<font color=\"green\"><i>&raquo;</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: