Warning: this is an htmlized version!
The original is across this link,
and the conversion rules are here.
-- anggdefs.lua - 2014mar25, Edrx
-- This is part of blogme3.

-- This file contains the definitions of (most of) the blogme words
-- that I use to generate the html pages in <http://angg.twu.net/>.
-- I'm not going to try to convince anyone that this is a good mark-up
-- language - but most of the words are similar to the ones that I
-- used in TH, and so the habit and historical reasons etc etc.

-- http://angg.twu.net/blogme3/anggdefs.lua.html
-- (find-a2ps (buffer-file-name))

-- Quick index:
-- «.tools»			(to "tools")
-- «.basic-special-words»	(to "basic-special-words")
-- «.basic-words-for-html»	(to "basic-words-for-html")
-- «.images»			(to "images")
-- «.Q»				(to "Q")
-- «.BG»			(to "BG")
-- «.PREBOXBLOGME»		(to "PREBOXBLOGME")
-- «.local-copies»		(to "local-copies")
-- «.local-copies-aargh»	(to "local-copies-aargh")
-- «.file-sizes»		(to "file-sizes")
-- «.headers»			(to "headers")
-- «.htmlizetxt»		(to "htmlizetxt")
-- «.untabify-and-trim»		(to "untabify-and-trim")
-- «.ls2html»			(to "ls2html")
-- «.localvariables»		(to "localvariables")
-- «.WITHINDEX»			(to "WITHINDEX")
-- «.readqline»			(to "readqline")
-- «.DELAY»			(to "DELAY")
-- «._name»			(to "_name")
-- «.parsing-lines»		(to "parsing-lines")
-- «.eev_math_glyphs_edrx»	(to "eev_math_glyphs_edrx")
-- «.glyphs-for-dednat4»	(to "glyphs-for-dednat4")
-- «._TARGETS»			(to "_TARGETS")
-- «.section-numbers»		(to "section-numbers")
-- «.over»			(to "over")
-- «.MDEF»			(to "MDEF")
-- «.extra-options»		(to "extra-options")
-- «.-anggat»			(to "-anggat")
-- «.-tgt»			(to "-tgt")
-- «.-cgiplain»			(to "-cgiplain")
-- «.-lsmaybe»			(to "-lsmaybe")
-- «.-lua2html»			(to "-lua2html")
-- «.-org2html»			(to "-org2html")
-- «.patched-listings»		(to "patched-listings")
-- «.setvbuf»			(to "setvbuf")
-- «.HTMLIZELINES»		(to "HTMLIZELINES")
-- «.PROMPTLINE»		(to "PROMPTLINE")
-- «.TRAFFIC»			(to "TRAFFIC")
-- «.-t2html»			(to "-t2html")
-- «.wikirefs»			(to "wikirefs")
-- «.REDIRECTTO»		(to "REDIRECTTO")
-- «.cgiquote»			(to "cgiquote")
-- «.javascript»		(to "javascript")
-- «.html5-audio»		(to "html5-audio")
-- «.puro»			(to "puro")
-- «.htmlizelines_aulas»	(to "htmlizelines_aulas")
-- «.mailto»			(to "mailto")
-- «.chapa1»			(to "chapa1")
-- «.Sexp»			(to "Sexp")
-- «.meta_seek»			(to "meta_seek")
-- «.asurl_hack»		(to "asurl_hack")
-- «.youtube»			(to "youtube")
-- «.youtube-static»		(to "youtube-static")
-- «.at_home»			(to "at_home")



--------[ Tools ]--------
-- «tools»  (to ".tools")

join = table.concat
nilify = function (obj) if obj=="" then return nil else return obj end end
filter = function (arr, f)
    local brr = {}
    f = f or nilify
    for _,item in ipairs(arr) do
      if f(item) then tinsert(brr, item) end
    end
    return brr
  end

--------[ Basic special words ]--------
-- «basic-special-words»  (to ".basic-special-words")

def [[ lua:  1Q code assert(loadstring(code))() ]]  -- execute as lua code
def [[ expr: 1Q code assert(loadstring("return "..code))() ]]  -- lua expr
def [[ #    0  _    ""   ]]                        -- ignore (comment)
def  " \'   1Q text text "                         -- quote (as in Lisp)
def [[ <    0  _    "["  ]]                        -- "[<]" --> "["
def [[ >    0  _    "]"  ]]                        -- "[>]" --> "]"


def_ [[ set 2 varname,text _G[varname] = text; return text ]]
def  [[ $   1 varname      _G[varname]                     ]]

--------[ Basic words for html ]--------
-- «basic-words-for-html»  (to ".basic-words-for-html")
-- (find-angg "TH/Htmllib.tcl")
-- (find-angg "TH/index-old.th")
-- (find-blogmefile "blogme2-outer.lua")

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 [[ UL     1  str       "<ul>\n$str</ul>\n"        ]]
def [[ LI     1  str       "<li>$str\n"               ]]
def [[ LIST1  1L arr       UL(join(map(LI, filter(arr)), ""))]]
def [[ LIST2  1L arr       UL(join(map(LI, filter(arr)), ""))]]
def [[ LIST3  1L arr       UL(join(map(LI, filter(arr)), ""))]]
def [[ HLIST1 2L head,arr  H2(head)..LIST1(arr)       ]]
def [[ HLIST2 2L head,arr  head.."\n"..LIST2(arr)     ]]
def [[ HLIST3 2L head,arr  head.."\n"..LIST3(arr)     ]]

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 [[ Name   2 tag,str    NAME(unanchor(tag), str)             ]]
def [[ COLOR  2 color,str  "<font color=\"$color\">$str</font>" ]]

def [[ NAMEHREF 2 anchor,url,body
                  "<a name=\"$anchor\" href=\"$url\">$body</a>" ]]

-- «images»  (to ".images")
--; (find-es "html" "scaled-images")
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>" ]]

-- 2011mar27:
def [[ RSCALEDIMAGE 3 target,perc,image
       "<a href=\"$target\">" ..
       "<img src=\"$image\" width=\"$perc\" border=0>" ..
       "</a>" ]]
def [[ SCALEDIMAGE 2 perc,image
       "<a href=\"$image\">" ..
       "<img src=\"$image\" width=\"$perc\" border=0>" ..
       "</a>" ]]

bdef [[ P     1 str        "\n\n<p>$str</p>" ]]

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"   ]]

def [[ TABLE 1 text  "<table>$text</table>\n" ]]
def [[ TR    1 text  "<tr>$text</tr>\n" ]]
def [[ TD    1 text  "<td>$text</td>\n" ]]
def [[ TH    1 text  "<th>$text</th>\n" ]]
def [[ DIV   1 text  "<div>$text</div>\n" ]]

def [[ TABLE+ 2 attribs,text  "<table $attribs>$text</table>\n" ]]
def [[ TR+    2 attribs,text  "<tr $attribs>$text</tr>\n"       ]]
def [[ TD+    2 attribs,text  "<td $attribs>$text</td>\n"       ]]
def [[ TH+    2 attribs,text  "<th $attribs>$text</th>\n"       ]]
def [[ DIV+   2 attribs,text  "<div $attribs>$text</div>\n"     ]]

def [[ UL+    2 attribs,str   "<ul $attribs>\n$str</ul>\n"      ]]

def [[ STYLE  1 style "style=\"$style\"" ]]
def [[ CLASS  1 class "class=\"$class\"" ]]

def [[ NARROW 1 text "\n<blockquote>\n$text\n</blockquote>\n"              ]]
def [[ BOX    1 body "\n<table><tr><td>\n"..body.."\n</td></tr></table>\n" ]]
def [[ BORDERLESSBOX 1 body
               "<table border=\"0\"><tr><td>\n$body\n</td></tr></table>\n" ]]
def [[ BORDERLESSBOX+ 2 attribs,body
      "<table border=\"0\" $attribs><tr><td>\n$body\n</td></tr></table>\n" ]]

def [[ PREBOX  3 boxattribs,prestyle,body
       '<table border="0" cellpadding="0" cellspacing="0"'..boxattribs..'>'..
       '<tr><td>\n'..
       '<pre style="'..prestyle..'">\n'..
       body..
       '</pre>'..
       '</td></tr></table>\n' ]]

-- 2007jul23
def [[ BORDERLESSBOXA 2 attribs,body
      "<table border=\"0\" $attribs><tr><td>\n$body\n</td></tr></table>\n" ]]
def [[ SPANCLASS 2 class,body "<span class=\"$class\">$body</span>" ]]
def [[ SPANSTYLE 2 style,body "<span style=\"$style\">$body</span>" ]]
def [[ TTSTYLE   2 style,body "<code style=\"$style\">$body</code>" ]]
def [[ PRESTYLE  2 style,body "<pre style=\"$style\">\n$body</pre>" ]]
def [[ PREBOX3  3 boxattribs,prestyle,body
       BORDERLESSBOXA(boxattribs, PRESTYLE(prestyle, body)) ]]

def [[ BR   0 _ "\n<br>\n"            ]]
def [[ RULE 0 _ "\n\n<hr size=1>\n\n" ]]

def [[ br 1 _ "<p><br/></p>" ]]

-- (find-angg "TH/Htmllib.tcl")
-- (find-angg "TH/index-old.th")
-- (find-blogmefile "blogme2-middle.lua")
-- (find-blogmefile "blogme2-outer.lua")

--------[ Q ]--------
-- «Q»  (to ".Q")

Q_re    = "([&<>])"
Q_table = { ["&"]="&amp;", ["<"]="&lt;", [">"]="&gt;" }
def [[ Q 1 text translatechars(text, Q_re, Q_table) ]]

--------[ SPANSTYLE, BG, BGFG ]--------
-- «BG»  (to ".BG")

def [[ SPANSTYLE 2 style,body "<span style=\"$style\">$body</span>" ]]
def [[ BG 2 bg,body
           SPANSTYLE("background-color: $bg;", body) ]]
def [[ BGFG 3 bg,fg,body
           SPANSTYLE("background-color: $bg; color: $fg;", body) ]]

--------[ PREBOXBLOGME and friends ]--------
-- «PREBOXBLOGME»  (to ".PREBOXBLOGME")
-- 2007oct09: many of my files had these definitions in the header,
-- it's better to have them here...

blogmestyle = "background: #ffda99"
prestyle    = "padding: 4px; margin: 1ex"
def [[ TTBLOGME     1 body TTSTYLE(blogmestyle, body) ]]
def [[ PREBOX       1 body PREBOX3("",                    prestyle, body) ]]
def [[ PREBOXBLOGME 1 body PREBOX3("", blogmestyle.."; "..prestyle, body) ]]
def [[ ORANGEBG     1 body BG("#ffda99", body) ]]

beigestyle  = "background: #fff7e7"
def [[ TTBEIGE      1 body TTSTYLE(beigestyle, body) ]]
def [[ PREBOXBEIGE  1 body PREBOX3("", beigestyle.."; "..prestyle, body) ]]
def [[ BEIGEBG      1 body BG("#fff7e7", body) ]]

--------[ Links to htmlized files ]--------
-- Most text files at angg generate htmlized versions of themselves at
-- the same directory, with a suffix ".html" added to their names...
-- For example,
--   <http://angg.twu.net/foo/bar.lua> is htmlized at:
--   <http://angg.twu.net/foo/bar.lua.html>.
-- The convention to point to anchors in blogme code is to just use a
-- "#" to separate the anchor from the name of the non-htmlized file;
-- the ".html" is added before the "#" if there is an "#anchor" part.
--   addhtml("foo/bar")         --> "foo/bar.html"
--   addhtml("foo/bar#anchor")  --> "foo/bar.html#anchor"
-- See: <http://angg.twu.net/eev-article.html#anchors>.

addhtml = function (url) 
    return (string.gsub(url, "^([^#]*)(#?)(.*)$", "%1.html%2%3"))
  end

replacehash = function (str, pat)
    return (string.gsub(str, "^([^#]*)(#?)(.*)$", pat))
  end
addehtml   = function (url) return replacehash(url, "%1.e.html%2%3") end
beforehash = function (url) return replacehash(url, "%1") end
-- addehtml is a fossil, for, e.g., [ES lua5#for] and (find-es "lua5" "for")

--------[ Local copies of files from the internet ]--------
-- «local-copies»  (to ".local-copies")
-- See: <http://angg.twu.net/eev-article.html#local-copies>,
--      <http://angg.twu.net/eev-article.html#psne>.
-- (find-angg "TH/Htmllib.tcl" "local_remote_urls")

tosnarf_prefix = "/home/edrx/snarf/"
tosnarf = function (str)
    local _, __, p, rest = string.find(str, "^([a-z]+)://(.*)")
    if _ and (p == "http" or p == "ftp" or p == "file") then
      return tosnarf_prefix..p.."/"..rest
    end
  end

def [[ R   2 url,body HREF(url, nilify(body) or url)                ]]
def [[ L   2 url,body HREF(tosnarf(url) or url, nilify(body) or url) ]]
def [[ LR  2 url,body L(url, body).." ("..R(url,"rmt")..")"         ]]



--------[ AAAAAARGHHHHHH ]--------
-- «local-copies-aargh»  (to ".local-copies-aargh")
-- One of the reasons why I gave up hacking TH was that it had these
-- words - coded in some burst of madness - whose code was almost
-- impossible to understand, and they were used all around in my
-- pages... So I decyphered their code (or sort of) and ported them to
-- blogme. The next step, of course, is to get rid of all occurrences
-- of them in my .blogme files.
--
-- (find-angg "TH/Generate" "link_functions" "procj AL1")
-- (find-blogmefile "blogme2-outer.lua" "AL = function (anggurl, text)")
-- (find-anggfile "TH/")
-- (find-angggrep "grep -nH -e MYURL TH/*.blogme")
-- (find-angggrep "grep -nH -e AURL  TH/*.blogme")
-- (find-angggrep "grep -nH -e MYL   TH/*.blogme")
-- (find-angggrep "grep -nH -e A0L   TH/*.blogme")

def [[ MYL 2 fname,text HREF(pathto(fname), nilify(text) or fname) ]]
def [[ A0L 2 url,body R(url, body) ]]
def [[ AL  2 a,text
  HREF(pathto(      addhtml(a)),  nilify(text) or beforehash(a)) ]]
def [[ ES  2 e,text
  HREF(pathto("e/"..addehtml(e)), nilify(text) or beforehash(e)) ]]

-- relativepathto_prefix = ""
-- def [[ relativepathto 1 str relativepathto_prefix .. str       ]]
-- def [[ section        1 str nilify(str) and ("#" .. str) or "" ]]
-- def [[ MYURL 2 url,name   pathto(nilify(name) and url or url.."#"..name) ]]
-- def [[ AURL  2 astem,name relativepathto(astem..".html"..section(name)) ]]
-- def [[ E     2 stem,anchor  "e/$stem.e.html"..section(anchor) ]]

-- bef_aft_hash = function (str)
--     local _, __, bef, aft = string.find(str or "", "^([^#]*)#?(.*)")
--     return {bef, aft}
--   end
-- readhvvrest = function ()
--     return bef_aft_hash(readvword()), readvrest() or ""
--   end
-- _AA["#2"] = readhvvrest

-- (find-angg "LUA/lua50init.lua" "readfile")

--------[ File sizes ]--------
-- «file-sizes»  (to ".file-sizes")

nbytes = function (fname)
    local f = io.open(fname)
    if f then return f:seek("end"), f:close() end
  end

MYLBYTES = function (fname, txt)
    local size = nbytes(fname)
    return MYL(fname, txt.." ("..(size or "??").." bytes)")
  end

IFL = J
IFR = J
ANAME = NAME

-- procj AL1 {anggurl text} {	# experimental version
--   foreach {astem name} $anggurl {}
--   L1 [AURL $astem $name] [or $text $astem]
-- }
-- 
-- beforehash = function (str)
-- afterhash

-- (find-angg "TH/Generate" "link_functions")
-- (find-zsh "cd ~/LUA/; lua blogme.lua")
-- (find-fline "index.blogme")

-- (find-blogme3 "notes.e.lua" "defs_as_lua")
-- (find-blogmefile "blogme2-outer.lua")

--------[ Headers ]--------
-- «headers»  (to ".headers")

dtd_transitional =
[[<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
    "http://www.w3.org/TR/html4/loose.dtd">
]]
dtd_strict =
[[<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN"
    "http://www.w3.org/TR/REC-html40/strict.dtd">
]]
headdtd = dtd_transitional
html_dtd = dtd_transitional

metastr = ""	      -- keywords, etc; addmeta, addkeywords are missing
def [[ TITLEDHTML 2 title,body
  headdtd..HTML(HEAD(TITLE(title)..metastr..headstyle).."\n"..BODY(body)) ]]

-- New way:
html_style    = ""   -- (find-wdgrefw3m "html40/head/head.html" "STYLE")
html_meta     = ""   -- (find-wdgrefw3m "html40/head/head.html" "META")
html_favicon  = ""
html_speedbar = ""
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..localhack()       ]]
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)))   ]]

-- Example: [SETHEADSTYLE h3 { background-color: orange; }]
def [[ HEADSTYLE    1 styles
         "<style type=\"text/css\"><!--\n$styles -->\n</style>\n" ]]
def [[ SETHEADSTYLE 1 styles set("html_style", HEADSTYLE(styles)) ]]
def [[ SETFAVICON 1 url  set("html_favicon",
         "<link rel=\"shortcut icon\" href=\"$url\" />\n") ]]

def [==[ LUCIDA 1 body [[
body { color: #000000;
       background: #ffffff;
       position: relative;
       font-size: 14px;
       font-family: 'Lucida Grande', Verdana, Arial, Sans-Serif;
       text-align: justify;
       width: 90%;
       left: 20px;
}   
.title { font-size: 22px; padding-bottom: 50px; }
.section { padding-bottom: 50px; }
.section .title-section { font-size: 18px; border-bottom: 1px #000000 dotted; }
.subsection { padding-top: 20px; padding-left: 20px; }
.subsection .title-subsection { font-size: 18px; }
.subsubsection { padding-top: 20px; padding-left: 40px; }
.subsubsection .title-subsubsection { font-size: 18px; }
]]..body
]==]

--------[ ? ]--------

-- Old:
-- headstyle = ""        -- for an inline stylesheet
-- def [[ SETHEADSTYLE 1 styles set("headstyle", HEADSTYLE(styles)) ]]
-- _G["SETHEADSTYLE"] = function (styles) headstyle = HEADSTYLE(styles) end
-- _A["SETHEADSTYLE"] = vargs1
-- HTMLIZE = lambda("title, body",
--   [[TITLEDHTML(Q(title), H3(Q(title)).."\n"..body..localhack())]])
-- def [[ HTMLIZE 2 title,body
--          TITLEDHTML(Q(title), H3(Q(title)).."\n"..body..localhack()) ]]
-- def [[ htmlize 2 title,body set("blogme_output", HTMLIZE(title, body)) ]]

def [[ localhack 0 _ "\n(Local hack not implemented)" ]]
def [[ localhack 0 _ ""                               ]]

-- Missing: this should change temporarily the file name and should check
-- the brackets
-- def [[ INCLUDE 1 fname withsubj(readfile(fname), vparse) ]]

-- 2007nov04: imported this from:
-- (find-blogme3file "blogme3.lua" "myinclude =")
myinclude = function (fname, verbose)
    if verbose then print("  Including: "..fname) end
    doblogme(readfile(ee_expand(fname)))
  end
def_ [[ INCLUDE 1 fname   myinclude(fname, nil)  ]]



def [[ WAYBACK 1 url "http://web.archive.org/web/*/"..url ]]
def [[ pkg     2 section,name
  R("http://packages.debian.org/testing/$section/"..name, name) ]]

--------[ htmlizetxt ]--------
-- «htmlizetxt» (to ".htmlizetxt")
-- 2014apr03: a hack for creating htmls more easily editable in W$... 
-- (find-blogme3 "options.lua" "basic-options")

crlf = function (str) return ((str:gsub("\r", "")):gsub("\n", "\r\n")) end
def_ [[ htmlizetxt 2 title,body
                     set("blogme_output", crlf(sgmlify(html_all(title, body))))
                     writefile(outputfile..".txt", blogme_output) ]]

--------[ Untabify and trim ]--------
-- «untabify-and-trim»  (to ".untabify-and-trim")
-- (find-dn4file "dednat4.lua" "untabify =")
-- (find-es "lua5" "string.gsub")
untabify_table =
  {"        ", "       ", "      ", "     ", "    ", "   ", "  ", " "}
--{"--------", "-------", "------", "-----", "----", "---", "--", "-"}
untabify_strtab = function (strbeforetab)
    return strbeforetab ..
      untabify_table[math.mod(strlen(strbeforetab), 8) + 1]
  end
two_d_trim = function (str)
    str = gsub(str, "^([ \t]*\n)*", "")   -- remove initial blank lines
    str = gsub(str, "[ \t]+\n", "\n")     -- remove whitespace at the right
    str = gsub(str, "[ \t\n]*$", "")      -- remove whitespace at the end
    str = gsub(str, "([^\t\n]*)\t", untabify_strtab)  -- untabify
    return str
  end

--------[ localvariables (experimental, for to-shadow) ]--------
-- «localvariables»  (to ".localvariables")
-- (find-enode "Specifying File Variables")
-- This is not being used yet.
--
-- The idea here is that some files will have a "shadow file"
-- (remember how in Forth it was common to have for each block of code
-- a block of comments) whose name is specified in the "Local
-- Variables:" section; a link like ``(to-shadow "anchor")'' works
-- from Emacs like ``(find-anchor ee-shadow-file "anchor")'', and to
-- htmlize that we need to read the value of ee-shadow-file from the
-- local variables section at the end of the file...

localvariablesline = function (lines)
    local nlines = #lines
    for i=nlines,nlines-12,-1 do
      local prefix = lines[i]:match "^(.*)Local Variables:"
      if prefix then
        local dots = string.rep(".", #prefix)
        local re = "("..dots..")([-_A-Za-z0-9]+):%s+(.*)"
        local re = dots.."([-_A-Za-z0-9]+):%s+(.*)"
	print(re)
        return i, prefix, re
      end
    end
  end

localvariables = function (lines)
    local lvline, prefix, re = localvariablesline(lines)
    if lvline then
      for i=lvline+1,#lines do
        print(i..": "..lines[i])   -- <-- change this
	print(lines[i]:match(re))  -- <-- and this
      end
    end
  end

--------[ Sec, INDEX, WITHINDEX (experimental) ]--------
-- «WITHINDEX»  (to ".WITHINDEX")
-- (find-es "blogme" "withindex")
-- (find-blogme3file "definers.lua" "5 readvvvvvrest")
-- (find-blogme3file "brackets.lua" "readvvvvvrest =")

readvvvvvvrest = function () return readvword(), readvvvvvrest() end
_AA["6"] = readvvvvvvrest

secindex = {}
unanchor = function (str) return string.sub(str, 2, -2) end
pushindex = function (indexentry, body)
    table.insert(secindex, indexentry)
    return body
  end
def [[ ANCHOR 3 anchor,target,body NAME(anchor, HREF("#"..target, body)) ]]
def [[ Sec    6 n,anchor,to,totarget,f,title
       pushindex(
         ANCHOR("."..unanchor(anchor), unanchor(anchor), n.." "..title),
         ANCHOR(unanchor(anchor), "."..unanchor(anchor), _G[f](n.." "..title))
       )
    ]]
def [[ INDEX 1 _ HLIST2(BF("Quick index:"), secindex) ]]
def [[ WITHINDEX 1 body INDEX()..body ]]

--------[ sec (experimental) ]--------
-- «readqline»  (to ".readqline")
-- (find-blogme3file "brackets.lua" "parsewchars =")
-- For simplicity, the "rest of line" in readqline cannot include []s.
-- Note that the newline is optional; "readqline" never fails.
readqline = function () return parsebypattern("^[ \t]*([^\n%[%]]*)\n?()") end
readlvvrest = function () return readqline(), readvword(), readvrest() end
_AA["lvv"] = readlvvrest

unanchor = function (str) return string.match(str, "\171([!-~]+)\187") or "" end
def [[ sec   lvv  line,f,title
       pushindex(
         ANCHOR("."..unanchor(line), unanchor(line), title),
         ANCHOR(unanchor(line), "."..unanchor(line), _G[f](title))
       )
    ]]

-- 2007oct08: sec is better than Sec, but the parameters are
-- different. Use this:
-- def [[ Sec   lvv  line,f,title  sec(line, f, title) ]]

--------[ DELAY ]--------
-- «DELAY» (to ".DELAY")
-- This is a great hack for creating indexes.
-- In [DELAY [foo] bar] the "[foo]" is only evaluated after the "bar".

_AA["QR"] = function () return readqword(), readvrest() end
def [[ DELAY  QR a,b doblogme(a)..b ]]

--------[ _name ]--------
-- «_name»  (to "._name")
def [[ _name 1 anchor,rest NAME(unanchor(anchor), "") ]]

--------[ 2007oct28: parsing lines ]--------
-- «parsing-lines»  (to ".parsing-lines")
-- Damn, this overrides readqline with something whose code is uglier...
-- (find-blogme3file "brackets.lua" "parsewchars =")
-- Parse horizontal spaces,
-- parse horizontal regular chars,
-- parse quoted lines or values of lines (newlines in []s are ignored):
parsehspaces = function () return parsebypattern("^([ \t]+)()") end
parsehrchars = function () return parsebypattern("^([^\n%[%]]+)()") end
readhrcharsorqblock_ = function () return parsehrchars() or readqblock_() end
readhrcharsorvblock_ = function () return parsehrchars() or readvblock_() end
readqline__ = function () return myconcat(mygather(readhrcharsorqblock_)) end
readvline__ = function () return myconcat(mygather(readhrcharsorvblock_)) end
readqline_  = function () parsehspaces(); return readqline__() end
readvline_  = function () parsehspaces(); return readvline__() end
-- readqline = function () return readqline_() or "" end
-- readvline = function () return readvline_() or "" end
parsenewline = function () return parsebypattern("^(\n)()") end
withnewline = function (s) parsenewline(); return s end
readqline   = function () return withnewline(readqline_() or "") end
readvline   = function () return withnewline(readvline_() or "") end

--------[ 2007oct29: tsec (for typewriter-ish notes) ]--------
-- (find-TH "dnc2007")
-- (find-TH "2007monads")
-- (find-ecolor-links "#eecc99")
_AA["lllq"] = function () return
    readqline(),
    readvline(),
    readqline(),
    readqrest__() or ""
  end
def [[ TSECTITLE 1 title BG("#ffeebb", title) ]]
def [[ tsec lllq anchorline,title,bar,rest
       PRE(sec(anchorline, "TSECTITLE", Q(title)).."\n"..
           string.rep(strsub(bar, 1, 1), strlen(title)).."\n"..
           Q(rest.."\n")) ]]
-- def [[ __tsec lllq ... PP(...) ]]

--------[ eev_math_glyphs_edrx ]--------
-- «eev_math_glyphs_edrx»  (to ".eev_math_glyphs_edrx")
-- Usage: (find-THgrep "grep -nH -e eev_math_glyphs_edrx *.blogme")
-- (eev-math-glyphs-edrx)
-- (find-eevfile "eev-math-glyphs.el")
-- (find-eevfile "eev-math-glyphs.el" "supset")
-- (find-efunction 'eev-math-glyphs-edrx)
-- (find-es "blogme" "other-glyphs")
-- (find-angg ".emacs" "square-brackets")
-- (find-eoutput '(ascstr 0 255))
-- (find-eoutput '(insert 299233 299376))
-- (find-eoutput '(insert 299233 299376) "" '(switch-to-buffer (htmlize-buffer)))
-- (find-eoutput '(insert 343255))
-- (find-eoutput '(insert 343255) "" '(switch-to-buffer (htmlize-buffer)))
-- (find-eoutput '(insert 343235))
-- (find-eoutput '(insert 299376))
-- (find-eoutput '(insert 299502))
-- (find-eleimfile "quail/sgml-input.el")
-- (find-eleimfile "quail/latin-ltx.el")
-- (find-anggfile "TH/davinci.blogme" "STANDOUT")
eev_math_glyphs_edrx = function ()
    sgmlify_table["\12"]  = BGFG("red", "yellow", "L")
    sgmlify_table["\14"]  = "&sigma;"
    sgmlify_table["\17"]  = "&#10214;"
    sgmlify_table["\16"]  = "&#10215;"
    sgmlify_table["\21"]  = "&pi;"
    sgmlify_table["\31"]  = "&or;"
  --sgmlify_table["\130"] = "&infin;"
    sgmlify_table["\130"] = "&#8734;"
  --sgmlify_table["\164"] = "&otimes;"
    sgmlify_table["\164"] = "&#8855;"
  --sgmlify_table["\167"] = "&top;"
    sgmlify_table["\167"] = "&#8868;"
  --sgmlify_table["\174"] = "&bottom;"
    sgmlify_table["\174"] = "&#8869;"
    sgmlify_table["\180"] = "&and;"
    sgmlify_table["\182"] = "&sup;"
    sgmlify_table["\183"] = "&middot;"
    sgmlify_table["\198"] = "&Sigma;"
    sgmlify_table["\204"] = "&cap;"
    sgmlify_table["\216"] = "&Omega;"
    sgmlify_table["\221"] = "&isin;"
    sgmlify_table["\229"] = "&Pi;"
  --sgmlify_table["\238"] = "&natur;"
    sgmlify_table["\238"] = "&#9838;"
    sgmlify_table["\240"] = "&lambda;"
  --sgmlify_table["\241"] = "&square;"
  --sgmlify_table["\241"] = "&#9744;"
    sgmlify_table["\241"] = "&#9633;"
    sgmlify_table["\206"] = "&exist;"
    sgmlify_table["\253"] = "&forall;"
    sgmlify_table["\254"] = "&cup;"
    sgmlify_re = "([\12\14-\31\128-\254])"
  end


-- «glyphs-for-dednat4»  (to ".glyphs-for-dednat4")
-- An emergency hack, just to make this look better:
--   (find-dn4ex "eedemo2.tex" "beta-reductions")
-- (2008jul12)
sgmlify_table["\31"]  = "&or;"
sgmlify_table["\180"] = "&and;"
sgmlify_table["\182"] = "&sup;"
sgmlify_re = "([\12\14-\31\128-\254])"



--------[ _TARGETS ]--------
-- «_TARGETS»  (to "._TARGETS")
-- exprimental, 2007sep29
-- (find-es "blogme" "_TARGETS")
load_TARGETS = function ()
    require "escripts"
    def [[ TGT 1 sexp Tgt(SexpLink:match(sexp)) ]]
    _target = _target or {}
    -- There are several possible definitions for the word "_",
    -- so I will not include one here...
    process_TARGET_line = function (linestr)
        local word, sexp = string.match(linestr, "^%s*(%S+)%s+%->%s+(%(.*%))%s*$")
        if word then _target[word] = TGT(sexp) end
        local word, url = string.match(linestr, "^%s*(%S+)%s+%=>%s+(%S+)%s*$")
        if word then _target[word] = url end
      end
    process_TARGET_lines = function (bigstr)
        string.gsub(bigstr, "([^\n]+)", process_TARGET_line)
      end
    def [[ _TARGETS 1Q lines   process_TARGET_lines(lines) ]]
  end

load_TARGETS()

def [[ --> 1 sexp sexp ]]
def [[ --> 1 sexp TGT(sexp:gsub("%s+", " ")) ]]

-- 2007oct24: There are many possible definitions for _ and __...
-- I think that I will want to overwrite these in some of my .blogme files,
-- but I'm including these as a "default" definition for convenience.
def [[ __ 2 str,text _target[str] and HREF(_target[str], nilify(text) or str)
                                   or BG("red", str) ]]
def [[ _  1 body __(gsub(body, " ", "."), body) ]]

--------[ 2007oct24: section numbers ]--------
-- «section-numbers»  (to ".section-numbers")
__secn = "0"
incrsecn = function (pat)
    local a, b = string.match(__secn, pat)
    if not a then                      -- not deep enough?
      repeat __secn = __secn .. ".1"   -- keep adding ".1"s
      until string.match(__secn, pat)  -- until deep enough
      return __secn                    -- and return this.
    end
    __secn = a .. (b+1)  -- else increase the right digit (drop the rest)
    return __secn        -- and return that.
  end
nplus = function () return incrsecn("^(%d-)(%d+)") end
nnplus = function () return incrsecn("^(%d+%.)(%d+)") end
nnnplus = function () return incrsecn("^(%d+%.%d+%.)(%d+)") end
nnnnplus = function () return incrsecn("^(%d+%.%d+%.%d+%.)(%d+)") end
-- A test:
-- __secn = "0"; print(nplus(), nplus(), nnplus(), nnnnplus(), nnplus())
                  -->  1        2        2.1       2.1.1.1     2.2

def [[ ++N    0 _ nplus() ]]
def [[ ++NN   0 _ nnplus() ]]
def [[ ++NNN  0 _ nnnplus() ]]
def [[ ++NNNN 0 _ nnnnplus() ]]

--------[ 2007oct26: over, under, layers ]--------
-- «over»  (to ".over")

over = function (bottomtable, toptable)
    return setmetatable(toptable, {__index = bottomtable})
  end
under = function (toptable)
    local mt = getmetatable(toptable)
    if mt then return mt.__index end
  end
layers = function (tbl)
    return function (state, depth)
        if not depth then depth = 0; return depth, tbl end
        depth, tbl = depth + 1, under(tbl)
        if tbl then return depth, tbl end
      end
  end

-- A = {a=44, b=55}
-- B = over(A, {c=66, d=77})
-- C = over(B, {d=88, e=99})
-- print(B.c, B.a)  --> 66 44
-- PP(C)                      --> C
-- PP(under(C))               --> B
-- PP(under(under(C)))        --> A
-- PP(under(under(under(C)))) --> nil
-- for depth,tbl in layers(C) do PP(depth, tbl) end
--> 0 {"d"=88, "e"=99}
--> 1 {"c"=66, "d"=77}
--> 2 {"a"=44, "b"=55}

-- (find-es "lua5" "generators-pseudocode")

--------[ 2007oct27: MDEF ]--------
-- «MDEF»  (to ".MDEF")
-- Experimental: "Macro DEF".
-- This one is a clean way to create blogme words that are "macros".
-- It should make DEF and DDEF obsolete (and should take their place).
-- (find-es "blogme" "MDEF")

_V = _V or {}
def_ [[ set 2 varname,text _G[varname] = text; return text ]]
def  [[ $   1 varname      _V[varname] or _G[varname]      ]]

runwithlocalvars = function (varnames, values, f, ...)
    _V = over(_V, {})                -- create a new frame for local vars
    for i,varname in ipairs(split(varnames, "([^,]+)")) do -- for each varname
      _V[varname] = values[i]        -- set its value in the new frame
    end
    local results = pack(f(...))     -- run f (with the new local vars)
    _V = under(_V)                   -- drop the new frame
    return unpack(results)
  end

def [=[ MDEF 4Q name,apspec,arglist,body
    def_set_AG(name, apspec,
        format("function (%s)\
            return runwithlocalvars(%q, {%s}, doblogme, %q)\
          end", arglist, arglist, arglist, body))
    ]=]

mdef = function (defstr) MDEF(def_split(defstr)) end


-- MDEF("AC", "2", "a,c", "(a: [$ a], c: [$ c])")
-- print(defs_as_lua())


--------[ extra options ]--------
-- «extra-options»  (to ".extra-options")
_O = _O or {}

--------[ -anggat ]--------
-- «-anggat»  (to ".-anggat")
-- Experimental, 2007dec28
-- (find-blogme3 "angglisp.lua" "code_c_d_angg")
-- (find-eev "eepitch.readme")
dooption_anggat = function (url)
    pathtoangg = url
    eevarticle = url.."eev-article.html"
    eepitchreadme = url.."eev-current/eepitch.readme.html"
 end
_O["-anggat"] = function (url, ...) dooption_anggat(url); dooptions(...) end



--------[ -tgt ]--------
-- «-tgt»  (to ".-tgt")
-- (find-angg ".emacs" "tgt")
-- (find-blogme3 "elisp.lua" "TGT")
-- (find-blogme3 "options.lua" "basic-options")
-- (find-blogme3 "angglisp.lua")
-- (find-eev "eepitch.readme")
dooption_tgt = function (sexp)
    pathtoroot    = "http://angg.twu.net/"
    eevarticle    = "http://angg.twu.net/eev-article.html"
    eepitchreadme = "http://angg.twu.net/eev-current/eepitch.readme.html"
    eepitch_el    = "http://angg.twu.net/eev-current/eepitch.el.html"
    eevintrosdir  = pathto("eev-intros/")
    eevintrosdir  = "http://angg.twu.net/eev-intros/"
    require "angglisp"
    print(TGT(sexp))
  end
_O["-tgt"] = function (sexp, ...) dooption_tgt(sexp); dooptions(...) end

--------[ ls2html (experimental) ]--------
-- «ls2html»  (to ".ls2html")
-- (find-angg "LUA/lstoindexhtml.lua")
-- (find-angg ".zshrc" "lstoindexhtml_lua_maybe")
-- (find-node "(coreutils)Toolbox introduction")
-- (find-node "(coreutils)ls invocation")
-- (find-sh "'ls' -laF /tmp/")
-- (find-sh0 "cd /tmp/; ~/blogme3/blogme3 -o index.html -ls ''")
-- (find-w3m "/tmp/index.html")

lsre = function (lsline)
    local _, __, nonfname = string.find(lsline, "^(.* )[^ ]*$")
    local dots = string.rep(".", string.len(nonfname))
    local re = "("..dots..")([^ */=@|]*)(.*)"
    return re
  end
lsline2html = function (re, lsline, prefix)
    local _, __, l, fname, r = string.find(lsline, re)
    return Q(l) .. HREF(fname, (prefix or "")..Q(fname)) .. Q(r)
  end
lsoutput2html = function (lsoutput, prefix)
    local lines = splitlines(lsoutput)
    local re = lsre(lines[2])
    local f = function (lsline) return
        lsline2html(re, lsline, prefix).."\n"
      end
    table.remove(lines, 1)  -- the first line is "total <nblocks>", remove it
    return table.concat(map(f, lines), "")
  end
ls2html = function (what, prefix)
    return lsoutput2html(getoutput("'ls' -laF " .. what), prefix)
  end
def [[ LS 2 what,prefix
         lsoutput2html(getoutput("'ls' -laF " .. what), prefix) ]]
dooption_ls = function (dir)
    htmlize(dir,
      "<!-- Generated by http://angg.twu.net/blogme3.html (-ls) -->\n"
      .. PRE(LS(dir, "")))
    writefile(outputfile, blogme_output)
  end
_O["-ls"]  = function (dir, ...) dooption_ls(dir); dooptions(unpack(arg)) end

--------[ -lsmaybe ]--------
-- «-lsmaybe»  (to ".-lsmaybe")
-- (find-angg ".zshrc" "lstoindexhtml_lua_maybe")
readfileifpossible = function (fname)
    local fd, err = io.open(fname, "r")
    local bigstr = fd and fd:read("*a")
    if fd then fd:close() end
    return bigstr
  end
dooption_lsmaybe = function (dir)
    local contents = readfileifpossible(outputfile)
    if contents then
      if contents:sub(1,256):find("Generated by.*%-ls") then
        print("Regenerating: "..outputfile)
      else
        print("Not changing: "..outputfile)
      end
    else
      print("Generating:   "..outputfile)
      dooption_ls(dir)
    end
  end
_O["-lsmaybe"]  = function (dir, ...) dooption_lsmaybe(dir); dooptions(unpack(arg)) end

backslashfilename = function (fname)
    return (fname:gsub("[^+-:@-Z_a-z]", "\\%0"))
  end

--------[ -cgiplain ]--------
-- «-cgiplain»  (to ".-cgiplain")
-- (find-blogme3 "options.lua" "basic-options" "dooption_i =")
-- (find-es "http" "cgi-test")
-- Experimental, 2008jan02
dooption_cgiplain = function (fname)
    dooption_o("STDOUT")      -- arbitrary string
    doblogme(readfile(fname))
    printf("Content-type: text/plain\n\n%s", blogme_output)
  end
_O["-cgiplain"] = function (fname, ...) dooption_cgiplain(fname); dooptions(unpack(arg)) end

dooption_cgihtml = function (fname)
    dooption_o("STDOUT")      -- arbitrary string
    doblogme(readfile(fname))
    printf("Content-type: text/html\n\n%s", blogme_output)
  end
_O["-cgihtml"] = function (fname, ...) dooption_cgihtml(fname); dooptions(unpack(arg)) end

--------[ -lua2html: a modified -a2html ]--------
-- «-lua2html»  (to ".-lua2html")
-- (find-es "blogme" "lua2html")
-- (find-ecolor-links "sienna")
htmlizeline_lua = function (line)
    local tag,rest = line:match"^([A-Za-z0-9_.]+)([ \t]+=.*)$"
    if tag then
      return NAME(tag, COLOR("#8b4513", tag))..htmlizeline(rest).."\n"
    end
    return htmlizeline(line).."\n"
  end
htmlizelines_lua = function (bigstr)
    return table.concat(map(htmlizeline_lua, splitlines(bigstr)), "")
  end
dooption_lua2html = function (fname)
    loada2html()
    htmlizefile(fname, outputfile, htmlizelines_lua)
  end
_O["-lua2html"] = function (fn, ...) dooption_lua2html(fn); dooptions(unpack(arg)) end

--------[ -org2html: another modified -a2html ]--------
-- «-org2html»  (to ".-org2html")
-- (find-es "blogme" "org2html")
htmlizeline_org = function (line)
    if line:match"^%*[ \t]+" then
      return BGFG("blue", "white", htmlizeline(line)).."\n"
    end
    return htmlizeline(line).."\n"
  end
htmlizelines_org = function (bigstr)
    return table.concat(map(htmlizeline_org, splitlines(bigstr)), "")
  end
dooption_org2html = function (fname)
    loada2html()
    htmlizefile(fname, outputfile, htmlizelines_org)
  end
_O["-org2html"] = function (fn, ...) dooption_org2html(fn); dooptions(unpack(arg)) end


--------[ deprecated options ]--------
-- «.deprecated-options»	(to "deprecated-options")
-- «deprecated-options»  (to ".deprecated-options")
-- (find-blogme3file "rumilisp.lua")
dooption_rumi   = function () dofile(blogmedir.."rumilisp.lua") end
dooption_ldb    = function () loadldb(); debug.debug = ldg        end
dooption_ldbnow = function () loadldb(); debug.debug = ldg; ldb() end
_O["-ldb"]    = function (...) dooption_ldb();  dooptions(unpack(arg)) end
_O["-ldbnow"] = function (...) dooption_ldbnow(); dooptions(unpack(arg)) end
_O["-rumi"]   = function (...) dooption_rumi(); dooptions(unpack(arg)) end


--------[ patched listings ]--------
-- «patched-listings»  (to ".patched-listings")
-- (find-TH "eev-article")
-- (find-es "blogme" "patched-listings")

_listing_parts = {}
_listing_add = function (text)
    tinsert(_listing_parts, text)
    return text
  end
parselspaces = function () return parsebypattern("^([ \t]*\n?)()") end
_AA["1q"]    = function () parselspaces(); return readqrest__() or "" end
def [[ L'  1q body     body ]]    --'
def [[ PRERECTBG 2 bg,body
  "<table border=0 cellpadding=0 cellspacing=0 style=\"margin: 0; background: $bg\"><tr><td>" ..
  "$body</tr></td></table>" ]]
def [[ PATCH' 1q body  PRERECTBG("orange", _listing_add(body)) ]]  --'
def [[ OUT'   1q body  PRERECTBG("red",    _listing_add(body)) ]]  --'
def [[ ORIG'  1q body  _listing_add(body) ]]                       --'
def [[ PLISTING 1 body  "<pre style=\"margin: 0\">$body</pre>" ]]
def [[ PLISTING 1 body  PRE(body) ]]


--------[ etc - big mess - 2007oct14 ]--------
-- «setvbuf»  (to ".setvbuf")
-- Without a setvbuf errors are unmanageable. By default stderr is
-- unbuffered and stdout is buffered; when an error happens Lua spits
-- out a traceback to stderr and only then closes - and flushes -
-- stdout, and we get some stdout output, then the traceback, then the
-- rest of the output - which is horrible.
-- The stdout is only used for debug output in blogme, so this does
-- not affect performance.
-- (find-luamanualw3m "#pdf-file:setvbuf")
-- (find-node "(libc)Controlling Buffering")
io.stdout:setvbuf("no")           -- for errors

--------[ HTMLIZELINES ]--------
-- «HTMLIZELINES»  (to ".HTMLIZELINES")
-- loada2html()
def [[ HTMLIZELINES 1  body htmlizelines(body) ]]
def [[ E'           1Q body htmlizelines(body) ]]
def [[ BE'          1Q body PREBOXBLOGME(htmlizelines(body)) ]]
def [[ PE'          1Q body PRE(htmlizelines(body)) ]]
-- to do: change parsespaces in these 1Qs to parse only "[ \t]*\n?"

--------[ PROMPTLINE ]--------
-- «PROMPTLINE»  (to ".PROMPTLINE")
-- (find-TH "luaforth" "lua-api-from-gdb")
-- (find-TH "blogme3")
def [[ PROMPTLINE 2 prompt,command
       COLOR("red", prompt).." "..COLOR("green", command) ]]

--------[ TRAFFIC ]--------
-- «TRAFFIC»  (to ".TRAFFIC")
-- (find-es "blogme" "traffic-lights-glyphs")
-- (find-angg ".emacs" "eev-traffic-light-glyphs")
-- (find-blogme3file "escripts.lua" "htmlizeline =")

traffic = function (char, str)
    if char == "\01" then return COLOR("red",   htmlizelines(str)) end
    if char == "\02" then return COLOR("green", htmlizelines(str)) end
    if char == "\04" then return BGFG("red", "yellow", BF(htmlizelines(str))) end
    return htmlizelines(str)
  end
def [[ TRAFFIC 1 body
       ("\03"..body):gsub("([\01-\04])([^\01-\04]*)", traffic) ]]

-- «-t2html»  (to ".-t2html")
-- (find-blogme3 "options.lua" "_O" "-a2html")
-- (find-blogme3 "options.lua" "basic-options")
-- (find-blogme3 "options.lua" "htmlizefile")
dooption_t2html = function (fname) htmlizefile(fname, outputfile, TRAFFIC) end
_O["-t2html"] = function (fn, ...) dooption_t2html(fn); dooptions(unpack(arg)) end

--------[ wikirefs ]--------
-- 2008jan03, for omnisys. unfinished, not tested, not working.
-- «wikirefs»  (to ".wikirefs")
extractwikirefs = function (filecontents)
    local lines = splitlines(filecontents)
    local linechars = {}
    -- local shorts, longs = {}, {}
    for i=1,#lines do
      local body, word, rest = lines[i]:match("^#%s+((%S+)%s*(.*))")
      if     word == "refs" and rest == "" then linechars[i] = "R"
      elseif word == "sfer" and rest == "" then linechars[i] = "r"
      elseif word == "tags" and rest == "" then linechars[i] = "T"
      elseif word == "stag" and rest == "" then linechars[i] = "t"
      elseif word and rest                 then linechars[i] = "#"
      else                                      linechars[i] = " "
      end
    end
    local chars = table.concat(linechars)
    local refs = {}
    for b, e in chars:gmatch("R()#+()r") do
      for i=b,e-1 do
        -- print(lines[i])
        local body, word, rest = lines[i]:match("^#%s+((%S+)%s*(.*))")
        refs[word] = rest
      end
    end
    return refs, lines, chars
  end

replacewikirefs = function (bigstr, refs, htmlizer)
    refs = refs or extractwikirefs(bigstr)
    htmlizer = htmlizer or TRAFFIC
    local strs = {}
    local f = function (pre, open, ref, close)
      print(ref)
      tinsert(strs, (htmlizer(pre)))
      tinsert(strs, open)
      tinsert(strs, (refs[ref] and R(refs[ref], Q(ref)) or Q(ref)))
      tinsert(strs, close)
      return "" end
    -- Slow. See: (find-angg "LUA/lua50init.lua" "lpeg_gsub")
    local rest = bigstr:gsub("(.-)(%[_[ \t\n]+)([!-Z^-~]+)(%])", f)
    return table.concat(strs)..htmlizer(rest)
  end

replacewikirefs = function (bigstr, refs, htmlizer)
    refs = refs or extractwikirefs(bigstr)
    htmlizer = htmlizer or TRAFFIC
    local Space, TagChar, Open, Close, Begin, Middle, End, WikiTagT
    Space   = lpeg.S(" \t\n")
    TagChar = lpeg.R("!~") - lpeg.S("'%[\\]<>&\"")
    Open    = lpeg.P("[_")
    Close   = lpeg.P("]")
    Begin   = (Open * Space^1):C()
    Middle  = (TagChar^1):C()
    End     = Close:C()
    WikiTagT = (Begin * Middle * End) / function (o, tag, c)
        return o.."<"..tag..">"..c
      end
    WikiTagT = (Begin * Middle * End) / function (o, tag, c)
        PP(refs, tag)
        if refs[tag]
        then return o..R(refs[tag], tag)..c
        else return o..tag..c
        end
      end
    return WikiTagT:gsub(bigstr, htmlizer)
  end

dooption_w2html = function (fname) htmlizefile(fname, outputfile, replacewikirefs) end
_O["-w2html"] = function (fn, ...) dooption_w2html(fn); dooptions(unpack(arg)) end

--------[ REDIRECTTO ]--------
-- «REDIRECTTO»  (to ".REDIRECTTO")
-- (find-THLfile "Estatistica.html" "meta http-equiv=\"refresh\"")
-- (find-THfile "Estatistica.th")
-- (find-anggfile "TH/Generate" "REDIRECTTO")
def [[ REDIRECTTO 1 url
         "<meta http-equiv=\"refresh\" content=\"2;URL=$url\">" ]]

--------[ cgiquote ]--------
-- «cgiquote»  (to ".cgiquote")
-- (find-angg "TH/Generate" "cgi_links" "proc cgiquote")
cgiquote = function (str)
    return (str:gsub("%%", "%%25")
               :gsub("\"", "%%22")
               :gsub("#",  "%%23")
               :gsub("&",  "%%26")
               :gsub("%+", "%%2b")
               :gsub(" ",  "+")
               :gsub("=",  "%%3d"))
  end
def [[ IMDBN 2 name,text
         R("http://us.imdb.com/Name?"..cgiquote(name), text) ]]
def [[ IMDBT 2 code,text
         R("http://us.imdb.com/Title?"..code, text) ]]
def [[ GOOGLE 2 query,text
         R("http://www.google.com/search?q="..cgiquote(query),
           nilify(text) or "google for: "..Q(query)) ]]
def [[ GOOGLEMAPS 2 query,text
         R("http://maps.google.com/maps?f=q&q="..cgiquote(query),
           nilify(text) or "google maps: "..Q(query)) ]]

--------[ javascript ]--------
-- «javascript»  (to ".javascript")
-- (find-es "javascript" "blogme")
def [[ JSFROM 1 fname "<script src=\"$fname\"></script>\n"               ]]
def [[ JS0  1Q body  "<script language=\"JavaScript\">\n$body\n</script>" ]]
def [[ JS00 1Q body  "<script>\n$body</script>"   ]]
def [[ JS0  1Q body  "<script>\n$body\n</script>" ]]
def [[ JS   1Q body  "<script language=\"JavaScript\">\n" ..
                     "<!--\n$body\n//-->\n" ..
                     "</script>" ]]
def [[ JSR  2 jsbody,text  R("javascript:$jsbody;", nilify(text) or jsbody) ]]
def [[ JREF 2 jsbody,text  R("javascript:$jsbody;", nilify(text) or jsbody) ]]

-- «html5-audio» (to ".html5-audio")
-- (find-blogme3 "html5-audio.js")
-- (find-blogme3 "html5-audio-mini.js")
-- (find-TH "tmp")
-- (find-THfile "audios/")
def [[ JSINCLUDE  1 fname   JS00(readfile(ee_expand(fname))) ]]
def [[ AUDIO     1 url     "<audio preload=\"auto\" controls>\n"..
                           "<source src=\"$url\">\n</audio>\n" ]]
def [[ PREID     2 id,body "<pre id=\"$id\">\n$body</pre>\n" ]]
def [[ activate_audio_links 2 n,id "audio_activate($n, \"$id\")" ]]
def [[ activate_audio_links_a 1 id "activate_audio_links_a(\"$id\")" ]]
def [[ activate_audio_links_b 1 id "activate_audio_links_b(\"$id\")" ]]
def [[ activate_audio_links_c 1 id "activate_audio_links_c(\"$id\")" ]]
-- def [[ AUDIO_INDEX 2 url,body
--          JS0(readfile(ee_expand(blogmedir.."html5-audio-mini.js")))..
--          "\n\n"..
--          AUDIO(url)..
--          PREID("audio_index_a", body)..
--          JS0(activate_audio_links_a("audio_index_a")).."\n" ]]

def [==[ AUDIO_INDEX 2 url,body
         -- JS00(readfile(ee_expand(blogmedir.."html5-audio-mini.js")))..
         JSINCLUDE(blogmedir.."html5-audio-mini.js")..
         "\n\n"..
[[<!--
 !                  _ _          ___  
 !   __ _ _   _  __| (_) ___    / _ \ 
 !  / _` | | | |/ _` | |/ _ \  | | | |
 ! | (_| | |_| | (_| | | (_) | | |_| |
 !  \__,_|\__,_|\__,_|_|\___/   \___/ 
 !                                    
 !-->]].."\n"..
         AUDIO(url)..
         PREID("audio_index_a", body)..
         JS0(activate_audio_links(0, "audio_index_a")).."\n" ]==]
def [==[ AUDIO_INDEX_B 2 url,body
[[<!--
 !                  _ _         _ 
 !   __ _ _   _  __| (_) ___   / |
 !  / _` | | | |/ _` | |/ _ \  | |
 ! | (_| | |_| | (_| | | (_) | | |
 !  \__,_|\__,_|\__,_|_|\___/  |_|
 !                                
 !-->]].."\n"..
         AUDIO(url)..
         PREID("audio_index_b", body)..
         JS0(activate_audio_links(1, "audio_index_b")).."\n" ]==]
def [==[ AUDIO_INDEX_C 2 url,body
[[<!--
 !                  _ _         ____  
 !   __ _ _   _  __| (_) ___   |___ \ 
 !  / _` | | | |/ _` | |/ _ \    __) |
 ! | (_| | |_| | (_| | | (_) |  / __/ 
 !  \__,_|\__,_|\__,_|_|\___/  |_____|
 !                                    
 !-->]].."\n"..
         AUDIO(url)..
         PREID("audio_index_c", body)..
         JS0(activate_audio_links(2, "audio_index_c")).."\n" ]==]





def [==[ AUDIO_INDEX_D 2 url,body
[[<!--
 !                  _ _         _____ 
 !   __ _ _   _  __| (_) ___   |___ / 
 !  / _` | | | |/ _` | |/ _ \    |_ \ 
 ! | (_| | |_| | (_| | | (_) |  ___) |
 !  \__,_|\__,_|\__,_|_|\___/  |____/ 
 !                                    
 !-->]].."\n"..
         AUDIO(url)..
         PREID("audio_index_d", body)..
         JS0(activate_audio_links(3, "audio_index_d")).."\n" ]==]

def [==[ AUDIO_INDEX_E 2 url,body
[[<!--
 !                  _ _         _  _   
 !   __ _ _   _  __| (_) ___   | || |  
 !  / _` | | | |/ _` | |/ _ \  | || |_ 
 ! | (_| | |_| | (_| | | (_) | |__   _|
 !  \__,_|\__,_|\__,_|_|\___/     |_|  
 !                                     
 !-->]].."\n"..
         AUDIO(url)..
         PREID("audio_index_e", body)..
         JS0(activate_audio_links(4, "audio_index_e")).."\n" ]==]

def [==[ AUDIO_INDEX_F 2 url,body
[[<!--
 !                  _ _         ____  
 !   __ _ _   _  __| (_) ___   | ___| 
 !  / _` | | | |/ _` | |/ _ \  |___ \ 
 ! | (_| | |_| | (_| | | (_) |  ___) |
 !  \__,_|\__,_|\__,_|_|\___/  |____/ 
 !                                    
 !-->]].."\n"..
         AUDIO(url)..
         PREID("audio_index_f", body)..
         JS0(activate_audio_links(5, "audio_index_c")).."\n" ]==]




-- 
def [[ ptime        2 funname,time "("..JREF("$funname('$time')", time)..")" ]]
def [[ seekbox      2 funname,time
                  "<input size=8 value=\"$time\" onkeydown=\"$funname()\">" ]]
def [[ seekboxptime 3 kfunname,funname,time
                  seekbox(kfunname, time)..ptime(funname, time) ]]

-- (find-es "javascript" "textarea-eval")
DDEF("TEXTAREAEVAL", "5", "formname,cols,rows,outrows,initialcode", [[
  <form name="$formname">
  <textarea name="input" cols=$cols rows=$rows>
$initialcode
  </textarea>
  <br>
  <a href="javascript:docopy(document.$formname);">docopy()</a>
  <a href="javascript:doeval(document.$formname);">doeval()</a>
  <br>
  <textarea name="output" cols=$cols rows=$outrows>
  </textarea>
  </form>
]])
def [[ TEXTAREAEVALRUN 5 formname,cols,rows,outrows,initialcode
       TEXTAREAEVAL(formname, cols, rows, outrows, initialcode) ..
       JS("doeval(document.$formname)") ]]



def [[ GETOUTPUT0 1Q sh_code getoutput(sh_code) ]]
def [[ GETOUTPUT  1Q sh_code (getoutput(sh_code):gsub("\n+$", "")) ]]

def [==[ VIDEO_INDEX 2 pre_id,body
         JSINCLUDE(blogmedir.."local-videos-mini.js")..
         "\n\n\n"..
[[<!--
 !        _     _                
 ! __   _(_) __| | ___  ___  ___ 
 ! \ \ / / |/ _` |/ _ \/ _ \/ __|
 !  \ V /| | (_| |  __/ (_) \__ \
 !   \_/ |_|\__,_|\___|\___/|___/
 !                               
 !-->]].."\n"..
         PREID(pre_id, body)..
         JS0("yt_htmlize_pre(\""..pre_id.."\")").."\n" ]==]




--------[ pages for my courses at PURO ]--------
-- «puro»  (to ".puro")
DDEF("MES", "2", "month,days", [[
  <center>
  <table width="90%" bgcolor="#000000" cellspacing="1" cellpadding="5" border="0">
  <tr bgcolor="#E0E0E0">
     <td align="center" colspan="2">
     <b>$month</b>
     </td>
  </tr>
  $days
  </table>
  </center>
]])
DDEF("AULA", "3", "n,date,body", [[
  <tr valign="top">
     <td align="center" bgcolor="#FFFFFF">
        $date
        <br>
        <br>
        (Aula $n)
      </td>
      <td bgcolor="#FFFFFF">
        <p align="justify">
        $body
        </p>
      </td>
  </tr>
]])
DDEF("PROVA", "3", "n,date,body", [[
  <tr valign="top">
     <td align="center" bgcolor="#FBDCC8">
        $date
        <br>
        <br>
        (Aula $n)
      </td>
      <td bgcolor="#FFFFFF">
        <p align="justify">
        $body
        </p>
      </td>
  </tr>
]])

-- «htmlizelines_aulas»  (to ".htmlizelines_aulas")
-- (find-blogme3 "anggdefs.lua" "TRAFFIC")
-- (find-blogme3file "escripts.lua" "htmlizelines =")
-- 2011jun14
-- (find-TH "2011.1-MD")
-- (find-TH "2011.1-GA")
htmlizeline_aula = function (li)
    local n, aaula, rest = li:match("^([0-9.]+)(. aula)(.*)$")
    if n then 
      local tag = n.."a-aula"
      local taula = Q(n..aaula)
      return NAME(tag, R("#"..tag, Q(n..aaula)))..htmlizeline(rest)
      -- PP(n, aaula, rest)
    else
      return htmlizeline(li)
    end
  end
htmlizelines_aulas = function (bigstr)
    return (bigstr:gsub("[^\n]+", htmlizeline_aula))
  end
def [[ BEA'    1Q body PREBOXBLOGME(htmlizelines_aulas(body)) ]]


-- «mailto»  (to ".mailto")
def [[ MAILTO 1 email R("mailto:"..email, TT(email)) ]]

-- «chapa1»  (to ".chapa1")
def [==[ CHAPA1_ 2 imagetarget,body
  _B.P(R(imagetarget,
      "<IMG SRC=\"PURO/chapa1.jpg\" ALIGN=\"left\" WIDTH=\"6.25%\" BORDER=0>")..
    "\n"..body)..
  "<BR clear=left>\n"
  ]==]

def [[ CHAPA1 1 _
  CHAPA1_("chapa1.html", "&nbsp;"..R("chapa1.html", "Chapa 1"))
  ]]



--------[ the Sexp class, for hyperlink sexps (2013jan17) ]--------
-- «Sexp» (to ".Sexp")
-- (find-blogme3file "escripts.lua" "htmlizeline =")
-- (find-angg "LUA/lua50init.lua" "Sexp" "hrefto =")
Sexp = Sexp or {}

Sexp.__index.Q      = Q
Sexp.__index.seekto = function (sexp, secs)
    return sexp:hrefto("javascript:seekto("..secs..")")
  end
Sexp.htmlizeline = function (line) return Sexp{line=line}:getlinehtml() end
Sexp.htmlizelines = function (bigstr)
    return (bigstr:gsub("[^\n]+", Sexp.htmlizeline))
  end
def [[ SQ 1q bigstr   Sexp.htmlizelines(bigstr) ]]  

mmss_to_secs = function (mmss)
    local     mm, ss = mmss:match"^(%d?%d):(%d%d)$"
    if mm then return mm*60+ss end
    local hh, mm, ss = mmss:match"^(%d?%d):(%d%d):(%d%d)$"
    if hh then return hh*3600+mm*60+ss end
  end

-- «meta_seek» (to ".meta_seek")
-- Usage: elispSPECIAL["find-foo-audio"] = meta_seek
-- See: (find-TH "html5-audio")
meta_seek = function (sexp)
    sexp:getsexpargs()
    local mmss = sexp:string(2)
    local secs = mmss and mmss_to_secs(mmss)
    local r = sexp.ranges[2]
    sexp:setrange(r[1]+1, r[2]-1, secs and sexp:seekto(secs))
    sexp.sexphtml = sexp:tohtml0()
  end


--------[ asurl_hack ]--------
-- «asurl_hack» (to ".asurl_hack")
-- (find-THgrep "grep -nH -e gsub *.blogme | grep angg")
-- (find-THgrep "grep -nH -e anggtwunet_becomes *.blogme")
-- (find-blogme3file "escripts.lua" "asurl_hack =")
anggtwunet_becomes = function (prefix)
    asurl_hack = function (url)
        return (url:gsub("^http://angg.twu.net/", prefix))
      end
  end


--------[ youtube ]--------
-- «youtube» (to ".youtube")
-- (find-blogme3 "youtube.lua")

def [[ foo_videos0 0 _ JS0(readfile(blogmedir.."local-videos.js")) ]]
def [[ foo_videos 2 mpid,bodyid
         JS0(readfile(blogmedir.."local-videos.js")..
         "get_mp4s_from('$mpid')\n"..
         "youtube_activate('$bodyid')") ]]

lua_exec = function (code) return assert(loadstring(code))() end
lua_expr = function (code) return assert(loadstring("return "..code))() end

def [[ htmlize0  2 title,body set("blogme_output", html_all(title, body))   ]]
def [[ pre_id    2  id,body  "<pre id=\"$id\">\n$body\n</pre>\n" ]]
def [[ pre_id'   2Q id,body  "<pre id=\"$id\">\n$body\n</pre>\n" ]]
def [[ lr_files  1  code     pre_id("mp4s", lua_expr(code))      ]]
def [[ lr_files' 1Q body     pre_id("mp4s", body)                ]]
def [[ lr_body   1  code     pre_id("foo", lua_expr(code))       ]]
def [[ lr_body'  1Q body     pre_id("foo", body)                 ]]

def [[ lr_activate 0 _       JS0(readfile(blogmedir.."local-videos.js")..
                     'get_mp4s_from("mp4s"); youtube_activate("foo")') ]]
def [[ lr_activate 0 _       JSFROM("local-videos.js")..
                 JS0('get_mp4s_from("mp4s"); youtube_activate("corpo")') ]]

-- Obsolete (?)
-- (find-fline "~/blogme3/local-videos.blogme")

--------[ youtube-static ]--------
-- «youtube-static» (to ".youtube-static")
-- (find-angg "LUA/lua50init.lua" "youtube_split")

youtube_fname_split_simple = function (str)
    local a, hash, ext = str:match "^(.-)(...........)(%.%w%w%w?%w?%w?)$"
    if hash and not hash:match "[^-_A-Za-z0-9]" then return a, hash, ext end
  end
hash_to_fname = {}
youtube_read_lst = function (fname)
    for fname in ee_readfile(fname):gmatch("([^\n]+)") do
      local a,hash,ext = youtube_fname_split_simple(fname)
      if hash then hash_to_fname[hash] = fname end
    end
  end

-- (find-angg "LUA/lua50init.lua" "youtube_split")
youtube_yt_line = function (li)
  local a,hash,b,title,c = youtube_split_url0(li)
  if not a then return end
  if a:match"[^ ]$" then return end
  local url = youtube_make_url(hash)
  local ytlink = "(" .. HREF(url, "YT") .. ")"
  local fname  = hash_to_fname[hash]
  local titlelink = fname and HREF(fname, Q(title)) or Q(title)
  return a..ytlink..b..titlelink..c
end
youtube_url_line = function (li)
    local a,url,b = li:match("^(.-)(https?://%S+)(.*)$")
    if not a then return end
    if a:match"[^ ]$" then return end
    return Q(a)..HREF(url, Q(url))..Q(b)
  end

-- «at_home» (to ".at_home")
-- (find-angg ".zshrc" "linkdasruas" "export HOST")
-- (find-fline "/etc/hostname")
-- if readfile("/etc/hostname"):match("lakhesys") then ... end
at_home = function () return os.getenv("HOST") == "lakhesys" end

--------[ lpeg.gsub ]--------
-- (find-angg "LUA/lua50init.lua" "lpeg_gsub")
lpeg.togsub = lpeg_togsub
lpeg.gsub_  = lpeg_gsub_
lpeg.gsub   = lpeg_gsub

-- 2008may26
def [[ IF  0 _  assert(loadstring("return "..readqword()))() and readvrest() ]]

def [[ STANDOUT  1 body BGFG("red", "yellow", body) ]]



-- Local Variables:
-- coding: raw-text-unix
-- ee-anchor-format:     "«%s»"
-- End: