comparison lisp/modes/c-comment.el @ 0:376386a54a3c r19-14

Import from CVS: tag r19-14
author cvs
date Mon, 13 Aug 2007 08:45:50 +0200
parents
children e45d5e7c476e
comparison
equal deleted inserted replaced
-1:000000000000 0:376386a54a3c
1 ;;; c-comment.el --- edit C comments
2
3 ;; Keywords: c
4
5 ;;; Copyright (C) 1987, 1988, 1989 Kyle E. Jones
6 ;;;
7 ;;; Verbatim copies of this file may be freely redistributed.
8 ;;;
9 ;;; Modified versions of this file may be redistributed provided that this
10 ;;; notice remains unchanged, the file contains prominent notice of
11 ;;; author and time of modifications, and redistribution of the file
12 ;;; is not further restricted in any way.
13 ;;;
14 ;;; This file is distributed `as is', without warranties of any kind.
15
16 ;;; Synched up with: Not in FSF.
17
18 (provide 'c-comment-edit)
19
20 (defvar c-comment-leader " *"
21 "*Leader used when rebuilding edited C comments. The value of this variable
22 should be a two-character string. Values of \" \", \" *\" and \"**\" produce the
23 comment styles:
24 /* /* /*
25 ... * ... ** ...
26 ... * ... ** ...
27 */ */ */
28 respectively.")
29
30 (defconst c-comment-leader-regexp "^[ ]*\\(\\*\\*\\|\\*\\)?[ ]?"
31 "Regexp used to match C comment leaders.")
32
33 (defvar c-comment-edit-mode 'text-mode
34 "*Major mode used by `c-comment-edit' when editing C comments.")
35
36 (defvar c-comment-edit-hook nil
37 "*Function to call whenever `c-comment-edit' is used.
38 The function is called just before the `c-comment-edit' function allows you to
39 begin editing the comment.")
40
41 (defvar c-comment-edit-buffer-alist nil
42 "Assoc list of C buffers and their associated comment buffers.
43 Elements are of the form (C-BUFFER COMMENT-BUFFER COMMENT-START COMMENT-END)
44 COMMENT-START and COMMENT-END are markers in the C-BUFFER.")
45
46 (defmacro save-point (&rest body)
47 "Save value of point, evalutes FORMS and restore value of point.
48 If the saved value of point is no longer valid go to (point-max).
49 The variable `save-point' is lambda-bound to the value of point for
50 the duration of this call."
51 (list 'let '((save-point (point)))
52 (list 'unwind-protect
53 (cons 'progn body)
54 '(goto-char (min (point-max) save-point)))))
55
56 (defmacro marker (pos &optional buffer)
57 (list 'set-marker '(make-marker) pos buffer))
58
59
60 ;;;### autoload
61 (defun c-comment-edit (search-prefix)
62 "Edit multi-line C comments.
63 This command allows the easy editing of a multi-line C comment like this:
64 /*
65 * ...
66 * ...
67 */
68 The comment may be indented or flush with the left margin.
69
70 If point is within a comment, that comment is used. Otherwise the
71 comment to be edited is found by searching forward from point.
72
73 With one \\[universal-argument] searching starts after moving back one
74 paragraph.
75 With two \\[universal-argument]'s searching starts at the beginning of the
76 current or proceeding C function.
77 With three \\[universal-argument]'s searching starts at the beginning of the
78 current page.
79 With four \\[universal-argument]'s searching starts at the beginning of the
80 current buffer (clipping restrictions apply).
81
82 Once located, the comment is copied into a temporary buffer, the comment
83 leaders and delimiters are stripped away and the resulting buffer is
84 selected for editing. The major mode of this buffer is controlled by
85 the variable `c-comment-edit-mode'.
86
87 Use \\[c-comment-edit-end] when you have finished editing the comment. The
88 comment will be inserted into the original buffer with the appropriate
89 delimiters and indention, replacing the old version of the comment. If
90 you don't want your edited version of the comment to replace the
91 original, use \\[c-comment-edit-abort]."
92 (interactive "*P")
93 (let ((c-buffer (current-buffer))
94 marker tem c-comment-fill-column c-comment-buffer
95 c-comment-start c-comment-end
96 (inhibit-quit t))
97 ;; honor search-prefix
98 (cond ((equal search-prefix '(4))
99 (backward-paragraph))
100 ((equal search-prefix '(16))
101 (end-of-defun)
102 (beginning-of-defun)
103 (backward-paragraph))
104 ((equal search-prefix '(64))
105 (backward-page))
106 ((equal search-prefix '(256))
107 (goto-char (point-min))))
108 (if (and (null search-prefix) (setq tem (within-c-comment-p)))
109 (setq c-comment-start (marker (car tem))
110 c-comment-end (marker (cdr tem)))
111 (let (start end)
112 (condition-case error-data
113 (save-point
114 (search-forward "/*")
115 (setq start (- (point) 2))
116 (search-forward "*/")
117 (setq end (point)))
118 (search-failed (error "No C comment found.")))
119 (setq c-comment-start (marker start))
120 (setq c-comment-end (marker end))))
121 ;; calculate the correct fill-column for the comment
122 (setq c-comment-fill-column (- fill-column
123 (save-excursion
124 (goto-char c-comment-start)
125 (current-column))))
126 ;; create the comment buffer
127 (setq c-comment-buffer
128 (generate-new-buffer (concat (buffer-name) " *C Comment Edit*")))
129 ;; link into the c-comment-edit-buffer-alist
130 (setq c-comment-edit-buffer-alist
131 (cons (list (current-buffer) c-comment-buffer
132 c-comment-start c-comment-end)
133 c-comment-edit-buffer-alist))
134 ;; copy to the comment to the comment-edit buffer
135 (copy-to-buffer c-comment-buffer (+ c-comment-start 2) (- c-comment-end 2))
136 ;; mark the position of point, relative to the beginning of the
137 ;; comment, in the comment buffer. (iff point is within a comment.)
138 (or search-prefix (< (point) c-comment-start)
139 (setq marker (marker (+ (- (point) c-comment-start 2) 1)
140 c-comment-buffer)))
141 ;; select the comment buffer for editing
142 (switch-to-buffer c-comment-buffer)
143 ;; remove the comment leaders and delimiters
144 (goto-char (point-min))
145 (while (not (eobp))
146 (and (re-search-forward c-comment-leader-regexp nil t)
147 (replace-match "" nil t))
148 (forward-line))
149 ;; run appropriate major mode
150 (funcall (or c-comment-edit-mode 'fundamental-mode))
151 ;; override user's default fill-column here since it will lose if
152 ;; the comment is indented in the C buffer.
153 (setq fill-column c-comment-fill-column)
154 ;; delete one leading whitespace char
155 (goto-char (point-min))
156 (if (looking-at "[ \n\t]")
157 (delete-char 1))
158 ;; restore cursor if possible
159 (goto-char (or marker (point-min)))
160 (set-buffer-modified-p nil))
161 ;; run user hook, if present.
162 (if c-comment-edit-hook
163 (funcall c-comment-edit-hook))
164 ;; final admonition
165 (message
166 (substitute-command-keys
167 "Type \\[c-comment-edit-end] to end edit, \\[c-comment-edit-abort] to abort with no change.")))
168
169 (defun c-comment-edit-end ()
170 "End c-comment-edit.
171 C comment is replaced by its edited counterpart in the appropriate C buffer.
172 Indentation will be the same as the original."
173 (interactive)
174 (let ((tuple (find-c-comment-buffer)))
175 (if (null tuple)
176 (error "Not a c-comment-edit buffer."))
177 (let ((inhibit-quit t)
178 (c-comment-c-buffer (car tuple))
179 (c-comment-buffer (nth 1 tuple))
180 (c-comment-start (nth 2 tuple))
181 (c-comment-end (nth 3 tuple)))
182 (cond
183 ((buffer-modified-p)
184 ;; rebuild the comment
185 (goto-char (point-min))
186 (insert "/*\n")
187 (if (string= c-comment-leader " ")
188 (while (not (eobp))
189 (if (not (eolp))
190 (insert c-comment-leader " "))
191 (forward-line))
192 (while (not (eobp))
193 (insert c-comment-leader (if (eolp) "" " "))
194 (forward-line)))
195 (if (not (char-equal (preceding-char) ?\n))
196 (insert "\n"))
197 (insert (if (string= c-comment-leader " *") " */" "*/"))
198 ;; indent if necessary
199 (let ((indention
200 (save-excursion
201 (set-buffer c-comment-c-buffer)
202 (goto-char c-comment-start)
203 (current-column))))
204 (goto-char (point-min))
205 (cond ((not (zerop indention))
206 ;; first line is already indented
207 ;; in the C buffer
208 (forward-line)
209 (while (not (eobp))
210 (indent-to indention)
211 (forward-line)))))
212 ;; replace the old comment with the new
213 (save-excursion
214 (set-buffer c-comment-c-buffer)
215 (save-point
216 (save-excursion
217 (delete-region c-comment-start c-comment-end)
218 (goto-char c-comment-start)
219 (set-buffer c-comment-buffer)
220 (append-to-buffer c-comment-c-buffer
221 (point-min) (point-max))))))
222 (t (message "No change.")))
223 ;; switch to the C buffer
224 (if (get-buffer-window c-comment-c-buffer)
225 (select-window (get-buffer-window c-comment-c-buffer))
226 (switch-to-buffer c-comment-c-buffer))
227 ;; delete the window viewing the comment buffer
228 (and (get-buffer-window c-comment-buffer)
229 (delete-window (get-buffer-window c-comment-buffer)))
230 ;; unlink the tuple from c-comment-edit-buffer-alist
231 (setq c-comment-edit-buffer-alist
232 (delq tuple c-comment-edit-buffer-alist))
233 ;; let Emacs reclaim various resources
234 (save-excursion
235 (set-buffer c-comment-buffer)
236 (set-buffer-modified-p nil)
237 (kill-buffer c-comment-buffer))
238 (set-marker c-comment-start nil)
239 (set-marker c-comment-end nil))))
240
241 (defun c-comment-edit-abort ()
242 "Abort a c-comment-edit with no change."
243 (interactive)
244 (let* ((tuple (find-c-comment-buffer))
245 (c-comment-c-buffer (car tuple))
246 (c-comment-buffer (nth 1 tuple))
247 (c-comment-start (nth 2 tuple))
248 (c-comment-end (nth 3 tuple)))
249 (if (null tuple)
250 (error "Not a c-comment-edit buffer."))
251 ;; switch to the C buffer
252 (if (get-buffer-window c-comment-c-buffer)
253 (select-window (get-buffer-window c-comment-c-buffer))
254 (switch-to-buffer c-comment-c-buffer))
255 (let ((inhibit-quit t))
256 (save-excursion
257 (set-buffer c-comment-buffer)
258 (set-buffer-modified-p nil)
259 (kill-buffer c-comment-buffer))
260 ;; unlink the tuple from c-comment-edit-buffer-alist
261 (setq c-comment-edit-buffer-alist
262 (delq tuple c-comment-edit-buffer-alist))
263 (set-marker c-comment-start nil)
264 (set-marker c-comment-end nil)
265 (message "Aborted with no change."))))
266
267 ;; this loses on /* /* */ but doing it right would be grim.
268 (defun within-c-comment-p ()
269 (condition-case error-data
270 (let (start end)
271 (save-point
272 (search-backward "/*")
273 (setq start (point))
274 (search-forward "*/")
275 (setq end (point)))
276 (if (< (point) end) (cons start end) nil))
277 (search-failed nil)))
278
279 (defun find-c-comment-buffer (&optional buffer)
280 (or buffer (setq buffer (current-buffer)))
281 (let ((list c-comment-edit-buffer-alist))
282 (catch 'return-value
283 (while list
284 (if (eq (nth 1 (car list)) buffer)
285 (throw 'return-value (car list))
286 (setq list (cdr list)))))))
287
288 (defun find-c-comment-c-buffer (&optional buffer)
289 (or buffer (setq buffer (current-buffer)))
290 (let ((list c-comment-edit-buffer-alist))
291 (catch 'return-value
292 (while list
293 (if (eq (car (car list)) buffer)
294 (throw 'return-value (car list))
295 (setq list (cdr list)))))))
296
297 ;; keys;
298 (define-key mode-specific-map "\e" 'c-comment-edit-end)
299 (define-key mode-specific-map "\C-]" 'c-comment-edit-abort)
300
301