From: Robert Weiner Date: Tue, 11 Aug 2020 14:52:01 +0000 (+0200) Subject: Allow count-lines to ignore invisible lines X-Git-Tag: emacs-28.0.90~6687 X-Git-Url: http://git.eshelyaron.com/gitweb/?a=commitdiff_plain;h=4d4d3e42caca5d823dd66b62f25a1bdd833ba484;p=emacs.git Allow count-lines to ignore invisible lines * 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). --- diff --git a/doc/lispref/positions.texi b/doc/lispref/positions.texi index d7856ce73e3..91419702ca1 100644 --- a/doc/lispref/positions.texi +++ b/doc/lispref/positions.texi @@ -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 diff --git a/etc/NEWS b/etc/NEWS index f914e1be20c..5c44c970dde 100644 --- a/etc/NEWS +++ b/etc/NEWS @@ -868,6 +868,10 @@ have now been removed. * 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 diff --git a/lisp/simple.el b/lisp/simple.el index 4d59108a34f..6f72c3b81b9 100644 --- a/lisp/simple.el +++ b/lisp/simple.el @@ -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.