Initial Commit
[packages] / xemacs-packages / semantic / bovine / erlang-edoc.el
1 ;;; erlang-edoc.el --- Erlang programs documenting support for Semantic
2
3 ;; Copyright (C) 2002, 2004, 2007 Vladimir G. Sekissov
4
5 ;; Author:  <svg@surnet.ru>
6 ;; Keywords: languages, docs
7 ;; $Id: erlang-edoc.el,v 1.1 2007-11-26 15:11:51 michaels Exp $
8
9 ;; This file is free software; you can redistribute it and/or modify
10 ;; it under the terms of the GNU General Public License as published by
11 ;; the Free Software Foundation; either version 2, or (at your option)
12 ;; any later version.
13
14 ;; This file is distributed in the hope that it will be useful,
15 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
16 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17 ;; GNU General Public License for more details.
18
19 ;; You should have received a copy of the GNU General Public License
20 ;; along with GNU Emacs; see the file COPYING.  If not, write to
21 ;; the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
22 ;; Boston, MA 02110-1301, USA.
23
24 ;;; Commentary:
25 ;;
26 ;; Derived from document.el of Eric M. Ludlam <zappo@gnu.org>
27
28 (provide 'erlang-edoc)
29
30 (require 'document)
31 (require 'document-vars)
32
33 ;;; Code:
34 (defcustom erlang-edoc-function-comment "
35 %b
36 %m @spec %F( %P ) -> Return
37 %m
38 %m       %T
39 %m @doc %f%p
40 %m
41 %m @end
42 %e
43 "
44   "See `document-function-comment'"
45   :group 'document
46   :type 'string)
47
48 (defcustom erlang-edoc-record-comment "
49 %b
50 %m @type %F().
51 %m    <dl>
52 %m      %T
53 %m    </dl>
54 %m      %f%p
55 %m @end
56 %e
57 "
58   "See `document-function-comment'"
59   :group 'document
60   :type 'string)
61
62 (defcustom erlang-edoc-type-spec "%P = %D"
63   "Parameter type spec.
64 %P - align parameter name to longest,
65 %p - as is,
66 %D - description."
67   :group 'semantic
68   :type 'string)
69
70 (defcustom erlang-edoc-desc-spec "<dt>%P</dt><dd>%D</dd>"
71   "Parameter description spec.
72 %P - align parameter name to longest,
73 %p - as is,
74 %D - description."
75   :group 'semantic
76   :type 'string)
77
78 (defsubst erlang-edoc--tag-name (nonterm)
79   "Nonterminal name."
80   (if (stringp nonterm) nonterm (semantic-tag-name nonterm)))
81
82 (defun erlang-edoc-inline ()
83   "Document the current nonterminal with an inline comment."
84   (interactive)
85   (semantic-fetch-tags)
86   (let ((ct (semantic-brute-find-tag-by-position (point) (current-buffer))))
87     (erlang-edoc-insert-comment ct (current-buffer))))
88
89 (defun erlang-edoc-insert-comment-new (nonterm template)
90   "Insert a new comment which explains the function found in NONTERM."
91   (let ((pnt 0)
92         (st 0)
93         (zpnt 0)
94         )
95     ;; nonterm should always be correct.
96     (goto-char (semantic-tag-start nonterm))
97     (setq st (point))
98     (insert (funcall template nonterm 'zpnt 'pnt))
99     (goto-char (+ zpnt st))
100     (message "Setting fill prefix to: \"%s\""
101              (setq fill-prefix
102                    (concat (document-comment-line-prefix)
103                            (make-string
104                             (- (current-column)
105                                (length (document-comment-line-prefix)))
106                             ? ))))
107     (goto-char (+ pnt st))
108     (auto-fill-mode 1)
109     ))
110
111 (defun erlang-edoc-insert-comment (nonterm buffer)
112   "Insert mode-comment documentation about NONTERM from BUFFER."
113   (let ((tt (semantic-tag-class nonterm)))
114     (cond
115      ((eq tt 'function)
116       (erlang-edoc-insert-comment-new nonterm #'erlang-edoc--function-template)
117       (message "Done..."))
118       ((eq tt 'type)
119        (erlang-edoc-insert-comment-new nonterm #'erlang-edoc--record-template)
120        (message "Done..."))
121       (t
122       (error "Type %S is not yet managed by document `erlang-edoc-inline'" tt))
123       )))
124
125 (defun erlang-edoc--function-template (nonterm pref-var focus-var)
126   "Generate NONTERM function template for insertion."
127   (let  ((fname (erlang-edoc--strip-arity (semantic-tag-name nonterm)))
128          (params (semantic-tag-function-arguments nonterm)))
129          (Sformat (list (list ?F fname)
130                         (list ?P (erlang-edoc--param-specs params))
131                         (list ?T '(lambda ()
132                                     (erlang-edoc--type-specs
133                                      params t)))
134                         (list ?f '(lambda ()
135                                     (set pref-var (Sformat-point)) ""))
136                         (list ?p '(lambda ()
137                                     (setq focus-var (Sformat-point)) ""))
138                         (list ?b (document-comment-start))
139                         (list ?m (document-comment-line-prefix))
140                         (list ?e (document-comment-end)))
141                   erlang-edoc-function-comment)
142          ))
143
144 (defun erlang-edoc--record-template (nonterm pref-var focus-var)
145   "Generate NONTERM record template for insertion."
146   (let ((tname (semantic-tag-name nonterm))
147         (params (semantic-tag-type-members nonterm)))
148     (Sformat (list (list ?F tname)
149                    (list ?T '(lambda ()
150                                (erlang-edoc--type-specs
151                                 params t erlang-edoc-desc-spec)))
152                    (list ?f '(lambda () (set pref-var (Sformat-point)) ""))
153                    (list ?p '(lambda () (set focus-var (Sformat-point)) ""))
154                    (list ?b (document-comment-start))
155                    (list ?m (document-comment-line-prefix))
156                    (list ?e (document-comment-end)))
157              erlang-edoc-record-comment)
158     ))
159
160 (defun erlang-edoc--strip-arity (tag-name)
161   "Strip arity from TAG-NAME"
162   ;;stripping arity
163   (substring  tag-name 0 (string-match "/[0-9]+$" tag-name)))
164
165 (defun erlang-edoc--param-specs (params)
166   "Parameters specification string for PARAMS"
167   (apply 'concat (cons (erlang-edoc--tag-name (car params))
168                        (mapcar (lambda (p)
169                                  (concat ", "
170                                          (erlang-edoc--tag-name p)))
171                                (cdr params))))
172   )
173
174 (defun erlang-edoc--type-specs (params &optional add-comment template)
175   "Convert a parameter list PARAMS into a vertical list separated by =es."
176   (let* ((tmpl (if template
177                    template
178                  erlang-edoc-type-spec))
179          (col (if Sformat-formatting (Sformat-column) (current-column)))
180          (newl params)
181          (longest (document-longest-name newl))
182          (newp ""))
183     (while newl
184       (let* ((n (car newl))
185              (nn (erlang-edoc--tag-name n))
186              (nc (if add-comment
187                      (or (erlang-edoc--nonterm-comment n)
188                          "undocumented")
189                    ""))
190              )
191         (let ((nextp (Sformat
192                       (list (list ?P
193                                   (substring (concat
194                                               nn
195                                               "                   ")
196                                              0 longest))
197                             (list ?D nc)
198                             (list ?p n)
199                             )
200                       tmpl)))
201           (setq newp
202                 (concat
203                  newp nextp
204                  (concat "\n" (document-comment-line-prefix)
205                          (make-string
206                           (- col (length (document-comment-line-prefix)))
207                           ? ))))))
208       (setq newl (cdr newl)))
209     (if (= (length newp) 0) "" newp)
210     ))
211
212 (defun erlang-edoc--nonterm-comment (nonterm)
213   "Extract inline comment for NONTERM."
214   (cond ((stringp nonterm) nil)
215         ((not (semantic-tag-end nonterm)) nil)
216         ((not (semantic-tag-start nonterm)) nil)
217         (t
218          (save-excursion
219            (goto-char (semantic-tag-start nonterm))
220            (let*
221                ((le (line-end-position))
222                 (ss (cond ((re-search-forward ",\\s-*" le t 1)
223                            (match-end 0))
224                           ((re-search-forward "%" le t 1)
225                            (- (match-end 0) 1))
226                           (t nil)))
227                 (str (if ss (buffer-substring-no-properties ss le) ""))
228                 (ds (progn
229                       (and (string-match "^\\(\\s-*\\s<+\\)\\s-*" str)
230                            (match-end 0))))
231                 (de (or (string-match "\\s-+$" str)
232                         (length str)))
233                 )
234              (cond ((not ds) nil)
235                    ((<= de ds ) nil)
236                    (t (let ((ret (substring str ds de)))
237                         (if (= (length ret) 0) nil ret)))
238                    ))
239            ))))
240               
241 ;;; erlang-edoc.el ends here