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