;;;; ;;;; writer.stk -- Skribe Writer Stuff ;;;; ;;;; Copyright © 2003-2004 Erick Gallesio - I3S-CNRS/ESSI ;;;; ;;;; ;;;; 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, ;;;; USA. ;;;; ;;;; Author: Erick Gallesio [eg@essi.fr] ;;;; Creation date: 15-Sep-2003 22:21 (eg) ;;;; Last file update: 4-Mar-2004 10:48 (eg) ;;;; (define-module (skribe writer) :export (invoke markup-writer markup-writer-get markup-writer-get* lookup-markup-writer copy-markup-writer)) (use-modules (skribe debug) ; (skribe engine) (skribe output) (oop goops) (ice-9 optargs)) ;;;; ====================================================================== ;;;; ;;;; INVOKE ;;;; ;;;; ====================================================================== (define (invoke proc node e) (with-debug 5 'invoke (debug-item "e=" (engine-ident e)) (debug-item "node=" node " " (if (markup? node) (markup-markup node) "")) (if (string? proc) (display proc) (if (procedure? proc) (proc node e))))) ;;;; ====================================================================== ;;;; ;;;; LOOKUP-MARKUP-WRITER ;;;; ;;;; ====================================================================== (define (lookup-markup-writer node e) (let ((writers (slot-ref e 'writers)) (delegate (slot-ref e 'delegate))) (let Loop ((w* writers)) (cond ((pair? w*) (let ((pred (slot-ref (car w*) 'pred))) (if (pred node e) (car w*) (loop (cdr w*))))) ((engine? delegate) (lookup-markup-writer node delegate)) (else #f))))) ;;;; ====================================================================== ;;;; ;;;; MAKE-WRITER-PREDICATE ;;;; ;;;; ====================================================================== (define (make-writer-predicate markup predicate class) (let* ((t1 (if (symbol? markup) (lambda (n e) (is-markup? n markup)) (lambda (n e) #t))) (t2 (if class (lambda (n e) (and (t1 n e) (equal? (markup-class n) class))) t1))) (if predicate (cond ((not (procedure? predicate)) (skribe-error 'markup-writer "Illegal predicate (procedure expected)" predicate)) ((not (eq? (%procedure-arity predicate) 2)) (skribe-error 'markup-writer "Illegal predicate arity (2 arguments expected)" predicate)) (else (lambda (n e) (and (t2 n e) (predicate n e))))) t2))) ;;;; ====================================================================== ;;;; ;;;; MARKUP-WRITER ;;;; ;;;; ====================================================================== (define* (markup-writer markup #:optional engine #:key (predicate #f) (class #f) (options '()) (validate #f) (before #f) (action 'unspecified) (after #f)) (let ((e (or engine (default-engine)))) (cond ((and (not (symbol? markup)) (not (eq? markup #t))) (skribe-error 'markup-writer "Illegal markup" markup)) ((not (engine? e)) (skribe-error 'markup-writer "Illegal engine" e)) ((and (not predicate) (not class) (null? options) (not before) (eq? action 'unspecified) (not after)) (skribe-error 'markup-writer "Illegal writer" markup)) (else (let ((m (make-writer-predicate markup predicate class)) (ac (if (eq? action 'unspecified) (lambda (n e) (output (markup-body n) e)) action))) (engine-add-writer! e markup m predicate options before ac after class validate)))))) ;;;; ====================================================================== ;;;; ;;;; MARKUP-WRITER-GET ;;;; ;;;; ====================================================================== (define* (markup-writer-get markup :optional engine :key (class #f) (pred #f)) (let ((e (or engine (default-engine)))) (cond ((not (symbol? markup)) (skribe-error 'markup-writer-get "Illegal symbol" markup)) ((not (engine? e)) (skribe-error 'markup-writer-get "Illegal engine" e)) (else (let liip ((e e)) (let loop ((w* (slot-ref e 'writers))) (cond ((pair? w*) (if (and (eq? (writer-ident (car w*)) markup) (equal? (writer-class (car w*)) class) (or (unspecified? pred) (eq? (slot-ref (car w*) 'upred) pred))) (car w*) (loop (cdr w*)))) ((engine? (slot-ref e 'delegate)) (liip (slot-ref e 'delegate))) (else #f)))))))) ;;;; ====================================================================== ;;;; ;;;; MARKUP-WRITER-GET* ;;;; ;;;; ====================================================================== ;; Finds all writers that matches MARKUP with optional CLASS attribute. (define* (markup-writer-get* markup #:optional engine #:key (class #f)) (let ((e (or engine (default-engine)))) (cond ((not (symbol? markup)) (skribe-error 'markup-writer "Illegal symbol" markup)) ((not (engine? e)) (skribe-error 'markup-writer "Illegal engine" e)) (else (let liip ((e e) (res '())) (let loop ((w* (slot-ref e 'writers)) (res res)) (cond ((pair? w*) (if (and (eq? (slot-ref (car w*) 'ident) markup) (equal? (slot-ref (car w*) 'class) class)) (loop (cdr w*) (cons (car w*) res)) (loop (cdr w*) res))) ((engine? (slot-ref e 'delegate)) (liip (slot-ref e 'delegate) res)) (else (reverse! res))))))))) ;;; ====================================================================== ;;;; ;;;; COPY-MARKUP-WRITER ;;;; ;;;; ====================================================================== (define* (copy-markup-writer markup old-engine :optional new-engine :key (predicate 'unspecified) (class 'unspecified) (options 'unspecified) (validate 'unspecified) (before 'unspecified) (action 'unspecified) (after 'unspecified)) (let ((old (markup-writer-get markup old-engine)) (new-engine (or new-engine old-engine))) (markup-writer markup new-engine :pred (if (unspecified? predicate) (slot-ref old 'pred) predicate) :class (if (unspecified? class) (slot-ref old 'class) class) :options (if (unspecified? options) (slot-ref old 'options) options) :validate (if (unspecified? validate) (slot-ref old 'validate) validate) :before (if (unspecified? before) (slot-ref old 'before) before) :action (if (unspecified? action) (slot-ref old 'action) action) :after (if (unspecified? after) (slot-ref old 'after) after))))