Warning: this is an htmlized version!
The original is here, and the conversion rules are here. |
This is the `README' file of BlogMe. Copyright 2005 Eduardo Ochs <edrx@mat.puc-rio.br> Author: Eduardo Ochs <edrx@mat.puc-rio.br> Version: 2005feb26 License: GPL (I'll add the complete headers later) Latest: http://angg.twu.net/blogme/README VERY IMPORTANT (added in 2005aug25): this README describes -- VERY imprecisely -- blogme.lua, but I have just finished rewriting blogme.lua, and I now declare that the original blogme.lua is UGLY & OBSOLETE. Blogme2 consists of the files whose names start with "blogme2" at <http://angg.twu.net/blogme/>, plus the doc file <http://angg.twu.net/blogme/INTERNALS>, and edrxlib.lua. The "language" that blogme.lua accepts is extensible and can deal with input having a lot of explicit mark-up, like this, [HLIST2 Items: [HREF http://foo/bar a link] [HREF http://another/link] [IT Italic text] [BF Boldface] ] and conceivably also with input with a lot of _implicit_ mark-up and with control structures, like these examples (which haven't been implemented yet): [BLOGME Tuesday, February 15, 2005 I usually write my notes in plain text files using Emacs; in these files "["s and "]"s can appear unquoted, urls appear anywhere without any special markup (like http://angg.twu.net/) and should be recognized and htmlized to links, some lines are dates or "anchors" and should be treated in special ways, the number of blank lines between paragraphs matter, in text paragraphs maybe _this markup_ should mean bold or italic, and there may be links to images that should be inlined, etc etc etc. ] [IF somecondition [(then this)] [(else this)] ] We also support executing blocks of Lua code on-the-fly, like this: [lua: -- we can put any block of Lua code here -- as long as its "["s and "]"s are balanced ] The trick is simple. In this language there is only one special syntactical construct, "[...]". We only have four classes of characters "[", "]", whitespace, and "word"; "[...]" blocks in the text are treated specially, and we use Lua's "%b[]" regexp-ish construct to skip over the body of a "[...]" quickly, skipping over all balanced "[]" pairs inside. The first "word" of such a block (we call it the "head" of the block) determines how to deal with the "rest" of the block. To "evaluate" an expression like [HREF http://foo/bar a link] we only parse its "head" - "HREF" - and then we run the Lua function called HREF. It is up to that function HREF to parse what comes after the head (the "rest"); HREF may evaluate the []-expressions in the rest, or use the rest without evaluations, or even ignore the rest completely. After the execution of HREF the parsing resumes from the point after the associated "]". Actually the evaluation process is a bit more sophisticated than that. Instead of executing just HREF() we use an auxiliary table, _GETARGS, and we execute: HREF(_GETARGS["HREF"]()) _GETARGS["HREF"] returns a function, vargs2, that uses the rest to produce arguments for HREF. Running vargs2() in that situation returns "http://foo/bar", "a link" and HREF is called as HREF("http://foo/bar", "a link"). So, to define HREF as a head all we would need to do ("would" because it's already defined) is: HREF = function (url, text) return "<a href=\""..url.."\">"..text.."</a>" end _GETARGS["HREF"] = vargs2 Defining new heads is so common - and writing out the full Lua code for a new head, as above, is so boring - that there are several tools to help us with that. I will explain only one of them, "def": def [[ HREF 2 url,text "<a href=\"$url\">$text</a>" ]] "def" is a lua function taking one argument, a string; it splits that string into its three first "words" (delimited by blanks) and a "rest"; here is its definition: restspecs = { ["1"]=vargs1, ["2"]=vargs2, ["3"]=vargs3, ["4"]=vargs4, ["1L"]=vargs1_a, ["2L"]=vargs2_a, ["3L"]=vargs3_a, ["4L"]=vargs4_a } def = function (str) local _, __, name, restspec, arglist, body = string.find (str, "^%s*([^%s]+)%s+([^%s]+)%s+([^%s]+)%s(.*)") _G[name] = lambda(arglist, undollar(body)) _GETARGS[name] = restspecs[restspec] or _G[restspec] or error("Bad restspec: "..name) end The first "word" ("name") is the name of the head that we're defining; the second "word" ("restspec") determines the _GETARGS function for that head, and it may be either a special string (one of the ones registered in the table "restspecs") or the name of a global function. More later. #* # Download and unpack: rm -Rv ~/blogme/ mkdir ~/blogme/ cd ~/blogme/ wget http://201.8.6.142/tmp/blogme.tgz tar -xvzf blogme.tgz #* # Test: cd ~/blogme/ time lua50 blogme.lua -o index.html -i index.blogme #* # Pack: cd ~/blogme/ tar -cvzf /var/www/tmp/blogme.tgz README blogme.lua edrxlib.lua index.blogme #*