aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--modules/music-config.el38
-rw-r--r--tests/test-music-config--renumber-rows.el55
2 files changed, 91 insertions, 2 deletions
diff --git a/modules/music-config.el b/modules/music-config.el
index bff0f5ce..e9f7c2bb 100644
--- a/modules/music-config.el
+++ b/modules/music-config.el
@@ -364,7 +364,8 @@ that right-aligns the metadata drifts point to arbitrary visual columns
and snaps every landing back to the row start. An active isearch owns
point until it ends; the snap lands when the search exits."
(unless (or (bolp) (bound-and-true-p isearch-mode))
- (beginning-of-line)))
+ (beginning-of-line))
+ (cj/music--highlight-current-number))
(defvar-local cj/music--renumber-timer nil
"Pending idle timer for the playlist row renumber, or nil.")
@@ -401,7 +402,40 @@ debounce timer can outlive the playlist buffer."
(propertize (format "%3d " n)
'face 'cj/music-keyhint-face
'cursor t))))
- (forward-line 1))))))))
+ (forward-line 1))))
+ ;; The rebuild deleted the marked overlay; re-mark the current row.
+ (setq cj/music--current-number-overlay nil)
+ (cj/music--highlight-current-number)))))
+
+(defvar-local cj/music--current-number-overlay nil
+ "The number overlay currently rendered as the you-are-here mark, or nil.")
+
+(defun cj/music--set-number-face (ov current)
+ "Re-render number overlay OV's string; CURRENT non-nil marks it inverse.
+Keeps the text and the cursor property, swaps only the face."
+ (let ((s (overlay-get ov 'before-string)))
+ (overlay-put ov 'before-string
+ (propertize (substring-no-properties s)
+ 'face (if current
+ '(:inherit cj/music-keyhint-face :inverse-video t)
+ 'cj/music-keyhint-face)
+ 'cursor t))))
+
+(defun cj/music--highlight-current-number ()
+ "Render the current row's number in inverse video, restoring the last one.
+The block cursor draws only in the selected window, and the playlist dock
+is glanced at from other windows constantly, so the number itself carries
+the you-are-here mark -- visible whether or not the window has focus."
+ (let ((ov (seq-find (lambda (o) (overlay-get o 'cj-music-row-number))
+ (overlays-in (line-beginning-position)
+ (min (1+ (line-beginning-position)) (point-max))))))
+ (unless (eq ov cj/music--current-number-overlay)
+ (when (and (overlayp cj/music--current-number-overlay)
+ (overlay-buffer cj/music--current-number-overlay))
+ (cj/music--set-number-face cj/music--current-number-overlay nil))
+ (setq cj/music--current-number-overlay ov)
+ (when ov
+ (cj/music--set-number-face ov t)))))
(defun cj/music--schedule-renumber (&rest _)
"Debounced renumber of the current playlist buffer after a text change.
diff --git a/tests/test-music-config--renumber-rows.el b/tests/test-music-config--renumber-rows.el
index 449f6d2e..656bbfc9 100644
--- a/tests/test-music-config--renumber-rows.el
+++ b/tests/test-music-config--renumber-rows.el
@@ -83,6 +83,61 @@ can fire after the playlist buffer is gone)."
(kill-buffer buf)
(should-not (cj/music--renumber-rows buf))))
+;;; Current-row indicator
+
+(ert-deftest test-music-highlight-current-number-marks-current-row ()
+ "Normal: the current row's number renders inverse-video; moving to another
+row restores the old one and marks the new one. The block cursor only
+draws in the selected window, so the number itself carries the mark."
+ (with-temp-buffer
+ (insert "track one\ntrack two\ntrack three\n")
+ (cj/music--renumber-rows (current-buffer))
+ (goto-char (point-min))
+ (forward-line 1)
+ (cj/music--highlight-current-number)
+ (let ((numbers (test-music-renumber--numbers (current-buffer))))
+ (should-not (plist-get (get-text-property 0 'face (nth 0 numbers)) :inverse-video))
+ (should (plist-get (get-text-property 0 'face (nth 1 numbers)) :inverse-video)))
+ (forward-line 1)
+ (cj/music--highlight-current-number)
+ (let ((numbers (test-music-renumber--numbers (current-buffer))))
+ (should-not (plist-get (get-text-property 0 'face (nth 1 numbers)) :inverse-video))
+ (should (plist-get (get-text-property 0 'face (nth 2 numbers)) :inverse-video)))))
+
+(ert-deftest test-music-highlight-current-number-survives-renumber ()
+ "Boundary: a renumber rebuilds the overlays; the highlight re-applies to
+the current row rather than pointing at a dead overlay."
+ (with-temp-buffer
+ (insert "track one\ntrack two\n")
+ (cj/music--renumber-rows (current-buffer))
+ (goto-char (point-min))
+ (forward-line 1)
+ (cj/music--highlight-current-number)
+ (cj/music--renumber-rows (current-buffer))
+ (let ((numbers (test-music-renumber--numbers (current-buffer))))
+ (should (plist-get (get-text-property 0 'face (nth 1 numbers)) :inverse-video)))))
+
+(ert-deftest test-music-highlight-current-number-keeps-cursor-property ()
+ "Boundary: re-facing a number keeps the cursor property intact."
+ (with-temp-buffer
+ (insert "track one\n")
+ (cj/music--renumber-rows (current-buffer))
+ (goto-char (point-min))
+ (cj/music--highlight-current-number)
+ (let ((s (car (test-music-renumber--numbers (current-buffer)))))
+ (should (get-text-property 0 'cursor s)))))
+
+(ert-deftest test-music-ensure-playlist-buffer-sticky-hl-line ()
+ "Normal: hl-line in the playlist stays visible when the window isn't
+selected -- the dock is glanced at from other windows constantly."
+ (let (created)
+ (cl-letf (((symbol-function 'emms-playlist-mode) #'ignore))
+ (unwind-protect
+ (progn
+ (setq created (cj/music--ensure-playlist-buffer))
+ (should (buffer-local-value 'hl-line-sticky-flag created)))
+ (when (buffer-live-p created) (kill-buffer created))))))
+
;;; Hook wiring
(ert-deftest test-music-renumber-ensure-playlist-buffer-wires-hook ()