s c h e m e w i k i . o r g

/ Sandbox.SchemeTOC

This Web


WebHome 
WebChanges 
WebTopicList 
WebStatistics 

All Webs


Chicken
Cookbook
Erlang
Know
Main
Plugins
Sandbox
Scm
TWiki  

Schematics


Schematics Home
TWiki Shorthand

Offsite Links


Schemers.org
Lambda the Ultimate
twiki.org

SchemeTOC

#|
   Convert s-exp definition of table of contents into format for presentation, e.g. twiki.

   See example in test case at end of program.

   Pseudo-grammar:

      title : string
      topic : symbol

      chapter-expr  : ( CHAPTER title section-exprs )

      section-exprs : section-expr | section section-exprs

      section-expr  : ( SECTION topic ) | ( SECTION title recipe-exprs )

      recipe-exprs  : recipe | recipe recipe-exprs

      recipe        : ( RECIPE topic )
|#

(define expect
  (lambda (sym expr pred)
    (if (not (eq? sym (car expr))) 
        (error (format "expecting '~a', found '~a' in ~a" sym (car expr) expr)))
    (if (< (length expr) 2)
        (error (format "~a missing a title or topic identifier in ~a" sym expr)))
    (let ((title-or-topic (cadr expr)))
      (if (pred title-or-topic)
          title-or-topic
          (error (format "~a title or topic identifier ~a wrong type in ~a" sym title-or-topic expr))))))

(define (symbol-or-string? s) (or (symbol? s) (string? s)))

; same define-interface as in ScmToXexpr
(define-interface ^toc-converter (chapter-def section-def section-ref recipe-ref))

; topic-symbol -> twiki-string
(define toc-topic
  (lambda (topic-sym)
    (format "%~a{\"~a\"}%\n" "TOC" (symbol->string topic-sym))))

(define include-topic
  (lambda (topic-sym)
    (format "%~a{\"~a\"}%\n" "INCLUDE" (symbol->string topic-sym))))

(define twiki-heading
  (lambda (n text)
    (string-append "---" (make-string n #\+) " " text "\n")))

; TODO
(define toc-page-converter
  (^toc-converter 
   (lambda (chapter-title sections)
     ...) ;todo
   (lambda (section-title recipes)
     ...) ;todo
   (lambda (section-topic)
     ...) ;todo
   (lambda (recipe-topic)
     ...))) ;todo
     
(define index-page-converter
  (^toc-converter 
   ; chapter-def
   (lambda (chapter-title sections)
     (cons (twiki-heading 1 chapter-title) sections))
   ; section-def
   (lambda (section-title recipes)
     (cons (twiki-heading 2 section-title) recipes))
   include-topic ; section-ref
   toc-topic))   ; recipe-ref

; returns a function which accepts an interface implementation
; and applies it to the specified function f.
(define with-interface
  (lambda (f)
    (lambda (impl)
      (impl f))))

; todo: ->twiki names overly specific; output depends on interface
(define make-toc-converter
  (with-interface ; toc-converter
   (lambda (chapter-def section-def section-ref recipe-ref)
     
     (define recipe->twiki
       (lambda (recipe)
         (let ((topic (expect 'recipe recipe symbol?)))
           (recipe-ref topic))))
     
     (define section->twiki
       (lambda (section)
         (let ((title-or-topic (expect 'section section symbol-or-string?)))
           (cond
             ((symbol? title-or-topic) (section-ref title-or-topic))
             ((string? title-or-topic) (section-def title-or-topic 
                                                    (map recipe->twiki (cddr section))))))))
     (lambda (chapter)
       (let ((title (expect 'chapter chapter string?)))
         (chapter-def title (map section->twiki (cddr chapter))))))))

(define cvt-idx (make-toc-converter index-page-converter))

; test
(let ((twiki-toc 
       (cvt-idx
        #cs'(chapter "String Recipes"
                     (section StringRecipesIntro)
                     (section "Recipes"
                              (recipe StringBasics)
                              (recipe IsAString))
                     (section "Other recipes of interest"
                              (recipe GreasyHashBrowns))
                     (section StringRecipeReferences)))))
  ; todo: flatten or otherwise structure list better?
  (for-each (lambda (item)
              (cond
                ((string? item) (display item))
                ((pair? item)   (for-each display item))
                (else (error (format "invalid entry in toc: ~a" item)))))
            twiki-toc))

#|
Test currently produces this:
   ---+ String Recipes
   %INCLUDE{"StringRecipesIntro"}%
   ---++ Recipes
   %TOC{"StringBasics"}%
   %TOC{"IsAString"}%
   ---++ Other recipes of interest
   %TOC{"GreasyHashBrowns"}%
   %INCLUDE{"StringRecipeReferences"}%
(will replace INCLUDEs with TOC for top-level contents page) |#

-- AntonVanStraaten - 14 May 2004

 
 
© 2004 by the contributing authors. / You are Main.guest