docbook.scm 8.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241
  1. ;;;; (texinfo docbook) -- translating sdocbook into stexinfo
  2. ;;;;
  3. ;;;; Copyright (C) 2009, 2010, 2012 Free Software Foundation, Inc.
  4. ;;;; Copyright (C) 2007, 2009 Andy Wingo <wingo at pobox dot com>
  5. ;;;;
  6. ;;;; This library is free software; you can redistribute it and/or
  7. ;;;; modify it under the terms of the GNU Lesser General Public
  8. ;;;; License as published by the Free Software Foundation; either
  9. ;;;; version 3 of the License, or (at your option) any later version.
  10. ;;;;
  11. ;;;; This library is distributed in the hope that it will be useful,
  12. ;;;; but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. ;;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  14. ;;;; Lesser General Public License for more details.
  15. ;;;;
  16. ;;;; You should have received a copy of the GNU Lesser General Public
  17. ;;;; License along with this library; if not, write to the Free Software
  18. ;;;; Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  19. ;;;;
  20. ;;; Commentary:
  21. ;;
  22. ;; @c
  23. ;; This module exports procedures for transforming a limited subset of
  24. ;; the SXML representation of docbook into stexi. It is not complete by
  25. ;; any means. The intention is to gather a number of routines and
  26. ;; stylesheets so that external modules can parse specific subsets of
  27. ;; docbook, for example that set generated by certain tools.
  28. ;;
  29. ;;; Code:
  30. (define-module (texinfo docbook)
  31. #:use-module (sxml fold)
  32. #:use-module ((srfi srfi-1) #:select (fold))
  33. #:export (*sdocbook->stexi-rules*
  34. *sdocbook-block-commands*
  35. sdocbook-flatten
  36. filter-empty-elements
  37. replace-titles))
  38. (define (identity . args)
  39. args)
  40. (define (identity-deattr tag . body)
  41. `(,tag ,@(if (and (pair? body) (pair? (car body))
  42. (eq? (caar body) '@))
  43. (cdr body)
  44. body)))
  45. (define (detag-one tag body)
  46. body)
  47. (define tag-replacements
  48. '((parameter var)
  49. (replaceable var)
  50. (type code)
  51. (function code)
  52. (literal samp)
  53. (emphasis emph)
  54. (simpara para)
  55. (programlisting example)
  56. (firstterm dfn)
  57. (filename file)
  58. (quote cite)
  59. (application cite)
  60. (symbol code)
  61. (note cartouche)
  62. (envar env)))
  63. (define ignore-list '())
  64. (define (stringify exp)
  65. (with-output-to-string (lambda () (write exp))))
  66. (define *sdocbook->stexi-rules*
  67. #;
  68. "A stylesheet for use with SSAX's @code{pre-post-order}, which defines
  69. a number of generic rules for transforming docbook into texinfo."
  70. `((@ *preorder* . ,identity)
  71. (% *preorder* . ,identity)
  72. (para . ,identity-deattr)
  73. (orderedlist ((listitem
  74. . ,(lambda (tag . body)
  75. `(item ,@body))))
  76. . ,(lambda (tag . body)
  77. `(enumerate ,@body)))
  78. (itemizedlist ((listitem
  79. . ,(lambda (tag . body)
  80. `(item ,@body))))
  81. . ,(lambda (tag . body)
  82. `(itemize ,@body)))
  83. (acronym . ,(lambda (tag . body)
  84. `(acronym (% (acronym . ,body)))))
  85. (term . ,detag-one)
  86. (informalexample . ,detag-one)
  87. (section . ,identity)
  88. (subsection . ,identity)
  89. (subsubsection . ,identity)
  90. (ulink . ,(lambda (tag attrs . body)
  91. (cond
  92. ((assq 'url (cdr attrs))
  93. => (lambda (url)
  94. `(uref (% ,url (title ,@body)))))
  95. (else
  96. (car body)))))
  97. (*text* . ,detag-one)
  98. (*default* . ,(lambda (tag . body)
  99. (let ((subst (assq tag tag-replacements)))
  100. (cond
  101. (subst
  102. (if (and (pair? body) (pair? (car body)) (eq? (caar body) '@))
  103. (begin
  104. (warn "Ignoring" tag "attributes" (car body))
  105. (append (cdr subst) (cdr body)))
  106. (append (cdr subst) body)))
  107. ((memq tag ignore-list) #f)
  108. (else
  109. (warn "Don't know how to convert" tag "to stexi")
  110. `(c (% (all ,(stringify (cons tag body))))))))))))
  111. ;; (variablelist
  112. ;; ((varlistentry
  113. ;; . ,(lambda (tag term . body)
  114. ;; `(entry (% (heading ,@(cdr term))) ,@body)))
  115. ;; (listitem
  116. ;; . ,(lambda (tag simpara)
  117. ;; simpara)))
  118. ;; . ,(lambda (tag attrs . body)
  119. ;; `(table (% (formatter (var))) ,@body)))
  120. (define *sdocbook-block-commands*
  121. #;
  122. "The set of sdocbook element tags that should not be nested inside
  123. each other. @xref{texinfo docbook sdocbook-flatten,,sdocbook-flatten},
  124. for more information."
  125. '(para programlisting informalexample indexterm variablelist
  126. orderedlist refsect1 refsect2 refsect3 refsect4 title example
  127. note itemizedlist))
  128. (define (inline-command? command)
  129. (not (memq command *sdocbook-block-commands*)))
  130. (define (sdocbook-flatten sdocbook)
  131. "\"Flatten\" a fragment of sdocbook so that block elements do not nest
  132. inside each other.
  133. Docbook is a nested format, where e.g. a @code{refsect2} normally
  134. appears inside a @code{refsect1}. Logical divisions in the document are
  135. represented via the tree topology; a @code{refsect2} element
  136. @emph{contains} all of the elements in its section.
  137. On the contrary, texinfo is a flat format, in which sections are marked
  138. off by standalone section headers like @code{@@chapter}, and block
  139. elements do not nest inside each other.
  140. This function takes a nested sdocbook fragment @var{sdocbook} and
  141. flattens all of the sections, such that e.g.
  142. @example
  143. (refsect1 (refsect2 (para \"Hello\")))
  144. @end example
  145. becomes
  146. @example
  147. ((refsect1) (refsect2) (para \"Hello\"))
  148. @end example
  149. Oftentimes (always?) sectioning elements have @code{<title>} as their
  150. first element child; users interested in processing the @code{refsect*}
  151. elements into proper sectioning elements like @code{chapter} might be
  152. interested in @code{replace-titles} and @code{filter-empty-elements}.
  153. @xref{texinfo docbook replace-titles,,replace-titles}, and @ref{texinfo
  154. docbook filter-empty-elements,,filter-empty-elements}.
  155. Returns a nodeset, as described in @ref{sxml xpath}. That is to say,
  156. this function returns an untagged list of stexi elements."
  157. (define (fhere str accum block cont)
  158. (values (cons str accum)
  159. block
  160. cont))
  161. (define (fdown node accum block cont)
  162. (let ((command (car node))
  163. (attrs (and (pair? (cdr node)) (pair? (cadr node))
  164. (eq? (caadr node) '%)
  165. (cadr node))))
  166. (values (if attrs (cddr node) (cdr node))
  167. '()
  168. '()
  169. (lambda (accum block)
  170. (values
  171. `(,command ,@(if attrs (list attrs) '())
  172. ,@(reverse accum))
  173. block)))))
  174. (define (fup node paccum pblock pcont kaccum kblock kcont)
  175. (call-with-values (lambda () (kcont kaccum kblock))
  176. (lambda (ret block)
  177. (if (inline-command? (car ret))
  178. (values (cons ret paccum) (append kblock pblock) pcont)
  179. (values paccum (append kblock (cons ret pblock)) pcont)))))
  180. (call-with-values
  181. (lambda () (foldts*-values fdown fup fhere sdocbook '() '() #f))
  182. (lambda (accum block cont)
  183. (reverse block))))
  184. (define (filter-empty-elements sdocbook)
  185. "Filters out empty elements in an sdocbook nodeset. Mostly useful
  186. after running @code{sdocbook-flatten}."
  187. (reverse
  188. (fold
  189. (lambda (x rest)
  190. (if (and (pair? x) (null? (cdr x)))
  191. rest
  192. (cons x rest)))
  193. '()
  194. sdocbook)))
  195. (define (replace-titles sdocbook-fragment)
  196. "Iterate over the sdocbook nodeset @var{sdocbook-fragment},
  197. transforming contiguous @code{refsect} and @code{title} elements into
  198. the appropriate texinfo sectioning command. Most useful after having run
  199. @code{sdocbook-flatten}.
  200. For example:
  201. @example
  202. (replace-titles '((refsect1) (title \"Foo\") (para \"Bar.\")))
  203. @result{} '((chapter \"Foo\") (para \"Bar.\"))
  204. @end example
  205. "
  206. (define sections '((refsect1 . chapter)
  207. (refsect2 . section)
  208. (refsect3 . subsection)
  209. (refsect4 . subsubsection)))
  210. (let lp ((in sdocbook-fragment) (out '()))
  211. (cond
  212. ((null? in)
  213. (reverse out))
  214. ((and (pair? (car in)) (assq (caar in) sections))
  215. ;; pull out the title
  216. => (lambda (pair)
  217. (lp (cddr in) (cons `(,(cdr pair) ,@(cdadr in)) out))))
  218. (else
  219. (lp (cdr in) (cons (car in) out))))))