;;; syntax.skb -- The Skribilo syntaxes.
;;; -*- coding: iso-8859-1 -*-
;;;
;;; Copyright 2008, 2009 Ludovic Courtès <ludo@gnu.org>
;;; Copyright 2001, 2002, 2003, 2004 Manuel Serrano
;;;
;;;
;;; This file is part of Skribilo.
;;;
;;; Skribilo is free software: you can redistribute it and/or modify
;;; it under the terms of the GNU General Public License as published by
;;; the Free Software Foundation, either version 3 of the License, or
;;; (at your option) any later version.
;;;
;;; Skribilo is distributed in the hope that it will be useful,
;;; but WITHOUT ANY WARRANTY; without even the implied warranty of
;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
;;; GNU General Public License for more details.
;;;
;;; You should have received a copy of the GNU General Public License
;;; along with Skribilo. If not, see <http://www.gnu.org/licenses/>.
;*---------------------------------------------------------------------*/
;* The Skribilo syntaxes */
;*---------------------------------------------------------------------*/
(chapter :title "Syntax"
:ident "syntax"
(p [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 ,(emph [reader]). The input syntax (and reader) can be selected at
document compilation time using the ,(tt [--reader]) option of the
compiler (see ,(numref :text [Chapter] :ident "compiler")).
Nevertheless, it has a ``preferred'' syntax (the default syntax), which
is that of the ,(ref :url *skribe-url* :text [Skribe document
preparation system]). Thus, the Skribe syntax is first described, and
then alternate syntaxes are presented.])
(section :title [The Skribe Syntax]
:ident "skribe-syntax"
(p [By default or when the ,(tt [--reader=skribe]) option is
passed to the compiler, a Skribilo document is composed of ,(emph
[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:
,(itemize (item [An atomic expression, such as a string of characters, a number.])
(item [A list.])
(item [A text.]))
Here are several examples of correct Skribe expressions:
,(center (frame :margin 5 :border 0 :width *prgm-width*
(color :margin 5 :bg *disp-color* :width 100.
(itemize (item [,(color :fg "#009900" (tt "\"foo\"")), a string of characters composed of the
characters `,(color :fg "#009900" "f")', `,(color :fg "#009900" "o")'
and `,(color :fg "#009900" "o")'.])
(item [,(color :fg "#009900" (tt "123") " " (tt "3.14")), two numbers.])
(item [,(color :fg "#009900" (tt "#t") " " (tt "#f")), the ,(emph "true") and ,(emph "false")
Skribe value.])
(item [,(color :fg "#009900" (tt "(bold \"foo bar\")")), a list.])
(item [,(color :fg "#009900" (tt (char 91)"A text sample"(char 93))), a simple text containing
three words and no escape sequence.])
(item [,(color :fg "#009900" (tt (char 91)"Another text sample (that is still) simple"(char 93))),
another simple text.])
(item [,(color :fg "#009900" (tt (char 91)"Another ,(bold \"text\") sample"(char 93))),
a more complex text that contains two words (,(color :fg "#009900" (tt "Another")) and ,(color :fg "#009900" (tt "sample")))
and an expression ,(color :fg "#009900" (tt "(bold \"text\")")). The escape sequence is introduced
with the `,(color :fg "#009900" (tt ",("))' characters.])))))
,(p [
Expressions are evaluated, thus ,(color :fg "#009900" (tt "(bold \"foo\")"))
has the effect of typesetting the word ,(color :fg "#009900" (tt "foo")) in
bold face to produce ,(color :fg "#009999" (bold "foo")). Escape sequences
enable evaluation of expressions inside the text. Thus the text
,(color :fg "#009900" (tt (char 91)"Another ,(bold \"text\") sample"(char 93)))
produces `,(color :fg "#009999" (tt [Another ,(bold "text") sample]))'.
On the other hand
,(color :fg "#009900" (tt (char 91)"Another (bold \"text\") sample"(char 93)))
produces
`,(color :fg "#009999" (tt [Another (bold "text") sample]))' because it does not contain
the escape sequence `,(color :fg "#009900" (char #\,)(char #\())'.])
])
;*---------------------------------------------------------------------*/
;* Formal syntax */
;*---------------------------------------------------------------------*/
(subsection :title [Formal Syntax]
(disp :verb #t :bg *prgm-skribe-color* [
<expr> --> <atom>
| <text>
| <list>
<list> --> (<expr>+)
<text> --> ,(bold (color :fg "red" (char 91))),(it "any sequence but `,(' or a `,")<list>,(it "'"),(bold (color :fg "red" (char 93)))
<atom> --> <boolean>
| <integer>
| <float>
| <string>
| <color>
<integer> --> ,(tt (char 91))0-9,(tt (char 93))+
<float> --> ,(tt (char 91))0-9,(tt (char 93))+.,(tt (char 91))0-9,(tt (char 93))*
| ,(tt (char 91))0-9,(tt (char 93))*.,(tt (char 91))0-9,(tt (char 93))+
<string> --> ,(tt #\")...,(tt #\")
<color> --> <string>
| ,(tt #\")#,(tt (char 91))0-9a-f,(tt (char 93)),(tt (char 91))0-9a-f,(tt (char 93)),(tt (char 91))0-9a-f,(tt (char 93)),(tt (char 91))0-9a-f,(tt (char 93)),(tt (char 91))0-9a-f,(tt (char 93)),(tt (char 91))0-9a-f,(tt (char 93)),(tt #\")]))
;*---------------------------------------------------------------------*/
;* Values */
;*---------------------------------------------------------------------*/
(subsection :title "Values" :file #f :toc #t
;*--- width -----------------------------------------------------------*/
(subsubsection :title "Width" (p [
,(mark "width")
A Skribe ,(emph "width") refers to the horizontal size a construction
occupies on an output document. There are three different ways for
specifying a width:])
(description (item :key "An absolute pixel size"
[This is represented by an ,(emph "exact") integer value
(such as ,(code "350")).])
(item :key "A relative size"
[This is represented by an ,(emph "inexact") integer value
(such as ,(code "50.0")) which ranges in the interval
,(char 91)-100.0 .. 100.0,(char 93)])
(item :key "An engine dependent representation"
[This is represented by a string that is directly emitted
in the output document (such as HTML column ,(code "\"0*\"")
specification). Note that this way of specifying width
is strictly unportable.])))))
(section :title [The Outline Syntax]
:ident "outline-syntax"
(p [Alternatively, Skribilo allows documents to be written in a
plain text format, with almost no markup. Instead, conventions borrowed
from ,(ref :text [Emacs' Outline Mode] :url
"http://www.gnu.org/software/emacs/manual/html_node/emacs/Outline-Mode.html")
to denote the text structure as well as other common conventions are
used to express various formatting ideas. This syntax is implemented by
the ,(tt [outline]) reader; thus, it is made available by passing the
,(tt [--reader=outline]) option to the ,(ref :ident "compiler" :text
[compiler]). The major elements of this syntax are the following:])
(description
(item :key [Document title and author]
[The document title is introduced by adding a line starting
with ,(code [Title:]) at the beginning of the text file, and followed by
the title. Likewise, the author can be specified with a line starting
with ,(code [Author:]).])
(item :key [Sectioning]
[Chapters are introduced using a heading preceding by a
single ,(tt [*]) (star) character. For instance, ,(tt [* The First
Part]) on a line on its own, followed by an empty line, introduces a new
chapter entitled ``The First Part''. Likewise, two stars introduce a
section, three stars introduce a subsection, etc.])
(item :key [Emphasis, italics, bold]
[Words or phrases surrounded by the ,(tt [_]) (underscore)
character are emphasized; those surrounded by ,(tt [/]) (slash)
characters are italicized; finally, those surrounded by ,(tt [*]) (star)
characters are typeset in boldface (see Section ,(ref :section
"Ornaments")).])
(item :key [Quotes]
[Words enclosed in double quotes (i.e., two back-quote
characters, then two single-quote characters) are interpreted as quoted
text, as per ,(tt "q").])
(item :key [Code]
[Words enclosed in single quotes (i.e., one back-quote
character, then one single-quote) are interpreted as code and are
typeset using a fixed-width font, as per ,(markup-ref "tt").])
(item :key [Hyperlinks]
[URLs are automatically recognized and converted into a
,(code [(ref :url ...)]) form (see ,(markup-ref "ref")). In addition,
,(tt [outline]) has limited support for Org-Mode-style hyperlinks; for
instance, ,(code "[[http://gnu.org/][The GNU Project]]") yields ,(ref
:url "http://gnu.org/" :text [The GNU Project]).]))
(p [Here is an example showing how the ,(tt [outline]) syntax maps
to the native ,(tt [skribe]) syntax:])
(let ((src (string-append %top-srcdir "/doc/user/src/outline.txt")))
(example-produce
(example :legend [The ,(tt [outline]) syntax]
(tt
(flush :side 'left
(pre (with-input-from-file src
(lambda ()
(set-correct-file-encoding!)
(let loop ((line (read-line))
(result '()))
(if (eof-object? line)
(string-join (reverse result)
(string #\newline))
(loop (read-line)
(cons line result))))))))))
(prgm
(with-output-to-string
(lambda ()
(let* ((read (make-reader 'outline))
(input (open-input-file src)))
(set-correct-file-encoding! input)
(pretty-print (read input) :width 65)))))))
(p [The ,(tt [outline]) mode makes it possible to quickly create
documents that can be output in variety of formats (see ,(numref :text
[Chapter] :ident "engines")). 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.]))
(section :title [The Gemtext Syntax] :ident "gemtext-syntax"
(p [,(ref
:url "https://gemini.circumlunar.space/docs/gemtext.gmi"
:text "Gemtext"), the lightweight markup language used by the ,(ref
:url "https://gemini.circumlunar.space" :text "Gemini protocol"), is
supported as an input syntax. To use it, just pass ,(tt
[--reader=gemtext]) to the compiler. When used programmatically, the
Gemtext reader can be customized using the following options.])
(doc-markup 'make-gemtext-reader
'((:join-lines? [If ,(code "#t"), lines which are not
separated by a blank line are joined into a single paragraph. This is
a relaxation of the Gemtext standard, and is not done by default.])
(:section-numbers? [If ,(code "#t"), sections are
numbered. Else, they are not.]))
:common-args '()
:source "skribilo/reader/gemtext.scm"
:idx *function-index*))
(section :title [The RSS 2.0 Syntax]
:ident "rss2-syntax"
(p [RSS 2.0 (aka. ,(ref :url "http://en.wikipedia.org/wiki/RSS" :text
(emph [Really Simple Syndication]))) is supported as an input syntax.
To use it, just pass ,(tt [--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:]
(disp :verb #t [
$ 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 produces a two-column PDF file with the contents of the RSS feed of
GNU Planet, where each item of the feed is mapped to a Skribilo
``chapter''.]))
(section :title [Documents in Scheme Programs]
:ident "scheme-syntax"
(p [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 ,(ref :ident "skribe-syntax" :text [Skribe
syntax]) described above, modulo the ,(code "[...]") constructs. A
typical Scheme program that would produce and output a document, pretty
much like what the ,(ref :ident "compiler" :text [,(tt [skribilo])
compiler does]), would look like this:]
(example :legend [Programming Skribilo documents in Scheme.]
(prgm :language scheme :file "src/scheme.scm"))
[This should give you an idea of the wonderful, life-changing
things that can be achieved with a bit of ,(emph [document
programming]).]))
(section :title [Writing New Readers]
:ident "custom-syntax"
(p [Skribilo is extensible and makes it easy to add ,(emph [custom
readers]), allowing the use of virtually any input syntax. A reader is
essentially a procedure like R5RS' ,(tt [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 ,(ref
:ident "scheme-syntax").])
(p [The are a few additional details, though. Implementations of
readers are required to use the ,(tt [(skribilo reader)]) modules and
the ,(tt [define-reader]) macro. In addition, the reader must live in
its own module, under the ,(tt [(skribilo reader)]) module hierarchy, so
that the reader lookup mechanism (used by the ,(tt [--reader]) option of
the compiler) can find it. This mechanism is the same as that used for
engines (see ,(numref :text [Section] :ident "custom-engine")). A
skeleton for a reader would be like this:]
(example :legend [Writing a new reader.]
(prgm :language scheme [
(define-module (skribilo reader my-reader)
#:use-module (skribilo reader)
#:export (reader-specification))
(define (make-my-reader)
(lambda (port)
...))
(define-reader my-reader ;; the reader name
"0.1" ;; a version number
make-my-reader) ;; the procedure that returns
;; a reader procedure
]))
[Users and encouraged to look at examples in the Skribilo
source for additional details.])))
;;; Local Variables:
;;; ispell-local-dictionary: "american"
;;; End: