1 ;;; -*- lisp; show-trailing-whitespace: t; indent-tabs: nil -*-
3 ;;;; Part of this software was originally written as docstrings.lisp in
4 ;;;; SBCL, but is now part of the texinfo-docstrings project. The file
5 ;;;; docstrings.lisp was written by Rudi Schlatte <rudi@constantly.at>,
6 ;;;; mangled by Nikodemus Siivola, turned into a stand-alone project by
7 ;;;; Luis Oliveira. SBCL is in the public domain and is provided with
8 ;;;; absolutely no warranty.
10 ;;;; texinfo-docstrings is:
12 ;;;; Copyright (c) 2008 David Lichteblau:
14 ;;;; Permission is hereby granted, free of charge, to any person
15 ;;;; obtaining a copy of this software and associated documentation
16 ;;;; files (the "Software"), to deal in the Software without
17 ;;;; restriction, including without limitation the rights to use, copy,
18 ;;;; modify, merge, publish, distribute, sublicense, and/or sell copies
19 ;;;; of the Software, and to permit persons to whom the Software is
20 ;;;; furnished to do so, subject to the following conditions:
22 ;;;; The above copyright notice and this permission notice shall be
23 ;;;; included in all copies or substantial portions of the Software.
25 ;;;; THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
26 ;;;; EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
27 ;;;; MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
28 ;;;; NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
29 ;;;; HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
30 ;;;; WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
31 ;;;; OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
32 ;;;; DEALINGS IN THE SOFTWARE.
34 (in-package #:texinfo-docstrings
)
36 (define-document-format :html
"html")
40 (defvar *html-indent
* 0)
42 (defmacro with-html
((stream tag attributes
) &body forms
)
43 (sb-int:once-only
((stream stream
) (tag tag
))
45 (format ,stream
"~vT<~(~A~)~{ ~(~A~)=~S~}>~%" *html-indent
* ,tag
,attributes
)
46 (let ((*html-indent
* (+ 2 *html-indent
*)))
48 (format ,stream
"~vT</~(~A~)>~%" *html-indent
* ,tag
))))
50 (defmethod format-document-start (stream package
(format (eql :html
)))
51 (write-line "<html>" stream
)
52 (with-html (stream :head nil
)
53 (format-html stream
:link
'(:rel
"stylesheet" :type
"text/css" :href
"style.css") nil
)
54 (format-html stream
:title nil
(package-name package
)))
55 (write-line "<body>" stream
)
56 (format-html stream
:h1
'(:class
"package-name") (package-name package
)))
58 (defmethod format-document-end (stream package
(format (eql :html
)))
59 (write-line "</body></html>" stream
))
61 (defun html-escape (string)
62 (with-output-to-string (s)
63 (loop for char across string
65 (#\
< (write-string "<" s
))
66 (#\
> (write-string ">" s
))
67 (#\
& (write-string "&" s
))
68 (t (write-char char s
))))))
70 (defun format-html (stream tag attributes string
)
71 (format stream
"~vT<~(~A~)~{ ~(~A~)=~S~}~:[>~;/>~]~@[~A~]~@[</~(~A~)>~]~%"
72 *html-indent
* tag attributes
(not string
) string
(when string tag
)))
74 (defun html-text (string)
75 (with-output-to-string (result)
77 (dolist (symbol/index
(parse-docstrings.sbcl
::locate-symbols string
))
78 (write-string (html-escape (subseq string last
(first symbol
/index
))) result
)
79 (let ((symbol-name (apply #'subseq string symbol
/index
)))
80 (format result
"<var>~A</var>" (html-escape symbol-name
)))
81 (setf last
(second symbol
/index
)))
82 (write-string (html-escape (subseq string last
)) result
))))
84 (defmethod format-doc (stream (doc parse-docstrings
:documentation
*) format
)
85 (let ((name (html-escape (princ-to-string (parse-docstrings:get-name doc
)))))
86 (with-html (stream :div
'(:class
"item"))
87 (with-html (stream :div
'(:class
"type"))
88 (format-html stream
:a
(list :name name
)
89 (html-escape (format nil
"[~A]" (string-downcase (princ-to-string (parse-docstrings:get-kind doc
)))))))
90 (with-html (stream :div
'(:class
"signature"))
91 (format-html stream
:code
'(:class
"name") name
)
92 (let ((ll (parse-docstrings:lambda-list doc
)))
94 (with-html (stream :span
'(:class
"args"))
96 (labels ((markup-ll (elt)
97 (cond ((member elt lambda-list-keywords
)
98 (format-html stream
:code
'(:class
"llkw") (html-escape (princ-to-string elt
))))
100 (write-string "(" stream
)
101 (mapcar #'markup-ll elt
)
102 (write-string ")" stream
))
104 (format-html stream
:var
() (html-escape (string-downcase (princ-to-string elt
))))))))
105 (markup-ll elt
)))))))
106 (with-html (stream :div
'(:class
"item-body"))
107 (let ((content (parse-docstrings:get-content doc
)))
108 (format-doc stream content format
)))))
111 (defmethod format-doc (stream
112 (lisp parse-docstrings
:lisp-block
)
113 (format (eql :html
)))
117 (html-escape (parse-docstrings:get-string lisp
))))
119 (defmethod format-doc (stream
120 (list parse-docstrings
:itemization
)
121 (format (eql :html
)))
122 (with-html (stream :ul
'(:class
"itemization"))
123 (dolist (item (parse-docstrings:get-items list
))
124 (with-html (stream :li
'(:class
"item"))
125 (format-html-item stream item
)))))
127 (defgeneric format-html-item
(stream item
))
129 (defmethod format-html-item (stream item
)
130 (format-doc stream item
:html
))
132 (defmethod format-html-item (stream (item parse-docstrings
:section
))
133 (dolist (b (parse-docstrings:get-blocks item
))
134 (format-doc stream b
:html
)))
136 (defmethod format-doc (stream
137 (section parse-docstrings
:section
)
138 (format (eql :html
)))
139 (dolist (b (parse-docstrings:get-blocks section
))
140 (format-doc stream b format
)))
142 (defmethod format-doc (stream
143 (paragraph parse-docstrings
:paragraph
)
144 (format (eql :html
)))
148 (html-text (parse-docstrings:get-string paragraph
))))
150 (defmethod format-doc (stream
151 (tabulation parse-docstrings
:tabulation
)
152 (format (eql :html
)))
153 (with-html (stream :dl
'(:class
"tabulation"))
154 (dolist (i (parse-docstrings:get-items tabulation
))
155 (format-doc stream i format
))))
157 (defmethod format-doc (stream
158 (item parse-docstrings
:tabulation-item
)
159 (format (eql :html
)))
160 (format-html stream
:dt
161 '(:class
"tabulation-title")
162 (html-escape (parse-docstrings:get-title item
)))
163 (with-html (stream :dd
'(:class
"tabulation-body"))
164 (format-html-item stream
(parse-docstrings:get-body item
))))