]> git.eshelyaron.com Git - emacs.git/commitdiff
Allow count-lines to ignore invisible lines
authorRobert Weiner <rsw@gnu.org>
Tue, 11 Aug 2020 14:52:01 +0000 (16:52 +0200)
committerLars Ingebrigtsen <larsi@gnus.org>
Tue, 11 Aug 2020 14:52:11 +0000 (16:52 +0200)
* doc/lispref/positions.texi (Text Lines): Document it (bug#23675).

* lisp/simple.el (count-lines): Add an optional parameter to
ignore invisible lines (bug#23675).

doc/lispref/positions.texi
etc/NEWS
lisp/simple.el

index d7856ce73e36539008b442615b9427267de5cac4..91419702ca1370679fdd807132dc2df0cf1329c6 100644 (file)
@@ -411,7 +411,7 @@ function counts that line as one line successfully moved.
 In an interactive call, @var{count} is the numeric prefix argument.
 @end deffn
 
-@defun count-lines start end
+@defun count-lines start end &optional ignore-invisible-lines
 @cindex lines in region
 @anchor{Definition of count-lines}
 This function returns the number of lines between the positions
@@ -420,6 +420,9 @@ This function returns the number of lines between the positions
 1, even if @var{start} and @var{end} are on the same line.  This is
 because the text between them, considered in isolation, must contain at
 least one line unless it is empty.
+
+If the optional @var{ignore-invisible-lines} is non-@code{nil},
+invisible lines will not be included in the count.
 @end defun
 
 @deffn Command count-words start end
index f914e1be20c7fc94b8a3135e6a3406d73f2e6d5c..5c44c970dde82d454088c746a6bcd6ac49200f43 100644 (file)
--- a/etc/NEWS
+++ b/etc/NEWS
@@ -868,6 +868,10 @@ have now been removed.
 \f
 * Lisp Changes in Emacs 28.1
 
++++
+** The 'count-lines' function now takes an optional parameter to
+ignore invisible lines.
+
 ---
 ** New function 'custom-add-choice'.
 This function can be used by modes to add elements to the
index 4d59108a34fe0587e89700b049856cf85d34b773..6f72c3b81b99a6d1268c2a8ec17876aed64299b4 100644 (file)
@@ -1366,28 +1366,47 @@ END, without printing any message."
          (message "line %d (narrowed line %d)"
                   (+ n (line-number-at-pos start) -1) n))))))
 
-(defun count-lines (start end)
+(defun count-lines (start end &optional ignore-invisible-lines)
   "Return number of lines between START and END.
-This is usually the number of newlines between them,
-but can be one more if START is not equal to END
-and the greater of them is not at the start of a line."
+This is usually the number of newlines between them, but can be
+one more if START is not equal to END and the greater of them is
+not at the start of a line.
+
+When IGNORE-INVISIBLE-LINES is non-nil, invisible lines are not
+included in the count."
   (save-excursion
     (save-restriction
       (narrow-to-region start end)
       (goto-char (point-min))
-      (if (eq selective-display t)
-         (save-match-data
-           (let ((done 0))
-                     (while (re-search-forward "[\n\C-m]" nil t 40)
-                       (setq done (+ 40 done)))
-                     (while (re-search-forward "[\n\C-m]" nil t 1)
-                       (setq done (+ 1 done)))
-                     (goto-char (point-max))
-                     (if (and (/= start end)
-                      (not (bolp)))
-                 (1+ done)
-               done)))
-       (- (buffer-size) (forward-line (buffer-size)))))))
+      (cond ((and (not ignore-invisible-lines)
+                  (eq selective-display t))
+            (save-match-data
+              (let ((done 0))
+                (while (re-search-forward "\n\\|\r[^\n]" nil t 40)
+                  (setq done (+ 40 done)))
+                (while (re-search-forward "\n\\|\r[^\n]" nil t 1)
+                  (setq done (+ 1 done)))
+                (goto-char (point-max))
+                (if (and (/= start end)
+                         (not (bolp)))
+                    (1+ done)
+                  done))))
+           (ignore-invisible-lines
+            (save-match-data
+              (- (buffer-size)
+                  (forward-line (buffer-size))
+                 (let ((invisible-count 0)
+                       prop)
+                   (goto-char (point-min))
+                   (while (re-search-forward "\n\\|\r[^\n]" nil t)
+                     (setq prop (get-char-property (1- (point)) 'invisible))
+                     (if (if (eq buffer-invisibility-spec t)
+                             prop
+                           (or (memq prop buffer-invisibility-spec)
+                               (assq prop buffer-invisibility-spec)))
+                         (setq invisible-count (1+ invisible-count))))
+                   invisible-count))))
+           (t (- (buffer-size) (forward-line (buffer-size))))))))
 
 (defun line-number-at-pos (&optional pos absolute)
   "Return buffer line number at position POS.