├── .gitignore ├── .hgignore ├── tests.el ├── README.creole └── wikidoc.el /.gitignore: -------------------------------------------------------------------------------- 1 | /wikidoc.el~ 2 | -------------------------------------------------------------------------------- /.hgignore: -------------------------------------------------------------------------------- 1 | syntax: regexp 2 | .*~$ 3 | \#.* 4 | -------------------------------------------------------------------------------- /tests.el: -------------------------------------------------------------------------------- 1 | ;;; tests for wikidoc -*- lexical-binding: t -*- 2 | 3 | (require 'ert) 4 | (require 'wikidoc) 5 | 6 | (ert-deftest wikidoc-test-convert-line () 7 | "Can we convert lines with lisp refs and arguments?" 8 | (let ((l '("This is a line of documentation with `lisp-references'" . 9 | "This is a line of documentation with [[lisp-references]]"))) 10 | (should 11 | (equal 12 | (cdr l) 13 | (wikidoc--convert-line (car l))))) 14 | (let ((l 15 | '("A line of doc with 2 args of car and cdr: CAR and CDR" . 16 | "A line of doc with 2 args of car and cdr: //car// and //cdr//"))) 17 | (should 18 | (equal 19 | (cdr l) 20 | (wikidoc--convert-line (car l) '(car cdr)))))) 21 | 22 | 23 | ;;; tests.el ends here 24 | -------------------------------------------------------------------------------- /README.creole: -------------------------------------------------------------------------------- 1 | This is an Emacs Lisp program to generate wiki documentation from 2 | Emacs Lisp functions. 3 | 4 | Right now it only does wikicreole. 5 | 6 | 7 | == API == 8 | 9 | This is wikidoc's API, as generated by wikidoc itself. 10 | 11 | === wikidoc-grab-list prefix &optional no-private === 12 | 13 | Grab a list or functions matching //prefix// possibly with //no-private// 14 | 15 | 16 | === wikidoc-insert elisp-prefix buffer === 17 | 18 | Make creole doc for functions beginning with //elisp-prefix// in //buffer//. 19 | 20 | When called interactively with a PREFIX argument this function 21 | will use the current buffer for //buffer//. 22 | 23 | Otherwise the //buffer// will be created named like: 24 | 25 | {{{ 26 | *wikidoc-//elisp-prefix//* 27 | }}} 28 | 29 | If Transient Mark mode is set in the specified buffer the active 30 | region is killed before the new wiki text is inserted. 31 | 32 | 33 | -------------------------------------------------------------------------------- /wikidoc.el: -------------------------------------------------------------------------------- 1 | ;;; wikidoc.el --- use elisp doc strings to make other documentation 2 | 3 | ;; Copyright (C) 2010, 2011, 2012 Nic Ferrier 4 | 5 | ;; Author: Nic Ferrier 6 | ;; Maintainer: Nic Ferrier 7 | ;; Created: 5th October 2010 8 | ;; Package-requires: ((s.el "1.9.0")) 9 | ;; Version: 0.9 10 | ;; Keywords: lisp 11 | 12 | ;; This file is NOT part of GNU Emacs. 13 | 14 | ;; This program is free software; you can redistribute it and/or modify 15 | ;; it under the terms of the GNU General Public License as published by 16 | ;; the Free Software Foundation, either version 3 of the License, or 17 | ;; (at your option) any later version. 18 | 19 | ;; This program is distributed in the hope that it will be useful, 20 | ;; but WITHOUT ANY WARRANTY; without even the implied warranty of 21 | ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 22 | ;; GNU General Public License for more details. 23 | 24 | ;; You should have received a copy of the GNU General Public License 25 | ;; along with this program. If not, see . 26 | 27 | ;;; Commentary: 28 | ;; 29 | ;; This is for making documentation from Elisp doc strings. It is 30 | ;; intended as an alternative to using info. 31 | ;; 32 | ;; Right now, the only output format is creole-wiki. But that could 33 | ;; change. 34 | 35 | ;;; Source code 36 | ;; 37 | ;; https://github.com/nicferrier/elwikidoc 38 | 39 | ;;; Style note 40 | ;; 41 | ;; This codes uses the emacs style of: 42 | ;; 43 | ;; wikidoc---private-function 44 | ;; 45 | ;; for private functions. 46 | ;; 47 | ;;; Examples 48 | ;; 49 | ;; This is the main paragraph converter: 50 | ;; 51 | ;; (wikidoc--convert "this is a function. 52 | ;; this is an example 53 | ;; this should 'not' be changed to a link 54 | ;; This is the main text. It can include references to other 'functions'. 55 | ;; When there are 'two' references 'on the same line' it should 56 | ;; still work.") 57 | 58 | ;;; Code: 59 | 60 | (require 's) 61 | (eval-when-compile (require 'cl)) 62 | 63 | ;;;###autoload 64 | (defun wikidoc-grab-list (prefix &optional no-private) 65 | "Grab a list or functions matching PREFIX possibly with NO-PRIVATE" 66 | (let ((prefix-sym (symbol-name prefix)) 67 | (res '())) 68 | (mapatoms 69 | (lambda (atom) 70 | (let ((sn (symbol-name atom))) 71 | (and (fboundp atom) 72 | (if (string-prefix-p prefix-sym sn) 73 | (if no-private 74 | (if (not (string-match "[^-]+--.*" sn)) 75 | (setq res (cons atom res))) 76 | (setq res (cons atom res))))))) 77 | obarray) 78 | res)) 79 | 80 | (defconst wikidoc--convert-line-creole-name-reference "[[%s]]") 81 | (defconst wikidoc--convert-line-creole-arg-reference "//%s//") 82 | 83 | (defconst wikidoc--convert-line-name-reference 84 | wikidoc--convert-line-creole-name-reference) 85 | 86 | (defconst wikidoc--convert-line-arg-reference 87 | wikidoc--convert-line-creole-arg-reference) 88 | 89 | (defun wikidoc--convert-line (line &optional arguments-to-mangle) 90 | "Converts a single LINE of function documentation. 91 | 92 | This deals with things like quoted LISP forms which can be turned 93 | into links. 94 | 95 | ARGUMENTS-TO-MANGLE can be a list of arguments which are to be 96 | detected and replaced like: 97 | 98 | ARGUMENT -> //argument// 99 | 100 | The list should be of symbols, not strings." 101 | (let* ((case-fold-search nil) 102 | (arglstre 103 | (when arguments-to-mangle 104 | (regexp-opt 105 | (loop for arg in 106 | (cond 107 | ;; CL style arguments are a list of lists 108 | ((and (listp arguments-to-mangle) 109 | (listp (car arguments-to-mangle))) 110 | (car arguments-to-mangle)) 111 | ;; Normal function args are just a list 112 | (t 113 | arguments-to-mangle)) 114 | collect 115 | (cond 116 | ((listp arg) 117 | (upcase (symbol-name (car arg)))) 118 | ((symbolp arg) 119 | (upcase (symbol-name arg))))))))) 120 | (save-match-data 121 | (while (string-match ".*\\(`[^']+'\\).*" line) 122 | (setq line 123 | (replace-match 124 | (format 125 | wikidoc--convert-line-name-reference 126 | (let ((name (match-string 1 line))) 127 | (save-match-data 128 | (string-match "`\\([^']+\\)'" name) 129 | (match-string 1 name)))) 130 | nil nil line 1))) 131 | (if arglstre 132 | (replace-regexp-in-string 133 | arglstre 134 | (lambda (matched) 135 | (format 136 | wikidoc--convert-line-arg-reference 137 | (downcase matched))) 138 | line t nil) 139 | line)))) 140 | 141 | (defun wikidoc--convert (str &optional arguments-to-mangle) 142 | "Convert function documentation type doc STR to creole. 143 | 144 | ARGUMENTS-TO-MANGLE can be a list of arguments which are to be 145 | detected and replaced like: 146 | 147 | ARGUMENT -> //argument// 148 | 149 | The list should be of symbols, not strings." 150 | (let (in-pre) 151 | (concat 152 | (mapconcat 153 | (lambda (line) 154 | (cond 155 | ((string-match "^ " line) 156 | (if in-pre 157 | line 158 | (progn 159 | (setq in-pre 't) 160 | (concat 161 | "{{{\n" 162 | (wikidoc--convert-line line arguments-to-mangle))))) 163 | ((and in-pre (not (string-match "^ " line))) 164 | (setq in-pre nil) 165 | (concat "}}}\n" (wikidoc--convert-line line arguments-to-mangle))) 166 | ('t 167 | (wikidoc--convert-line line arguments-to-mangle)))) 168 | (split-string str "\n") 169 | "\n") 170 | ;; end any pre that we started 171 | (if in-pre "\n}}}\n")))) 172 | 173 | (defconst wikidoc--convert-fn-creole-template 174 | "=== ${name} ${args} ===\n\n${description}\n\n\n") 175 | 176 | (defconst wikidoc--convert-fn-template wikidoc--convert-fn-creole-template 177 | "By default this is `wikidoc--convert-fn-creole-template'. 178 | 179 | The `s-format' keys used are: 180 | 181 | NAME - the name of the function 182 | ARGS - the arg list of the function 183 | DESCRIPTION - the function doc body 184 | 185 | Each can be put in the template in whatever way you like") 186 | 187 | (defun wikidoc--convert-args (args) 188 | (mapconcat 189 | (lambda (arg) 190 | (cond 191 | ((or 192 | (equal '&optional arg) 193 | (equal '&key arg) 194 | (equal '&rest arg)) 195 | (format "%s" arg)) 196 | ((listp arg) 197 | (add-to-list 'arglist (car arg)) 198 | (format "%s (%S)" 199 | (car arg) 200 | (cadr arg))) 201 | ('t 202 | (add-to-list 'arglist arg) 203 | (format "%s" arg)))) 204 | (if (and (listp args) 205 | (listp (car args))) 206 | (car args) 207 | args) 208 | " ")) 209 | 210 | (defun wikidoc--convert-fn (fn) 211 | "Converter function for documentation of FN to WikiCreole. 212 | 213 | The documentation is written, in WikiCreole form, into the 214 | current buffer." 215 | (let* (arglist 216 | (fundoc-list 217 | (or 218 | (help-split-fundoc 219 | (documentation fn) nil) 220 | (cons "()" (documentation fn)))) 221 | (args 222 | (or 223 | (cdar 224 | (read-from-string 225 | (downcase 226 | (car fundoc-list)))) 227 | (help-function-arglist fn t))) 228 | (docbody (cdr fundoc-list)) 229 | (fmted 230 | (s-format 231 | wikidoc--convert-fn-template 232 | 'aget 233 | `(("name" . ,(symbol-name fn)) ;; the func name 234 | ("args" . ,(wikidoc--convert-args args)) ;; the args 235 | ("description" . 236 | ,(when docbody 237 | (wikidoc--convert docbody arglist))))))) 238 | (when (and docbody fmted) 239 | (insert fmted)))) 240 | 241 | ;;;###autoload 242 | (defun wikidoc-insert (elisp-prefix buffer) 243 | "Make creole doc for functions beginning with ELISP-PREFIX in BUFFER. 244 | 245 | When called interactively with a PREFIX argument this function 246 | will use the current buffer for BUFFER. 247 | 248 | Otherwise the BUFFER will be created named like: 249 | 250 | *wikidoc-ELISP-PREFIX* 251 | 252 | If Transient Mark mode is set in the specified buffer the active 253 | region is killed before the new wiki text is inserted. 254 | " 255 | (interactive 256 | (let ((elisp-prefix 257 | (completing-read "elisp prefix: " 258 | obarray nil nil nil nil))) 259 | (list (intern elisp-prefix) 260 | (if current-prefix-arg 261 | (current-buffer) 262 | nil)))) 263 | (let* ((lst (sort 264 | (wikidoc-grab-list elisp-prefix 't) 265 | 'string-lessp))) 266 | (if (not (bufferp buffer)) 267 | (progn 268 | (setq buffer (get-buffer-create (format "*wikidoc-%s*" elisp-prefix))) 269 | (with-current-buffer buffer 270 | (mapc 'wikidoc--convert-fn lst)) 271 | (switch-to-buffer buffer)) 272 | (progn 273 | (with-current-buffer buffer 274 | (if (use-region-p) 275 | (delete-region (region-beginning) (region-end))) 276 | (mapc 'wikidoc--convert-fn lst)))))) 277 | 278 | 279 | (defun wikidoc-rst-example () 280 | "This is just an example function. Check the source." 281 | 282 | ;; rebind the template variables to make rst come out 283 | 284 | (let ((wikidoc--convert-fn-template 285 | "\n\n.. el:function:: `${name}' ${args}\n\t${description}\n") 286 | (wikidoc--convert-line-arg-reference "``%s''")) 287 | (wikidoc-insert 'gh-issues- (current-buffer)))) 288 | 289 | (provide 'wikidoc) 290 | 291 | ;;; wikidoc.el ends here 292 | --------------------------------------------------------------------------------