2. Skribilo User Manual — Syntax |
This chapter describes the syntax or Skribilo documents---or rather, the available syntaxes Skribilo documents can use. Skribilo actually supports several input syntaxes, each of which is implemented by a reader. The input syntax (and reader) can be selected at document compilation time using the --reader option of the compiler (see Chapter 14). Nevertheless, it has a ``preferred'' syntax (the default syntax), which is that of the Skribe document preparation system. Thus, the Skribe syntax is first described, and then alternate syntaxes are presented.
By default or when the --reader=skribe option is passed to the compiler, a Skribilo document is composed of Skribe expressions, which resemble expressions in the Scheme programming language, with a few extensions to make them more convenient to use within documents. A Skribe expression can be:
Here are several examples of correct Skribe expressions:Expressions are evaluated, thus (bold "foo") has the effect of typesetting the word foo in bold face to produce foo. Escape sequences enable evaluation of expressions inside the text. Thus the text [Another ,(bold "text") sample] produces `Another text sample'. On the other hand [Another (bold "text") sample] produces `Another (bold "text") sample' because it does not contain the escape sequence `,('.
<expr> --> <atom> | <text> | <list> <list> --> (<expr>+) <text> --> [any sequence but `,(' or a `,<list>'] <atom> --> <boolean> | <integer> | <float> | <string> | <color> <integer> --> [0-9]+ <float> --> [0-9]+.[0-9]* | [0-9]*.[0-9]+ <string> --> ... <color> --> <string> | #[0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f]
A Skribe width refers to the horizontal size a construction occupies on an output document. There are three different ways for specifying a width:
350
).50.0
) which ranges in the interval
[-100.0 .. 100.0]"0*"
specification). Note that this way of specifying width
is strictly unportable.Alternatively, Skribilo allows documents to be written in a plain text format, with almost no markup. Instead, conventions borrowed from Emacs' Outline Mode to denote the text structure as well as other common conventions are used to express various formatting ideas. This syntax is implemented by the outline reader; thus, it is made available by passing the --reader=outline option to the compiler. The major elements of this syntax are the following:
Title:
at the beginning of the text file, and followed by
the title. Likewise, the author can be specified with a line starting
with Author:
.tt
.(ref :url ...)
form (see ref
). In addition,
outline has limited support for Org-Mode-style hyperlinks; for
instance, [[http://gnu.org/][The GNU Project]]
yields The GNU Project.Here is an example showing how the outline syntax maps to the native skribe syntax:
-*- mode: outline; coding: iso-8859-1; -*- Title: Demonstrating Skribilo's Outline Syntax Author: Ludovic Courtes Keywords: Skribilo outline Emacs This document aims to *demonstrate* [[http://skribilo.nongnu.org/][Skribilo]]'s outline syntax. * The First Chapter The first chapter contains a couple of sections. They look as though they had been introduced with the `section' markup of the Skribe syntax. ** The First Section This section is pretty much empty. ** The Second Section This section introduces lists. *** Bullet Lists This section contains a wonderful `itemize'-style bullet list: - the first item; - the second item; - the last one, which spans two lines of text. And that's it. Note that list items had to be separated by empty lines. *** Enumerations This section shows an `enumerate'-style list: 1. The first item; 2. The second one; 3. The last one. Note that list items are numbered this time. * The Second Chapter The second chapter does _not_ add anything useful. Text like this that starts after an empty line is put into a new paragraph.Ex. 1: The outline syntax
... produces:
(document #:title "Demonstrating Skribilo's Outline Syntax" #:author (author #:name "Ludovic Courtes") #:keywords '("Skribilo outline Emacs") (p (list (list (list "This document aims to " (bold "demonstrate") "") "\n") (list "" (ref #:url "http://skribilo.nongnu.org/" #:text "Skribilo") "'s outline syntax.") "\n")) (chapter #:title "The First Chapter" (p (list (list (list "The first chapter contains a couple of sections." "\n") "They look as though they had been introduced with" "\n") (list "the " (tt "section") " markup of the Skribe syntax.") "\n")) (section #:title "The First Section" (p (list "This section is pretty much empty." "\n"))) (section #:title "The Second Section" (p (list "This section introduces lists." "\n")) (subsection #:title "Bullet Lists" (p (list (list "This section contains a wonderful " (tt "itemize") "-style bullet list:") "\n")) (itemize (item (list "the first item;")) (item (list "the second item;")) (item (list (list "the last one, which spans") " two lines of text."))) (p (list (list "And that's it. Note that list items had to be" "\n") "separated by empty lines." "\n"))) (subsection #:title "Enumerations" (p (list (list "This section shows an " (tt "enumerate") "-style list:") "\n")) (enumerate (item (list "The first item;")) (item (list "The second one;")) (item (list "The last one."))) (p (list "Note that list items are numbered this time." "\n"))))) (chapter #:title "The Second Chapter" (p (list (list "The second chapter does " (emph "not") " add anything useful.") "\n")) (p (list (list "Text like this that starts after an empty line is" "\n") "put into a new paragraph." "\n"))))
The outline mode makes it possible to quickly create documents that can be output in variety of formats (see Chapter 13). The downside is that, being a very simple markup-less document format, there are many things that cannot be done using it, most notably tables, bibliographies, and cross-references.
Gemtext, the lightweight markup language used by the Gemini protocol, is supported as an input syntax. To use it, just pass --reader=gemtext to the compiler. When used programmatically, the Gemtext reader can be customized using the following options.
(make-gemtext-reader :section-numbers? :join-lines?)
RSS 2.0 (aka. Really Simple Syndication) is supported as an input syntax. To use it, just pass --reader=rss-2 to the compiler. This makes it possible to generate Skribilo documents from RSS 2.0 feeds, which can be useful or at least funny. Consider the following example:
$ wget http://planet.gnu.org/rss20.xml $ skribilo -R rss-2 -t lout -c column-number=2 < rss20.xml \ | lout | ps2pdf - > gnu-planet.pdf
It is also possible to create and output Skribilo documents
from a Guile Scheme program. In that case, you get to use the Scheme
syntax, which is close to the Skribe
syntax described above, modulo the [...]
constructs. A
typical Scheme program that would produce and output a document, pretty
much like what the skribilo
compiler does, would look like this:
(use-modules (skribilo engine) ;; provides `find-engine' (skribilo evaluator) ;; provides `evaluate-document' (skribilo package base) ;; provides `chapter', etc. (srfi srfi-1)) (let (;; Select an engine, i.e., an output format. (e (find-engine 'html)) ;; Create a document. (d (document #:title "Some Title" (chapter #:title "The Chapter" (p "The paragraph... " "Text consists of " "a list of strings.") (apply itemize (map number->string (iota 10))))))) ;; "Evaluate" the document to an HTML file. (with-output-to-file "foo.html" (lambda () (evaluate-document d e))))
Skribilo is extensible and makes it easy to add custom readers, allowing the use of virtually any input syntax. A reader is essentially a procedure like R5RS' read, i.e., a one-argument procedure that takes a port and returns an S-expression. The returned S-expression should be a valid ``document program'' as shown in scheme-syntax.
The are a few additional details, though. Implementations of readers are required to use the (skribilo reader) modules and the define-reader macro. In addition, the reader must live in its own module, under the (skribilo reader) module hierarchy, so that the reader lookup mechanism (used by the --reader option of the compiler) can find it. This mechanism is the same as that used for engines (see Section 13.1.5). A skeleton for a reader would be like this: