From e2208276021def42dadd5e422aa96e9004040dd9 Mon Sep 17 00:00:00 2001 From: Craig Jennings Date: Sun, 7 Jun 2026 06:43:17 -0500 Subject: feat(render): highlight unsaved comments and update the cues live Completes the modified-ticket indicator (docs/modified-ticket-indicator-spec.org) on top of the field highlight and count. A changed comment now gets its own highlight by ownership: your own comment (pushable) takes pearl-modified-highlight and bubbles up to the ticket heading; a non-own comment, which save skips, takes the muted pearl-modified-local; a comment seen before the viewer resolves takes the neutral pearl-modified-unknown until classification lands. The viewer is resolved only when a comment is actually dirty, so opening or editing a clean or field-only buffer makes no network call. The cues update live: a buffer-local after-change hook debounces a redecorate on an idle timer (pearl-modified-idle-delay), so an edit shows within a fraction of a second instead of waiting for a save or refresh. The timer is cancelled when pearl-mode turns off or the buffer is killed. One pearl--redecorate-modified now drives the field highlights, the comment classification, and the count from a single scan, called on mode enable, fetch/refresh, and the idle tick. --- tests/test-pearl-modified.el | 60 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 60 insertions(+) (limited to 'tests') diff --git a/tests/test-pearl-modified.el b/tests/test-pearl-modified.el index cfef923..8529b07 100644 --- a/tests/test-pearl-modified.el +++ b/tests/test-pearl-modified.el @@ -171,5 +171,65 @@ (should (null (seq-filter (lambda (o) (overlay-get o 'pearl-modified)) (overlays-in (point-min) (point-max))))))) +;;; phase 4 -- per-comment highlight by ownership + +(ert-deftest test-pearl-comment-highlight-face-own-is-pushable () + (should (eq 'pearl-modified-highlight + (pearl--comment-highlight-face '(:author-id "v") "v")))) + +(ert-deftest test-pearl-comment-highlight-face-non-own-is-local () + (should (eq 'pearl-modified-local + (pearl--comment-highlight-face '(:author-id "other") "v")))) + +(ert-deftest test-pearl-comment-highlight-face-unresolved-viewer-is-unknown () + (should (eq 'pearl-modified-unknown + (pearl--comment-highlight-face '(:author-id "v") nil))) + (should (eq 'pearl-modified-unknown + (pearl--comment-highlight-face '(:author-id "v") "v" t)))) + +(ert-deftest test-pearl-comment-region-spans-the-comment-subtree () + (with-temp-buffer + (insert "* F\n** TODO PEARL-1 Alpha\n:PROPERTIES:\n:LINEAR-ID: i1\n:END:\n" + "*** Comments\n**** Comment by X\n:PROPERTIES:\n:LINEAR-COMMENT-ID: c1\n:END:\n" + "the comment body\n") + (org-mode) + (goto-char (point-min)) (re-search-forward "Comment by X") (org-back-to-heading t) + (let ((text (let ((r (pearl--comment-region))) + (buffer-substring-no-properties (car r) (cdr r))))) + (should (string-match-p "Comment by X" text)) + (should (string-match-p "the comment body" text))))) + +;;; phase 3 -- live after-change trigger + +(ert-deftest test-pearl-modified-after-change-schedules-timer () + "An edit schedules a debounced redecorate timer when the indicator is on." + (with-temp-buffer + (let ((pearl-show-modified-indicator t) + (pearl--modified-timer nil)) + (pearl--modified-after-change) + (should (timerp pearl--modified-timer)) + (pearl--modified-cleanup) + (should (null pearl--modified-timer))))) + +(ert-deftest test-pearl-modified-after-change-off-schedules-nothing () + "With the indicator disabled, an edit schedules no timer." + (with-temp-buffer + (let ((pearl-show-modified-indicator nil) + (pearl--modified-timer nil)) + (pearl--modified-after-change) + (should (null pearl--modified-timer))))) + +(ert-deftest test-pearl-modified-after-change-cancels-prior-timer () + "A second edit replaces the pending timer rather than leaking it." + (with-temp-buffer + (let ((pearl-show-modified-indicator t) + (pearl--modified-timer nil)) + (pearl--modified-after-change) + (let ((first pearl--modified-timer)) + (pearl--modified-after-change) + (should-not (eq first pearl--modified-timer)) + (should (timerp pearl--modified-timer)) + (pearl--modified-cleanup))))) + (provide 'test-pearl-modified) ;;; test-pearl-modified.el ends here -- cgit v1.2.3