1333
|
1 ;;; newcomment.el --- (un)comment regions of buffers
|
|
2
|
|
3 ;; Copyright (C) 1999, 2000 Free Software Foundation Inc.
|
|
4
|
|
5 ;; Author: code extracted from Emacs-20's simple.el
|
|
6 ;; Maintainer: Stefan Monnier <monnier@cs.yale.edu>
|
|
7 ;; Keywords: comment uncomment
|
|
8
|
|
9 ;; This file is part of GNU Emacs.
|
|
10
|
|
11 ;; GNU Emacs is free software; you can redistribute it and/or modify
|
|
12 ;; it under the terms of the GNU General Public License as published by
|
|
13 ;; the Free Software Foundation; either version 2, or (at your option)
|
|
14 ;; any later version.
|
|
15
|
|
16 ;; GNU Emacs is distributed in the hope that it will be useful,
|
|
17 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
18 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
19 ;; GNU General Public License for more details.
|
|
20
|
|
21 ;; You should have received a copy of the GNU General Public License
|
|
22 ;; along with GNU Emacs; see the file COPYING. If not, write to the
|
|
23 ;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
|
24 ;; Boston, MA 02111-1307, USA.
|
|
25
|
2511
|
26 ;;; Synched up with: FSF 21.3.
|
|
27
|
1333
|
28 ;;; Commentary:
|
|
29
|
|
30 ;; A replacement for simple.el's comment-related functions.
|
|
31
|
|
32 ;;; Bugs:
|
|
33
|
2511
|
34 ;; - boxed comments in Perl are not properly uncommented because they are
|
|
35 ;; uncommented one-line at a time.
|
|
36 ;; - nested comments in sgml-mode are not properly quoted.
|
1333
|
37 ;; - single-char nestable comment-start can only do the "\\s<+" stuff
|
|
38 ;; if the corresponding closing marker happens to be right.
|
|
39 ;; - uncomment-region with a numeric argument can render multichar
|
|
40 ;; comment markers invalid.
|
|
41 ;; - comment-indent or comment-region when called inside a comment
|
|
42 ;; will happily break the surrounding comment.
|
|
43 ;; - comment-quote-nested will not (un)quote properly all nested comment
|
|
44 ;; markers if there are more than just comment-start and comment-end.
|
|
45 ;; For example, in Pascal where {...*) and (*...} are possible.
|
|
46
|
|
47 ;;; Todo:
|
|
48
|
2511
|
49 ;; - rebox.el-style refill.
|
|
50 ;; - quantized steps in comment-alignment.
|
|
51 ;; - try to align tail comments.
|
|
52 ;; - check what c-comment-line-break-function has to say.
|
|
53 ;; - spill auto-fill of comments onto the end of the next line.
|
1333
|
54 ;; - uncomment-region with a consp (for blocks) or somehow make the
|
2511
|
55 ;; deletion of continuation markers less dangerous.
|
|
56 ;; - drop block-comment-<foo> unless it's really used.
|
|
57 ;; - uncomment-region on a subpart of a comment.
|
|
58 ;; - support gnu-style "multi-line with space in continue".
|
1333
|
59 ;; - somehow allow comment-dwim to use the region even if transient-mark-mode
|
|
60 ;; is not turned on.
|
|
61
|
|
62 ;; - when auto-filling a comment, try to move the comment to the left
|
|
63 ;; rather than break it (if possible).
|
|
64 ;; - sometimes default the comment-column to the same
|
|
65 ;; one used on the preceding line(s).
|
|
66
|
|
67 ;;; Code:
|
|
68
|
|
69 ;;;###autoload
|
|
70 (defalias 'indent-for-comment 'comment-indent)
|
|
71 ;;;###autoload
|
|
72 (defalias 'set-comment-column 'comment-set-column)
|
|
73 ;;;###autoload
|
|
74 (defalias 'kill-comment 'comment-kill)
|
|
75 ;;;###autoload
|
|
76 (defalias 'indent-new-comment-line 'comment-indent-new-line)
|
|
77
|
|
78 (defgroup comment nil
|
|
79 "Indenting and filling of comments."
|
|
80 :prefix "comment-"
|
|
81 :version "21.1"
|
|
82 :group 'fill)
|
|
83
|
|
84 (defvar comment-use-syntax 'undecided
|
|
85 "Non-nil if syntax-tables can be used instead of regexps.
|
|
86 Can also be `undecided' which means that a somewhat expensive test will
|
|
87 be used to try to determine whether syntax-tables should be trusted
|
|
88 to understand comments or not in the given buffer.
|
|
89 Major modes should set this variable.")
|
|
90
|
2511
|
91 (defcustom comment-fill-column nil
|
|
92 "Column to use for `comment-indent'. If nil, use `fill-column' instead."
|
|
93 :type '(choice (const nil) integer))
|
|
94
|
1333
|
95 ;;;###autoload
|
|
96 (defcustom comment-column 32
|
|
97 "*Column to indent right-margin comments to.
|
|
98 Each mode establishes a different default value for this variable; you
|
2511
|
99 can set the value for a particular mode using that mode's hook.
|
|
100 Comments might be indented to a value smaller than this in order
|
|
101 not to go beyond `comment-fill-column'."
|
|
102 :type 'integer)
|
1333
|
103 (make-variable-buffer-local 'comment-column)
|
|
104
|
|
105 ;;;###autoload
|
|
106 (defvar comment-start nil
|
|
107 "*String to insert to start a new comment, or nil if no comment syntax.")
|
|
108
|
|
109 ;;;###autoload
|
|
110 (defvar comment-start-skip nil
|
|
111 "*Regexp to match the start of a comment plus everything up to its body.
|
|
112 If there are any \\(...\\) pairs, the comment delimiter text is held to begin
|
|
113 at the place matched by the close of the first pair.")
|
|
114
|
|
115 ;;;###autoload
|
|
116 (defvar comment-end-skip nil
|
|
117 "Regexp to match the end of a comment plus everything up to its body.")
|
|
118
|
|
119 ;;;###autoload
|
|
120 (defvar comment-end ""
|
|
121 "*String to insert to end a new comment.
|
|
122 Should be an empty string if comments are terminated by end-of-line.")
|
|
123
|
|
124 ;;;###autoload
|
|
125 (defvar comment-indent-function 'comment-indent-default
|
|
126 "Function to compute desired indentation for a comment.
|
|
127 This function is called with no args with point at the beginning of
|
|
128 the comment's starting delimiter and should return either the desired
|
|
129 column indentation or nil.
|
|
130 If nil is returned, indentation is delegated to `indent-according-to-mode'.")
|
|
131
|
|
132 (defvar block-comment-start nil)
|
|
133 (defvar block-comment-end nil)
|
|
134
|
|
135 (defvar comment-quote-nested t
|
|
136 "Non-nil if nested comments should be quoted.
|
|
137 This should be locally set by each major mode if needed.")
|
|
138
|
|
139 (defvar comment-continue nil
|
|
140 "Continuation string to insert for multiline comments.
|
|
141 This string will be added at the beginning of each line except the very
|
|
142 first one when commenting a region with a commenting style that allows
|
|
143 comments to span several lines.
|
|
144 It should generally have the same length as `comment-start' in order to
|
|
145 preserve indentation.
|
|
146 If it is nil a value will be automatically derived from `comment-start'
|
|
147 by replacing its first character with a space.")
|
|
148
|
|
149 (defvar comment-add 0
|
|
150 "How many more comment chars should be inserted by `comment-region'.
|
|
151 This determines the default value of the numeric argument of `comment-region'.
|
|
152 This should generally stay 0, except for a few modes like Lisp where
|
|
153 it can be convenient to set it to 1 so that regions are commented with
|
|
154 two semi-colons.")
|
|
155
|
|
156 (defconst comment-styles
|
|
157 '((plain . (nil nil nil nil))
|
|
158 (indent . (nil nil nil t))
|
|
159 (aligned . (nil t nil t))
|
|
160 (multi-line . (t nil nil t))
|
|
161 (extra-line . (t nil t t))
|
|
162 (box . (nil t t t))
|
|
163 (box-multi . (t t t t)))
|
|
164 "Possible comment styles of the form (STYLE . (MULTI ALIGN EXTRA INDENT)).
|
|
165 STYLE should be a mnemonic symbol.
|
|
166 MULTI specifies that comments are allowed to span multiple lines.
|
|
167 ALIGN specifies that the `comment-end' markers should be aligned.
|
|
168 EXTRA specifies that an extra line should be used before and after the
|
|
169 region to comment (to put the `comment-end' and `comment-start').
|
|
170 INDENT specifies that the `comment-start' markers should not be put at the
|
|
171 left margin but at the current indentation of the region to comment.")
|
|
172
|
|
173 ;;;###autoload
|
|
174 (defcustom comment-style 'plain
|
|
175 "*Style to be used for `comment-region'.
|
|
176 See `comment-styles' for a list of available styles."
|
|
177 :type (if (boundp 'comment-styles)
|
|
178 `(choice ,@(mapcar (lambda (s) `(const ,(car s))) comment-styles))
|
|
179 'symbol))
|
|
180
|
|
181 ;;;###autoload
|
|
182 (defcustom comment-padding " "
|
|
183 "Padding string that `comment-region' puts between comment chars and text.
|
|
184 Can also be an integer which will be automatically turned into a string
|
|
185 of the corresponding number of spaces.
|
|
186
|
|
187 Extra spacing between the comment characters and the comment text
|
2511
|
188 makes the comment easier to read. Default is 1. nil means 0."
|
1333
|
189 :type '(choice string integer (const nil)))
|
|
190
|
|
191 ;;;###autoload
|
|
192 (defcustom comment-multi-line t ; XEmacs - this works well with adaptive fill
|
|
193 "*Non-nil means \\[indent-new-comment-line] should continue same comment
|
|
194 on new line, with no new terminator or starter.
|
|
195 This is obsolete because you might as well use \\[newline-and-indent]."
|
2511
|
196 :type 'boolean)
|
1333
|
197
|
|
198 ;;;;
|
|
199 ;;;; Helpers
|
|
200 ;;;;
|
|
201
|
|
202 (defun comment-string-strip (str beforep afterp)
|
|
203 "Strip STR of any leading (if BEFOREP) and/or trailing (if AFTERP) space."
|
|
204 (string-match (concat "\\`" (if beforep "\\s-*")
|
|
205 "\\(.*?\\)" (if afterp "\\s-*\n?")
|
|
206 "\\'") str)
|
|
207 (match-string 1 str))
|
|
208
|
|
209 (defun comment-string-reverse (s)
|
|
210 "Return the mirror image of string S, without any trailing space."
|
|
211 (comment-string-strip (concat (nreverse (string-to-list s))) nil t))
|
|
212
|
2511
|
213 ;;;###autoload
|
1333
|
214 (defun comment-normalize-vars (&optional noerror)
|
|
215 (if (not comment-start) (or noerror (error "No comment syntax is defined"))
|
|
216 ;; comment-use-syntax
|
|
217 (when (eq comment-use-syntax 'undecided)
|
|
218 (set (make-local-variable 'comment-use-syntax)
|
|
219 (let ((st (syntax-table))
|
|
220 (cs comment-start)
|
|
221 (ce (if (string= "" comment-end) "\n" comment-end)))
|
|
222 ;; Try to skip over a comment using forward-comment
|
|
223 ;; to see if the syntax tables properly recognize it.
|
|
224 (with-temp-buffer
|
|
225 (set-syntax-table st)
|
|
226 (insert cs " hello " ce)
|
|
227 (goto-char (point-min))
|
|
228 (and (forward-comment 1) (eobp))))))
|
|
229 ;; comment-padding
|
|
230 (unless comment-padding (setq comment-padding 0))
|
|
231 (when (integerp comment-padding)
|
|
232 (setq comment-padding (make-string comment-padding ? )))
|
|
233 ;; comment markers
|
|
234 ;;(setq comment-start (comment-string-strip comment-start t nil))
|
|
235 ;;(setq comment-end (comment-string-strip comment-end nil t))
|
|
236 ;; comment-continue
|
|
237 (unless (or comment-continue (string= comment-end ""))
|
|
238 (set (make-local-variable 'comment-continue)
|
|
239 (concat (if (string-match "\\S-\\S-" comment-start) " " "|")
|
2511
|
240 (substring comment-start 1)))
|
|
241 ;; Hasn't been necessary yet.
|
|
242 ;; (unless (string-match comment-start-skip comment-continue)
|
|
243 ;; (kill-local-variable 'comment-continue))
|
|
244 )
|
1333
|
245 ;; comment-skip regexps
|
2511
|
246 (unless (and comment-start-skip
|
|
247 ;; In case comment-start has changed since last time.
|
|
248 (string-match comment-start-skip comment-start))
|
1333
|
249 (set (make-local-variable 'comment-start-skip)
|
|
250 (concat "\\(\\(^\\|[^\\\\\n]\\)\\(\\\\\\\\\\)*\\)\\(\\s<+\\|"
|
|
251 (regexp-quote (comment-string-strip comment-start t t))
|
|
252 ;; Let's not allow any \s- but only [ \t] since \n
|
|
253 ;; might be both a comment-end marker and \s-.
|
|
254 "+\\)[ \t]*")))
|
2511
|
255 (unless (and comment-end-skip
|
|
256 ;; In case comment-end has changed since last time.
|
|
257 (string-match comment-end-skip comment-end))
|
1333
|
258 (let ((ce (if (string= "" comment-end) "\n"
|
|
259 (comment-string-strip comment-end t t))))
|
|
260 (set (make-local-variable 'comment-end-skip)
|
|
261 ;; We use [ \t] rather than \s- because we don't want to
|
|
262 ;; remove ^L in C mode when uncommenting.
|
|
263 (concat "[ \t]*\\(\\s>" (if comment-quote-nested "" "+")
|
|
264 "\\|" (regexp-quote (substring ce 0 1))
|
|
265 (if (and comment-quote-nested (<= (length ce) 1)) "" "+")
|
|
266 (regexp-quote (substring ce 1))
|
|
267 "\\)"))))))
|
2511
|
268
|
1333
|
269 (defun comment-quote-re (str unp)
|
|
270 (concat (regexp-quote (substring str 0 1))
|
|
271 "\\\\" (if unp "+" "*")
|
|
272 (regexp-quote (substring str 1))))
|
|
273
|
|
274 (defun comment-quote-nested (cs ce unp)
|
|
275 "Quote or unquote nested comments.
|
|
276 If UNP is non-nil, unquote nested comment markers."
|
|
277 (setq cs (comment-string-strip cs t t))
|
|
278 (setq ce (comment-string-strip ce t t))
|
|
279 (when (and comment-quote-nested (> (length ce) 0))
|
|
280 (let ((re (concat (comment-quote-re ce unp)
|
|
281 "\\|" (comment-quote-re cs unp))))
|
|
282 (goto-char (point-min))
|
|
283 (while (re-search-forward re nil t)
|
|
284 (goto-char (match-beginning 0))
|
|
285 (forward-char 1)
|
|
286 (if unp (delete-char 1) (insert "\\"))
|
|
287 (when (= (length ce) 1)
|
|
288 ;; If the comment-end is a single char, adding a \ after that
|
|
289 ;; "first" char won't deactivate it, so we turn such a CE
|
|
290 ;; into !CS. I.e. for pascal, we turn } into !{
|
|
291 (if (not unp)
|
|
292 (when (string= (match-string 0) ce)
|
|
293 (replace-match (concat "!" cs) t t))
|
|
294 (when (and (< (point-min) (match-beginning 0))
|
|
295 (string= (buffer-substring (1- (match-beginning 0))
|
|
296 (1- (match-end 0)))
|
|
297 (concat "!" cs)))
|
|
298 (backward-char 2)
|
|
299 (delete-char (- (match-end 0) (match-beginning 0)))
|
|
300 (insert ce))))))))
|
|
301
|
|
302 ;;;;
|
|
303 ;;;; Navigation
|
|
304 ;;;;
|
|
305
|
|
306 (defun comment-search-forward (limit &optional noerror)
|
|
307 "Find a comment start between point and LIMIT.
|
|
308 Moves point to inside the comment and returns the position of the
|
|
309 comment-starter. If no comment is found, moves point to LIMIT
|
|
310 and raises an error or returns nil of NOERROR is non-nil."
|
|
311 (if (not comment-use-syntax)
|
|
312 (if (re-search-forward comment-start-skip limit noerror)
|
|
313 (or (match-end 1) (match-beginning 0))
|
|
314 (goto-char limit)
|
|
315 (unless noerror (error "No comment")))
|
|
316 (let* ((pt (point))
|
|
317 ;; Assume (at first) that pt is outside of any string.
|
|
318 (s (parse-partial-sexp pt (or limit (point-max)) nil nil nil t)))
|
|
319 (when (and (nth 8 s) (nth 3 s))
|
|
320 ;; The search ended inside a string. Try to see if it
|
|
321 ;; works better when we assume that pt is inside a string.
|
|
322 (setq s (parse-partial-sexp
|
|
323 pt (or limit (point-max)) nil nil
|
|
324 (list nil nil nil (nth 3 s) nil nil nil nil)
|
|
325 t)))
|
|
326 (if (not (and (nth 8 s) (not (nth 3 s))))
|
|
327 (unless noerror (error "No comment"))
|
|
328 ;; We found the comment.
|
|
329 (let ((pos (point))
|
|
330 (start (nth 8 s))
|
|
331 (bol (line-beginning-position))
|
|
332 (end nil))
|
|
333 (while (and (null end) (>= (point) bol))
|
|
334 (if (looking-at comment-start-skip)
|
|
335 (setq end (min (or limit (point-max)) (match-end 0)))
|
|
336 (backward-char)))
|
|
337 (goto-char (or end pos))
|
|
338 start)))))
|
|
339
|
|
340 (defun comment-search-backward (&optional limit noerror)
|
|
341 "Find a comment start between LIMIT and point.
|
|
342 Moves point to inside the comment and returns the position of the
|
|
343 comment-starter. If no comment is found, moves point to LIMIT
|
|
344 and raises an error or returns nil of NOERROR is non-nil."
|
|
345 ;; FIXME: If a comment-start appears inside a comment, we may erroneously
|
|
346 ;; stop there. This can be rather bad in general, but since
|
|
347 ;; comment-search-backward is only used to find the comment-column (in
|
|
348 ;; comment-set-column) and to find the comment-start string (via
|
|
349 ;; comment-beginning) in indent-new-comment-line, it should be harmless.
|
|
350 (if (not (re-search-backward comment-start-skip limit t))
|
|
351 (unless noerror (error "No comment"))
|
|
352 (beginning-of-line)
|
|
353 (let* ((end (match-end 0))
|
|
354 (cs (comment-search-forward end t))
|
|
355 (pt (point)))
|
|
356 (if (not cs)
|
|
357 (progn (beginning-of-line)
|
|
358 (comment-search-backward limit noerror))
|
|
359 (while (progn (goto-char cs)
|
|
360 (comment-forward)
|
|
361 (and (< (point) end)
|
|
362 (setq cs (comment-search-forward end t))))
|
|
363 (setq pt (point)))
|
|
364 (goto-char pt)
|
|
365 cs))))
|
|
366
|
|
367 (defun comment-beginning ()
|
|
368 "Find the beginning of the enclosing comment.
|
|
369 Returns nil if not inside a comment, else moves point and returns
|
|
370 the same as `comment-search-forward'."
|
|
371 ;; HACK ATTACK!
|
|
372 ;; We should really test `in-string-p' but that can be expensive.
|
|
373 (unless (eq (get-text-property (point) 'face) 'font-lock-string-face)
|
|
374 (let ((pt (point))
|
|
375 (cs (comment-search-backward nil t)))
|
|
376 (when cs
|
|
377 (if (save-excursion
|
|
378 (goto-char cs)
|
|
379 (and
|
|
380 ;; For modes where comment-start and comment-end are the same,
|
|
381 ;; the search above may have found a `ce' rather than a `cs'.
|
|
382 (or (not (looking-at comment-end-skip))
|
|
383 ;; Maybe font-lock knows that it's a `cs'?
|
|
384 (eq (get-text-property (match-end 0) 'face)
|
|
385 'font-lock-comment-face)
|
|
386 (unless (eq (get-text-property (point) 'face)
|
|
387 'font-lock-comment-face)
|
|
388 ;; Let's assume it's a `cs' if we're on the same line.
|
|
389 (>= (line-end-position) pt)))
|
|
390 ;; Make sure that PT is not past the end of the comment.
|
|
391 (if (comment-forward 1) (> (point) pt) (eobp))))
|
|
392 cs
|
|
393 (goto-char pt)
|
|
394 nil)))))
|
|
395
|
|
396 (defun comment-forward (&optional n)
|
|
397 "Skip forward over N comments.
|
|
398 Just like `forward-comment' but only for positive N
|
|
399 and can use regexps instead of syntax."
|
|
400 (setq n (or n 1))
|
|
401 (if (< n 0) (error "No comment-backward")
|
|
402 (if comment-use-syntax (forward-comment n)
|
|
403 (while (> n 0)
|
|
404 (setq n
|
|
405 (if (or (forward-comment 1)
|
|
406 (and (looking-at comment-start-skip)
|
|
407 (goto-char (match-end 0))
|
|
408 (re-search-forward comment-end-skip nil 'move)))
|
|
409 (1- n) -1)))
|
|
410 (= n 0))))
|
|
411
|
|
412 (defun comment-enter-backward ()
|
|
413 "Move from the end of a comment to the end of its content.
|
|
414 Point is assumed to be just at the end of a comment."
|
|
415 (if (bolp)
|
|
416 ;; comment-end = ""
|
|
417 (progn (backward-char) (skip-syntax-backward " "))
|
|
418 (let ((end (point)))
|
|
419 (beginning-of-line)
|
|
420 (save-restriction
|
|
421 (narrow-to-region (point) end)
|
|
422 (if (re-search-forward (concat comment-end-skip "\\'") nil t)
|
|
423 (goto-char (match-beginning 0))
|
|
424 ;; comment-end-skip not found probably because it was not set right.
|
|
425 ;; Since \\s> should catch the single-char case, we'll blindly
|
|
426 ;; assume we're at the end of a two-char comment-end.
|
|
427 (goto-char (point-max))
|
|
428 (backward-char 2)
|
|
429 (skip-chars-backward (string (char-after)))
|
|
430 (skip-syntax-backward " "))))))
|
|
431
|
|
432 ;;;;
|
|
433 ;;;; Commands
|
|
434 ;;;;
|
|
435
|
|
436 ;;;###autoload
|
|
437
|
|
438 ;; #### XEmacs had this: in place of just (current-column)
|
|
439 ; (defconst comment-indent-function
|
|
440 ; ;; XEmacs - add at least one space after the end of the text on the
|
|
441 ; ;; current line...
|
|
442 ; (lambda ()
|
|
443 ; (save-excursion
|
|
444 ; (beginning-of-line)
|
|
445 ; (let ((eol (save-excursion (end-of-line) (point))))
|
|
446 ; (and comment-start-skip
|
|
447 ; (re-search-forward comment-start-skip eol t)
|
|
448 ; (setq eol (match-beginning 0)))
|
|
449 ; (goto-char eol)
|
|
450 ; (skip-chars-backward " \t")
|
|
451 ; (max comment-column (1+ (current-column))))))
|
|
452 ; "Function to compute desired indentation for a comment.
|
|
453 ; This function is called with no args with point at the beginning of
|
|
454 ; the comment's starting delimiter.")
|
|
455
|
|
456 (defun comment-indent-default ()
|
|
457 "Default for `comment-indent-function'."
|
|
458 (if (and (looking-at "\\s<\\s<\\(\\s<\\)?")
|
|
459 (or (match-end 1) (/= (current-column) (current-indentation))))
|
|
460 0
|
|
461 (when (or (/= (current-column) (current-indentation))
|
|
462 (and (> comment-add 0) (looking-at "\\s<\\S<")))
|
|
463 comment-column)))
|
|
464
|
|
465 ;;;###autoload
|
|
466 (defun comment-indent (&optional continue)
|
|
467 "Indent this line's comment to comment column, or insert an empty comment.
|
|
468 If CONTINUE is non-nil, use the `comment-continue' markers if any.
|
|
469 Comments starting in column 0 are not moved."
|
|
470 (interactive "*")
|
|
471 (comment-normalize-vars)
|
|
472 (let* ((empty (save-excursion (beginning-of-line)
|
|
473 (looking-at "[ \t]*$")))
|
|
474 (starter (or (and continue comment-continue)
|
|
475 (and empty block-comment-start) comment-start))
|
|
476 (ender (or (and continue comment-continue "")
|
|
477 (and empty block-comment-end) comment-end)))
|
|
478 (unless starter (error "No comment syntax defined"))
|
|
479 (beginning-of-line)
|
|
480 (let* ((eolpos (line-end-position))
|
|
481 (begpos (comment-search-forward eolpos t))
|
|
482 cpos indent)
|
|
483 ;; An existing comment?
|
2511
|
484 (if begpos
|
|
485 (progn
|
|
486 (if (and (not (looking-at "[\t\n ]"))
|
|
487 (looking-at comment-end-skip))
|
|
488 ;; The comment is empty and we have skipped all its space
|
|
489 ;; and landed right before the comment-ender:
|
|
490 ;; Go back to the middle of the space.
|
|
491 (forward-char (/ (skip-chars-backward " \t") -2)))
|
|
492 (setq cpos (point-marker)))
|
1333
|
493 ;; If none, insert one.
|
|
494 (save-excursion
|
|
495 ;; Some comment-indent-function insist on not moving comments that
|
|
496 ;; are in column 0, so we first go to the likely target column.
|
|
497 (indent-to comment-column)
|
|
498 (setq begpos (point))
|
2511
|
499 ;; Ensure there's a space before the comment for things
|
|
500 ;; like sh where it matters (as well as being neater).
|
|
501 (unless (eq ?\ (char-syntax (char-before)))
|
|
502 (insert ?\ ))
|
1333
|
503 (insert starter)
|
|
504 (setq cpos (point-marker))
|
|
505 (insert ender)))
|
|
506 (goto-char begpos)
|
|
507 ;; Compute desired indent.
|
|
508 (setq indent (save-excursion (funcall comment-indent-function)))
|
|
509 (if (not indent)
|
2511
|
510 ;; comment-indent-function refuses: delegate to indent.
|
1333
|
511 (indent-according-to-mode)
|
|
512 ;; Avoid moving comments past the fill-column.
|
|
513 (unless (save-excursion (skip-chars-backward " \t") (bolp))
|
|
514 (setq indent
|
|
515 (min indent
|
|
516 (+ (current-column)
|
2511
|
517 (- (or comment-fill-column fill-column)
|
1333
|
518 (save-excursion (end-of-line) (current-column)))))))
|
|
519 ;; XEmacs change: Preserve indentation of comments starting in
|
|
520 ;; column 0, as documented.
|
2511
|
521 (unless (or (= (current-column) 0) (= (current-column) indent))
|
1333
|
522 ;; If that's different from current, change it.
|
2511
|
523 (delete-region (point) (progn (skip-chars-backward " \t") (point)))
|
1333
|
524 (indent-to (if (bolp) indent
|
|
525 (max indent (1+ (current-column)))))))
|
|
526 (goto-char cpos)
|
|
527 (set-marker cpos nil))))
|
|
528
|
|
529 ;;;###autoload
|
|
530 (defun comment-set-column (arg)
|
|
531 "Set the comment column based on point.
|
|
532 With no ARG, set the comment column to the current column.
|
|
533 With just minus as arg, kill any comment on this line.
|
|
534 With any other arg, set comment column to indentation of the previous comment
|
|
535 and then align or create a comment on this line at that column."
|
|
536 (interactive "P")
|
|
537 (cond
|
|
538 ((eq arg '-) (comment-kill nil))
|
|
539 (arg
|
|
540 (save-excursion
|
|
541 (beginning-of-line)
|
|
542 (comment-search-backward)
|
|
543 (beginning-of-line)
|
|
544 (goto-char (comment-search-forward (line-end-position)))
|
|
545 (setq comment-column (current-column))
|
|
546 (lmessage 'command "Comment column set to %d" comment-column))
|
|
547 (comment-indent))
|
|
548 (t (setq comment-column (current-column))
|
|
549 (lmessage 'command "Comment column set to %d" comment-column))))
|
|
550
|
|
551 ;;;###autoload
|
|
552 (defun comment-kill (arg)
|
|
553 "Kill the comment on this line, if any.
|
|
554 With prefix ARG, kill comments on that many lines starting with this one."
|
|
555 ;; XEmacs change: add *
|
|
556 (interactive "*P")
|
|
557 (dotimes (_ (prefix-numeric-value arg))
|
|
558 (save-excursion
|
|
559 (beginning-of-line)
|
|
560 (let ((cs (comment-search-forward (line-end-position) t)))
|
|
561 (when cs
|
|
562 (goto-char cs)
|
|
563 (skip-syntax-backward " ")
|
|
564 (setq cs (point))
|
|
565 (comment-forward)
|
|
566 (kill-region cs (if (bolp) (1- (point)) (point)))
|
|
567 (indent-according-to-mode))))
|
|
568 (if arg (forward-line 1))))
|
|
569
|
|
570 (defun comment-padright (str &optional n)
|
|
571 "Construct a string composed of STR plus `comment-padding'.
|
|
572 It also adds N copies of the last non-whitespace chars of STR.
|
|
573 If STR already contains padding, the corresponding amount is
|
|
574 ignored from `comment-padding'.
|
|
575 N defaults to 0.
|
|
576 If N is `re', a regexp is returned instead, that would match
|
|
577 the string for any N."
|
|
578 (setq n (or n 0))
|
|
579 (when (and (stringp str) (not (string= "" str)))
|
|
580 ;; Separate the actual string from any leading/trailing padding
|
|
581 (string-match "\\`\\s-*\\(.*?\\)\\s-*\\'" str)
|
|
582 (let ((s (match-string 1 str)) ;actual string
|
|
583 (lpad (substring str 0 (match-beginning 1))) ;left padding
|
|
584 (rpad (concat (substring str (match-end 1)) ;original right padding
|
|
585 (substring comment-padding ;additional right padding
|
|
586 (min (- (match-end 0) (match-end 1))
|
|
587 (length comment-padding)))))
|
|
588 ;; We can only duplicate C if the comment-end has multiple chars
|
|
589 ;; or if comments can be nested, else the comment-end `}' would
|
|
590 ;; be turned into `}}}' where only the first ends the comment
|
|
591 ;; and the rest becomes bogus junk.
|
|
592 (multi (not (and comment-quote-nested
|
|
593 ;; comment-end is a single char
|
|
594 (string-match "\\`\\s-*\\S-\\s-*\\'" comment-end)))))
|
|
595 (if (not (symbolp n))
|
|
596 (concat lpad s (when multi (make-string n (aref str (1- (match-end 1))))) rpad)
|
|
597 ;; construct a regexp that would match anything from just S
|
|
598 ;; to any possible output of this function for any N.
|
|
599 (concat (mapconcat (lambda (c) (concat (regexp-quote (string c)) "?"))
|
|
600 lpad "") ;padding is not required
|
|
601 (regexp-quote s)
|
|
602 (when multi "+") ;the last char of S might be repeated
|
|
603 (mapconcat (lambda (c) (concat (regexp-quote (string c)) "?"))
|
|
604 rpad "")))))) ;padding is not required
|
|
605
|
|
606 (defun comment-padleft (str &optional n)
|
|
607 "Construct a string composed of `comment-padding' plus STR.
|
|
608 It also adds N copies of the first non-whitespace chars of STR.
|
|
609 If STR already contains padding, the corresponding amount is
|
|
610 ignored from `comment-padding'.
|
|
611 N defaults to 0.
|
|
612 If N is `re', a regexp is returned instead, that would match
|
|
613 the string for any N."
|
|
614 (setq n (or n 0))
|
|
615 (when (and (stringp str) (not (string= "" str)))
|
|
616 ;; Only separate the left pad because we assume there is no right pad.
|
|
617 (string-match "\\`\\s-*" str)
|
|
618 (let ((s (substring str (match-end 0)))
|
|
619 (pad (concat (substring comment-padding
|
|
620 (min (- (match-end 0) (match-beginning 0))
|
|
621 (length comment-padding)))
|
|
622 (match-string 0 str)))
|
|
623 (c (aref str (match-end 0))) ;the first non-space char of STR
|
|
624 ;; We can only duplicate C if the comment-end has multiple chars
|
|
625 ;; or if comments can be nested, else the comment-end `}' would
|
|
626 ;; be turned into `}}}' where only the first ends the comment
|
|
627 ;; and the rest becomes bogus junk.
|
|
628 (multi (not (and comment-quote-nested
|
|
629 ;; comment-end is a single char
|
|
630 (string-match "\\`\\s-*\\S-\\s-*\\'" comment-end)))))
|
|
631 (if (not (symbolp n))
|
|
632 (concat pad (when multi (make-string n c)) s)
|
|
633 ;; Construct a regexp that would match anything from just S
|
|
634 ;; to any possible output of this function for any N.
|
|
635 ;; We match any number of leading spaces because this regexp will
|
|
636 ;; be used for uncommenting where we might want to remove
|
|
637 ;; uncomment markers with arbitrary leading space (because
|
|
638 ;; they were aligned).
|
|
639 (concat "\\s-*"
|
|
640 (if multi (concat (regexp-quote (string c)) "*"))
|
|
641 (regexp-quote s))))))
|
|
642
|
|
643 ;;;###autoload
|
|
644 (defun uncomment-region (beg end &optional arg)
|
2511
|
645 "Uncomment each line in the BEG .. END region.
|
1333
|
646 The numeric prefix ARG can specify a number of chars to remove from the
|
|
647 comment markers."
|
|
648 (interactive "*r\nP")
|
|
649 (comment-normalize-vars)
|
|
650 (if (> beg end) (let (mid) (setq mid beg beg end end mid)))
|
|
651 (save-excursion
|
|
652 (goto-char beg)
|
|
653 (setq end (copy-marker end))
|
|
654
|
2511
|
655 (let* ((numarg (prefix-numeric-value arg))
|
|
656 (ccs comment-continue)
|
|
657 (srei (comment-padright ccs 're))
|
|
658 (sre (and srei (concat "^\\s-*?\\(" srei "\\)")))
|
|
659 spt)
|
1333
|
660 (while (and (< (point) end)
|
|
661 (setq spt (comment-search-forward end t)))
|
2511
|
662 (let ((ipt (point))
|
|
663 ;; Find the end of the comment.
|
|
664 (ept (progn
|
|
665 (goto-char spt)
|
|
666 (unless (comment-forward)
|
|
667 (error "Can't find the comment end"))
|
|
668 (point)))
|
|
669 (box nil)
|
|
670 (box-equal nil)) ;Whether we might be using `=' for boxes.
|
1333
|
671 (save-restriction
|
|
672 (narrow-to-region spt ept)
|
2511
|
673
|
1333
|
674 ;; Remove the comment-start.
|
|
675 (goto-char ipt)
|
|
676 (skip-syntax-backward " ")
|
|
677 ;; A box-comment starts with a looong comment-start marker.
|
2511
|
678 (when (and (or (and (= (- (point) (point-min)) 1)
|
|
679 (setq box-equal t)
|
|
680 (looking-at "=\\{7\\}")
|
|
681 (not (eq (char-before (point-max)) ?\n))
|
|
682 (skip-chars-forward "="))
|
|
683 (> (- (point) (point-min) (length comment-start)) 7))
|
|
684 (> (count-lines (point-min) (point-max)) 2))
|
1333
|
685 (setq box t))
|
|
686 (when (looking-at (regexp-quote comment-padding))
|
|
687 (goto-char (match-end 0)))
|
|
688 (when (and sre (looking-at (concat "\\s-*\n\\s-*" srei)))
|
|
689 (goto-char (match-end 0)))
|
|
690 (if (null arg) (delete-region (point-min) (point))
|
|
691 (skip-syntax-backward " ")
|
|
692 (delete-char (- numarg)))
|
|
693
|
|
694 ;; Remove the end-comment (and leading padding and such).
|
|
695 (goto-char (point-max)) (comment-enter-backward)
|
|
696 ;; Check for special `=' used sometimes in comment-box.
|
2511
|
697 (when (and box-equal (not (eq (char-before (point-max)) ?\n)))
|
1333
|
698 (let ((pos (point)))
|
|
699 ;; skip `=' but only if there are at least 7.
|
|
700 (when (> (skip-chars-backward "=") -7) (goto-char pos))))
|
|
701 (unless (looking-at "\\(\n\\|\\s-\\)*\\'")
|
|
702 (when (and (bolp) (not (bobp))) (backward-char))
|
|
703 (if (null arg) (delete-region (point) (point-max))
|
|
704 (skip-syntax-forward " ")
|
|
705 (delete-char numarg)))
|
|
706
|
|
707 ;; Unquote any nested end-comment.
|
|
708 (comment-quote-nested comment-start comment-end t)
|
|
709
|
|
710 ;; Eliminate continuation markers as well.
|
|
711 (when sre
|
|
712 (let* ((cce (comment-string-reverse (or comment-continue
|
|
713 comment-start)))
|
|
714 (erei (and box (comment-padleft cce 're)))
|
|
715 (ere (and erei (concat "\\(" erei "\\)\\s-*$"))))
|
|
716 (goto-char (point-min))
|
|
717 (while (progn
|
|
718 (if (and ere (re-search-forward
|
|
719 ere (line-end-position) t))
|
|
720 (replace-match "" t t nil (if (match-end 2) 2 1))
|
|
721 (setq ere nil))
|
|
722 (forward-line 1)
|
|
723 (re-search-forward sre (line-end-position) t))
|
|
724 (replace-match "" t t nil (if (match-end 2) 2 1)))))
|
2116
|
725 ;; Go to the end for the next comment.
|
1333
|
726 (goto-char (point-max)))))
|
|
727 (set-marker end nil))))
|
|
728
|
|
729 (defun comment-make-extra-lines (cs ce ccs cce min-indent max-indent &optional block)
|
|
730 "Make the leading and trailing extra lines.
|
|
731 This is used for `extra-line' style (or `box' style if BLOCK is specified)."
|
|
732 (let ((eindent 0))
|
|
733 (if (not block)
|
|
734 ;; Try to match CS and CE's content so they align aesthetically.
|
|
735 (progn
|
|
736 (setq ce (comment-string-strip ce t t))
|
|
737 (when (string-match "\\(.+\\).*\n\\(.*?\\)\\1" (concat ce "\n" cs))
|
|
738 (setq eindent
|
|
739 (max (- (match-end 2) (match-beginning 2) (match-beginning 0))
|
|
740 0))))
|
|
741 ;; box comment
|
|
742 (let* ((width (- max-indent min-indent))
|
|
743 (s (concat cs "a=m" cce))
|
|
744 (e (concat ccs "a=m" ce))
|
|
745 (c (if (string-match ".*\\S-\\S-" cs)
|
2511
|
746 (aref cs (1- (match-end 0)))
|
|
747 (if (and (equal comment-end "") (string-match ".*\\S-" cs))
|
|
748 (aref cs (1- (match-end 0))) ?=)))
|
|
749 (re "\\s-*a=m\\s-*")
|
|
750 ; Huh? (_ (string-match re s))
|
|
751 (lcs (length cs))
|
1333
|
752 (fill
|
|
753 (make-string (+ width (- (match-end 0)
|
2511
|
754 (match-beginning 0) lcs 3)) c)))
|
1333
|
755 (setq cs (replace-match fill t t s))
|
2511
|
756 (when (and (not (string-match comment-start-skip cs))
|
|
757 (string-match "a=m" s))
|
|
758 ;; The whitespace around CS cannot be ignored: put it back.
|
|
759 (setq re "a=m")
|
|
760 (setq fill (make-string (- width lcs) c))
|
|
761 (setq cs (replace-match fill t t s)))
|
|
762 (string-match re e)
|
1333
|
763 (setq ce (replace-match fill t t e))))
|
|
764 (cons (concat cs "\n" (make-string min-indent ? ) ccs)
|
|
765 (concat cce "\n" (make-string (+ min-indent eindent) ? ) ce))))
|
|
766
|
|
767 (defmacro comment-with-narrowing (beg end &rest body)
|
|
768 "Execute BODY with BEG..END narrowing.
|
|
769 Space is added (and then removed) at the beginning for the text's
|
|
770 indentation to be kept as it was before narrowing."
|
2511
|
771 (declare (debug t) (indent 2))
|
1333
|
772 (let ((bindent (make-symbol "bindent")))
|
|
773 `(let ((,bindent (save-excursion (goto-char beg) (current-column))))
|
|
774 (save-restriction
|
|
775 (narrow-to-region beg end)
|
|
776 (goto-char (point-min))
|
|
777 (insert (make-string ,bindent ? ))
|
|
778 (prog1
|
|
779 (progn ,@body)
|
|
780 ;; remove the bindent
|
|
781 (save-excursion
|
|
782 (goto-char (point-min))
|
|
783 (when (looking-at " *")
|
|
784 (let ((n (min (- (match-end 0) (match-beginning 0)) ,bindent)))
|
|
785 (delete-char n)
|
|
786 (setq ,bindent (- ,bindent n))))
|
|
787 (end-of-line)
|
|
788 (let ((e (point)))
|
|
789 (beginning-of-line)
|
|
790 (while (and (> ,bindent 0) (re-search-forward " *" e t))
|
|
791 (let ((n (min ,bindent (- (match-end 0) (match-beginning 0) 1))))
|
|
792 (goto-char (match-beginning 0))
|
|
793 (delete-char n)
|
|
794 (setq ,bindent (- ,bindent n)))))))))))
|
|
795
|
|
796 (defun comment-region-internal (beg end cs ce
|
|
797 &optional ccs cce block lines indent)
|
2511
|
798 "Comment region BEG .. END.
|
1333
|
799 CS and CE are the comment start resp end string.
|
|
800 CCS and CCE are the comment continuation strings for the start resp end
|
|
801 of lines (default to CS and CE).
|
|
802 BLOCK indicates that end of lines should be marked with either CCE, CE or CS
|
|
803 \(if CE is empty) and that those markers should be aligned.
|
|
804 LINES indicates that an extra lines will be used at the beginning and end
|
|
805 of the region for CE and CS.
|
|
806 INDENT indicates to put CS and CCS at the current indentation of the region
|
|
807 rather than at left margin."
|
|
808 ;;(assert (< beg end))
|
|
809 (let ((no-empty t))
|
|
810 ;; Sanitize CE and CCE.
|
|
811 (if (and (stringp ce) (string= "" ce)) (setq ce nil))
|
|
812 (if (and (stringp cce) (string= "" cce)) (setq cce nil))
|
|
813 ;; If CE is empty, multiline cannot be used.
|
|
814 (unless ce (setq ccs nil cce nil))
|
|
815 ;; Should we mark empty lines as well ?
|
|
816 (if (or ccs block lines) (setq no-empty nil))
|
|
817 ;; Make sure we have end-markers for BLOCK mode.
|
|
818 (when block (unless ce (setq ce (comment-string-reverse cs))))
|
|
819 ;; If BLOCK is not requested, we don't need CCE.
|
|
820 (unless block (setq cce nil))
|
|
821 ;; Continuation defaults to the same as CS and CE.
|
|
822 (unless ccs (setq ccs cs cce ce))
|
2511
|
823
|
1333
|
824 (save-excursion
|
|
825 (goto-char end)
|
|
826 ;; If the end is not at the end of a line and the comment-end
|
|
827 ;; is implicit (i.e. a newline), explicitly insert a newline.
|
|
828 (unless (or ce (eolp)) (insert "\n") (indent-according-to-mode))
|
|
829 (comment-with-narrowing beg end
|
|
830 (let ((min-indent (point-max))
|
|
831 (max-indent 0))
|
|
832 (goto-char (point-min))
|
|
833 ;; Quote any nested comment marker
|
|
834 (comment-quote-nested comment-start comment-end nil)
|
|
835
|
|
836 ;; Loop over all lines to find the needed indentations.
|
|
837 (goto-char (point-min))
|
|
838 (while
|
|
839 (progn
|
|
840 (unless (looking-at "[ \t]*$")
|
|
841 (setq min-indent (min min-indent (current-indentation))))
|
|
842 (end-of-line)
|
|
843 (setq max-indent (max max-indent (current-column)))
|
|
844 (not (or (eobp) (progn (forward-line) nil)))))
|
2511
|
845
|
1333
|
846 ;; Inserting ccs can change max-indent by (1- tab-width).
|
|
847 (setq max-indent
|
|
848 (+ max-indent (max (length cs) (length ccs)) tab-width -1))
|
|
849 (unless indent (setq min-indent 0))
|
|
850
|
|
851 ;; make the leading and trailing lines if requested
|
|
852 (when lines
|
|
853 (let ((csce
|
|
854 (comment-make-extra-lines
|
|
855 cs ce ccs cce min-indent max-indent block)))
|
|
856 (setq cs (car csce))
|
|
857 (setq ce (cdr csce))))
|
2511
|
858
|
1333
|
859 (goto-char (point-min))
|
|
860 ;; Loop over all lines from BEG to END.
|
|
861 (while
|
|
862 (progn
|
|
863 (unless (and no-empty (looking-at "[ \t]*$"))
|
|
864 (move-to-column min-indent t)
|
|
865 (insert cs) (setq cs ccs) ;switch to CCS after the first line
|
|
866 (end-of-line)
|
|
867 (if (eobp) (setq cce ce))
|
|
868 (when cce
|
|
869 (when block (move-to-column max-indent t))
|
|
870 (insert cce)))
|
|
871 (end-of-line)
|
|
872 (not (or (eobp) (progn (forward-line) nil))))))))))
|
|
873
|
|
874 ;;;###autoload
|
|
875 (defun comment-region (beg end &optional arg)
|
|
876 "Comment or uncomment each line in the region.
|
2511
|
877 With just \\[universal-argument] prefix arg, uncomment each line in region BEG .. END.
|
1333
|
878 Numeric prefix arg ARG means use ARG comment characters.
|
|
879 If ARG is negative, delete that many comment characters instead.
|
|
880 By default, comments start at the left margin, are terminated on each line,
|
|
881 even for syntax in which newline does not end the comment and blank lines
|
|
882 do not get comments. This can be changed with `comment-style'.
|
|
883
|
|
884 The strings used as comment starts are built from
|
|
885 `comment-start' without trailing spaces and `comment-padding'."
|
|
886 (interactive "*r\nP")
|
|
887 (comment-normalize-vars)
|
|
888 (if (> beg end) (let (mid) (setq mid beg beg end end mid)))
|
|
889 (let* ((numarg (prefix-numeric-value arg))
|
|
890 (add comment-add)
|
|
891 (style (cdr (assoc comment-style comment-styles)))
|
|
892 (lines (nth 2 style))
|
|
893 (block (nth 1 style))
|
|
894 (multi (nth 0 style)))
|
|
895 (save-excursion
|
|
896 ;; we use `chars' instead of `syntax' because `\n' might be
|
|
897 ;; of end-comment syntax rather than of whitespace syntax.
|
|
898 ;; sanitize BEG and END
|
|
899 (goto-char beg) (skip-chars-forward " \t\n\r") (beginning-of-line)
|
|
900 (setq beg (max beg (point)))
|
|
901 (goto-char end) (skip-chars-backward " \t\n\r") (end-of-line)
|
|
902 (setq end (min end (point)))
|
|
903 (if (>= beg end) (error "Nothing to comment"))
|
|
904
|
|
905 ;; sanitize LINES
|
|
906 (setq lines
|
|
907 (and
|
|
908 lines ;; multi
|
|
909 (progn (goto-char beg) (beginning-of-line)
|
|
910 (skip-syntax-forward " ")
|
|
911 (>= (point) beg))
|
|
912 (progn (goto-char end) (end-of-line) (skip-syntax-backward " ")
|
|
913 (<= (point) end))
|
2511
|
914 (or block (not (string= "" comment-end)))
|
|
915 (or block (progn (goto-char beg) (search-forward "\n" end t))))))
|
1333
|
916
|
|
917 ;; don't add end-markers just because the user asked for `block'
|
|
918 (unless (or lines (string= "" comment-end)) (setq block nil))
|
|
919
|
|
920 (cond
|
|
921 ((consp arg) (uncomment-region beg end))
|
|
922 ((< numarg 0) (uncomment-region beg end (- numarg)))
|
|
923 (t
|
|
924 (setq numarg (if (and (null arg) (= (length comment-start) 1))
|
|
925 add (1- numarg)))
|
|
926 (comment-region-internal
|
|
927 beg end
|
|
928 (let ((s (comment-padright comment-start numarg)))
|
|
929 (if (string-match comment-start-skip s) s
|
|
930 (comment-padright comment-start)))
|
|
931 (let ((s (comment-padleft comment-end numarg)))
|
|
932 (and s (if (string-match comment-end-skip s) s
|
|
933 (comment-padright comment-end))))
|
|
934 (if multi (comment-padright comment-continue numarg))
|
|
935 (if multi (comment-padleft (comment-string-reverse comment-continue) numarg))
|
|
936 block
|
|
937 lines
|
|
938 (nth 3 style))))))
|
|
939
|
|
940 (defun comment-box (beg end &optional arg)
|
2511
|
941 "Comment out the BEG .. END region, putting it inside a box.
|
1333
|
942 The numeric prefix ARG specifies how many characters to add to begin- and
|
|
943 end- comment markers additionally to what `comment-add' already specifies."
|
|
944 (interactive "*r\np")
|
|
945 (let ((comment-style (if (cadr (assoc comment-style comment-styles))
|
|
946 'box-multi 'box)))
|
|
947 (comment-region beg end (+ comment-add arg))))
|
|
948
|
2511
|
949
|
|
950 ;;;###autoload
|
|
951 (defun comment-or-uncomment-region (beg end &optional arg)
|
|
952 "Call `comment-region', unless the region only consists of comments,
|
|
953 in which case call `uncomment-region'. If a prefix arg is given, it
|
|
954 is passed on to the respective function."
|
|
955 (interactive "*r\nP")
|
|
956 (funcall (if (save-excursion ;; check for already commented region
|
|
957 (goto-char beg)
|
|
958 (comment-forward (point-max))
|
|
959 (<= end (point)))
|
|
960 'uncomment-region 'comment-region)
|
|
961 beg end arg))
|
|
962
|
1333
|
963 ;;;###autoload
|
|
964 (defun comment-dwim (arg)
|
|
965 "Call the comment command you want (Do What I Mean).
|
|
966 If the region is active and `transient-mark-mode' is on, call
|
|
967 `comment-region' (unless it only consists of comments, in which
|
|
968 case it calls `uncomment-region').
|
|
969 Else, if the current line is empty, insert a comment and indent it.
|
|
970 Else if a prefix ARG is specified, call `comment-kill'.
|
|
971 Else, call `comment-indent'."
|
|
972 (interactive "*P")
|
|
973 (comment-normalize-vars)
|
|
974 (if (region-active-p) ;mark-active transient-mark-mode)
|
2511
|
975 (comment-or-uncomment-region (region-beginning) (region-end) arg)
|
1333
|
976 (if (save-excursion (beginning-of-line) (not (looking-at "\\s-*$")))
|
|
977 ;; FIXME: If there's no comment to kill on this line and ARG is
|
|
978 ;; specified, calling comment-kill is not very clever.
|
|
979 (if arg (comment-kill (and (integerp arg) arg)) (comment-indent))
|
|
980 (let ((add (if arg (prefix-numeric-value arg)
|
|
981 (if (= (length comment-start) 1) comment-add 0))))
|
|
982 ;; Some modes insist on keeping column 0 comment in column 0
|
|
983 ;; so we need to move away from it before inserting the comment.
|
|
984 (indent-according-to-mode)
|
|
985 (insert (comment-padright comment-start add))
|
|
986 (save-excursion
|
|
987 (unless (string= "" comment-end)
|
|
988 (insert (comment-padleft comment-end add)))
|
|
989 (indent-according-to-mode))))))
|
|
990
|
|
991 (defcustom comment-auto-fill-only-comments nil
|
|
992 "Non-nil means to only auto-fill inside comments.
|
|
993 This has no effect in modes that do not define a comment syntax."
|
2511
|
994 :type 'boolean)
|
|
995
|
|
996 (defun comment-valid-prefix (prefix compos)
|
|
997 (or
|
|
998 ;; Accept any prefix if the current comment is not EOL-terminated.
|
|
999 (save-excursion (goto-char compos) (comment-forward) (not (bolp)))
|
|
1000 ;; Accept any prefix that starts with a comment-start marker.
|
|
1001 (string-match (concat "\\`[ \t]*\\(?:" comment-start-skip "\\)")
|
|
1002 fill-prefix)))
|
1333
|
1003
|
|
1004 ;;;###autoload
|
|
1005 (defun comment-indent-new-line (&optional soft)
|
|
1006 "Break line at point and indent, continuing comment if within one.
|
|
1007 This indents the body of the continued comment
|
|
1008 under the previous comment line.
|
|
1009
|
|
1010 This command is intended for styles where you write a comment per line,
|
|
1011 starting a new comment (and terminating it if necessary) on each line.
|
|
1012 If you want to continue one comment across several lines, use \\[newline-and-indent].
|
|
1013
|
|
1014 If a fill column is specified, it overrides the use of the comment column
|
|
1015 or comment indentation.
|
|
1016
|
|
1017 The inserted newline is marked hard if variable `use-hard-newlines' is true,
|
|
1018 unless optional argument SOFT is non-nil."
|
|
1019 (interactive)
|
|
1020 (comment-normalize-vars t)
|
|
1021 (let (compos comin)
|
|
1022 ;; If we are not inside a comment and we only auto-fill comments,
|
|
1023 ;; don't do anything (unless no comment syntax is defined).
|
|
1024 (unless (and comment-start
|
|
1025 comment-auto-fill-only-comments
|
2511
|
1026 (not (interactive-p))
|
1333
|
1027 (not (save-excursion
|
|
1028 (prog1 (setq compos (comment-beginning))
|
|
1029 (setq comin (point))))))
|
|
1030
|
|
1031 ;; XEmacs: next 3 lines from old version.
|
|
1032 (skip-chars-backward " \t")
|
|
1033 (if (featurep 'mule)
|
|
1034 (declare-fboundp (kinsoku-process)))
|
2511
|
1035
|
|
1036 ;; Now we know we should auto-fill.
|
|
1037 ;; Insert the newline before removing empty space so that markers
|
|
1038 ;; get preserved better.
|
1333
|
1039 (if soft (insert-and-inherit ?\n) (newline 1))
|
2511
|
1040 (save-excursion (forward-char -1) (delete-horizontal-space))
|
|
1041 (delete-horizontal-space)
|
|
1042
|
|
1043 (if (and fill-prefix (not adaptive-fill-mode))
|
|
1044 ;; Blindly trust a non-adaptive fill-prefix.
|
1333
|
1045 (progn
|
|
1046 (indent-to-left-margin)
|
2511
|
1047 (insert-before-markers-and-inherit fill-prefix))
|
1333
|
1048
|
|
1049 ;;#### jhod: probably need to fix this for kinsoku processing
|
|
1050 ;; If necessary check whether we're inside a comment.
|
2511
|
1051 (unless (or compos (null comment-start))
|
1333
|
1052 (save-excursion
|
|
1053 (backward-char)
|
|
1054 (setq compos (comment-beginning))
|
|
1055 (setq comin (point))))
|
|
1056
|
2511
|
1057 (cond
|
|
1058 ;; If there's an adaptive prefix, use it unless we're inside
|
|
1059 ;; a comment and the prefix is not a comment starter.
|
|
1060 ((and fill-prefix
|
|
1061 (or (not compos)
|
|
1062 (comment-valid-prefix fill-prefix compos)))
|
|
1063 (indent-to-left-margin)
|
|
1064 (insert-and-inherit fill-prefix))
|
|
1065 ;; If we're not inside a comment, just try to indent.
|
|
1066 ;; #### XEmacs: the line `(if comcol' was changed as follows.
|
|
1067 ;; I'm leaving it out since who knows if it's applicable any more.
|
|
1068 ;; --ben
|
|
1069 ;; (if (and comcol (not fill-prefix)) ; XEmacs - (ENE) from fa-extras.
|
|
1070 ((not compos) (indent-according-to-mode))
|
|
1071 (t
|
1333
|
1072 (let* ((comment-column
|
|
1073 ;; The continuation indentation should be somewhere between
|
|
1074 ;; the current line's indentation (plus 2 for good measure)
|
|
1075 ;; and the current comment's indentation, with a preference
|
|
1076 ;; for comment-column.
|
|
1077 (save-excursion
|
2511
|
1078 ;; FIXME: use prev line's info rather than first line's.
|
1333
|
1079 (goto-char compos)
|
|
1080 (min (current-column) (max comment-column
|
|
1081 (+ 2 (current-indentation))))))
|
|
1082 (comstart (buffer-substring compos comin))
|
|
1083 (normalp
|
|
1084 (string-match (regexp-quote (comment-string-strip
|
|
1085 comment-start t t))
|
|
1086 comstart))
|
|
1087 (comment-end
|
|
1088 (if normalp comment-end
|
|
1089 ;; The comment starter is not the normal comment-start
|
|
1090 ;; so we can't just use comment-end.
|
|
1091 (save-excursion
|
|
1092 (goto-char compos)
|
|
1093 (if (not (comment-forward)) comment-end
|
|
1094 (comment-string-strip
|
|
1095 (buffer-substring
|
|
1096 (save-excursion (comment-enter-backward) (point))
|
|
1097 (point))
|
|
1098 nil t)))))
|
|
1099 (comment-start comstart)
|
2511
|
1100 (continuep (or comment-multi-line
|
|
1101 (cadr (assoc comment-style comment-styles))))
|
1333
|
1102 ;; Force comment-continue to be recreated from comment-start.
|
|
1103 ;; FIXME: wrong if comment-continue was set explicitly!
|
2511
|
1104 ;; FIXME: use prev line's continuation if available.
|
1333
|
1105 (comment-continue nil))
|
2511
|
1106 (if (and comment-multi-line (> (length comment-end) 0))
|
|
1107 (indent-according-to-mode)
|
|
1108 (insert-and-inherit ?\n)
|
|
1109 (forward-char -1)
|
|
1110 (comment-indent continuep)
|
|
1111 (save-excursion
|
|
1112 (let ((pt (point)))
|
|
1113 (end-of-line)
|
|
1114 (let ((comend (buffer-substring pt (point))))
|
|
1115 ;; The 1+ is to make sure we delete the \n inserted above.
|
|
1116 (delete-region pt (1+ (point)))
|
|
1117 (end-of-line 0)
|
|
1118 (insert comend))))))))))))
|
1333
|
1119
|
|
1120 (provide 'newcomment)
|
|
1121
|
|
1122 ;;; newcomment.el ends here
|