Hi Stefan and emacs-devel,

Inspired by the nlinum-relative package[1], I have come up with the below patch for nlinum that just sets the current line number in a different face `nlinum-current-line-face'. @SheJinxin, hope this is fine with you.

By submitting this patch to the list, I am looking forward to how the performance can be improved. Right now, this works as I want but I do this by flushing the text properties in post-command-hook. I do not know enough about jit-lock to use it or how to use it to update the face for the current line number each time the cursor moves across lines. What's the best way?

I am also looking forward for a review to find a bug because at times, very rarely (once a month or so), I see about 15-20 consecutive lines set to the same nlinum-current-line-face. As I cannot reproduce that issue, I don't know where to start the debug from. Hopefully review of the below patch by more experienced eyes can help catch this bug?

Thanks.

The result of this patch looks like this in my theme:

pasted1
The first draft of the patch follows:

diff --git a/packages/nlinum/nlinum.el b/packages/nlinum/nlinum.el
index 98c9cbc..02a7e0b 100644
--- a/packages/nlinum/nlinum.el
+++ b/packages/nlinum/nlinum.el
@@ -41,6 +41,14 @@
 (defvar nlinum--width 2)
 (make-variable-buffer-local 'nlinum--width)
 
+(defface nlinum-current-line-face
+  '((t :inherit linum :weight bold))
+  "Face for displaying current line."
+  :group 'nlinum)
+
+(defvar-local nlinum--current-line 0
+  "Store current line number before jit-lock.")
+
 ;; (defvar nlinum--desc "")
 
 ;;;###autoload
@@ -51,7 +59,7 @@ and disable it otherwise.  If called from Lisp, enable the mode
 if ARG is omitted or nil.
 
 Linum mode is a buffer-local minor mode."
-  :lighter nil ;; (" NLinum" nlinum--desc)
+  :lighter nil ; (" NLinum" nlinum--desc)
   (jit-lock-unregister #'nlinum--region)
   (remove-hook 'window-configuration-change-hook #'nlinum--setup-window t)
   (remove-hook 'text-scale-mode-hook #'nlinum--setup-window t)
@@ -60,6 +68,7 @@ Linum mode is a buffer-local minor mode."
   (remove-overlays (point-min) (point-max) 'nlinum t)
   ;; (kill-local-variable 'nlinum--ol-counter)
   (kill-local-variable 'nlinum--width)
+  (remove-hook 'post-command-hook #'nlinum--current-line-update t)
   (when nlinum-mode
     ;; FIXME: Another approach would be to make the mode permanent-local,
     ;; which might indeed be preferable.
@@ -67,7 +76,8 @@ Linum mode is a buffer-local minor mode."
     (add-hook 'text-scale-mode-hook #'nlinum--setup-window nil t)
     (add-hook 'window-configuration-change-hook #'nlinum--setup-window nil t)
     (add-hook 'after-change-functions #'nlinum--after-change nil t)
-    (jit-lock-register #'nlinum--region t))
+    (jit-lock-register #'nlinum--region t)
+    (add-hook 'post-command-hook #'nlinum--current-line-update nil t))
   (nlinum--setup-windows))
 
 (defun nlinum--face-height (face)
@@ -131,6 +141,22 @@ Linum mode is a buffer-local minor mode."
                          (point-min) (point-max) '(fontified)))))
                   (current-buffer)))
 
+(defun nlinum--current-line-update ()
+  "Reflush display on current window"
+  (when nlinum-mode
+    (nlinum--after-change)
+    (setq nlinum--current-line (string-to-number (format-mode-line "%l")))
+    ;; Do reflush only in the visible portion in the window, not the whole
+    ;; buffer, when possible.
+    (let* ((start (window-start))
+           (end (window-end))
+           (out-of-range-p (< (point-max) end)))
+      (when out-of-range-p
+        (setq start (point-min))
+        (setq end (point-max)))
+      (with-silent-modifications
+        (remove-text-properties start end '(fontified))))))
+
 ;; (defun nlinum--ol-count ()
 ;;   (let ((i 0))
 ;;     (dolist (ol (overlays-in (point-min) (point-max)))
@@ -215,11 +241,15 @@ Used by the default `nlinum-format-function'."
 
 (defvar nlinum-format-function
   (lambda (line width)
-    (let ((str (format nlinum-format line)))
+    (let* ((line-diff (abs (- line nlinum--current-line)))
+           (current-line-p (eq line-diff 0))
+           (str (format nlinum-format line)))
       (when (< (length str) width)
         ;; Left pad to try and right-align the line-numbers.
         (setq str (concat (make-string (- width (length str)) ?\ ) str)))
-      (put-text-property 0 width 'face 'linum str)
+      (if current-line-p
+          (put-text-property 0 width 'face 'nlinum-current-line-face str)
+        (put-text-property 0 width 'face 'linum str))
       str))
   "Function to build the string representing the line number.
 Takes 2 arguments LINE and WIDTH, both of them numbers, and should return

[1]: https://github.com/CodeFalling/nlinum-relative
--

Kaushal Modi