;;; edocs.el --- Extract documentation from file(s)
;; Copyright (C) 2013 Tom Willemse
;; Author: Tom Willemse " title " — " sub "
"))
(defmacro edocs--with-tag (tag attrs &rest contents)
"Put insertion of TAG (possibly with ATTRS) around CONTENTS."
(declare (indent 2))
`(progn
(insert "<" ,tag)
(insert (mapconcat
(lambda (itm) (format " %s=%S" (car itm) (cdr itm))) ,attrs ""))
(insert ">")
,@contents
(insert "" ,tag ">")))
(defun edocs--format-text (txt)
"Perform formatting operations on TXT."
(replace-regexp-in-string "\n\n" "
" txt)) (defun edocs--format-commentary (cmt) "Perform special commentary formatting operations on CMT." (edocs--format-text (replace-regexp-in-string ";; " "" (replace-regexp-in-string ";;; Commentary:\n+" "" cmt)))) (defun edocs--format-doc (doc) "Perform formatting operations on DOC or on DOC's `cdr'." (edocs--format-text (if (consp doc) (cdr doc) doc))) (defun edocs--package-desc-p (package-info) "Check to see if PACKAGE-INFO is a package-desc struct." (and (fboundp 'package-desc-p) (package-desc-p package-info))) (defun edocs--module-name (package-info) "Extract the module name from PACKAGE-INFO. The location of this information seems to have changed since Emacs 24.3. If the function `package-desc-p' is bound and returns t for PACKAGE-INFO, it is the new style and we should get it accordingly. Otherwise we assume we're dealing with an old-style package description and return the first element." (if (edocs--package-desc-p package-info) (symbol-name (package-desc-name package-info)) (aref package-info 0))) (defun edocs--module-summary (package-info) "Extract a short description from PACKAGE-INFO. See the docstring for `edocs--module-name' for more information." (if (edocs--package-desc-p package-info) (package-desc-summary package-info) (aref package-info 2))) (defun edocs--format-symbol (symbol) "Format the information in SYMBOL." (let ((docs (edocs--get-docs (car symbol) (cdr symbol)))) (mapc (lambda (doc) (edocs--with-tag "div" nil (insert "– " (edocs--get-type-display (car symbol)) ": " (cdr symbol) " " (if (consp doc) (car doc) "")) (edocs--with-tag "div" '(("class" . "docstring")) (edocs--with-tag "p" nil (insert (or (edocs--format-doc doc) "Not documented.")))))) (if (or (not (listp docs)) (not (listp (cdr docs)))) (list docs) docs)))) (defun edocs-generate () "Generate nice-looking documentation for a module or file." (interactive) (let ((buffer (get-buffer-create "*edocs*")) (binfo (package-buffer-info)) (commentary (lm-commentary)) (symbols (edocs--list-symbols))) (with-current-buffer buffer (unless edocs-generate-only-body (edocs--insert-header)) (edocs--with-tag "div" '(("class" . "container")) (edocs--insert-title (edocs--module-name binfo) (edocs--module-summary binfo)) (edocs--with-tag "p" nil (insert (edocs--format-commentary commentary))) (mapc #'edocs--format-symbol symbols)) (unless edocs-generate-only-body (edocs--insert-footer))) (switch-to-buffer buffer))) (defun edocs--generate-batch-1 (file) "Generate docs for FILE." (with-current-buffer (find-file file) (eval-buffer) (edocs-generate) (write-file (concat (file-name-sans-extension file) ".html")))) (defun edocs-generate-batch () "Generate module docs using batch operations." (mapc #'edocs--generate-batch-1 command-line-args-left)) (provide 'edocs) ;;; edocs.el ends here