Re: bug#23675: 30.0.50: make count-lines optionally ignore invisible lines
"J.P." <[email protected]>
| Newsgroups | gmane.emacs.erc.general |
|---|---|
| Message-ID | <[email protected]> |
Closed in 2020 (Emacs 28). Perhaps I'm not understanding how the `ignore-invisible-lines' parameter for `count-lines' is supposed to work, but it doesn't seem to make the function consider `invisible' text properties that have lists as values. I bring this up because ERC will likely be needing a line-counting function that's list-aware, at least in the manner shown in the attached tests. The change to `count-lines' accompanying these tests was merely lifted from `forward-visible-line' to make them pass, but it's quite possibly flawed and/or incomplete. If a proper solution ever emerges to address this, hopefully it'll come at the hands of someone better informed than I in the ways of Emacs invisibility. In the meantime (2023), ERC will likely be doing its own subpar rendition unless someone takes up the challenge for 30.1 (and Compat agrees to adopt it). Thanks.
0001-POC-Honor-invisible-text-prop-list-values-in-count-l.patch
(text/x-patch, 4.9 KB)
From 68fb034a60f74ea3cab9acd8e35bdf52ba9d5024 Mon Sep 17 00:00:00 2001 From: "F. Jason Park" <[email protected]> Date: Thu, 3 Aug 2023 22:24:57 -0700 Subject: [PATCH] [POC] Honor invisible text-prop list values in count-lines * lisp/simple.el (count-lines): Use `invisible-p' when `ignore-invisible-lines' parameter is non-nil. * test/lisp/simple-tests.el (simple-tests-count-lines/invisible/interval, simple-tests-count-lines/invisible/list/single, simple-tests-count-lines/invisible/list/tail): Add tests. (Bug#23675) --- lisp/simple.el | 19 ++++-------- test/lisp/simple-tests.el | 62 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 67 insertions(+), 14 deletions(-) diff --git a/lisp/simple.el b/lisp/simple.el index 6dc08ff0eb0..5c414fb364f 100644 --- a/lisp/simple.el +++ b/lisp/simple.el @@ -1782,20 +1782,11 @@ count-lines done)))) (ignore-invisible-lines (goto-char (point-min)) - (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)))) + (let ((count (if (eobp) 0 1))) + (while (and (zerop (forward-line)) (not (eobp))) + (unless (invisible-p (1- (point))) + (cl-incf count))) + count)) (t (goto-char (point-max)) (if (bolp) diff --git a/test/lisp/simple-tests.el b/test/lisp/simple-tests.el index 7dabb735522..e8e83c9a5cd 100644 --- a/test/lisp/simple-tests.el +++ b/test/lisp/simple-tests.el @@ -67,6 +67,68 @@ simple-test-count-lines/ignore-invisible-lines (insert (propertize "\nbar\nbaz\nzut" 'invisible t)) (should (= (count-lines (point-min) (point-max) t) 2)))) +(ert-deftest simple-tests-count-lines/invisible/interval () + (with-current-buffer (get-buffer-create "*count-lines/invisible/interval*") + (should (= 0 (count-lines (point-min) (point-max) t))) ; invisible + (insert "pre\n" + "before\n" + (propertize "0\n" 'invisible t) + (propertize "1\n" 'invisible t) + (propertize "2\n" 'invisible t) + (propertize "3\n" 'invisible t) + "after\n" + "post\n") + (should (equal buffer-invisibility-spec 't)) + (with-restriction 5 (- (point-max) 5) + (goto-char (point-min)) + (should (looking-at "before")) + (goto-char (point-max)) + (should (looking-back "after\n"))) + (should (= 6 (count-lines 5 (- (point-max) 5)))) + (should (= 2 (count-lines 5 (- (point-max) 5) t))) ; invisible + (when noninteractive (kill-buffer)))) + +(ert-deftest simple-tests-count-lines/invisible/list/single () + (with-current-buffer (get-buffer-create "*count-lines/invisible/list/head*") + (insert "before\n" + (propertize "0\n" 'invisible '(0)) + (propertize "1\n" 'invisible '(1)) + (propertize "2\n" 'invisible '(2)) + (propertize "3\n" 'invisible '(3)) + "after\n") + (setq buffer-invisibility-spec '(0 1 (2 . t) 3 t)) + (should (= 6 (count-lines (point-min) (point-max)))) + (should (= 2 (count-lines (point-min) (point-max) t))) ; invisible + (when noninteractive (kill-buffer))) + + (with-current-buffer (get-buffer-create "*count-lines/invisible/list/alt*") + (insert "before\n" + (propertize "0\n" 'invisible '(0)) + "a\n" + (propertize "1\n" 'invisible '(1)) + "b\n" + (propertize "2\n" 'invisible '(2)) + "c\n" + (propertize "3\n" 'invisible '(3)) + "after\n") + (setq buffer-invisibility-spec '(0 1 (2 . t) 3 t)) + (should (= 9 (count-lines (point-min) (point-max)))) + (should (= 5 (count-lines (point-min) (point-max) t))) ; invisible + (when noninteractive (kill-buffer)))) + +(ert-deftest simple-tests-count-lines/invisible/list/tail () + (with-current-buffer (get-buffer-create "*count-lines/invisible/list/tail*") + (insert "before\n" + (propertize "0\n" 'invisible '(x 0)) + (propertize "1\n" 'invisible '(x 1)) + (propertize "2\n" 'invisible '(x 2)) + (propertize "3\n" 'invisible '(x 3)) + "after\n") + (setq buffer-invisibility-spec '(0 (1 . t) 2 3 t)) + (should (= 6 (count-lines (point-min) (point-max)))) + (should (= 2 (count-lines (point-min) (point-max) t))) ; invisible + (when noninteractive (kill-buffer)))) + (ert-deftest simple-text-count-lines-non-ascii () (with-temp-buffer (insert "あ\nい\nう\nえ\nお\n") -- 2.41.0