;;; 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: