Initial Commit
[packages] / xemacs-packages / semantic / bovine / erlang-edoc.el.upstream
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.upstream,v 1.1 2007-11-26 15:11:52 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 (require 'document)
29 (require 'document-vars)
30
31 ;;; Code:
32 (defcustom erlang-edoc-function-comment "
33 %b
34 %m @spec %F( %P ) -> Return
35 %m
36 %m       %T
37 %m @doc %f%p
38 %m
39 %m @end
40 %e
41 "
42   "See `document-function-comment'"
43   :group 'document
44   :type 'string)
45
46 (defcustom erlang-edoc-record-comment "
47 %b
48 %m @type %F().
49 %m    <dl>
50 %m      %T
51 %m    </dl>
52 %m      %f%p
53 %m @end
54 %e
55 "
56   "See `document-function-comment'"
57   :group 'document
58   :type 'string)
59
60 (defcustom erlang-edoc-type-spec "%P = %D"
61   "Parameter type spec.
62 %P - align parameter name to longest,
63 %p - as is,
64 %D - description."
65   :group 'semantic
66   :type 'string)
67
68 (defcustom erlang-edoc-desc-spec "<dt>%P</dt><dd>%D</dd>"
69   "Parameter description spec.
70 %P - align parameter name to longest,
71 %p - as is,
72 %D - description."
73   :group 'semantic
74   :type 'string)
75
76 (defsubst erlang-edoc--tag-name (nonterm)
77   "Nonterminal name."
78   (if (stringp nonterm) nonterm (semantic-tag-name nonterm)))
79
80 (defun erlang-edoc-inline ()
81   "Document the current nonterminal with an inline comment."
82   (interactive)
83   (semantic-fetch-tags)
84   (let ((ct (semantic-brute-find-tag-by-position (point) (current-buffer))))
85     (erlang-edoc-insert-comment ct (current-buffer))))
86
87 (defun erlang-edoc-insert-comment-new (nonterm template)
88   "Insert a new comment which explains the function found in NONTERM."
89   (let ((pnt 0)
90         (st 0)
91         (zpnt 0)
92         )
93     ;; nonterm should always be correct.
94     (goto-char (semantic-tag-start nonterm))
95     (setq st (point))
96     (insert (funcall template nonterm 'zpnt 'pnt))
97     (goto-char (+ zpnt st))
98     (message "Setting fill prefix to: \"%s\""
99              (setq fill-prefix
100                    (concat (document-comment-line-prefix)
101                            (make-string
102                             (- (current-column)
103                                (length (document-comment-line-prefix)))
104                             ? ))))
105     (goto-char (+ pnt st))
106     (auto-fill-mode 1)
107     ))
108
109 (defun erlang-edoc-insert-comment (nonterm buffer)
110   "Insert mode-comment documentation about NONTERM from BUFFER."
111   (let ((tt (semantic-tag-class nonterm)))
112     (cond
113      ((eq tt 'function)
114       (erlang-edoc-insert-comment-new nonterm #'erlang-edoc--function-template)
115       (message "Done..."))
116       ((eq tt 'type)
117        (erlang-edoc-insert-comment-new nonterm #'erlang-edoc--record-template)
118        (message "Done..."))
119       (t
120       (error "Type %S is not yet managed by document `erlang-edoc-inline'" tt))
121       )))
122
123 (defun erlang-edoc--function-template (nonterm pref-var focus-var)
124   "Generate NONTERM function template for insertion."
125   (let  ((fname (erlang-edoc--strip-arity (semantic-tag-name nonterm)))
126          (params (semantic-tag-function-arguments nonterm)))
127          (Sformat (list (list ?F fname)
128                         (list ?P (erlang-edoc--param-specs params))
129                         (list ?T '(lambda ()
130                                     (erlang-edoc--type-specs
131                                      params t)))
132                         (list ?f '(lambda ()
133                                     (set pref-var (Sformat-point)) ""))
134                         (list ?p '(lambda ()
135                                     (setq focus-var (Sformat-point)) ""))
136                         (list ?b (document-comment-start))
137                         (list ?m (document-comment-line-prefix))
138                         (list ?e (document-comment-end)))
139                   erlang-edoc-function-comment)
140          ))
141
142 (defun erlang-edoc--record-template (nonterm pref-var focus-var)
143   "Generate NONTERM record template for insertion."
144   (let ((tname (semantic-tag-name nonterm))
145         (params (semantic-tag-type-members nonterm)))
146     (Sformat (list (list ?F tname)
147                    (list ?T '(lambda ()
148                                (erlang-edoc--type-specs
149                                 params t erlang-edoc-desc-spec)))
150                    (list ?f '(lambda () (set pref-var (Sformat-point)) ""))
151                    (list ?p '(lambda () (set focus-var (Sformat-point)) ""))
152                    (list ?b (document-comment-start))
153                    (list ?m (document-comment-line-prefix))
154                    (list ?e (document-comment-end)))
155              erlang-edoc-record-comment)
156     ))
157
158 (defun erlang-edoc--strip-arity (tag-name)
159   "Strip arity from TAG-NAME"
160   ;;stripping arity
161   (substring  tag-name 0 (string-match "/[0-9]+$" tag-name)))
162
163 (defun erlang-edoc--param-specs (params)
164   "Parameters specification string for PARAMS"
165   (apply 'concat (cons (erlang-edoc--tag-name (car params))
166                        (mapcar (lambda (p)
167                                  (concat ", "
168                                          (erlang-edoc--tag-name p)))
169                                (cdr params))))
170   )
171
172 (defun erlang-edoc--type-specs (params &optional add-comment template)
173   "Convert a parameter list PARAMS into a vertical list separated by =es."
174   (let* ((tmpl (if template
175                    template
176                  erlang-edoc-type-spec))
177          (col (if Sformat-formatting (Sformat-column) (current-column)))
178          (newl params)
179          (longest (document-longest-name newl))
180          (newp ""))
181     (while newl
182       (let* ((n (car newl))
183              (nn (erlang-edoc--tag-name n))
184              (nc (if add-comment
185                      (or (erlang-edoc--nonterm-comment n)
186                          "undocumented")
187                    ""))
188              )
189         (let ((nextp (Sformat
190                       (list (list ?P
191                                   (substring (concat
192                                               nn
193                                               "                   ")
194                                              0 longest))
195                             (list ?D nc)
196                             (list ?p n)
197                             )
198                       tmpl)))
199           (setq newp
200                 (concat
201                  newp nextp
202                  (concat "\n" (document-comment-line-prefix)
203                          (make-string
204                           (- col (length (document-comment-line-prefix)))
205                           ? ))))))
206       (setq newl (cdr newl)))
207     (if (= (length newp) 0) "" newp)
208     ))
209
210 (defun erlang-edoc--nonterm-comment (nonterm)
211   "Extract inline comment for NONTERM."
212   (cond ((stringp nonterm) nil)
213         ((not (semantic-tag-end nonterm)) nil)
214         ((not (semantic-tag-start nonterm)) nil)
215         (t
216          (save-excursion
217            (goto-char (semantic-tag-start nonterm))
218            (let*
219                ((le (line-end-position))
220                 (ss (cond ((re-search-forward ",\\s-*" le t 1)
221                            (match-end 0))
222                           ((re-search-forward "%" le t 1)
223                            (- (match-end 0) 1))
224                           (t nil)))
225                 (str (if ss (buffer-substring-no-properties ss le) ""))
226                 (ds (progn
227                       (and (string-match "^\\(\\s-*\\s<+\\)\\s-*" str)
228                            (match-end 0))))
229                 (de (or (string-match "\\s-+$" str)
230                         (length str)))
231                 )
232              (cond ((not ds) nil)
233                    ((<= de ds ) nil)
234                    (t (let ((ret (substring str ds de)))
235                         (if (= (length ret) 0) nil ret)))
236                    ))
237            ))))
238               
239 (provide 'erlang-edoc)
240 ;;; erlang-edoc.el ends here