From 11e6b69b53af34118d615302b80c601f1247f6d2 Mon Sep 17 00:00:00 2001 From: Johannes Mueller Date: Sat, 14 Mar 2026 17:08:50 +0100 Subject: [PATCH 1/3] Introduce cov-next-uncovered and cov-prev-uncovered --- cov.el | 26 +++++++ test/clover/uncovered/all-covered | 10 +++ test/clover/uncovered/clover.xml | 38 +++++++++++ .../uncovered/multiple-uncovered-unsorted | 10 +++ test/clover/uncovered/one-uncovered | 11 +++ test/cov-test.el | 68 +++++++++++++++++++ 6 files changed, 163 insertions(+) create mode 100644 test/clover/uncovered/all-covered create mode 100644 test/clover/uncovered/clover.xml create mode 100644 test/clover/uncovered/multiple-uncovered-unsorted create mode 100644 test/clover/uncovered/one-uncovered diff --git a/cov.el b/cov.el index a5f40d7..7750d0a 100644 --- a/cov.el +++ b/cov.el @@ -774,6 +774,32 @@ even if part of the line is outside any narrrowing." (cov-turn-on) (cov-turn-off)))) +;;;###autoload +(defun cov-next-uncovered () + "Go to next uncovered line." + (interactive) + (let ((next-uncovered (cl-find-if (lambda (line) (> line (line-number-at-pos))) + (sort (cov--buffer-uncovered))))) + (if next-uncovered + (progn (goto-char (point-min)) + (forward-line (1- next-uncovered))) + (message "No more uncovered sections.")))) + +;;;###autoload +(defun cov-prev-uncovered () + "Go to previous unvocered line." + (interactive) + (let ((prev-uncovered (cl-find-if (lambda (line) (< line (line-number-at-pos))) + (sort (cov--buffer-uncovered) :reverse t)))) + (if prev-uncovered + (progn (goto-char (point-min)) + (forward-line (1- prev-uncovered))) + (message "No more uncovered sections.")))) + +(defun cov--buffer-uncovered () + "Compile list of line numbers of statements that have a zero coverage." + (mapcar #'car (seq-filter (lambda (line) (eql (cadr line) 0)) (cov--get-buffer-coverage)))) + (provide 'cov) ;;; cov.el ends here diff --git a/test/clover/uncovered/all-covered b/test/clover/uncovered/all-covered new file mode 100644 index 0000000..0ef3554 --- /dev/null +++ b/test/clover/uncovered/all-covered @@ -0,0 +1,10 @@ +comment line + +a line executed 100% +a line executed 86% +a line executed 85% +a line executed 84% +a line executed 46% +a line executed 45% +a line executed 44% +a line executed 1% diff --git a/test/clover/uncovered/clover.xml b/test/clover/uncovered/clover.xml new file mode 100644 index 0000000..cb8acd5 --- /dev/null +++ b/test/clover/uncovered/clover.xml @@ -0,0 +1,38 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/test/clover/uncovered/multiple-uncovered-unsorted b/test/clover/uncovered/multiple-uncovered-unsorted new file mode 100644 index 0000000..84706be --- /dev/null +++ b/test/clover/uncovered/multiple-uncovered-unsorted @@ -0,0 +1,10 @@ +comment line + +a line executed 100% +a line executed 86% +a line executed 85% +first line never executed +a line executed 46% +a line executed 45% +second line never executed +a line executed 1% diff --git a/test/clover/uncovered/one-uncovered b/test/clover/uncovered/one-uncovered new file mode 100644 index 0000000..7c683f6 --- /dev/null +++ b/test/clover/uncovered/one-uncovered @@ -0,0 +1,11 @@ +comment line + +a line executed 100% +a line executed 86% +a line executed 85% +a line executed 84% +a line executed 46% +a line executed 45% +a line executed 44% +a line executed 1% +a line never executed diff --git a/test/cov-test.el b/test/cov-test.el index 02a8f0d..069a09a 100644 --- a/test/cov-test.el +++ b/test/cov-test.el @@ -945,6 +945,74 @@ text properties with list values." (dolist (overlay cov-overlays) (should (equal (overlay-get overlay 'help-echo) (pop expected))))))) +(ert-deftest cov-mode--next-uncovered-no-uncovered () + (cov--with-test-buffer "clover/uncovered/all-covered" + (cov-mode 0) + (cov-mode 1) + (mocker-let ((message (msg) ((:input '("No more uncovered sections."))))) + (cov-next-uncovered)))) + +(ert-deftest cov-mode--next-uncovered-one-uncovered () + (cov--with-test-buffer "clover/uncovered/one-uncovered" + (cov-mode 0) + (cov-mode 1) + (mocker-let ((message (msg) ((:input '("No more uncovered sections.") :occur 0)))) + (cov-next-uncovered)) + (should (eql (point) 183)) + (mocker-let ((message (msg) ((:input '("No more uncovered sections.") :occur 1)))) + (cov-next-uncovered)) + (should (eql (point) 183)))) + +(ert-deftest cov-mode--next-uncovered-two-uncovered () + (cov--with-test-buffer "clover/uncovered/multiple-uncovered-unsorted" + (cov-mode 0) + (cov-mode 1) + (mocker-let ((message (msg) ((:input '("No more uncovered sections.") :occur 0)))) + (cov-next-uncovered)) + (should (eql (point) 78)) + (mocker-let ((message (msg) ((:input '("No more uncovered sections.") :occur 0)))) + (cov-next-uncovered)) + (should (eql (point) 146)) + (mocker-let ((message (msg) ((:input '("No more uncovered sections.") :occur 1)))) + (cov-next-uncovered)) + (should (eql (point) 146)))) + +(ert-deftest cov-mode--prev-uncovered-no-uncovered () + (cov--with-test-buffer "clover/uncovered/all-covered" + (cov-mode 0) + (cov-mode 1) + (goto-char (point-max)) + (mocker-let ((message (msg) ((:input '("No more uncovered sections."))))) + (cov-prev-uncovered)))) + +(ert-deftest cov-mode--prev-uncovered-one-uncovered () + (cov--with-test-buffer "clover/uncovered/one-uncovered" + (cov-mode 0) + (cov-mode 1) + (goto-char (point-max)) + (mocker-let ((message (msg) ((:input '("No more uncovered sections.") :occur 0)))) + (cov-prev-uncovered)) + (should (eql (point) 183)) + (mocker-let ((message (msg) ((:input '("No more uncovered sections.") :occur 1)))) + (cov-prev-uncovered)) + (should (eql (point) 183)))) + +(ert-deftest cov-mode--prev-uncovered-two-uncovered () + (cov--with-test-buffer "clover/uncovered/multiple-uncovered-unsorted" + (cov-mode 0) + (cov-mode 1) + (goto-char (point-max)) + (mocker-let ((message (msg) ((:input '("No more uncovered sections.") :occur 0)))) + (cov-prev-uncovered)) + (should (eql (point) 146)) + (mocker-let ((message (msg) ((:input '("No more uncovered sections.") :occur 0)))) + (cov-prev-uncovered)) + (should (eql (point) 78)) + (mocker-let ((message (msg) ((:input '("No more uncovered sections.") :occur 1)))) + (cov-prev-uncovered)) + (should (eql (point) 78)))) + + ;; Local Variables: ;; indent-tabs-mode: nil ;; End: From a61961039fc2a2014a571a9efc11e70e24029cee Mon Sep 17 00:00:00 2001 From: Johannes Mueller Date: Sat, 14 Mar 2026 17:37:50 +0100 Subject: [PATCH 2/3] Introduce cov-number-uncovered --- cov.el | 5 +++++ test/clover/uncovered/no-coverage-data | 9 +++++++++ test/cov-test.el | 23 +++++++++++++++++++++++ 3 files changed, 37 insertions(+) create mode 100644 test/clover/uncovered/no-coverage-data diff --git a/cov.el b/cov.el index 7750d0a..4601627 100644 --- a/cov.el +++ b/cov.el @@ -800,6 +800,11 @@ even if part of the line is outside any narrrowing." "Compile list of line numbers of statements that have a zero coverage." (mapcar #'car (seq-filter (lambda (line) (eql (cadr line) 0)) (cov--get-buffer-coverage)))) +(defun cov-number-uncovered () + "Caclulate number of uncovered statements in current buffer." + (when (cov--get-buffer-coverage) + (length (cov--buffer-uncovered)))) + (provide 'cov) ;;; cov.el ends here diff --git a/test/clover/uncovered/no-coverage-data b/test/clover/uncovered/no-coverage-data new file mode 100644 index 0000000..98cc87b --- /dev/null +++ b/test/clover/uncovered/no-coverage-data @@ -0,0 +1,9 @@ +comment line + +a line with unknown coverage +a line with unknown coverage +a line with unknown coverage +a line with unknown coverage +a line with unknown coverage +a line with unknown coverage +a line with unknown coverage diff --git a/test/cov-test.el b/test/cov-test.el index 069a09a..2365ee3 100644 --- a/test/cov-test.el +++ b/test/cov-test.el @@ -1012,6 +1012,29 @@ text properties with list values." (cov-prev-uncovered)) (should (eql (point) 78)))) +(ert-deftest cov-mode--number-uncovered-allcovered () + (cov--with-test-buffer "clover/uncovered/all-covered" + (cov-mode 0) + (cov-mode 1) + (should (eq (cov-number-uncovered) 0)))) + +(ert-deftest cov-mode--number-uncovered-one-uncovered () + (cov--with-test-buffer "clover/uncovered/one-uncovered" + (cov-mode 0) + (cov-mode 1) + (should (eq (cov-number-uncovered) 1)))) + +(ert-deftest cov-mode--number-uncovered-two-uncovered () + (cov--with-test-buffer "clover/uncovered/multiple-uncovered-unsorted" + (cov-mode 0) + (cov-mode 1) + (should (eq (cov-number-uncovered) 2)))) + +(ert-deftest cov-mode--number-uncovered-no-coverage-data () + (cov--with-test-buffer "clover/uncovered/no-coverage-data" + (cov-mode 0) + (cov-mode 1) + (should (eq (cov-number-uncovered) nil)))) ;; Local Variables: ;; indent-tabs-mode: nil From 65efb1a02e11f8c323603cfe447c8aec319b73c0 Mon Sep 17 00:00:00 2001 From: Johannes Mueller Date: Sat, 14 Mar 2026 18:11:40 +0100 Subject: [PATCH 3/3] Show number of uncovered statements in lighter --- cov.el | 10 +++++++++- test/cov-test.el | 25 +++++++++++++++++++++++++ 2 files changed, 34 insertions(+), 1 deletion(-) diff --git a/cov.el b/cov.el index 4601627..629b674 100644 --- a/cov.el +++ b/cov.el @@ -768,7 +768,7 @@ even if part of the line is outside any narrrowing." ;;;###autoload (define-minor-mode cov-mode "Minor mode for cov." - :lighter " cov" + :lighter (:eval (format " cov(%s)" (cov--lighter-indicator))) (progn (if cov-mode (cov-turn-on) @@ -805,6 +805,14 @@ even if part of the line is outside any narrrowing." (when (cov--get-buffer-coverage) (length (cov--buffer-uncovered)))) +(defun cov--lighter-indicator () + "Setup string to show how many statements are uncovered in current buffer." + (let ((uncovered (cov-number-uncovered)) + (total (length (cov--get-buffer-coverage)))) + (if uncovered + (format "%s/%s" uncovered total) + "?"))) + (provide 'cov) ;;; cov.el ends here diff --git a/test/cov-test.el b/test/cov-test.el index 2365ee3..f6c1b69 100644 --- a/test/cov-test.el +++ b/test/cov-test.el @@ -1036,6 +1036,31 @@ text properties with list values." (cov-mode 1) (should (eq (cov-number-uncovered) nil)))) + +(ert-deftest cov-mode--lighter-allcovered () + (cov--with-test-buffer "clover/uncovered/all-covered" + (cov-mode 0) + (cov-mode 1) + (should (equal (cov--lighter-indicator) "0/8")))) + +(ert-deftest cov-mode--lighter-one-uncovered () + (cov--with-test-buffer "clover/uncovered/one-uncovered" + (cov-mode 0) + (cov-mode 1) + (should (equal (cov--lighter-indicator) "1/9")))) + +(ert-deftest cov-mode--lighter-two-uncovered () + (cov--with-test-buffer "clover/uncovered/multiple-uncovered-unsorted" + (cov-mode 0) + (cov-mode 1) + (should (equal (cov--lighter-indicator) "2/8")))) + +(ert-deftest cov-mode--lighter-no-coverage-data () + (cov--with-test-buffer "clover/uncovered/no-coverage-data" + (cov-mode 0) + (cov-mode 1) + (should (equal (cov--lighter-indicator) "?")))) + ;; Local Variables: ;; indent-tabs-mode: nil ;; End: