aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/guile/skribilo/ast.scm22
-rw-r--r--src/guile/skribilo/biblio.scm103
-rw-r--r--src/guile/skribilo/biblio/Makefile.am2
-rw-r--r--src/guile/skribilo/biblio/template.scm195
-rw-r--r--src/guile/skribilo/color.scm3
-rw-r--r--src/guile/skribilo/engine/base.scm128
-rw-r--r--src/guile/skribilo/engine/latex.scm11
-rw-r--r--src/guile/skribilo/engine/lout.scm170
-rw-r--r--src/guile/skribilo/package/base.scm51
-rw-r--r--src/guile/skribilo/package/eq.scm188
-rw-r--r--src/guile/skribilo/package/eq/lout.scm179
-rw-r--r--src/guile/skribilo/package/slide.scm13
-rw-r--r--src/guile/skribilo/package/slide/base.scm2
-rw-r--r--src/guile/skribilo/package/slide/html.scm127
-rw-r--r--src/guile/skribilo/package/slide/lout.scm57
-rw-r--r--src/guile/skribilo/prog.scm10
-rw-r--r--src/guile/skribilo/reader/outline.scm54
-rw-r--r--src/guile/skribilo/utils/compat.scm13
18 files changed, 936 insertions, 392 deletions
diff --git a/src/guile/skribilo/ast.scm b/src/guile/skribilo/ast.scm
index 542f629..55f37bf 100644
--- a/src/guile/skribilo/ast.scm
+++ b/src/guile/skribilo/ast.scm
@@ -30,6 +30,9 @@
:autoload (skribilo location) (location?)
:autoload (srfi srfi-1) (fold)
+
+ :use-module (ice-9 optargs)
+
:export (<ast> ast? ast-loc ast-loc-set!
ast-parent ast->string ast->file-location
ast-resolved?
@@ -62,6 +65,9 @@
find-up find1-up
ast-document ast-chapter ast-section
+ ;; numbering
+ markup-number-string
+
;; error conditions
&ast-error &ast-orphan-error &ast-cycle-error
&markup-unknown-option-error &markup-already-bound-error
@@ -596,6 +602,22 @@
(define (ast-section m)
(find1-up (lambda (n) (is-markup? n 'section)) m))
+
+;;;
+;;; Section numbering.
+;;;
+
+(define* (markup-number-string markup :optional (sep "."))
+ ;; Return a structure number string such as "1.2".
+ (let loop ((markup markup))
+ (if (document? markup)
+ ""
+ (let ((parent-num (loop (ast-parent markup)))
+ (num (markup-option markup :number)))
+ (string-append parent-num
+ (if (string=? "" parent-num) "" sep)
+ (if (number? num) (number->string num) ""))))))
+
;;; arch-tag: e2489bd6-1b6d-4b03-bdfb-83cffd2f7ce7
diff --git a/src/guile/skribilo/biblio.scm b/src/guile/skribilo/biblio.scm
index 1fb4b78..55f2ea9 100644
--- a/src/guile/skribilo/biblio.scm
+++ b/src/guile/skribilo/biblio.scm
@@ -1,5 +1,6 @@
;;; biblio.scm -- Bibliography functions.
;;;
+;;; Copyright 2001, 2002, 2003, 2004 Manuel Serrano
;;; Copyright 2003, 2004 Erick Gallesio - I3S-CNRS/ESSI <eg@essi.fr>
;;; Copyright 2005, 2006 Ludovic Courtès <ludovic.courtes@laas.fr>
;;;
@@ -24,9 +25,10 @@
:use-module (skribilo utils strings)
:use-module (skribilo utils syntax) ;; `when', `unless'
+ :use-module (srfi srfi-1)
:autoload (srfi srfi-34) (raise)
:use-module (srfi srfi-35)
- :use-module (srfi srfi-1)
+ :use-module (srfi srfi-39)
:autoload (skribilo condition) (&file-search-error)
:autoload (skribilo reader) (%default-reader)
@@ -36,9 +38,9 @@
:use-module (ice-9 optargs)
:use-module (oop goops)
- :export (bib-table? make-bib-table default-bib-table
+ :export (bib-table? make-bib-table *bib-table*
bib-add! bib-duplicate bib-for-each bib-map
- skribe-open-bib-file parse-bib
+ open-bib-file parse-bib
bib-load! resolve-bib resolve-the-bib make-bib-entry
@@ -52,27 +54,15 @@
;;; Provides the bibliography data type and basic bibliography handling,
;;; including simple procedures to sort bibliography entries.
;;;
-;;; FIXME: This module need cleanup!
-;;;
;;; Code:
(fluid-set! current-reader %skribilo-module-reader)
-
-;; FIXME: Should be a fluid?
-(define *bib-table* #f)
-
-;; Forward declarations
-(define skribe-open-bib-file #f)
-(define parse-bib #f)
-
-;;; ======================================================================
;;;
-;;; Utilities
+;;; Accessors.
;;;
-;;; ======================================================================
(define (make-bib-table ident)
(make-hash-table))
@@ -80,10 +70,9 @@
(define (bib-table? obj)
(hash-table? obj))
-(define (default-bib-table)
- (unless *bib-table*
- (set! *bib-table* (make-bib-table "default-bib-table")))
- *bib-table*)
+;; The current bib table.
+(define *bib-table*
+ (make-parameter (make-bib-table "default-bib-table")))
(define (%bib-error who entry)
(let ((msg "bibliography syntax error on entry"))
@@ -91,22 +80,34 @@
(skribe-line-error (%epair-file entry) (%epair-line entry) who msg entry)
(skribe-error who msg entry))))
-(define* (bib-for-each proc :optional (table (default-bib-table)))
+(define (bib-add! table . entries)
+ (if (not (bib-table? table))
+ (skribe-error 'bib-add! "Illegal bibliography table" table)
+ (for-each (lambda (entry)
+ (cond
+ ((and (list? entry) (> (length entry) 2))
+ (let* ((kind (car entry))
+ (key (format #f "~A" (cadr entry)))
+ (fields (cddr entry))
+ (old (hash-ref table key)))
+ (if old
+ (bib-duplicate key #f old)
+ (hash-set! table key
+ (make-bib-entry kind key fields #f)))))
+ (else
+ (%bib-error 'bib-add! entry))))
+ entries)))
+
+(define* (bib-for-each proc :optional (table (*bib-table*)))
(hash-for-each (lambda (ident entry)
(proc ident entry))
table))
-(define* (bib-map proc :optional (table (default-bib-table)))
+(define* (bib-map proc :optional (table (*bib-table*)))
(hash-map->list (lambda (ident entry)
(proc ident entry))
table))
-
-;;; ======================================================================
-;;;
-;;; BIB-DUPLICATE
-;;;
-;;; ======================================================================
(define (bib-duplicate ident from old)
(let ((ofrom (markup-option old 'from)))
(skribe-warning 2
@@ -120,11 +121,11 @@
" ignoring redefinition."))))
-;;; ======================================================================
+
;;;
-;;; PARSE-BIB
+;;; Parsing.
;;;
-;;; ======================================================================
+
(define (parse-bib table port)
(let ((read %default-reader)) ;; FIXME: We should use a fluid
(if (not (bib-table? table))
@@ -146,43 +147,15 @@
(else
(%bib-error 'bib-parse entry)))))))))
-
-;;; ======================================================================
-;;;
-;;; BIB-ADD!
-;;;
-;;; ======================================================================
-(define (bib-add! table . entries)
- (if (not (bib-table? table))
- (skribe-error 'bib-add! "Illegal bibliography table" table)
- (for-each (lambda (entry)
- (cond
- ((and (list? entry) (> (length entry) 2))
- (let* ((kind (car entry))
- (key (format #f "~A" (cadr entry)))
- (fields (cddr entry))
- (old (hash-ref table key)))
- (if old
- (bib-duplicate key #f old)
- (hash-set! table key
- (make-bib-entry kind key fields #f)))))
- (else
- (%bib-error 'bib-add! entry))))
- entries)))
-
-
-;;; ======================================================================
-;;;
-;;; SKRIBE-OPEN-BIB-FILE
-;;;
-;;; ======================================================================
-;; FIXME: Factoriser
-(define (skribe-open-bib-file file command)
+(define* (open-bib-file file :optional (command #f))
(let ((path (search-path (*bib-path*) file)))
(if (string? path)
(begin
(when (> (*verbose*) 0)
- (format (current-error-port) " [loading bibliography: ~S]\n" path))
+ (format (current-error-port)
+ " [loading bibliography: ~S]\n" path))
+ ;; FIXME: The following `open-input-file' won't work with actual
+ ;; commands. We need to use `(ice-9 popen)'.
(open-input-file (if (string? command)
(string-append "| "
(format #f command path))
@@ -209,7 +182,7 @@
(if (not (bib-table? table))
(skribe-error 'bib-load "Illegal bibliography table" table)
;; read the file
- (let ((p (skribe-open-bib-file filename command)))
+ (let ((p (open-bib-file filename command)))
(if (not (input-port? p))
(skribe-error 'bib-load "Can't open data base" filename)
(unwind-protect
diff --git a/src/guile/skribilo/biblio/Makefile.am b/src/guile/skribilo/biblio/Makefile.am
index 9442562..ee81406 100644
--- a/src/guile/skribilo/biblio/Makefile.am
+++ b/src/guile/skribilo/biblio/Makefile.am
@@ -1,4 +1,4 @@
guilemoduledir = $(GUILE_SITE)/skribilo/biblio
-dist_guilemodule_DATA = bibtex.scm author.scm abbrev.scm
+dist_guilemodule_DATA = bibtex.scm author.scm abbrev.scm template.scm
## arch-tag: aeffaead-c3f0-47f3-a0b3-bb3e22da2657
diff --git a/src/guile/skribilo/biblio/template.scm b/src/guile/skribilo/biblio/template.scm
new file mode 100644
index 0000000..5a82e26
--- /dev/null
+++ b/src/guile/skribilo/biblio/template.scm
@@ -0,0 +1,195 @@
+;;; template.scm -- Template system for bibliography entries.
+;;;
+;;; Copyright 2003, 2004 Manuel Serrano
+;;; Copyright 2006 Ludovic Courtès <ludovic.courtes@laas.fr>
+;;;
+;;;
+;;; This program 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 2 of the License, or
+;;; (at your option) any later version.
+;;;
+;;; This program 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 this program; if not, write to the Free Software
+;;; Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
+;;; USA.
+
+(define-module (skribilo biblio template)
+ :use-module (skribilo ast)
+ :autoload (skribilo lib) (skribe-error)
+ :autoload (skribilo output) (output)
+
+ :use-module (ice-9 optargs)
+
+ :use-module (skribilo utils syntax)
+
+ :export (output-bib-entry-template
+ make-bib-entry-template/default
+ make-bib-entry-template/skribe))
+
+(fluid-set! current-reader %skribilo-module-reader)
+
+;;; Author: Manuel Serrano, Ludovic Courtès
+;;;
+;;; Commentary:
+;;;
+;;; This module provides a helper procedure to output bibliography entries
+;;; according to a given template, as well as ready-to-use templates. A
+;;; template only contains part of the style information for a bibliography
+;;; entry. Specific style information can be added by modifying the markup
+;;; writers for `&bib-entry-author', `&bib-entry-title', etc. (see `(skribilo
+;;; package base)' for details).
+;;;
+;;; Code:
+
+
+;;;
+;;; Outputting a bibliography entry template for a specific entry.
+;;;
+
+(define* (output-bib-entry-template bib engine template
+ :optional (get-field markup-option))
+ ;; Output the fields of BIB (a bibliography entry) for ENGINE according to
+ ;; TEMPLATE. Example of templates are found below (e.g.,
+ ;; `make-bib-entry-template/default').
+ (let loop ((template template)
+ (pending #f)
+ (armed #f))
+ (cond
+ ((null? template)
+ 'done)
+ ((pair? (car template))
+ (if (eq? (caar template) 'or)
+ (let ((o1 (cadr (car template))))
+ (if (get-field bib o1)
+ (loop (cons o1 (cdr template))
+ pending
+ #t)
+ (let ((o2 (caddr (car template))))
+ (loop (cons o2 (cdr template))
+ pending
+ armed))))
+ (let ((o (get-field bib (cadr (car template)))))
+ (if o
+ (begin
+ (if (and pending armed)
+ (output pending engine))
+ (output (caar template) engine)
+ (output o engine)
+ (if (pair? (cddr (car template)))
+ (output (caddr (car template)) engine))
+ (loop (cdr template) #f #t))
+ (loop (cdr template) pending armed)))))
+ ((symbol? (car template))
+ (let ((o (get-field bib (car template))))
+ (if o
+ (begin
+ (if (and armed pending)
+ (output pending engine))
+ (output o engine)
+ (loop (cdr template) #f #t))
+ (loop (cdr template) pending armed))))
+ ((null? (cdr template))
+ (output (car template) engine))
+ ((string? (car template))
+ (loop (cdr template)
+ (if pending pending (car template))
+ armed))
+ (else
+ (skribe-error 'output-bib-fields
+ "Illegal templateiption"
+ (car template))))))
+
+
+;;;
+;;; Example bibliography entry templates.
+;;;
+
+(define (make-bib-entry-template/default kind)
+ ;; The default bibliography entry template.
+ (case kind
+ ((techreport)
+ `(author ". " (or title url documenturl) ". "
+ number ", " institution ", "
+ address ", " month " " year ", "
+ ("pp. " pages) "."))
+ ((article)
+ `(author ". " (or title url documenturl) ". "
+ "In " journal ", " volume
+ ("(" number ")") ", "
+ address ", " month " " year ", "
+ ("pp. " pages) "."))
+ ((inproceedings)
+ `(author ". " (or title url documenturl) ". "
+ "In " booktitle ", "
+ (series ", ")
+ ("(" number ")")
+ ("pp. " pages ", ")
+ ("" publisher ", ")
+ ;; FIXME: Addr., month.
+ year "."))
+ ((book) ;; FIXME: Title should be in italics
+ '(author ". " (or title url documenturl) ". "
+ publisher ", " address
+ ", " month " " year ", "
+ ("pp. " pages) "."))
+ ((phdthesis)
+ '(author ". " (or title url documenturl)
+ ". " type ", "
+ school ", " address
+ ", " month " " year"."))
+ ((misc)
+ '(author ". " (or title url documenturl) ". "
+ publisher ", " address
+ ", " month " " year
+ (", " url) "."))
+ (else
+ '(author ". " (or title url documenturl) ". "
+ publisher ", " address
+ ", " month " " year ", "
+ ("pp. " pages) "."))))
+
+(define (make-bib-entry-template/skribe kind)
+ ;; The awful template found by default in Skribe.
+ (case kind
+ ((techreport)
+ `(author " -- " (or title url documenturl) " -- "
+ number ", " institution ", "
+ address ", " month ", " year ", "
+ ("pp. " pages) "."))
+ ((article)
+ `(author " -- " (or title url documenturl) " -- "
+ journal ", " volume "" ("(" number ")") ", "
+ address ", " month ", " year ", "
+ ("pp. " pages) "."))
+ ((inproceedings)
+ `(author " -- " (or title url documenturl) " -- "
+ booktitle ", " series ", " ("(" number ")") ", "
+ address ", " month ", " year ", "
+ ("pp. " pages) "."))
+ ((book)
+ '(author " -- " (or title url documenturl) " -- "
+ publisher ", " address
+ ", " month ", " year ", " ("pp. " pages) "."))
+ ((phdthesis)
+ '(author " -- " (or title url documenturl) " -- " type ", "
+ school ", " address
+ ", " month ", " year"."))
+ ((misc)
+ '(author " -- " (or title url documenturl) " -- "
+ publisher ", " address
+ ", " month ", " year"."))
+ (else
+ '(author " -- " (or title url documenturl) " -- "
+ publisher ", " address
+ ", " month ", " year ", " ("pp. " pages) "."))))
+
+
+;;; arch-tag: 5931579f-b606-442d-9a45-6047c94da5a2
+
+;;; template.scm ends here
diff --git a/src/guile/skribilo/color.scm b/src/guile/skribilo/color.scm
index 8b6205f..6b3aa7b 100644
--- a/src/guile/skribilo/color.scm
+++ b/src/guile/skribilo/color.scm
@@ -571,7 +571,8 @@
("darkcyan" . "0 139 139")
("darkmagenta" . "139 0 139")
("darkred" . "139 0 0")
- ("lightgreen" . "144 238 144")))
+ ("lightgreen" . "144 238 144")
+ ("lightred" . "255 127 127")))
(define (%convert-color str)
diff --git a/src/guile/skribilo/engine/base.scm b/src/guile/skribilo/engine/base.scm
index 2a7a0d4..9c1fdd2 100644
--- a/src/guile/skribilo/engine/base.scm
+++ b/src/guile/skribilo/engine/base.scm
@@ -27,7 +27,8 @@
:use-module (skribilo evaluator)
:autoload (skribilo package base) (color)
:autoload (skribilo utils keywords) (list-split)
-
+ :autoload (skribilo biblio template) (make-bib-entry-template/default
+ output-bib-entry-template)
;; syntactic sugar
:use-module (skribilo reader)
:use-module (skribilo utils syntax))
@@ -236,91 +237,31 @@
:after "]")
;*---------------------------------------------------------------------*/
+;* &bib-entry-author ... */
+;*---------------------------------------------------------------------*/
+; (markup-writer '&bib-entry-author
+; :action (lambda (n e)
+; (let ((names (markup-body n)))
+; (skribe-eval
+; (sc (abbreviate-first-names names)) e))))
+
+;*---------------------------------------------------------------------*/
+;* &bib-entry-url ... */
+;*---------------------------------------------------------------------*/
+(markup-writer '&bib-entry-url
+ :action (lambda (n e)
+ (let ((url (markup-body n)))
+ (evaluate-document
+ (ref :text (it url) :url url) e))))
+
+;*---------------------------------------------------------------------*/
;* &bib-entry-body ... */
;*---------------------------------------------------------------------*/
(markup-writer '&bib-entry-body
:action (lambda (n e)
- (define (output-fields descr)
- (let loop ((descr descr)
- (pending #f)
- (armed #f))
- (cond
- ((null? descr)
- 'done)
- ((pair? (car descr))
- (if (eq? (caar descr) 'or)
- (let ((o1 (cadr (car descr))))
- (if (markup-option n o1)
- (loop (cons o1 (cdr descr))
- pending
- #t)
- (let ((o2 (caddr (car descr))))
- (loop (cons o2 (cdr descr))
- pending
- armed))))
- (let ((o (markup-option n (cadr (car descr)))))
- (if o
- (begin
- (if (and pending armed)
- (output pending e))
- (output (caar descr) e)
- (output o e)
- (if (pair? (cddr (car descr)))
- (output (caddr (car descr)) e))
- (loop (cdr descr) #f #t))
- (loop (cdr descr) pending armed)))))
- ((symbol? (car descr))
- (let ((o (markup-option n (car descr))))
- (if o
- (begin
- (if (and armed pending)
- (output pending e))
- (output o e)
- (loop (cdr descr) #f #t))
- (loop (cdr descr) pending armed))))
- ((null? (cdr descr))
- (output (car descr) e))
- ((string? (car descr))
- (loop (cdr descr)
- (if pending pending (car descr))
- armed))
- (else
- (skribe-error 'output-bib-fields
- "Illegal description"
- (car descr))))))
- (output-fields
- (case (markup-option n 'kind)
- ((techreport)
- `(author " -- " (or title url documenturl) " -- "
- number ", " institution ", "
- address ", " month ", " year ", "
- ("pp. " pages) "."))
- ((article)
- `(author " -- " (or title url documenturl) " -- "
- journal ", " volume "" ("(" number ")") ", "
- address ", " month ", " year ", "
- ("pp. " pages) "."))
- ((inproceedings)
- `(author " -- " (or title url documenturl) " -- "
- booktitle ", " series ", " ("(" number ")") ", "
- address ", " month ", " year ", "
- ("pp. " pages) "."))
- ((book)
- '(author " -- " (or title url documenturl) " -- "
- publisher ", " address
- ", " month ", " year ", " ("pp. " pages) "."))
- ((phdthesis)
- '(author " -- " (or title url documenturl) " -- " type ", "
- school ", " address
- ", " month ", " year"."))
- ((misc)
- '(author " -- " (or title url documenturl) " -- "
- publisher ", " address
- ", " month ", " year"."))
- (else
- '(author " -- " (or title url documenturl) " -- "
- publisher ", " address
- ", " month ", " year ", " ("pp. " pages) "."))))))
+ (let* ((kind (markup-option n 'kind))
+ (template (make-bib-entry-template/default kind)))
+ (output-bib-entry-template n e template))))
;*---------------------------------------------------------------------*/
;* &bib-entry-ident ... */
@@ -337,6 +278,21 @@
(evaluate-document (bold (markup-body n)) e)))
;*---------------------------------------------------------------------*/
+;* &bib-entry-booktitle ... */
+;*---------------------------------------------------------------------*/
+(markup-writer '&bib-entry-booktitle
+ :action (lambda (n e)
+ (let ((title (markup-body n)))
+ (evaluate-document (it title) e))))
+
+;*---------------------------------------------------------------------*/
+;* &bib-entry-journal ... */
+;*---------------------------------------------------------------------*/
+(markup-writer '&bib-entry-journal
+ :action (lambda (n e)
+ (evaluate-document (it (markup-body n)) e)))
+
+;*---------------------------------------------------------------------*/
;* &bib-entry-publisher ... */
;*---------------------------------------------------------------------*/
(markup-writer '&bib-entry-publisher
@@ -477,8 +433,12 @@
;*---------------------------------------------------------------------*/
(markup-writer '&prog-line
:before (lambda (n e)
- (let ((n (markup-ident n)))
- (if n (evaluate-document (it (list n) ": ") e))))
+ (let ((num (markup-option n :number)))
+ (if (number? num)
+ (evaluate-document
+ (it (string-append (string-pad (number->string num) 3)
+ ": "))
+ e))))
:after "\n")
;*---------------------------------------------------------------------*/
diff --git a/src/guile/skribilo/engine/latex.scm b/src/guile/skribilo/engine/latex.scm
index 8d5b88f..21ff6c5 100644
--- a/src/guile/skribilo/engine/latex.scm
+++ b/src/guile/skribilo/engine/latex.scm
@@ -18,7 +18,8 @@
;;; Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
;;; USA.
-(define-skribe-module (skribilo engine latex))
+(define-skribe-module (skribilo engine latex)
+ :use-module (srfi srfi-13))
;*---------------------------------------------------------------------*/
;* latex-verbatim-encoding ... */
@@ -997,8 +998,12 @@
;*---------------------------------------------------------------------*/
(markup-writer '&prog-line
:before (lambda (n e)
- (let ((n (markup-ident n)))
- (if n (skribe-eval (it (list n) ": ") e))))
+ (let ((num (markup-option n :number)))
+ (if (number? num)
+ (skribe-eval
+ (it (string-append (string-pad (number->string num) 3)
+ ": "))
+ e))))
:after "\\\\\n")
;*---------------------------------------------------------------------*/
diff --git a/src/guile/skribilo/engine/lout.scm b/src/guile/skribilo/engine/lout.scm
index 893ab2e..43aa356 100644
--- a/src/guile/skribilo/engine/lout.scm
+++ b/src/guile/skribilo/engine/lout.scm
@@ -24,6 +24,8 @@
(define-skribe-module (skribilo engine lout)
+ :use-module (srfi srfi-13)
+ :use-module (srfi srfi-14)
:autoload (ice-9 popen) (open-output-pipe)
:autoload (ice-9 rdelim) (read-line))
@@ -378,9 +380,9 @@
(let ((leader (engine-custom engine 'toc-leader))
(leader-space (engine-custom engine 'toc-leader-space)))
(apply string-append
- `("# @SkribeMark implements Skribe's marks "
+ `("# @SkribiloMark implements Skribe's marks "
"(i.e. cross-references)\n"
- "def @SkribeMark\n"
+ "def @SkribiloMark\n"
" right @Tag\n"
"{\n"
" @PageMark @Tag\n"
@@ -389,7 +391,29 @@
"# @SkribiloLeaders is used in `toc'\n"
"# (this is mostly copied from the expert's guide)\n"
"def @SkribiloLeaders { "
- ,leader " |" ,leader-space " @SkribiloLeaders }\n\n"))))
+ ,leader " |" ,leader-space " @SkribiloLeaders }\n\n"
+
+ "# Embedding an application in PDF (``Launch'' actions)\n"
+ "# (tested with XPdf 3.1 and Evince 0.4.0)\n"
+ "def @SkribiloEmbed\n"
+ " left command\n"
+ " import @PSLengths\n"
+ " named borderwidth { 1p }\n"
+ " right body\n"
+ "{\n"
+ " {\n"
+ " \"[ /Rect [0 0 xsize ysize]\"\n"
+ " \" /Color [0 0 1]\"\n"
+ " \" /Border [ 0 0 \" borderwidth \" ]\"\n"
+ " \" /Action /Launch\"\n"
+ " \" /File (\" command \")\"\n"
+ " \" /Subtype /Link\"\n"
+ " \"/ANN\"\n"
+ " \"pdfmark\"\n"
+ " }\n"
+ " @Graphic body\n"
+ "}\n\n"))))
+
(define (lout-make-doc-cover-sheet doc engine)
;; Create a cover sheet for node `doc' which is a doc-style Lout document.
@@ -410,18 +434,22 @@
(output title engine)
(display "The Lout Document"))
(display " }\n")
- (display "//1.7fx\n")
- (if date-line
- (begin
- (display "@Center { ")
- (output date-line engine)
- (display " }\n//1.4fx\n")))
+ (display "//2.0fx\n")
(if author
(begin
(display "@Center { ")
(output author engine)
(display " }\n")
- (display "//4fx\n")))
+ (display "//4.6fx\n")))
+ (if date-line
+ (begin
+ (display "@Center { ")
+ (output (if (eq? #t date-line)
+ (strftime "%e %B %Y" (localtime (current-time)))
+ date-line)
+ engine)
+ (display " }\n//1.7fx\n")))
+ (display "//0.5fx\n")
(if multi-column?
(display "\n} # @FullWidth\n"))))
@@ -444,13 +472,14 @@
(let ((split (let loop ((where 10))
(if (= 0 where)
10
- (if (char=? (string-ref text
- (- where 1))
- #\space)
+ (if (char-set-contains?
+ char-set:whitespace
+ (string-ref text (- where 1)))
(loop (- where 1))
where)))))
`(,(ref :url url :text (substring text 0 split))
- ,(substring text split len)))
+ ,(!lout (lout-make-url-breakable
+ (substring text split len)))))
(list markup))))
((markup? text)
@@ -475,7 +504,7 @@
(if num
(begin
(if (is-markup? node 'chapter) (display "@B { "))
- (printf "~a. |2s " (lout-structure-number-string node))
+ (printf "~a. |2s " (markup-number-string node))
(output title engine)
(if (is-markup? node 'chapter) (display " }")))
(if (is-markup? node 'chapter)
@@ -498,7 +527,7 @@
(define (lout-pdf-bookmark-title node engine)
;; Default implementation of the `pdf-bookmark-title-proc' custom that
;; returns a title (a string) for the PDF bookmark of `node'.
- (let ((number (lout-structure-number-string node)))
+ (let ((number (markup-number-string node)))
(string-append (if (string=? number "") "" (string-append number ". "))
(ast->string (markup-option node :title)))))
@@ -558,7 +587,7 @@
;; also honor this custom for `doc' documents.
(cover-sheet? #t)
- ;; For reports, the date line.
+ ;; For reports and slides, the date line.
(date-line #t)
;; For reports, an abstract.
@@ -604,7 +633,7 @@
(use-skribe-footnote-numbers? #t)
;; A procedure that is passed the engine
- ;; and produces Lout definitions.
+ ;; and returns Lout definitions (a string).
(inline-definitions-proc ,lout-definitions)
;; A procedure that takes a URL `ref' markup and
@@ -635,6 +664,10 @@
;; `lout-illustration' on other back-ends.
(lout-program-name "lout")
+ ;; Additional arguments that should be passed to
+ ;; Lout, e.g., `("-I foo" "-I bar")'.
+ (lout-program-arguments ())
+
;; Title and author information in the PDF
;; document information. If `#t', the
;; document's `:title' and `:author' are used.
@@ -1012,7 +1045,7 @@
(display "@SysInclude { tbl }\n"))
;; Write additional Lout definitions
- (display (lout-definitions e))
+ (display ((engine-custom e 'inline-definitions-proc) e))
(case doc-type
((report) (display "@Report\n"))
@@ -1051,23 +1084,25 @@
(output institution e)
(printf " }\n"))))))))
+ (if (memq doc-type '(report slides))
+ (let ((date-line (engine-custom e 'date-line)))
+ (display " @DateLine { ")
+ (if (or (string? date-line) (ast? date-line))
+ (output date-line e)
+ (display (if date-line "Yes" "No")))
+ (display " }\n")))
+
;; Lout reports make it possible to choose whether to prepend
;; a cover sheet (books and docs don't). Same for a date
;; line.
(if (eq? doc-type 'report)
(let ((cover-sheet? (engine-custom e 'cover-sheet?))
- (date-line (engine-custom e 'date-line))
(abstract (engine-custom e 'abstract))
(abstract-title (engine-custom e 'abstract-title)))
(display (string-append " @CoverSheet { "
(if cover-sheet?
"Yes" "No")
" }\n"))
- (display " @DateLine { ")
- (if (string? date-line)
- (output date-line e)
- (display (if date-line "Yes" "No")))
- (display " }\n")
(if abstract
(begin
@@ -1288,17 +1323,11 @@
doc-type)))))
(define-public (lout-structure-number-string markup)
- ;; Return a structure number string such as "1.2".
- ;; FIXME: External code has started to rely on this. This should be
- ;; generalized and moved elsewhere.
- (let loop ((struct markup))
- (if (document? struct)
- ""
- (let ((parent-num (loop (ast-parent struct)))
- (num (markup-option struct :number)))
- (string-append parent-num
- (if (string=? "" parent-num) "" ".")
- (if (number? num) (number->string num) ""))))))
+ ;; FIXME: External code has started to rely on this before this was moved
+ ;; to the `ast' module as `markup-number-string'. Thus, we'll have to keep it
+ ;; here for some time.
+ (markup-number-string markup "."))
+
;*---------------------------------------------------------------------*/
;* lout-block-before ... */
@@ -1317,7 +1346,7 @@
;; Lout markup)
(display "\n//1.8vx\n@B { ")
(output title e)
- (display " }\n@SkribeMark { ")
+ (display " }\n@SkribiloMark { ")
(display (lout-tagify ident))
(display " }\n//0.8vx\n\n"))
(begin
@@ -1327,7 +1356,7 @@
(if (number? number)
(printf " @BypassNumber { ~a }\n"
- (lout-structure-number-string n))
+ (markup-number-string n))
(if (not number)
;; this trick hides the section number
(printf " @BypassNumber { } # unnumbered\n")))
@@ -1646,8 +1675,12 @@
;; Program lines appear within a `lines @Break' block.
(markup-writer '&prog-line
:before (lambda (n e)
- (let ((n (markup-ident n)))
- (if n (skribe-eval (it (list n) ": ") e))))
+ (let ((num (markup-option n :number)))
+ (if (number? num)
+ (skribe-eval
+ (it (string-append (string-pad (number->string num) 3)
+ ": "))
+ e))))
:after "\n")
;*---------------------------------------------------------------------*/
@@ -2380,7 +2413,7 @@
:action (lambda (n e)
(if (markup-ident n)
(begin
- (display "{ @SkribeMark { ")
+ (display "{ @SkribiloMark { ")
(display (lout-tagify (markup-ident n)))
(display " } }"))
(skribe-error 'lout "mark: Node has no identifier" n))))
@@ -2462,6 +2495,7 @@
((is-markup? x 'bib-entry) x)
((is-markup? x 'bib-ref)
(handle-ast (markup-body x)))
+ ((is-markup? x 'unref) #f)
(else
(skribe-error
'lout
@@ -2469,9 +2503,14 @@
x)))))
(help-proc (lambda (proc)
(lambda (e1 e2)
- (proc (canonicalize-entry e1)
- (canonicalize-entry e2)))))
+ (let ((e1 (canonicalize-entry e1))
+ (e2 (canonicalize-entry e2)))
+ ;; don't pass `unref's to PROC
+ (if (and e1 e2)
+ (proc e1 e2)
+ #f)))))
(sort-proc (engine-custom e 'bib-refs-sort-proc)))
+
(let loop ((rs (if sort-proc
(sort entries (help-proc sort-proc))
entries)))
@@ -2491,6 +2530,19 @@
:after "]")
;*---------------------------------------------------------------------*/
+;* lout-make-url-breakable ... */
+;*---------------------------------------------------------------------*/
+(define-public lout-make-url-breakable
+ ;; Make the given string (which is assumed to be a URL) breakable.
+ (make-string-replace `((#\/ "\"/\"&0ik{}")
+ (#\. ".&0ik{}")
+ (#\- "-&0ik{}")
+ (#\_ "_&0ik{}")
+ (#\@ "\"@\"&0ik{}")
+ ,@lout-verbatim-encoding
+ (#\newline " "))))
+
+;*---------------------------------------------------------------------*/
;* url-ref ... */
;*---------------------------------------------------------------------*/
(markup-writer 'url-ref
@@ -2503,19 +2555,9 @@
(markup-option n '&transformed))
(begin
(printf "{ \"~a\" @ExternalLink { " url)
- (if text ;; FIXME: Should be (not (string-index text #\space))
- (output text e)
- (let ((filter-url (make-string-replace
- `((#\/ "\"/\"&-")
- (#\. ".&-")
- (#\- "&-")
- (#\_ "_&-")
- ,@lout-verbatim-encoding
- (#\newline "")))))
- ;; Filter the URL in a way to give Lout hints on
- ;; where hyphenation should take place.
- (fprint (current-error-port) "Here!!!" filter-url)
- (display (filter-url url) e)))
+ (if text
+ (output text e)
+ (display (lout-make-url-breakable url) e))
(printf " } }"))
(begin
(markup-option-add! n '&transformed #t)
@@ -2602,7 +2644,7 @@
;*---------------------------------------------------------------------*/
(markup-writer '&bib-entry-title
:action (lambda (n e)
- (let* ((t (bold (markup-body n)))
+ (let* ((t (markup-body n))
(en (handle-ast (ast-parent n)))
(url (markup-option en 'url))
(ht (if url (ref :url (markup-body url) :text t) t)))
@@ -2624,7 +2666,7 @@
:action (lambda (n e)
(let* ((en (handle-ast (ast-parent n)))
(url (markup-option en 'url))
- (t (bold (markup-body url))))
+ (t (it (markup-body url))))
(skribe-eval (ref :url (markup-body url) :text t) e))))
;*---------------------------------------------------------------------*/
@@ -2848,11 +2890,13 @@
(gensym 'lout-illustration)))
".eps"))
(port (open-output-pipe
- (string-append (or (engine-custom lout
- 'lout-program-name)
- "lout")
- " -o " output
- " -EPS"))))
+ (apply string-append
+ (or (engine-custom lout 'lout-program-name)
+ "lout")
+ " -o " output
+ " -EPS "
+ (engine-custom lout
+ 'lout-program-arguments)))))
;; send the illustration to Lout's standard input
(display (illustration-header) port)
diff --git a/src/guile/skribilo/package/base.scm b/src/guile/skribilo/package/base.scm
index 3145695..b904ed8 100644
--- a/src/guile/skribilo/package/base.scm
+++ b/src/guile/skribilo/package/base.scm
@@ -33,7 +33,7 @@
:autoload (skribilo engine) (engine? engine-class?)
;; optional ``sub-packages''
- :autoload (skribilo biblio) (default-bib-table resolve-bib
+ :autoload (skribilo biblio) (*bib-table* resolve-bib
bib-load! bib-add!)
:autoload (skribilo color) (skribe-use-color!)
:autoload (skribilo source) (language? source-read-lines source-fontify)
@@ -1017,7 +1017,7 @@
(subsection #f)
(subsubsection #f)
(bib #f)
- (bib-table (default-bib-table))
+ (bib-table (*bib-table*))
(url #f)
(figure #f)
(mark #f)
@@ -1189,6 +1189,49 @@
(line (line-ref line))
(else (skribe-error 'ref "illegal reference" opts)))))
+
+;*---------------------------------------------------------------------*/
+;* numref ... */
+;*---------------------------------------------------------------------*/
+(define-markup (numref #!rest opts
+ #!key (ident #f) (text "") (page #f)
+ (separator ".") (class #f))
+ ;; Produce a numbered reference to `ident'.
+ (new unresolved
+ (proc (lambda (n e env)
+ (let* ((parent (ast-parent n))
+ (doc (ast-document n))
+ (target (document-lookup-node doc ident))
+ (number (and target
+ (markup-option target :number))))
+ (cond
+ ((not target)
+ (skribe-warning/ast 1 n 'numref
+ (format #f "can't find `ident': ")
+ ident)
+ (new markup
+ (markup 'unref)
+ (ident (symbol->string (gensym "unref")))
+ (class class)
+ (required-options '(:text))
+ (options `((kind numref)
+ ,@(the-options opts :ident :class)))
+ (body (list ident ": " (ast->file-location n)))))
+ ((unresolved? number)
+ ;; Loop until `number' is resolved.
+ n)
+ (else
+ (let ((xref
+ (ref :text
+ (list (if text text "") " "
+ (if (number? number)
+ (markup-number-string target
+ separator)
+ ""))
+ :page page
+ :handle (handle target))))
+ (resolve! xref e env)))))))))
+
;*---------------------------------------------------------------------*/
;* resolve ... */
;*---------------------------------------------------------------------*/
@@ -1204,7 +1247,7 @@
;*---------------------------------------------------------------------*/
(define-markup (bibliography #!rest files
#!key
- (command #f) (bib-table (default-bib-table)))
+ (command #f) (bib-table (*bib-table*)))
(for-each (lambda (f)
(cond
((string? f)
@@ -1226,7 +1269,7 @@
(define-markup (the-bibliography #!rest opts
#!key
pred
- (bib-table (default-bib-table))
+ (bib-table (*bib-table*))
(sort bib-sort/authors)
(count 'partial))
(if (not (memq count '(partial full)))
diff --git a/src/guile/skribilo/package/eq.scm b/src/guile/skribilo/package/eq.scm
index e09dec6..821840f 100644
--- a/src/guile/skribilo/package/eq.scm
+++ b/src/guile/skribilo/package/eq.scm
@@ -19,7 +19,7 @@
;;; USA.
(define-module (skribilo package eq)
- :autoload (skribilo ast) (markup?)
+ :autoload (skribilo ast) (markup? find-up)
:autoload (skribilo output) (output)
:use-module (skribilo writer)
:use-module (skribilo engine)
@@ -29,6 +29,8 @@
:use-module (skribilo utils keywords) ;; `the-options', etc.
:autoload (skribilo package base) (it symbol sub sup)
:autoload (skribilo engine lout) (lout-illustration)
+
+ :use-module (srfi srfi-39)
:use-module (ice-9 optargs))
;;; Author: Ludovic Courtès
@@ -52,9 +54,14 @@
;;; Utilities.
;;;
+(define-public *embedded-renderer*
+ ;; Tells whether an engine is invoked as an embedded renderer or as the
+ ;; native engine.
+ (make-parameter #f))
+
(define %operators
'(/ * + - = != ~= < > <= >= sqrt expt sum product script
- in notin apply))
+ in notin apply limit combinations))
(define %symbols
;; A set of symbols that are automatically recognized within an `eq' quoted
@@ -110,24 +117,45 @@ a symbol representing the mathematical operator denoted by @var{m} (e.g.,
(string-length str))))
#f))
+(define-public (inline-equation? m)
+ "Return @code{#t} if @var{m} is an equation that is to be displayed inline."
+ (and (is-markup? m 'eq)
+ (let ((i (markup-option m :inline?)))
+ (case i
+ ((auto)
+ (not (find-up (lambda (n)
+ (is-markup? n 'eq-display))
+ m)))
+ ((#t) #t)
+ (else #f)))))
+
;;;
;;; Operator precedence.
;;;
(define %operator-precedence
- ;; FIXME: This needs to be augmented.
- '((+ . 1)
- (- . 1)
- (* . 2)
- (/ . 2)
- (sum . 3)
+ ;; Taken from http://en.wikipedia.org/wiki/Order_of_operations .
+ '((expt . 2)
+ (sqrt . 2)
+
+ (* . 3)
+ (/ . 3)
(product . 3)
- (= . 0)
- (< . 0)
- (> . 0)
- (<= . 0)
- (>= . 0)))
+
+ (+ . 4)
+ (- . 4)
+ (sum . 4)
+
+ (< . 6)
+ (> . 6)
+ (<= . 6)
+ (>= . 6)
+
+ (= . 7)
+ (!= . 7)
+ (~= . 7)))
+
(define-public (operator-precedence op)
(let ((p (assq op %operator-precedence)))
@@ -169,12 +197,27 @@ a symbol representing the mathematical operator denoted by @var{m} (e.g.,
;;; Markup.
;;;
-(define-markup (eq :rest opts :key (ident #f) (inline? #f)
- (renderer #f) (class "eq"))
- (new markup
+(define-markup (eq-display :rest opts :key (ident #f) (class "eq-display"))
+ (new container
+ (markup 'eq-display)
+ (ident (or ident (symbol->string (gensym "eq-display"))))
+ (class class)
+ (options (the-options opts :ident :class))
+ (body (the-body opts))))
+
+(define-markup (eq :rest opts :key (ident #f) (class "eq")
+ (inline? 'auto) (align-with #f)
+ (renderer #f) (div-style 'over)
+ (mul-style 'space))
+ (new container
(markup 'eq)
(ident (or ident (symbol->string (gensym "eq"))))
- (options (the-options opts))
+ (class class)
+ (options `((:div-style ,div-style) (:align-with ,align-with)
+ (:mul-style ,mul-style)
+ ,@(the-options opts
+ :ident :class
+ :div-style :mul-style :align-with)))
(body (let loop ((body (the-body opts))
(result '()))
(if (null? body)
@@ -187,8 +230,27 @@ a symbol representing the mathematical operator denoted by @var{m} (e.g.,
;; passed
))))))
-(define-simple-markup eq:/)
-(define-simple-markup eq:*)
+
+(define-markup (eq:/ :rest opts :key (ident #f) (div-style #f))
+ ;; If no `:div-style' is specified here, obey the top-level one.
+ (new markup
+ (markup 'eq:/)
+ (ident (or ident (symbol->string (gensym "eq:/"))))
+ (class #f)
+ (options `((:div-style ,div-style)
+ ,@(the-options opts :ident :div-style)))
+ (body (the-body opts))))
+
+(define-markup (eq:* :rest opts :key (ident #f) (mul-style #f))
+ ;; If no `:mul-style' is specified here, obey the top-level one.
+ (new markup
+ (markup 'eq:*)
+ (ident (or ident (symbol->string (gensym "eq:*"))))
+ (class #f)
+ (options `((:mul-style ,mul-style)
+ ,@(the-options opts :ident :mul-style)))
+ (body (the-body opts))))
+
(define-simple-markup eq:+)
(define-simple-markup eq:-)
@@ -252,12 +314,37 @@ a symbol representing the mathematical operator denoted by @var{m} (e.g.,
(loop (cdr body) (cons first result)))))))))
+(define-markup (eq:limit var lim :rest body :key (ident #f))
+ (new markup
+ (markup 'eq:limit)
+ (ident (or ident (symbol->string (gensym "eq:limit"))))
+ (options `((:var ,var) (:limit ,lim)
+ ,@(the-options body :ident)))
+ (body (the-body body))))
+
+(define-markup (eq:combinations x y :rest opts :key (ident #f))
+ (new markup
+ (markup 'eq:combinations)
+ (ident (or ident (symbol->string (gensym "eq:combinations"))))
+ (options `((:of ,x) (:among ,y)
+ ,@(the-options opts :ident)))
+ (body (the-body opts))))
+
;;;
;;; Text-based rendering.
;;;
+(markup-writer 'eq-display (lookup-engine-class 'base)
+ :action (lambda (node engine)
+ (for-each (lambda (node)
+ (let ((eq? (is-markup? node 'eq)))
+ (if eq? (output (linebreak) engine))
+ (output node engine)
+ (if eq? (output (linebreak) engine))))
+ (markup-body node))))
+
(markup-writer 'eq (lookup-engine-class 'base)
:action (lambda (node engine)
;; The `:renderer' option should be a symbol (naming an engine
@@ -269,22 +356,23 @@ a symbol representing the mathematical operator denoted by @var{m} (e.g.,
(cond ((not renderer) ;; default: use the current engine
(output (it (markup-body node)) engine))
((symbol? renderer)
- (case renderer
- ;; FIXME: We should have an `embed' slot for each
- ;; engine class similar to `lout-illustration'.
- ((lout)
- (let ((lout-code
- (with-output-to-string
- (lambda ()
- (output node
- (make-engine
- (lookup-engine-class 'lout)))))))
- (output (lout-illustration
- :ident (markup-ident node)
- lout-code)
- engine)))
- (else
- (skribe-error 'eq "invalid renderer" renderer))))
+ (parameterize ((*embedded-renderer* #t))
+ (case renderer
+ ;; FIXME: We should have an `embed' slot for each
+ ;; engine class similar to `lout-illustration'.
+ ((lout)
+ (let ((lout-code
+ (with-output-to-string
+ (lambda ()
+ (output node
+ (make-engine
+ (lookup-engine-class 'lout)))))))
+ (output (lout-illustration
+ :ident (markup-ident node)
+ lout-code)
+ engine)))
+ (else
+ (skribe-error 'eq "invalid renderer" renderer)))))
;; FIXME: `engine?' and `engine-class?'
(else
(skribe-error 'eq "`:renderer' -- wrong argument type"
@@ -303,10 +391,10 @@ a symbol representing the mathematical operator denoted by @var{m} (e.g.,
(nested-eq? (equation-markup? o))
(need-paren?
(and nested-eq?
-; (< (operator-precedence
-; (equation-markup-name->operator
-; (markup-markup o)))
-; ,precedence)
+ (>= (operator-precedence
+ (equation-markup-name->operator
+ (markup-markup o)))
+ ,precedence)
)
))
@@ -424,6 +512,28 @@ a symbol representing the mathematical operator denoted by @var{m} (e.g.,
(output (sup sup*) engine)
(output (sub sub*) engine))))
+(markup-writer 'eq:limit (lookup-engine-class 'base)
+ :action (lambda (node engine)
+ (let ((body (markup-body node))
+ (var (markup-option node :var))
+ (limit (markup-option node :limit)))
+ (display "lim (")
+ (output var engine)
+ (output (symbol "->") engine)
+ (output limit engine)
+ (display ", ")
+ (output body engine)
+ (display ")"))))
+
+(markup-writer 'eq:combinations (lookup-engine-class 'base)
+ :action (lambda (node engine)
+ (let ((of (markup-option node :of))
+ (among (markup-option node :among)))
+ (display "combinations(")
+ (output of engine)
+ (display ", ")
+ (output among engine)
+ (display ")"))))
diff --git a/src/guile/skribilo/package/eq/lout.scm b/src/guile/skribilo/package/eq/lout.scm
index c38e74c..cc305f1 100644
--- a/src/guile/skribilo/package/eq/lout.scm
+++ b/src/guile/skribilo/package/eq/lout.scm
@@ -50,12 +50,20 @@
;;; Simple markup writers.
;;;
+(markup-writer 'eq-display (lookup-engine-class 'lout)
+ :before "\n@BeginAlignedDisplays\n"
+ :after "\n@EndAlignedDisplays\n")
(markup-writer 'eq (lookup-engine-class 'lout)
- :options '(:inline?)
- :before "{ "
+ :options '(:inline? :align-with :div-style :mul-style)
+ :before (lambda (node engine)
+ (let* ((parent (ast-parent node))
+ (displayed? (is-markup? parent 'eq-display)))
+ (format #t "~a{ "
+ (if (and displayed? (not (*embedded-renderer*)))
+ "\n@IAD " ""))))
:action (lambda (node engine)
- (display (if (markup-option node :inline?)
+ (display (if (inline-equation? node)
"@E { "
"@Eq { "))
(let ((eq (markup-body node)))
@@ -64,6 +72,29 @@
:after " } }")
+;; Scaled parenthesis. We could use `pmatrix' here but it precludes
+;; line-breaking within equations.
+(define %left-paren "{ Base @Font @VScale \"(\" }")
+(define %right-paren "{ Base @Font @VScale \")\" }")
+
+(define (div-style->lout style)
+ (case style
+ ((over) "over")
+ ((fraction) "frac")
+ ((div) "div")
+ ((slash) "slash")
+ (else
+ (error "unsupported div style" style))))
+
+(define (mul-style->lout style)
+ (case style
+ ((space) "")
+ ((cross) "times")
+ ((asterisk) "*")
+ ((dot) "cdot")
+ (else
+ (error "unsupported mul style" style))))
+
(define-macro (simple-lout-markup-writer sym . args)
(let* ((lout-name (if (null? args)
@@ -74,45 +105,54 @@
(cadr args)))
(precedence (operator-precedence sym))
- ;; Note: We could use `pmatrix' here but it precludes line-breaking
- ;; within equations.
- (open-par `(if need-paren? "{ @VScale ( }" ""))
- (close-par `(if need-paren? "{ @VScale ) }" "")))
+ (open-par (if parentheses?
+ `(if need-paren? %left-paren "")
+ ""))
+ (close-par (if parentheses?
+ `(if need-paren? %right-paren "")
+ "")))
`(markup-writer ',(symbol-append 'eq: sym)
- (lookup-engine-class 'lout)
- :action (lambda (node engine)
- (let loop ((operands (markup-body node)))
- (if (null? operands)
- #t
- (let* ((op (car operands))
- (eq-op? (equation-markup? op))
- (need-paren?
- (and eq-op?
- (< (operator-precedence
- (equation-markup-name->operator
- (markup-markup op)))
- ,precedence)))
- (column (port-column
- (current-output-port))))
-
- ;; Work around Lout's limitations...
- (if (> column 1000) (display "\n"))
-
- (display (string-append " { "
- ,(if parentheses?
- open-par
- "")))
- (output op engine)
- (display (string-append ,(if parentheses?
- close-par
- "")
- " }"))
- (if (pair? (cdr operands))
- (display ,(string-append " "
- lout-name
- " ")))
- (loop (cdr operands)))))))))
+ (lookup-engine-class 'lout)
+ :action (lambda (node engine)
+ (let* ((lout-name ,(if (string? lout-name)
+ lout-name
+ `(,lout-name node
+ engine)))
+ (eq (ast-parent node))
+ (eq-parent (ast-parent eq)))
+
+ (let loop ((operands (markup-body node))
+ (first? #t))
+ (if (null? operands)
+ #t
+ (let* ((align?
+ (and first?
+ (is-markup? eq-parent 'eq-display)
+ (eq? ',sym
+ (markup-option eq :align-with))))
+ (op (car operands))
+ (eq-op? (equation-markup? op))
+ (need-paren?
+ (and eq-op?
+ (>= (operator-precedence
+ (equation-markup-name->operator
+ (markup-markup op)))
+ ,precedence)))
+ (column (port-column (current-output-port))))
+
+ ;; Work around Lout's limitations...
+ (if (> column 1000) (display "\n"))
+
+ (display (string-append " { " ,open-par))
+ (output op engine)
+ (display (string-append ,close-par " }"))
+ (if (pair? (cdr operands))
+ (display (string-append " "
+ (if align? "^" "")
+ lout-name
+ " ")))
+ (loop (cdr operands) #f)))))))))
;; `+' and `*' have higher precedence than `-', `/', `=', etc., so their
@@ -121,9 +161,26 @@
(simple-lout-markup-writer +)
-(simple-lout-markup-writer * "times")
(simple-lout-markup-writer - "-")
-(simple-lout-markup-writer / "over" #f)
+
+(simple-lout-markup-writer *
+ (lambda (n e)
+ ;; Obey either the per-node `:mul-style' or the
+ ;; top-level one.
+ (mul-style->lout
+ (or (markup-option n :mul-style)
+ (let ((eq (ast-parent n)))
+ (markup-option eq :mul-style))))))
+
+(simple-lout-markup-writer /
+ (lambda (n e)
+ ;; Obey either the per-node `:div-style' or the
+ ;; top-level one.
+ (div-style->lout
+ (or (markup-option n :div-style)
+ (let ((eq (ast-parent n)))
+ (markup-option eq :div-style)))))
+ #f)
(simple-lout-markup-writer =)
(simple-lout-markup-writer <)
(simple-lout-markup-writer >)
@@ -139,9 +196,9 @@
(second (cadr body))
(parentheses? (equation-markup? first)))
(display " { { ")
- (if parentheses? (display "("))
+ (if parentheses? (display %left-paren))
(output first engine)
- (if parentheses? (display ")"))
+ (if parentheses? (display %right-paren))
(display ,(string-append " } " lout-name " { "))
(output second engine)
(display " } } "))
@@ -149,15 +206,15 @@
"wrong number of arguments"
body))))))
-(binary-lout-markup-writer expt "sup")
-(binary-lout-markup-writer in "element")
+(binary-lout-markup-writer expt "sup")
+(binary-lout-markup-writer in "element")
(binary-lout-markup-writer notin "notelement")
(markup-writer 'eq:apply (lookup-engine-class 'lout)
:action (lambda (node engine)
(let ((func (car (markup-body node))))
(output func engine)
- (display "(")
+ (display %left-paren)
(let loop ((operands (cdr (markup-body node))))
(if (null? operands)
#t
@@ -166,8 +223,32 @@
(if (not (null? (cdr operands)))
(display ", "))
(loop (cdr operands)))))
- (display ")"))))
+ (display %right-paren))))
+
+(markup-writer 'eq:limit (lookup-engine-class 'lout)
+ :action (lambda (node engine)
+ (let ((body (markup-body node))
+ (var (markup-option node :var))
+ (limit (markup-option node :limit)))
+ (display "{ lim from { ")
+ (output var engine)
+ (display " --> ")
+ (output limit engine)
+ (display (string-append " } } @VContract { " %left-paren))
+ (output body engine)
+ (display (string-append %right-paren " } ")))))
+
+(markup-writer 'eq:combinations (lookup-engine-class 'lout)
+ :action (lambda (node engine)
+ (let ((of (markup-option node :of))
+ (among (markup-option node :among)))
+ (display " ` { matrix atleft { lpar } atright { rpar } { ")
+ (display "row col { ")
+ (output of engine)
+ (display " } row col { ")
+ (output among engine)
+ (display " } } } `\n"))))
;;;
@@ -207,7 +288,7 @@
(display " } ")))
(if sub
(begin
- (display " on { ")
+ (display (if sup " on { " " sub { "))
(output sub engine)
(display " } ")))
(display " } "))))
diff --git a/src/guile/skribilo/package/slide.scm b/src/guile/skribilo/package/slide.scm
index 68d2ba6..fbdf912 100644
--- a/src/guile/skribilo/package/slide.scm
+++ b/src/guile/skribilo/package/slide.scm
@@ -162,6 +162,7 @@
(define-markup (slide-embed #!rest opt
#!key
command
+ (arguments '())
(geometry-opt "-geometry")
(geometry #f) (rgeometry #f)
(transient #f) (transient-opt #f)
@@ -243,12 +244,14 @@
;*---------------------------------------------------------------------*/
(define-markup (slide-topic #!rest opt
#!key title (outline? #t)
- (ident #f) (class "slide-topic"))
+ (ident #f) (class #f))
(new container
(markup 'slide-topic)
(required-options '(:title :outline?))
(ident (or ident (symbol->string (gensym "slide-topic"))))
- (options (the-options opt))
+ (class class)
+ (options `((:outline? ,outline?)
+ ,@(the-options opt :outline? :class)))
(body (the-body opt))))
;*---------------------------------------------------------------------*/
@@ -256,12 +259,14 @@
;*---------------------------------------------------------------------*/
(define-markup (slide-subtopic #!rest opt
#!key title (outline? #f)
- (ident #f) (class "slide-subtopic"))
+ (ident #f) (class #f))
(new container
(markup 'slide-subtopic)
(required-options '(:title :outline?))
(ident (or ident (symbol->string (gensym "slide-subtopic"))))
- (options (the-options opt))
+ (class class)
+ (options `((:outline? ,outline?)
+ ,@(the-options opt :outline? :class)))
(body (the-body opt))))
diff --git a/src/guile/skribilo/package/slide/base.scm b/src/guile/skribilo/package/slide/base.scm
index 1d8d84c..0686a7c 100644
--- a/src/guile/skribilo/package/slide/base.scm
+++ b/src/guile/skribilo/package/slide/base.scm
@@ -155,7 +155,7 @@
(is-markup? n 'slide-topic))
topic))))
(output (slide :title %slide-outline-title :toc #f
- :class (markup-option topic :class)
+ :class (markup-class topic)
;; The mark below is needed for cross-referencing by PDF
;; bookmarks.
(if (markup-ident topic) (mark (markup-ident topic)) "")
diff --git a/src/guile/skribilo/package/slide/html.scm b/src/guile/skribilo/package/slide/html.scm
index d47ef82..9a5148d 100644
--- a/src/guile/skribilo/package/slide/html.scm
+++ b/src/guile/skribilo/package/slide/html.scm
@@ -18,43 +18,75 @@
;;; Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
;;; USA.
-(define-skribe-module (skribilo package slide html)
- :use-module (skribilo package slide))
+(define-module (skribilo package slide html)
+ :use-module (skribilo utils syntax)
+ :use-module (skribilo ast)
+ :use-module (skribilo engine)
+ :use-module (skribilo writer)
+ :autoload (skribilo resolve) (resolve!)
+ :autoload (skribilo output) (output)
+ :autoload (skribilo evaluator) (evaluate-document)
+ :autoload (skribilo engine html) (html-width html-title-authors)
+ :use-module (skribilo package slide)
+ :use-module ((skribilo package base) :select (ref)))
+
+
+(fluid-set! current-reader %skribilo-module-reader)
+
+
+
(define-public (%slide-html-initialize!)
- (let ((he (find-engine 'html)))
- (skribe-message "HTML slides setup...\n")
+ (let ((he (lookup-engine-class 'html)))
+ (display "HTML slides setup...\n" (current-error-port))
+
;; &html-page-title
(markup-writer '&html-document-title he
;;:predicate (lambda (n e) %slide-initialized)
:action html-slide-title)
+
;; slide
(markup-writer 'slide he
:options '(:title :number :transition :toc :bg)
:before (lambda (n e)
- (printf "<a name=\"~a\">" (markup-ident n))
- (display "<br>\n"))
+ (display "<br>\n")
+ (format #t "<a name=\"~a\">" (markup-ident n)))
:action (lambda (n e)
(let ((nb (markup-option n :number))
- (t (markup-option n :title)))
- (skribe-eval
- (center
- (color :width (slide-body-width e)
- :bg (or (markup-option n :bg) "#ffffff")
- (table :width 100.
- (tr (th :align 'left
- (list
- (if nb
- (format #f "~a / ~a -- " nb
- (slide-number)))
- t)))
- (tr (td (hrule)))
- (tr (td :width 100. :align 'left
- (markup-body n))))
- (linebreak)))
- e)))
+ (t (markup-option n :title))
+ (class (markup-class n)))
+ (if class
+ (let ((title-class (string-append class "-title")))
+ ;; When a class is specified, let the user play
+ ;; with CSS.
+ (format #t "\n<div class=\"~a\">" class)
+ (format #t "<div class=\"~a\">" title-class)
+ (format #t "~a / ~a -- " nb (slide-number))
+ (output t e)
+ (display "</div>\n")
+ (output (markup-body n) e)
+ (display "\n</div>\n"))
+ ;; When no class is specified, do HTML tricks.
+ (evaluate-document
+ (center
+ (color :width (slide-body-width e)
+ :bg (or (markup-option n :bg) "#ffffff")
+ (table :width 100.
+ (tr (th :align 'left
+ (list
+ (if nb
+ (format #f "~a / ~a -- "
+ nb
+ (slide-number)))
+ t)))
+ (tr (td (hrule)))
+ (tr (td :width 100. :align 'left
+ (markup-body n))))
+ (linebreak)))
+ e))))
:after "<br>")
+
;; slide-vspace
(markup-writer 'slide-vspace he
:action (lambda (n e) (display "<br>")))))
@@ -76,23 +108,23 @@
(tbg (engine-custom e 'title-background))
(tfg (engine-custom e 'title-foreground))
(tfont (engine-custom e 'title-font)))
- (printf "<center><table cellspacing='0' cellpadding='0' width=\"~a\" class=\"skribetitle\"><tbody>\n<tr>"
+ (format #t "<center><table cellspacing='0' cellpadding='0' width=\"~a\" class=\"skribilo-title\"><tbody>\n<tr>"
(html-width (slide-body-width e)))
(if (string? tbg)
- (printf "<td bgcolor=\"~a\">" tbg)
+ (format #t "<td bgcolor=\"~a\">" tbg)
(display "<td>"))
(if (string? tfg)
- (printf "<font color=\"~a\">" tfg))
+ (format #t "<font color=\"~a\">" tfg))
(if title
(begin
(display "<center>")
(if (string? tfont)
(begin
- (printf "<font ~a><strong>" tfont)
+ (format #t "<font ~a><strong>" tfont)
(output title e)
(display "</strong></font>"))
(begin
- (printf "<div class=\"skribetitle\"><strong><big><big><big>")
+ (display "<div class=\"skribilo-title\"><strong><big><big><big>")
(output title e)
(display "</big></big></big></strong</div>")))
(display "</center>\n")))
@@ -109,26 +141,47 @@
;;; Slide topics/subtopics.
;;;
-(markup-writer 'slide-topic (find-engine 'html)
+(markup-writer 'slide-topic (lookup-engine-class 'html)
:options '(:title :outline? :class :ident)
:action (lambda (n e)
(let ((title (markup-option n :title))
- (body (markup-body n)))
- (display "\n<h2 class=\"slide-topic:title\">")
+ (body (markup-body n))
+ (class (markup-class n)))
+ ;; top-level class
+ (if class (format #t "\n<div class=\"~a\">" class))
+
+ ;; the title
+ (if class
+ (format #t "\n<div class=\"~a-title\">" class)
+ (display "\n<h2 class=\"slide-topic:title\">"))
(if (markup-ident n)
- (printf "<a name=\"~a\"></a>" (markup-ident n)))
+ (format #t "<a name=\"~a\"></a>" (markup-ident n)))
(output title e)
- (display "</h2> <br>\n")
- (display "\n<div class=\"slide-topic:slide-list\">")
+ (if class
+ (display "</div>\n")
+ (display "</h2> <br>\n"))
+
+ ;; pointers to the slides
+ (if class
+ (format #t "\n<div class=\"~a-slide-list\">"
+ class)
+ (display "\n<div class=\"slide-topic:slide-list\">"))
(for-each (lambda (s)
- (output (markup-option s :title) e)
- (display "&nbsp;--&nbsp;"))
+ (let* ((title (markup-option s :title))
+ (ident (markup-ident s))
+ (sref (ref :text title :ident ident))
+ (sref* (resolve! sref e `((parent ,n)))))
+ (output sref* e)
+ (display "&nbsp;--&nbsp;")))
(filter (lambda (n)
(or (is-markup? n 'slide-subtopic)
(is-markup? n 'slide)))
(markup-body n)))
(display "\n</div> <!-- slide-topic:slide-list -->")
- (display "\n<hr><br>\n")
+
+ (if class
+ (display "\n</div> <!-- slide-topic -->\n")
+ (display "\n<hr><br>\n"))
;; the slides
(output (markup-body n) e))))
diff --git a/src/guile/skribilo/package/slide/lout.scm b/src/guile/skribilo/package/slide/lout.scm
index d53cff1..6597442 100644
--- a/src/guile/skribilo/package/slide/lout.scm
+++ b/src/guile/skribilo/package/slide/lout.scm
@@ -18,9 +18,17 @@
;;; Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
;;; USA.
-(define-skribe-module (skribilo package slide lout)
+(define-module (skribilo package slide lout)
:use-module (skribilo utils syntax)
+ :autoload (skribilo utils strings) (make-string-replace)
+ :use-module (skribilo engine)
+ :use-module (skribilo writer)
+ :autoload (skribilo output) (output)
+ :use-module (skribilo ast)
+
+ :use-module (srfi srfi-13) ;; `string-join'
+
;; XXX: If changing the following `autoload' to `use-module' doesn't work,
;; then you need to fix your Guile. See this thread about
;; `make-autoload-interface':
@@ -34,13 +42,14 @@
(fluid-set! current-reader %skribilo-module-reader)
+
;;; TODO:
;;;
;;; Make some more PS/PDF trickery.
(format (current-error-port) "Lout slides setup...~%")
-(let ((le (find-engine 'lout)))
+(let ((le (lookup-engine-class 'lout)))
;; FIXME: Automatically switching to `slides' is problematic, e.g., for the
;; user manual which embeds slides.
@@ -83,7 +92,7 @@
(and (pair? (markup-body n))
(number? (car (markup-body n)))))
:action (lambda (n e)
- (printf "\n//~a~a # slide-vspace\n"
+ (format #t "\n//~a~a # slide-vspace\n"
(car (markup-body n))
(case (markup-option n :unit)
((cm) "c")
@@ -94,6 +103,25 @@
"Unknown vspace unit"
(markup-option n :unit)))))))
+ (markup-writer 'slide-embed le
+ :options '(:command :arguments :alt :geometry :geometry-opt)
+ :action (lambda (n e)
+ (let ((command (markup-option n :command))
+ (args (markup-option n :arguments))
+ (alt (markup-option n :alt))
+ (geometry (markup-option n :geometry))
+ (geometry-opt (markup-option n :geometry-opt))
+ (filter (make-string-replace lout-verbatim-encoding)))
+ (format #t "~%\"~a\" @SkribiloEmbed { "
+ (string-append command " "
+ (if (and geometry-opt geometry)
+ (string-append geometry-opt " "
+ geometry " ")
+ "")
+ (string-join args " ")))
+ (output alt e)
+ (format #t " }\n"))))
+
(markup-writer 'slide-pause le
;; FIXME: Use a `pdfmark' custom action and a PDF transition action.
;; << /Type /Action
@@ -109,26 +137,7 @@
;; For movies, see
;; http://www.tug.org/tex-archive/macros/latex/contrib/movie15/movie15.sty .
- (markup-writer 'slide-embed le
- :options '(:alt :geometry :rgeometry :geometry-opt :command)
- ;; FIXME: `pdfmark'.
- ;; << /Type /Action /S /Launch
- :action (lambda (n e)
- (let ((command (markup-option n :command))
- (filter (make-string-replace lout-verbatim-encoding))
- (pdfmark "[ /Rect [ 0 ysize xsize 0 ]
-/Name /Comment
-/Contents (This is an embedded application)
-/ANN pdfmark
-
-[ /Type /Action
-/S /Launch
-/F (~a)
-/OBJ pdfmark"))
- (display (string-append
- "4c @Wide 3c @High "
- (lout-embedded-postscript-code
- (filter (format #f pdfmark command)))))))))
+ )
@@ -136,7 +145,7 @@
;;; Customs for a nice handling of topics/subtopics.
;;;
-(let ((lout (find-engine 'lout)))
+(let ((lout (lookup-engine-class 'lout)))
(if lout
(begin
(engine-custom-set! lout 'pdf-bookmark-node-pred
diff --git a/src/guile/skribilo/prog.scm b/src/guile/skribilo/prog.scm
index 266d607..2f531cd 100644
--- a/src/guile/skribilo/prog.scm
+++ b/src/guile/skribilo/prog.scm
@@ -24,8 +24,13 @@
:autoload (ice-9 receive) (receive)
:use-module (skribilo lib) ;; `new'
:autoload (skribilo ast) (node? node-body)
+ :use-module (skribilo utils syntax)
+
:export (make-prog-body resolve-line))
+(fluid-set! current-reader %skribilo-module-reader)
+
+
;;; ======================================================================
;;;
;;; COMPATIBILITY
@@ -211,8 +216,9 @@
(extract-mark (car lines) mark regexp)
(let* ((line-ident (symbol->string (gensym "&prog-line")))
(n (new markup
- (markup '&prog-line)
- (ident line-ident)
+ (markup '&prog-line)
+ (ident line-ident)
+ (options `((:number ,lnum)))
(body (if m (make-line-mark m line-ident l) l)))))
(loop (cdr lines)
(+ lnum 1)
diff --git a/src/guile/skribilo/reader/outline.scm b/src/guile/skribilo/reader/outline.scm
index 09792f5..7411892 100644
--- a/src/guile/skribilo/reader/outline.scm
+++ b/src/guile/skribilo/reader/outline.scm
@@ -22,7 +22,10 @@
:use-module (skribilo utils syntax)
:use-module (skribilo reader)
:use-module (ice-9 optargs)
+
:use-module (srfi srfi-11)
+ :use-module (srfi srfi-13)
+ :use-module (srfi srfi-14)
:autoload (ice-9 rdelim) (read-line)
:autoload (ice-9 regex) (make-regexp)
@@ -380,12 +383,19 @@ to @var{node-type}."
(define modeline-rx
(make-regexp "^[[:space:]]*-\\*- [a-zA-Z-]+ -\\*-[[:space:]]*$"))
(define title-rx (make-regexp "^[Tt]itle: (.+)$" regexp/extended))
- (define author-rx (make-regexp "^[Aa]uthor: (.+)$" regexp/extended))
+ (define author-rx (make-regexp "^[Aa]uthors?: (.+)$" regexp/extended))
+ (define keywords-rx
+ (make-regexp "^[Kk]ey ?[wW]ords?: (.+)$" regexp/extended))
+
+ (define (extract-keywords str)
+ (map string-trim-both
+ (string-tokenize str (char-set-complement (char-set #\,)))))
(let ((doc-proc (make-document-processor %node-processors %line-processor)))
(let loop ((title #f)
(author #f)
+ (keywords '())
(line (read-line port)))
(if (eof-object? line)
@@ -394,20 +404,34 @@ to @var{node-type}."
line)
(if (or (empty-line? line)
(regexp-exec modeline-rx line))
- (loop title author (read-line port))
- (let ((title-match (regexp-exec title-rx line)))
- (if title-match
- (loop (match:substring title-match 1)
- author (read-line port))
- (let ((author-match (regexp-exec author-rx line)))
- (if author-match
- (loop title (match:substring author-match 1)
- (read-line port))
-
- ;; Let's go.
- `(document :title ,title
- :author (author :name ,author)
- ,@(doc-proc line port)))))))))))
+ (loop title author keywords (read-line port))
+ (cond ((regexp-exec title-rx line)
+ =>
+ (lambda (title-match)
+ (loop (match:substring title-match 1)
+ author keywords (read-line port))))
+
+ ((regexp-exec author-rx line)
+ =>
+ (lambda (author-match)
+ (loop title (match:substring author-match 1)
+ keywords (read-line port))))
+
+ ((regexp-exec keywords-rx line)
+ =>
+ (lambda (kw-match)
+ (loop title author
+ (append keywords
+ (extract-keywords
+ (match:substring kw-match 1)))
+ (read-line port))))
+
+ (else
+ ;; Let's go.
+ `(document :title ,title
+ :author (author :name ,author)
+ :keywords ',keywords
+ ,@(doc-proc line port)))))))))
(define* (make-outline-reader :optional (version "0.1"))
diff --git a/src/guile/skribilo/utils/compat.scm b/src/guile/skribilo/utils/compat.scm
index 5074bd7..1142142 100644
--- a/src/guile/skribilo/utils/compat.scm
+++ b/src/guile/skribilo/utils/compat.scm
@@ -37,6 +37,7 @@
:autoload (skribilo output) (*document-being-output*)
:use-module ((skribilo engine) :renamer (symbol-prefix-proc 'orig:))
:use-module ((skribilo writer) :renamer (symbol-prefix-proc 'orig:))
+ :autoload (skribilo biblio) (*bib-table* open-bib-file)
:use-module (skribilo debug)
:re-export (file-size) ;; re-exported from `(skribilo utils files)'
@@ -357,6 +358,18 @@
;;;
+;;; Bibliography.
+;;;
+
+(define-public (default-bib-table)
+ (*bib-table*))
+
+(define-public (skribe-open-bib-file file command)
+ (open-bib-file file command))
+
+
+
+;;;
;;; Debugging facilities.
;;;