.import tutorial .import markdown . copy basic.css .title Livetext: A smart processor for text *[This README is currently mangled. Fixes coming soon!] Livetext is simply a tool for transforming text from one format into another. The source file has commands embedded in it, and the output is dependent on those commands. Why is this special? It's very flexible, very extensible, and it's extensible _[in Ruby]. .section Why Livetext? Livetext grew out of several motivations. One was a desire for a markup language that would permit me to write articles (and even books) in my own way and on my own terms. I've done this more than once (and I know others who have, as well). I liked Softcover, but I found it to be very complex. I never liked Markdown much -- I find it very dumb, and it's not extensible at all. (In fairness to Markdown, it does serve a different purpose in everyday life.) I wanted something that had the basic functionality of all my _[ad hoc] solutions but allowed extensions. Then my old solutions would be like subsets of the new format. This was a generalization similar to the way we began several years ago to view HTML as a subset of XML. .section What is Livetext really? Here goes: .list It's a text transformer It's Ruby-based (later on, more language agnostic) It's (potentially) agnostic about output format It's designed to be flexible, extensible, and easy It's designed to be "plugin" oriented It's like an old-fashioned text formatter (but extensible) It's like a macro processor (but not) It's like markdown and others (but not) It's like erb or HAML (but not) It's powerful but not too dangerous It's not necesarily a markdown replacement It's definitely not a softcover replacement It could possibly augment markdown, softcover, others .end .section How does it work? A Livetext file is simply a text file which may have commands interspersed. A command is simply a period followed by a name and optional parameters (at the beginning of a line). The period will be configurable later if you want to use another character. The names are (for now) actual Ruby method names, so names such as `to_s and `inspect are currently not allowed. At present, I am mostly emitting "dumb HTML" or Markdown as output. In theory, you can write code (or use someone else's) to manipulate text in any way and output any format. Technically, you could even emit PDF, PNG, or SVG formats. . Idea: Make an RMagick DSL as an example. It's possible to embed comments in the text. Later it will be possible to pass them through to the output in commented form. The command `.end is special, marking the end of a body of text. Some commands may operate on a block of lines rather than just a few parameters. (A text block is like a here-document.) There is no method name corresponding to the `.end command. The file extension I've chosen is `.lt3 (though this may change). *Note: The source for this README is a `.lt3 file which uses its own little _[ad hoc] library (called ``tutorial.rb). Refer to the repo to see these. .section Syntax, comments, and more At first, my idea was to provide predefined commands and allow user-defined commands (to be distinguished by a leading `. or `.. marker). So the single and double dots were both legal. However, my concept at present is that the double dots (currently unused) may be used for subcommmands. User-defined commands may be added to the standard namespace. There are plans to permit commands beginning with a specified character other than the period (to be stored in their own namespace. When a leading period is followed by a space, that line is a comment. When it is follwed by a name, that name is typically understood to be a method name. Any remaining text on the line is treated as a parameter list to be accessed by that method. Some methods accept a text block (multiple lines of text terminated by a `.end tag). .section Boldface and italics Very commonly we want to format short words or phrases in italics, boldface, or a monospaced (fixed width) font. The Markdown spec provides ways to do this that are fairly intuitive; but I personally don't like them. My own notation works a different way. First of all, note that these don't work across source lines; they're strictly intra-line. You may need (for example) an italicized phrase that spans across a newline; at present, you'll need a workaround for that. I find that most short items I want to format are single tokens. Therefore I use a prefixed character in front of such a token: Underscore for italics, asterisk for boldface, and backtick for "code font." The formatting ends when the first blank space is encountered, without any kind of suffixed character. I also find it's common to want to terminate such a string with some kind of naturally-occurring punctuation mark. If we double the initial delimiter, it will be understood to terminate at the first period, comma, or right parenthesis. Of course, there are cases where this won't work; a formatted string may contain spaces, or it may exclude characters before the blank space. In this case, we can use an opening bracket after the prefix and a closing bracket at the end of the string. This means that it can be difficult to include brackets inside a formatted token. The solution is simply to escape with a backslash. A delimiter character sitting by itself need not be escaped. It will be output as a literal. A delimiter character that is already inside another string need not be escaped. These cannot be nested (though there is a way to accomplish this using functions). Most of this is summarized in this example (taken from one of the testcases): .testcase basic_formatting .section Standard methods The module `Livetext::Standard contains the set of standard or predefined methods. Their names are essentially the same as the names of the dot-commands, with occasional exceptions. (For example, it is impractical to use the name `def as a method name, so the module has a `_def method instead.) Here is the current list: .xtable `comment :: Start a comment block `errout :: Write an error message to STDERR `def :: Define a new method inline `set :: Assign values to variables for later interpolation `include :: Include an outside text file (to be interpreted as Livetext) `mixin :: Mix this file of Ruby methods into the standard namespace `copy :: Copy this input file verbatim (no interpretation) `r :: Pass a single line through without processing `raw :: Pass this special text block (terminated with ``__EOF__) directly into output without processing `func :: Define a function to be invoked inline `say :: Print a message to the screen `banner :: Print a "noticeable" message to the screen `quit :: End processing and exit `nopass :: Don't pass lines through (just honor commands) `include :: Read and process another file (typically a `.lt3 file) `debug :: Turn on debugging `nopara :: Turn off the "blank line implies new paragraph" switch `newpage :: Start a new output page .end .section Examples from the tests Here are some tests from the suite. The file name reflects the general purpose of the test. .testcase hello_world .testcase comments_ignored_1 .testcase block_comment .testcase def_method .testcase simple_vars .testcase simple_include .testcase simple_mixin .testcase simple_copy .testcase copy_is_raw .testcase raw_text_block .section Writing custom methods Suppose you wanted to write a method called `chapter that would simply output a chapter number and title with certain heading tags and a horizontal rule following. There is more than one way to do this. The simplest way is just to define a method inline with the rest of the text. Here's an example. .code .comment This example shows how to define a simple method "chapter" inline .end . This is also a comment, by the way. .def chapter params = _args raise "chapter: expecting at least two args" unless params.size > 1 num, *title = params # Chapter number + title title = title.join(" ") # Join all words into one string text = <<-HTML