;;; newcomment.el --- (un)comment regions of buffers
;; Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004,
-;; 2005, 2006, 2007 Free Software Foundation, Inc.
+;; 2005, 2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc.
;; Author: code extracted from Emacs-20's simple.el
;; Maintainer: Stefan Monnier <monnier@iro.umontreal.ca>
;; Keywords: comment uncomment
+;; Package: emacs
;; This file is part of GNU Emacs.
-;; GNU Emacs is free software; you can redistribute it and/or modify
+;; GNU Emacs 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 3, or (at your option)
-;; any later version.
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
;; GNU Emacs is distributed in the hope that it will be useful,
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
;; GNU General Public License for more details.
;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to the
-;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
-;; Boston, MA 02110-1301, USA.
+;; along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>.
;;; Commentary:
;;;###autoload(put 'comment-end-skip 'safe-local-variable 'string-or-null-p)
;;;###autoload
-(defvar comment-end ""
+(defvar comment-end (purecopy "")
"*String to insert to end a new comment.
Should be an empty string if comments are terminated by end-of-line.")
;;;###autoload(put 'comment-end 'safe-local-variable 'string-or-null-p)
it is 1 so that regions are commented with two or three semi-colons.")
(defconst comment-styles
- '((plain . (nil nil nil nil))
- (indent . (nil nil nil t))
- (indent-or-triple
- . (nil nil nil multi-char))
- (aligned . (nil t nil t))
- (multi-line . (t nil nil t))
- (extra-line . (t nil t t))
- (box . (nil t t t))
- (box-multi . (t t t t)))
- "Comment region styles of the form (STYLE . (MULTI ALIGN EXTRA INDENT)).
+ '((plain nil nil nil nil
+ "Start in column 0 (do not indent), as in Emacs-20")
+ (indent-or-triple nil nil nil multi-char
+ "Start in column 0, but only for single-char starters")
+ (indent nil nil nil t
+ "Full comment per line, ends not aligned")
+ (aligned nil t nil t
+ "Full comment per line, ends aligned")
+ (box nil t t t
+ "Full comment per line, ends aligned, + top and bottom")
+ (extra-line t nil t t
+ "One comment for all lines, end on a line by itself")
+ (multi-line t nil nil t
+ "One comment for all lines, end on last commented line")
+ (box-multi t t t t
+ "One comment for all lines, + top and bottom"))
+ "Comment region style definitions.
+Each style is defined with a form (STYLE . (MULTI ALIGN EXTRA INDENT DOC)).
+DOC should succinctly describe the style.
STYLE should be a mnemonic symbol.
MULTI specifies that comments are allowed to span multiple lines.
+ e.g. in C it comments regions as
+ /* blabla
+ * bli */
+ rather than
+ /* blabla */
+ /* bli */
+ if `comment-end' is empty, this has no effect.
+
ALIGN specifies that the `comment-end' markers should be aligned.
+ e.g. in C it comments regions as
+ /* blabla */
+ /* bli */
+ rather than
+ /* blabla */
+ /* bli */
+ if `comment-end' is empty, this has no effect, unless EXTRA is also set,
+ in which case the comment gets wrapped in a box.
+
EXTRA specifies that an extra line should be used before and after the
region to comment (to put the `comment-end' and `comment-start').
+ e.g. in C it comments regions as
+ /*
+ * blabla
+ * bli
+ */
+ rather than
+ /* blabla
+ * bli */
+ if the comment style is not multi line, this has no effect, unless ALIGN
+ is also set, in which case the comment gets wrapped in a box.
+
INDENT specifies that the `comment-start' markers should not be put at the
left margin but at the current indentation of the region to comment.
If INDENT is `multi-char', that means indent multi-character
comment starters, but not one-character comment starters.")
;;;###autoload
-(defcustom comment-style 'indent-or-triple
+(defcustom comment-style 'indent
"Style to be used for `comment-region'.
See `comment-styles' for a list of available styles."
:type (if (boundp 'comment-styles)
- `(choice ,@(mapcar (lambda (s) `(const ,(car s)))
- comment-styles))
+ `(choice
+ ,@(mapcar (lambda (s)
+ `(const :tag ,(format "%s: %s" (car s) (nth 5 s))
+ ,(car s)))
+ comment-styles))
'symbol)
+ :version "23.1"
:group 'comment)
;;;###autoload
-(defcustom comment-padding " "
+(defcustom comment-padding (purecopy " ")
"Padding string that `comment-region' puts between comment chars and text.
Can also be an integer which will be automatically turned into a string
of the corresponding number of spaces.
"+\\)[ \t]*")))
(unless (and comment-end-skip
;; In case comment-end has changed since last time.
- (string-match comment-end-skip comment-end))
+ (string-match comment-end-skip
+ (if (string= "" comment-end) "\n" comment-end)))
(let ((ce (if (string= "" comment-end) "\n"
(comment-string-strip comment-end t t))))
(set (make-local-variable 'comment-end-skip)
;; comment-end = ""
(progn (backward-char) (skip-syntax-backward " "))
(cond
- ((save-restriction
- (narrow-to-region (line-beginning-position) (point))
- (goto-char (point-min))
- (re-search-forward (concat comment-end-skip "\\'") nil t))
+ ((save-excursion
+ (save-restriction
+ (narrow-to-region (line-beginning-position) (point))
+ (goto-char (point-min))
+ (re-search-forward (concat comment-end-skip "\\'") nil t)))
(goto-char (match-beginning 0)))
;; comment-end-skip not found probably because it was not set
;; right. Since \\s> should catch the single-char case, let's
(let* ((eolpos (line-end-position))
(begpos (comment-search-forward eolpos t))
cpos indent)
- ;; An existing comment?
- (if begpos
- (progn
- (if (and (not (looking-at "[\t\n ]"))
- (looking-at comment-end-skip))
- ;; The comment is empty and we have skipped all its space
- ;; and landed right before the comment-ender:
- ;; Go back to the middle of the space.
- (forward-char (/ (skip-chars-backward " \t") -2)))
- (setq cpos (point-marker)))
+ (if (and comment-insert-comment-function (not begpos))
+ ;; If no comment and c-i-c-f is set, let it do everything.
+ (funcall comment-insert-comment-function)
+ ;; An existing comment?
+ (if begpos
+ (progn
+ (if (and (not (looking-at "[\t\n ]"))
+ (looking-at comment-end-skip))
+ ;; The comment is empty and we have skipped all its space
+ ;; and landed right before the comment-ender:
+ ;; Go back to the middle of the space.
+ (forward-char (/ (skip-chars-backward " \t") -2)))
+ (setq cpos (point-marker)))
;; If none, insert one.
- (if comment-insert-comment-function
- (funcall comment-insert-comment-function)
(save-excursion
;; Some `comment-indent-function's insist on not moving
;; comments that are in column 0, so we first go to the
(setq begpos (point))
(insert starter)
(setq cpos (point-marker))
- (insert ender))))
- (goto-char begpos)
- ;; Compute desired indent.
- (setq indent (save-excursion (funcall comment-indent-function)))
- ;; If `indent' is nil and there's code before the comment, we can't
- ;; use `indent-according-to-mode', so we default to comment-column.
- (unless (or indent (save-excursion (skip-chars-backward " \t") (bolp)))
- (setq indent comment-column))
- (if (not indent)
- ;; comment-indent-function refuses: delegate to line-indent.
- (indent-according-to-mode)
- ;; If the comment is at the right of code, adjust the indentation.
- (unless (save-excursion (skip-chars-backward " \t") (bolp))
- (setq indent (comment-choose-indent indent)))
- ;; Update INDENT to leave at least one space
- ;; after other nonwhite text on the line.
- (save-excursion
- (skip-chars-backward " \t")
- (unless (bolp)
- (setq indent (max indent (1+ (current-column))))))
- ;; If that's different from comment's current position, change it.
- (unless (= (current-column) indent)
- (delete-region (point) (progn (skip-chars-backward " \t") (point)))
- (indent-to indent)))
- (goto-char cpos)
- (set-marker cpos nil))))
+ (insert ender)))
+ (goto-char begpos)
+ ;; Compute desired indent.
+ (setq indent (save-excursion (funcall comment-indent-function)))
+ ;; If `indent' is nil and there's code before the comment, we can't
+ ;; use `indent-according-to-mode', so we default to comment-column.
+ (unless (or indent (save-excursion (skip-chars-backward " \t") (bolp)))
+ (setq indent comment-column))
+ (if (not indent)
+ ;; comment-indent-function refuses: delegate to line-indent.
+ (indent-according-to-mode)
+ ;; If the comment is at the right of code, adjust the indentation.
+ (unless (save-excursion (skip-chars-backward " \t") (bolp))
+ (setq indent (comment-choose-indent indent)))
+ ;; Update INDENT to leave at least one space
+ ;; after other nonwhite text on the line.
+ (save-excursion
+ (skip-chars-backward " \t")
+ (unless (bolp)
+ (setq indent (max indent (1+ (current-column))))))
+ ;; If that's different from comment's current position, change it.
+ (unless (= (current-column) indent)
+ (delete-region (point) (progn (skip-chars-backward " \t") (point)))
+ (indent-to indent)))
+ (goto-char cpos)
+ (set-marker cpos nil)))))
;;;###autoload
(defun comment-set-column (arg)
;;;###autoload
(defun comment-kill (arg)
- "Kill the comment on this line, if any.
+ "Kill the first comment on this line, if any.
With prefix ARG, kill comments on that many lines starting with this one."
(interactive "P")
(comment-normalize-vars)
(delete-char n)
(setq ,bindent (- ,bindent n)))))))))))
-;; Compute the number of extra comment starter characters
-;; (extra semicolons in Lisp mode, extra stars in C mode, etc.)
-;; If ARG is non-nil, just follow ARG.
-;; If the comment-starter is multi-char, just follow ARG.
-;; Otherwise obey comment-add, and double it if EXTRA is non-nil.
(defun comment-add (arg)
+ "Compute the number of extra comment starter characters
+\(extra semicolons in Lisp mode, extra stars in C mode, etc.)
+If ARG is non-nil, just follow ARG.
+If the comment starter is multi-char, just follow ARG.
+Otherwise obey `comment-add'."
(if (and (null arg) (= (string-match "[ \t]*\\'" comment-start) 1))
(* comment-add 1)
(1- (prefix-numeric-value arg))))
the region rather than at left margin."
;;(assert (< beg end))
(let ((no-empty (not (or (eq comment-empty-lines t)
- (and comment-empty-lines (zerop (length ce)))))))
+ (and comment-empty-lines (zerop (length ce))))))
+ ce-sanitized)
;; Sanitize CE and CCE.
(if (and (stringp ce) (string= "" ce)) (setq ce nil))
+ (setq ce-sanitized ce)
(if (and (stringp cce) (string= "" cce)) (setq cce nil))
;; If CE is empty, multiline cannot be used.
(unless ce (setq ccs nil cce nil))
(goto-char end)
;; If the end is not at the end of a line and the comment-end
;; is implicit (i.e. a newline), explicitly insert a newline.
- (unless (or ce (eolp)) (insert "\n") (indent-according-to-mode))
+ (unless (or ce-sanitized (eolp)) (insert "\n") (indent-according-to-mode))
(comment-with-narrowing beg end
(let ((min-indent (point-max))
(max-indent 0))
With just \\[universal-argument] prefix arg, uncomment each line in region BEG .. END.
Numeric prefix ARG means use ARG comment characters.
If ARG is negative, delete that many comment characters instead.
-By default, comments start at the left margin, are terminated on each line,
-even for syntax in which newline does not end the comment and blank lines
-do not get comments. This can be changed with `comment-style'.
-The strings used as comment starts are built from
-`comment-start' without trailing spaces and `comment-padding'."
+The strings used as comment starts are built from `comment-start'
+and `comment-padding'; the strings used as comment ends are built
+from `comment-end' and `comment-padding'.
+
+By default, the `comment-start' markers are inserted at the
+current indentation of the region, and comments are terminated on
+each line (even for syntaxes in which newline does not end the
+comment and blank lines do not get comments). This can be
+changed with `comment-style'."
(interactive "*r\nP")
(comment-normalize-vars)
(if (> beg end) (let (mid) (setq mid beg beg end end mid)))
((< numarg 0) (uncomment-region beg end (- numarg)))
(t
(let ((multi-char (/= (string-match "[ \t]*\\'" comment-start) 1))
- indent)
+ indent triple)
(if (eq (nth 3 style) 'multi-char)
- (setq indent multi-char)
+ (save-excursion
+ (goto-char beg)
+ (setq indent multi-char
+ ;; Triple if we will put the comment starter at the margin
+ ;; and the first line of the region isn't indented
+ ;; at least two spaces.
+ triple (and (not multi-char) (looking-at "\t\\| "))))
(setq indent (nth 3 style)))
;; In Lisp and similar modes with one-character comment starters,
;; double it by default if `comment-add' says so.
;; If it isn't indented, triple it.
(if (and (null arg) (not multi-char))
- (setq numarg (* comment-add (if indent 1 2)))
+ (setq numarg (* comment-add (if triple 2 1)))
(setq numarg (1- (prefix-numeric-value arg))))
(comment-region-internal
(defun comment-dwim (arg)
"Call the comment command you want (Do What I Mean).
If the region is active and `transient-mark-mode' is on, call
- `comment-region' (unless it only consists of comments, in which
- case it calls `uncomment-region').
-Else, if the current line is empty, insert a comment and indent it.
+`comment-region' (unless it only consists of comments, in which
+case it calls `uncomment-region').
+Else, if the current line is empty, call `comment-insert-comment-function'
+if it is defined, otherwise insert a comment and indent it.
Else if a prefix ARG is specified, call `comment-kill'.
Else, call `comment-indent'.
You can configure `comment-style' to change the way regions are commented."
;; FIXME: If there's no comment to kill on this line and ARG is
;; specified, calling comment-kill is not very clever.
(if arg (comment-kill (and (integerp arg) arg)) (comment-indent))
- (let ((add (comment-add arg)))
- ;; Some modes insist on keeping column 0 comment in column 0
- ;; so we need to move away from it before inserting the comment.
- (indent-according-to-mode)
- (insert (comment-padright comment-start add))
- (save-excursion
- (unless (string= "" comment-end)
- (insert (comment-padleft comment-end add)))
- (indent-according-to-mode))))))
+ ;; Inserting a comment on a blank line. comment-indent calls
+ ;; c-i-c-f if needed in the non-blank case.
+ (if comment-insert-comment-function
+ (funcall comment-insert-comment-function)
+ (let ((add (comment-add arg)))
+ ;; Some modes insist on keeping column 0 comment in column 0
+ ;; so we need to move away from it before inserting the comment.
+ (indent-according-to-mode)
+ (insert (comment-padright comment-start add))
+ (save-excursion
+ (unless (string= "" comment-end)
+ (insert (comment-padleft comment-end add)))
+ (indent-according-to-mode)))))))
;;;###autoload
(defcustom comment-auto-fill-only-comments nil
(buffer-substring (point)
(progn (move-to-left-margin)
(point)))))))))))))
-
+
;;;###autoload
(defun comment-indent-new-line (&optional soft)
;; don't do anything (unless no comment syntax is defined).
(unless (and comment-start
comment-auto-fill-only-comments
- (not (interactive-p))
+ (not (called-interactively-p 'interactive))
(not (save-excursion
(prog1 (setq compos (comment-beginning))
(setq comin (point))))))