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