Add arch taglines
[bpt/emacs.git] / lisp / newcomment.el
index 07c4e3a..5e85fbc 100644 (file)
@@ -1,6 +1,6 @@
 ;;; newcomment.el --- (un)comment regions of buffers
 
-;; Copyright (C) 1999, 2000  Free Software Foundation Inc.
+;; Copyright (C) 1999,2000,2003  Free Software Foundation Inc.
 
 ;; Author: code extracted from Emacs-20's simple.el
 ;; Maintainer: Stefan Monnier <monnier@cs.yale.edu>
@@ -34,7 +34,6 @@
 ;; - nested comments in sgml-mode are not properly quoted.
 ;; - single-char nestable comment-start can only do the "\\s<+" stuff
 ;;   if the corresponding closing marker happens to be right.
-;; - comment-box in TeXinfo generate bogus comments @ccccc@
 ;; - uncomment-region with a numeric argument can render multichar
 ;;   comment markers invalid.
 ;; - comment-indent or comment-region when called inside a comment
 ;;;###autoload
 (defalias 'indent-new-comment-line 'comment-indent-new-line)
 
-;;;###autoload
 (defgroup comment nil
   "Indenting and filling of comments."
   :prefix "comment-"
   :version "21.1"
   :group 'fill)
 
+;; Autoload this to avoid warnings, since some major modes define it.
+;;;###autoload
 (defvar comment-use-syntax 'undecided
   "Non-nil if syntax-tables can be used instead of regexps.
 Can also be `undecided' which means that a somewhat expensive test will
@@ -194,6 +194,15 @@ makes the comment easier to read.  Default is 1.  nil means 0."
 This is obsolete because you might as well use \\[newline-and-indent]."
   :type 'boolean)
 
+(defcustom comment-empty-lines nil
+  "If nil, `comment-region' does not comment out empty lines.
+If t, it always comments out empty lines.
+if `eol' it only comments out empty lines if comments are
+terminated by the end of line (i.e. `comment-end' is empty)."
+  :type '(choice (const :tag "Never" nil)
+         (const :tag "Always" t)
+         (const :tag "EOl-terminated" 'eol)))
+
 ;;;;
 ;;;; Helpers
 ;;;;
@@ -211,7 +220,14 @@ This is obsolete because you might as well use \\[newline-and-indent]."
 
 ;;;###autoload
 (defun comment-normalize-vars (&optional noerror)
-  (if (not comment-start) (or noerror (error "No comment syntax is defined"))
+  "Check and setup the variables needed by other commenting functions.
+Functions autoloaded from newcomment.el, being entry points, should call
+this function before any other, so the rest of the code can assume that
+the variables are properly set."
+  (if (not comment-start)
+      (unless noerror
+       (set (make-local-variable 'comment-start)
+            (read-string "No comment syntax is defined.  Use: ")))
     ;; comment-use-syntax
     (when (eq comment-use-syntax 'undecided)
       (set (make-local-variable 'comment-use-syntax)
@@ -246,7 +262,7 @@ This is obsolete because you might as well use \\[newline-and-indent]."
                 ;; In case comment-start has changed since last time.
                 (string-match comment-start-skip comment-start))
       (set (make-local-variable 'comment-start-skip)
-          (concat "\\(\\(^\\|[^\\\\\n]\\)\\(\\\\\\\\\\)*\\)\\(\\s<+\\|"
+          (concat "\\(\\(^\\|[^\\\n]\\)\\(\\\\\\\\\\)*\\)\\(\\s<+\\|"
                   (regexp-quote (comment-string-strip comment-start t t))
                   ;; Let's not allow any \s- but only [ \t] since \n
                   ;; might be both a comment-end marker and \s-.
@@ -264,7 +280,7 @@ This is obsolete because you might as well use \\[newline-and-indent]."
                     (if (and comment-quote-nested (<= (length ce) 1)) "" "+")
                     (regexp-quote (substring ce 1))
                     "\\)"))))))
+
 (defun comment-quote-re (str unp)
   (concat (regexp-quote (substring str 0 1))
          "\\\\" (if unp "+" "*")
@@ -474,6 +490,10 @@ If CONTINUE is non-nil, use the `comment-continue' markers if any."
            ;; Some comment-indent-function insist on not moving comments that
            ;; are in column 0, so we first go to the likely target column.
            (indent-to comment-column)
+           ;; Ensure there's a space before the comment for things
+           ;; like sh where it matters (as well as being neater).
+           (unless (memq (char-before) '(nil ?\n ?\t ?\ ))
+             (insert ?\ ))
            (setq begpos (point))
            (insert starter)
            (setq cpos (point-marker))
@@ -482,15 +502,36 @@ If CONTINUE is non-nil, use the `comment-continue' markers if any."
       ;; Compute desired indent.
       (setq indent (save-excursion (funcall comment-indent-function)))
       (if (not indent)
-         ;; comment-indent-function refuses: delegate to indent.
+         ;; comment-indent-function refuses: delegate to line-indent.
          (indent-according-to-mode)
        ;; Avoid moving comments past the fill-column.
        (unless (save-excursion (skip-chars-backward " \t") (bolp))
-         (setq indent
-               (min indent
-                    (+ (current-column)
+         (let ((max (+ (current-column)
                        (- (or comment-fill-column fill-column)
-                          (save-excursion (end-of-line) (current-column)))))))
+                          (save-excursion (end-of-line) (current-column))))))
+           (if (<= max indent)
+               (setq indent max)       ;Don't move past the fill column.
+             ;; We can choose anywhere between indent..max.
+             ;; Let's try to align to a comment on the previous line.
+             (let ((other nil))
+               (save-excursion
+                 (when (and (zerop (forward-line -1))
+                            (setq other (comment-search-forward
+                                        (line-end-position) t)))
+                   (goto-char other) (setq other (current-column))))
+               (if (and other (<= other max) (> other indent))
+                   ;; There is a comment and it's in the range: bingo.
+                   (setq indent other)
+                 ;; Let's try to align to a comment on the next line, then.
+                 (let ((other nil))
+                   (save-excursion
+                     (when (and (zerop (forward-line 1))
+                                (setq other (comment-search-forward
+                                            (line-end-position) t)))
+                       (goto-char other) (setq other (current-column))))
+                   (if (and other (<= other max) (> other indent))
+                       ;; There is a comment and it's in the range: bingo.
+                       (setq indent other))))))))
        (unless (= (current-column) indent)
          ;; If that's different from current, change it.
          (delete-region (point) (progn (skip-chars-backward " \t") (point)))
@@ -510,6 +551,7 @@ With any other arg, set comment column to indentation of the previous comment
   (cond
    ((eq arg '-) (comment-kill nil))
    (arg
+    (comment-normalize-vars)
     (save-excursion
       (beginning-of-line)
       (comment-search-backward)
@@ -526,6 +568,7 @@ With any other arg, set comment column to indentation of the previous comment
   "Kill the comment on this line, if any.
 With prefix ARG, kill comments on that many lines starting with this one."
   (interactive "P")
+  (comment-normalize-vars)
   (dotimes (_ (prefix-numeric-value arg))
     (save-excursion
       (beginning-of-line)
@@ -614,7 +657,7 @@ If N is `re', a regexp is returned instead, that would match
 
 ;;;###autoload
 (defun uncomment-region (beg end &optional arg)
-  "Uncomment each line in the BEG..END region.
+  "Uncomment each line in the BEG .. END region.
 The numeric prefix ARG can specify a number of chars to remove from the
 comment markers."
   (interactive "*r\nP")
@@ -623,44 +666,59 @@ comment markers."
   (save-excursion
     (goto-char beg)
     (setq end (copy-marker end))
-    (let ((numarg (prefix-numeric-value arg))
-         spt)
+    (let* ((numarg (prefix-numeric-value arg))
+           (ccs comment-continue)
+           (srei (comment-padright ccs 're))
+           (csre (comment-padright comment-start 're))
+           (sre (and srei (concat "^\\s-*?\\(" srei "\\)")))
+           spt)
       (while (and (< (point) end)
                  (setq spt (comment-search-forward end t)))
-       (let* ((ipt (point))
-              ;; Find the end of the comment.
-              (ept (progn
-                     (goto-char spt)
-                     (unless (comment-forward)
-                       (error "Can't find the comment end"))
-                     (point)))
-              (box nil)
-              (ccs comment-continue)
-              (srei (comment-padright ccs 're))
-              (sre (and srei (concat "^\\s-*?\\(" srei "\\)"))))
+       (let ((ipt (point))
+              ;; Find the end of the comment.
+              (ept (progn
+                     (goto-char spt)
+                     (unless (comment-forward)
+                       (error "Can't find the comment end"))
+                     (point)))
+              (box nil)
+              (box-equal nil))     ;Whether we might be using `=' for boxes.
          (save-restriction
            (narrow-to-region spt ept)
+
            ;; Remove the comment-start.
            (goto-char ipt)
            (skip-syntax-backward " ")
-           ;; Check for special `=' used sometimes in comment-box.
-           (when (and (= (- (point) (point-min)) 1) (looking-at "=\\{7\\}"))
-             (skip-chars-forward "="))
            ;; A box-comment starts with a looong comment-start marker.
-           (when (> (- (point) (point-min) (length comment-start)) 7)
+           (when (and (or (and (= (- (point) (point-min)) 1)
+                               (setq box-equal t)
+                               (looking-at "=\\{7\\}")
+                               (not (eq (char-before (point-max)) ?\n))
+                               (skip-chars-forward "="))
+                          (> (- (point) (point-min) (length comment-start)) 7))
+                      (> (count-lines (point-min) (point-max)) 2))
              (setq box t))
-           (when (looking-at (regexp-quote comment-padding))
-             (goto-char (match-end 0)))
+           ;; Skip the padding.  Padding can come from comment-padding and/or
+           ;; from comment-start, so we first check comment-start.
+           (if (or (save-excursion (goto-char (point-min)) (looking-at csre))
+                   (looking-at (regexp-quote comment-padding)))
+               (goto-char (match-end 0)))
            (when (and sre (looking-at (concat "\\s-*\n\\s-*" srei)))
              (goto-char (match-end 0)))
            (if (null arg) (delete-region (point-min) (point))
              (skip-syntax-backward " ")
-             (delete-char (- numarg)))
+             (delete-char (- numarg))
+             (unless (or (bobp)
+                         (save-excursion (goto-char (point-min))
+                                         (looking-at comment-start-skip)))
+               ;; If there's something left but it doesn't look like
+               ;; a comment-start any more, just remove it.
+               (delete-region (point-min) (point))))
 
            ;; Remove the end-comment (and leading padding and such).
            (goto-char (point-max)) (comment-enter-backward)
            ;; Check for special `=' used sometimes in comment-box.
-           (when (= (- (point-max) (point)) 1)
+           (when (and box-equal (not (eq (char-before (point-max)) ?\n)))
              (let ((pos (point)))
                ;; skip `=' but only if there are at least 7.
                (when (> (skip-chars-backward "=") -7) (goto-char pos))))
@@ -668,7 +726,11 @@ comment markers."
              (when (and (bolp) (not (bobp))) (backward-char))
              (if (null arg) (delete-region (point) (point-max))
                (skip-syntax-forward " ")
-               (delete-char numarg)))
+               (delete-char numarg)
+               (unless (or (eobp) (looking-at comment-end-skip))
+                 ;; If there's something left but it doesn't look like
+                 ;; a comment-end any more, just remove it.
+                 (delete-region (point) (point-max)))))
 
            ;; Unquote any nested end-comment.
            (comment-quote-nested comment-start comment-end t)
@@ -730,16 +792,15 @@ This is used for `extra-line' style (or `box' style if BLOCK is specified)."
     (cons (concat cs "\n" (make-string min-indent ? ) ccs)
          (concat cce "\n" (make-string (+ min-indent eindent) ? ) ce))))
 
-(def-edebug-spec comment-with-narrowing t)
-(put 'comment-with-narrowing 'lisp-indent-function 2)
 (defmacro comment-with-narrowing (beg end &rest body)
   "Execute BODY with BEG..END narrowing.
 Space is added (and then removed) at the beginning for the text's
 indentation to be kept as it was before narrowing."
+  (declare (debug t) (indent 2))
   (let ((bindent (make-symbol "bindent")))
-    `(let ((,bindent (save-excursion (goto-char beg) (current-column))))
+    `(let ((,bindent (save-excursion (goto-char ,beg) (current-column))))
        (save-restriction
-        (narrow-to-region beg end)
+        (narrow-to-region ,beg ,end)
         (goto-char (point-min))
         (insert (make-string ,bindent ? ))
         (prog1
@@ -773,7 +834,8 @@ of the region for CE and CS.
 INDENT indicates to put CS and CCS at the current indentation of the region
 rather than at left margin."
   ;;(assert (< beg end))
-  (let ((no-empty t))
+  (let ((no-empty (not (or (eq comment-empty-lines t)
+                          (and comment-empty-lines (zerop (length ce)))))))
     ;; Sanitize CE and CCE.
     (if (and (stringp ce) (string= "" ce)) (setq ce nil))
     (if (and (stringp cce) (string= "" cce)) (setq cce nil))
@@ -787,7 +849,7 @@ rather than at left margin."
     (unless block (setq cce nil))
     ;; Continuation defaults to the same as CS and CE.
     (unless ccs (setq ccs cs cce ce))
-    
+
     (save-excursion
       (goto-char end)
       ;; If the end is not at the end of a line and the comment-end
@@ -809,7 +871,7 @@ rather than at left margin."
                (end-of-line)
                (setq max-indent (max max-indent (current-column)))
                (not (or (eobp) (progn (forward-line) nil)))))
-         
+
          ;; Inserting ccs can change max-indent by (1- tab-width).
          (setq max-indent
                (+ max-indent (max (length cs) (length ccs)) tab-width -1))
@@ -822,7 +884,7 @@ rather than at left margin."
                    cs ce ccs cce min-indent max-indent block)))
              (setq cs (car csce))
              (setq ce (cdr csce))))
-         
+
          (goto-char (point-min))
          ;; Loop over all lines from BEG to END.
          (while
@@ -920,6 +982,7 @@ end- comment markers additionally to what `comment-add' already specifies."
 in which case call `uncomment-region'.  If a prefix arg is given, it
 is passed on to the respective function."
   (interactive "*r\nP")
+  (comment-normalize-vars)
   (funcall (if (save-excursion ;; check for already commented region
                 (goto-char beg)
                 (comment-forward (point-max))
@@ -960,13 +1023,13 @@ Else, call `comment-indent'."
 This has no effect in modes that do not define a comment syntax."
   :type 'boolean)
 
-(defun comment-valid-prefix (prefix compos)
+(defun comment-valid-prefix-p (prefix compos)
   (or
    ;; Accept any prefix if the current comment is not EOL-terminated.
    (save-excursion (goto-char compos) (comment-forward) (not (bolp)))
    ;; Accept any prefix that starts with a comment-start marker.
    (string-match (concat "\\`[ \t]*\\(?:" comment-start-skip "\\)")
-                fill-prefix)))
+                prefix)))
 
 ;;;###autoload
 (defun comment-indent-new-line (&optional soft)
@@ -1020,7 +1083,7 @@ unless optional argument SOFT is non-nil."
         ;; a comment and the prefix is not a comment starter.
         ((and fill-prefix
               (or (not compos)
-                  (comment-valid-prefix fill-prefix compos)))
+                  (comment-valid-prefix-p fill-prefix compos)))
          (indent-to-left-margin)
          (insert-and-inherit fill-prefix))
         ;; If we're not inside a comment, just try to indent.
@@ -1076,4 +1139,5 @@ unless optional argument SOFT is non-nil."
 
 (provide 'newcomment)
 
+;;; arch-tag: 01e3320a-00c8-44ea-a696-8f8e7354c858
 ;;; newcomment.el ends here