From mboxrd@z Thu Jan 1 00:00:00 1970 Path: news.gmane.org!not-for-mail From: Kaushal Modi Newsgroups: gmane.emacs.devel Subject: Re: Patch to highlight current line number [nlinum.el] Date: Mon, 18 Jul 2016 04:31:11 +0000 Message-ID: References: NNTP-Posting-Host: plane.gmane.org Mime-Version: 1.0 Content-Type: multipart/alternative; boundary=001a1134fc8cbc7a510537e170d9 X-Trace: ger.gmane.org 1468816333 2149 80.91.229.3 (18 Jul 2016 04:32:13 GMT) X-Complaints-To: usenet@ger.gmane.org NNTP-Posting-Date: Mon, 18 Jul 2016 04:32:13 +0000 (UTC) Cc: code.falling@gmail.com, Emacs developers To: Stefan Monnier Original-X-From: emacs-devel-bounces+ged-emacs-devel=m.gmane.org@gnu.org Mon Jul 18 06:32:12 2016 Return-path: Envelope-to: ged-emacs-devel@m.gmane.org Original-Received: from lists.gnu.org ([208.118.235.17]) by plane.gmane.org with esmtp (Exim 4.69) (envelope-from ) id 1bP0Dz-0002kX-RT for ged-emacs-devel@m.gmane.org; Mon, 18 Jul 2016 06:32:12 +0200 Original-Received: from localhost ([::1]:44221 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1bP0Dy-0000Qf-RY for ged-emacs-devel@m.gmane.org; Mon, 18 Jul 2016 00:32:10 -0400 Original-Received: from eggs.gnu.org ([2001:4830:134:3::10]:46736) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1bP0DH-0000PW-99 for emacs-devel@gnu.org; Mon, 18 Jul 2016 00:31:29 -0400 Original-Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1bP0DD-0004Cu-GE for emacs-devel@gnu.org; Mon, 18 Jul 2016 00:31:26 -0400 Original-Received: from mail-oi0-x232.google.com ([2607:f8b0:4003:c06::232]:35516) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1bP0DD-0004Cn-7G for emacs-devel@gnu.org; Mon, 18 Jul 2016 00:31:23 -0400 Original-Received: by mail-oi0-x232.google.com with SMTP id l72so90897932oig.2 for ; Sun, 17 Jul 2016 21:31:22 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=mime-version:references:in-reply-to:from:date:message-id:subject:to :cc; bh=qXxV2RPJlfk7QwWE8WGR45GjuGkrb4lA9lk+vJuzXKw=; b=wHhnpg0muXLY0UfzVPK+Zd2f/teNuR5Risb5dEF3Yuz1PaeMqoS8hfnfTXO0h3Tepb Zl76qQVryvuj++iULWl6dd+QKisJ58On65E+eFZpIeHRhHwVitvvEJPRSDsMx28r5WvZ EXfveVrVkiCBioaoSyMEe6+xQpwT8S4LI4LWQwvWlSf9085scIpYGPVR+QjcZZrP2YL/ ceL0oAfMU4yf3w4wZNL/3FADay6iQH9RoixmcqTmF9/IQfJ87BX32ga06HGwyZ4ypda3 rUl/hc0YsBTRcckn8FF10dPDNkEoB0LICUiMpK54OaD4stQ+eSlMm3IhLoUqbCNsEdwb OhGQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:mime-version:references:in-reply-to:from:date :message-id:subject:to:cc; bh=qXxV2RPJlfk7QwWE8WGR45GjuGkrb4lA9lk+vJuzXKw=; b=VLP3UVJPQJuZMLSw0V3GZdrUKg9pQzE5yQluWmfpiyOl/o5TNWQUtxEpDsKBhvdwRv jKVRe1iJbDq0vfkMvBzhDR8JDI9wFy5nQd9khqn9b6vvv8tmEZxHIpcSimp+4/WNo9yZ ma8aEcWBSo35nii3lrUY9Tw4q/aesHBuAt1wZ7vS8l1p46TZod0VjiKINg/hzXCBTeDJ 0mrPP2knFZ138kq+yx2TmRmkNKeXKwC8z17UN40q1KsIsVNizIvfgg3A0kgjIpF4Hbhp 8mlfkRFl2Dy52Qij3a406OtHQ3nODW1KPyrIFBA9+wF12DYndJKW1FvIj+1BFro5dCS4 XyWQ== X-Gm-Message-State: ALyK8tLw13/Z22WL789MPFNioSLAEtMRsHqwcqAwYR9Tlk1B8uRsv3L+tpile15mApB9s4a0ziqRgRHSIAqdvA== X-Received: by 10.202.199.149 with SMTP id x143mr14938419oif.50.1468816282120; Sun, 17 Jul 2016 21:31:22 -0700 (PDT) In-Reply-To: X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] X-Received-From: 2607:f8b0:4003:c06::232 X-BeenThere: emacs-devel@gnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: "Emacs development discussions." List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: emacs-devel-bounces+ged-emacs-devel=m.gmane.org@gnu.org Original-Sender: "Emacs-devel" Xref: news.gmane.org gmane.emacs.devel:205791 Archived-At: --001a1134fc8cbc7a510537e170d9 Content-Type: text/plain; charset=UTF-8 Hi Stefan, Thank you for the through review of the patch. My replies are inline below. On Fri, Jul 15, 2016 at 10:15 PM Stefan Monnier wrote: > You might like to look at nhexl-mode to see how I've done that in > a similar context (tho the nhexl-mode approach is not really right > either). > I believe that is in reference to the use of post-command-hook, correct? I need to yet go through that code. > > - :lighter nil ;; (" NLinum" nlinum--desc) > > + :lighter nil ; (" NLinum" nlinum--desc) > > Nitpick: this change results in code that mis-indented because a single > ";" should be indented to comment-column or thereabout (use M-; to place > it right). I wanted the comment close to the code which is why I used > ";;". > OK. I have reverted that hunk in the patch. > > + (add-hook 'post-command-hook #'nlinum--current-line-update nil t)) > > Using post-command-hook is OK (that's what I use in nhexl-mode as well). > > I think it'd be better to use pre-redisplay-functions, but I haven't > played with that option yet, and post-command-hook is easier to work with. > Thanks. > In any case, the hard thing to get right (which you haven't tried to > solve and neither have I in nhexl-mode) is when the buffer is displayed > in several windows (in which case each window will want to highlight > potentially different line numbers since each window has a different > `point`). > I see .. so you are suggesting to highlight the line at the window point, instead of the line where (point) is, correct? I have never needed to do that, but I get it. For now, "C-x 4 c" could be used as a work around. > +(defun nlinum--current-line-update () > > + "Reflush display on current window" > > + (when nlinum-mode > > + (nlinum--after-change) > > Why (nlinum--after-change)? > You are correct, that wasn't needed. > > + (setq nlinum--current-line (string-to-number (format-mode-line > "%l"))) > > I think this should use `nlinum--line-number-at-pos`? > >From quick trial, that does not work. That function might need to be fixed for it work work in this use case where it is called in post-command-hook. >From quick trial, I saw the line numbers change in the whole buffer even when I moved the cursor horizontally. I need to yet look into that function to understand why that's happening. > > + ;; 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)))))) > > I think this is pessimistic. There's no need to refresh the whole > window's line numbers. The only line numbers that can/should change are > the line number of the old cursor position and that of the new > cursor position. And if point is still in the same line, there's > nothing to do. > In the below updated patch, I attempt to do this (code commented out in the patch), but failed. I tried removing the text properties on the current and last lines, but it is not working. I'll give more time to understand tomorrow. But if you can point out the issue with those remove-text-properties, that will be great. > + (let* ((line-diff (abs (- line nlinum--current-line))) > > + (current-line-p (eq line-diff 0)) > > "...-p" means "..-predicate", and a boolean variable is not a predicate > (a predicate in (E)Lisp is usually a function that returns a boolean). > Thanks. I learned that today. Fixed. > And you can simplify this to > > (is-current-line (= line nlinum--current-line)) > > > + (if current-line-p > > + (put-text-property 0 width 'face 'nlinum-current-line-face > str) > > + (put-text-property 0 width 'face 'linum str)) > > Aka > > (put-text-property 0 width 'face > (if current-line-p > 'nlinum-current-line-face > 'linum) > str)) > Done. Thanks. > Also I think it'd just always use the `linum` face, as in > > (put-text-property 0 width 'face > (if current-line-p > '(nlinum-current-line-face linum) > 'linum) > str)) > > Tho it's clearly a question of taste. > I tried implementing that, but doesn't work as I expected. nlinum-current-line-face is already inheriting linum face. And I have set the linum face height to be 0.9 (ratio). From what I understand, "'(nlinum-current-line-face linum)" applies linum face properties which nlinum-current-line-face does not change. As nlinum-current-line-face inherits linum, that face height is already 0.9. But when linum applies on top of that, the current line face reduces further by 0.9 (or so it looks like). So I end up with the current line number face at 0.81 height and the rest of the line numbers at 0.9. So I stuck with the applying just nlinum-current-line-face (it still inherits from linum). I have also made one cosmetic change .. Instead of `t' as argument values, I have replaced them with `:local' or `:contextual' as appropriate. I like doing that so that I do not need to look up the documentation to learn what happens when an arg is set to `t'. Also `:contextual' and `:local' show up in a different face, which I like. Let me know if that doing that is alright.. ===== Below is patch draft v2 diff --git a/packages/nlinum/nlinum.el b/packages/nlinum/nlinum.el index 98c9cbc..4d1cf64 100644 --- a/packages/nlinum/nlinum.el +++ b/packages/nlinum/nlinum.el @@ -36,11 +36,22 @@ ;;; Code: -(require 'linum) ;For its face. +(require 'linum) ; For its face. (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.") + +(defvar-local nlinum--last-line 0 + "Store line number where the point was before it moved to the current line.") + ;; (defvar nlinum--desc "") ;;;###autoload @@ -53,9 +64,10 @@ if ARG is omitted or nil. Linum mode is a buffer-local minor mode." :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) - (remove-hook 'after-change-functions #'nlinum--after-change t) + (remove-hook 'window-configuration-change-hook #'nlinum--setup-window :local) + (remove-hook 'text-scale-mode-hook #'nlinum--setup-window :local) + (remove-hook 'after-change-functions #'nlinum--after-change :local) + (remove-hook 'post-command-hook #'nlinum--current-line-update :local) (kill-local-variable 'nlinum--line-number-cache) (remove-overlays (point-min) (point-max) 'nlinum t) ;; (kill-local-variable 'nlinum--ol-counter) @@ -64,10 +76,11 @@ Linum mode is a buffer-local minor mode." ;; FIXME: Another approach would be to make the mode permanent-local, ;; which might indeed be preferable. (add-hook 'change-major-mode-hook (lambda () (nlinum-mode -1))) - (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)) + (add-hook 'text-scale-mode-hook #'nlinum--setup-window nil :local) + (add-hook 'window-configuration-change-hook #'nlinum--setup-window nil :local) + (add-hook 'after-change-functions #'nlinum--after-change nil :local) + (add-hook 'post-command-hook #'nlinum--current-line-update nil :local) + (jit-lock-register #'nlinum--region :contextual)) (nlinum--setup-windows)) (defun nlinum--face-height (face) @@ -131,6 +144,36 @@ Linum mode is a buffer-local minor mode." (point-min) (point-max) '(fontified))))) (current-buffer))) +(defun nlinum--current-line-update () + "Update current line number, flush text properties for last and current line." + (setq nlinum--last-line nlinum--current-line) + ;; (setq nlinum--current-line (nlinum--line-number-at-pos)) ; does not work + (setq nlinum--current-line (line-number-at-pos)) ; works + ;; (setq nlinum--current-line (string-to-number (format-mode-line "%l"))) ; works + + ;; Flush the text properties only if the point has changed lines. + (when (not (eq nlinum--current-line nlinum--last-line)) + (let* ((line-diff (- nlinum--last-line nlinum--current-line)) + (last-line-beg (line-beginning-position line-diff)) + (last-line-end (line-end-position line-diff)) + ;; (curr-line-beg (line-beginning-position)) + ;; (curr-line-end (line-end-position)) + ) + ;; (message "last:%d, curr:%d" nlinum--last-line nlinum--current-line) + (let* ((start (window-start)) ; works + (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)))) + ;; (with-silent-modifications ; does not work + ;; (remove-text-properties last-line-beg last-line-end '(fontified)) + ;; ;; (remove-text-properties curr-line-beg curr-line-end '(fontified)) + ;; ) + ))) + ;; (defun nlinum--ol-count () ;; (let ((i 0)) ;; (dolist (ol (overlays-in (point-min) (point-max))) @@ -215,11 +258,16 @@ Used by the default `nlinum-format-function'." (defvar nlinum-format-function (lambda (line width) - (let ((str (format nlinum-format line))) + (let* ((is-current-line (= line nlinum--current-line)) + (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) + (put-text-property 0 width 'face + (if is-current-line + 'nlinum-current-line-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 ===== Thanks. -- Kaushal Modi --001a1134fc8cbc7a510537e170d9 Content-Type: text/html; charset=UTF-8 Content-Transfer-Encoding: quoted-printable
Hi Stefan,

Thank you for the through re= view of the patch. My replies are inline below.

On Fri, Jul 15, 2016 at 10:15 PM Stefan Monnier <= ;monnier@iro.umontreal.ca&g= t; wrote:
You might like to look at= nhexl-mode to see how I've done that in
a similar context (tho the nhexl-mode approach is not really right
either).

I believe that is in reference= to the use of post-command-hook, correct? I need to yet go through that co= de.
=C2=A0
> -=C2=A0 :lighter nil ;; (" NLinum" nlinum--desc)
> +=C2=A0 :lighter nil ; (" NLinum" nlinum--desc)

Nitpick: this change results in code that mis-indented because a single
";" should be indented to comment-column or thereabout (use M-; t= o place
it right).=C2=A0 I wanted the comment close to the code which is why I used=
";;".

OK. I have reverted tha= t hunk in the patch.
=C2=A0
> +=C2=A0 =C2=A0 (add-hook 'post-command-hook #'nlinum--current-= line-update nil t))

Using post-command-hook is OK (that's what I use in nhexl-mode as well)= .

I think it'd be better to use pre-redisplay-functions, but I haven'= t
played with that option yet, and post-command-hook is easier to work with.<= br>

Thanks.
=C2=A0
In any case, the hard thing to get right (which you haven't tried to solve and neither have I in nhexl-mode) is when the buffer is displayed
in several windows (in which case each window will want to highlight
potentially different line numbers since each window has a different
`point`).

I see .. so you are suggestin= g to highlight the line at the window point, instead of the line where (poi= nt) is, correct? I have never needed to do that, but I get it. For now, &qu= ot;C-x 4 c" could be used as a work around.

> +(defun nlinum--current-line-update ()
> +=C2=A0 "Reflush display on current window"
> +=C2=A0 (when nlinum-mode
> +=C2=A0 =C2=A0 (nlinum--after-change)

Why (nlinum--after-change)?

You are cor= rect, that wasn't needed.
=C2=A0
> +=C2=A0 =C2=A0 (setq nlinum--current-line (string-to-number (format-mo= de-line "%l")))

I think this should use `nlinum--line-number-at-pos`?
=
From quick trial, that does not work. That function might ne= ed to be fixed for it work work in this use case where it is called in post= -command-hook. From quick trial, I saw the line numbers change in the whole= buffer even when I moved the cursor horizontally. I need to yet look into = that function to understand why that's happening.
=C2=A0
> +=C2=A0 =C2=A0 ;; Do reflush only in the visible portion in the window= , not the whole
> +=C2=A0 =C2=A0 ;; buffer, when possible.
> +=C2=A0 =C2=A0 (let* ((start (window-start))
> +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0(end (window-end))
> +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0(out-of-range-p (< (point= -max) end)))
> +=C2=A0 =C2=A0 =C2=A0 (when out-of-range-p
> +=C2=A0 =C2=A0 =C2=A0 =C2=A0 (setq start (point-min))
> +=C2=A0 =C2=A0 =C2=A0 =C2=A0 (setq end (point-max)))
> +=C2=A0 =C2=A0 =C2=A0 (with-silent-modifications
> +=C2=A0 =C2=A0 =C2=A0 =C2=A0 (remove-text-properties start end '(f= ontified))))))

I think this is pessimistic.=C2=A0 There's no need to refresh the whole=
window's line numbers.=C2=A0 The only line numbers that can/should chan= ge are
the line number of the old cursor position and that of the new
cursor position.=C2=A0 And if point is still in the same line, there's<= br> nothing to do.

In the below updated pat= ch, I attempt to do this (code commented out in the patch), but failed. I t= ried removing the text properties on the current and last lines, but it is = not working. I'll give more time to understand tomorrow. But if you can= point out the issue with those remove-text-properties, that will be great.=

> +=C2=A0 =C2=A0 (let* ((line-diff (abs (- line nlinum--current-line)))<= br> > +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0(current-line-p (eq line-dif= f 0))

"...-p" means "..-predicate", and a boolean variable is= not a predicate
(a predicate in (E)Lisp is usually a function that returns a boolean).
<= /blockquote>

Thanks. I learned that today. Fixed.
<= div>=C2=A0
And you can simplify this to

=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 (is-current-line (=3D line= nlinum--current-line))

> +=C2=A0 =C2=A0 =C2=A0 (if current-line-p
> +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 (put-text-property 0 width 'fa= ce 'nlinum-current-line-face str)
> +=C2=A0 =C2=A0 =C2=A0 =C2=A0 (put-text-property 0 width 'face '= ;linum str))

Aka

=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0(put-text-property 0 width 'face
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 (if current-line-p
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 'nlinum-current-line-face
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 'linum)
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 str))

Done. Th= anks.
=C2=A0
Also I think it'd just always use the `linum` face, as in

=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0(put-text-property 0 width 'face
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 (if current-line-p
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 '(nlinum-current-line-face linum= )
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 'linum)
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 str))

Tho it's clearly a question of taste.

I tried implementing that, but doesn't work as I expected. nlinum-cu= rrent-line-face is already inheriting linum face. And I have set the linum = face height to be 0.9 (ratio). From what I understand, "'(nlinum-current-line-face linum)" applies linum= face properties which nlinum-current-line-face does not change. As nlinum-= current-line-face inherits linum, that face height is already 0.9. But when= linum applies on top of that, the current line face reduces further by 0.9= (or so it looks like). So I end up with the current line number face at 0.= 81 height and the rest of the line numbers at 0.9.

So I stuck with the applying just nlinum-current-line-face (it still in= herits from linum).

I have also made one cosmet= ic change .. Instead of `t' as argument values, I have replaced them wi= th `:local' or `:contextual'= as appropriate. I like doing that so that I do not need to look up the doc= umentation to learn what happens when an arg is set to `t'. Also `:cont= extual' and `:local' show up in a different face, which I like. Let= me know if that doing that is alright..

=3D=3D= =3D=3D=3D Below is patch draft v2

diff --git a/packages/nlinum/nlinum.el b= /packages/nlinum/nlinum.el
index 98c9cbc..4d1cf64 100644
--- a/packages/nlinum/nlinum.el
+++ b/packages/nlinum/nlinum.el=
@@ -36,11 +36,22 @@
=C2=A0
=C2=A0;;; Code:
=C2=A0
-(require 'linum) =C2=A0 =C2=A0 =C2=A0 =C2=A0= =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0;For its face.
+(require 'linum) ; For its face.
=C2=A0
=C2= =A0(defvar nlinum--width 2)
=C2=A0(make-variable-buffer-local = 9;nlinum--width)
=C2=A0
+(defface nlinum-current-line-f= ace
+ =C2=A0'((t :inherit linum :weight bold))
+ = =C2=A0"Face for displaying current line."
+ =C2=A0:grou= p 'nlinum)
+
+(defvar-local nlinum--current-line 0<= /div>
+ =C2=A0"Store current line number.")
+
=
+(defvar-local nlinum--last-line 0
+ =C2=A0"Store line = number where the point was before it moved to the current line.")
+
=C2=A0;; (defvar nlinum--desc "")
=C2= =A0
=C2=A0;;;###autoload
@@ -53,9 +64,10 @@ if ARG is o= mitted or nil.
=C2=A0Linum mode is a buffer-local minor mode.&quo= t;
=C2=A0 =C2=A0:lighter nil ;; (" NLinum" nlinum--desc= )
=C2=A0 =C2=A0(jit-lock-unregister #'nlinum--region)
- =C2=A0(remove-hook 'window-configuration-change-hook #'nlinum-= -setup-window t)
- =C2=A0(remove-hook 'text-scale-mode-hook #= 'nlinum--setup-window t)
- =C2=A0(remove-hook 'after-chan= ge-functions #'nlinum--after-change t)
+ =C2=A0(remove-hook &= #39;window-configuration-change-hook #'nlinum--setup-window :local)
+ =C2=A0(remove-hook 'text-scale-mode-hook #'nlinum--setup-w= indow :local)
+ =C2=A0(remove-hook 'after-change-functions #&= #39;nlinum--after-change :local)
+ =C2=A0(remove-hook 'post-c= ommand-hook #'nlinum--current-line-update :local)
=C2=A0 =C2= =A0(kill-local-variable 'nlinum--line-number-cache)
=C2=A0 = =C2=A0(remove-overlays (point-min) (point-max) 'nlinum t)
=C2= =A0 =C2=A0;; (kill-local-variable 'nlinum--ol-counter)
@@ -64= ,10 +76,11 @@ Linum mode is a buffer-local minor mode."
=C2= =A0 =C2=A0 =C2=A0;; FIXME: Another approach would be to make the mode perma= nent-local,
=C2=A0 =C2=A0 =C2=A0;; which might indeed be preferab= le.
=C2=A0 =C2=A0 =C2=A0(add-hook 'change-major-mode-hook (la= mbda () (nlinum-mode -1)))
- =C2=A0 =C2=A0(add-hook 'text-sca= le-mode-hook #'nlinum--setup-window nil t)
- =C2=A0 =C2=A0(ad= d-hook 'window-configuration-change-hook #'nlinum--setup-window nil= t)
- =C2=A0 =C2=A0(add-hook 'after-change-functions #'nl= inum--after-change nil t)
- =C2=A0 =C2=A0(jit-lock-register #'= ;nlinum--region t))
+ =C2=A0 =C2=A0(add-hook 'text-scale-mode= -hook #'nlinum--setup-window nil :local)
+ =C2=A0 =C2=A0(add-= hook 'window-configuration-change-hook #'nlinum--setup-window nil := local)
+ =C2=A0 =C2=A0(add-hook 'after-change-functions #'= ;nlinum--after-change nil :local)
+ =C2=A0 =C2=A0(add-hook 'p= ost-command-hook #'nlinum--current-line-update nil :local)
+ = =C2=A0 =C2=A0(jit-lock-register #'nlinum--region :contextual))
=C2=A0 =C2=A0(nlinum--setup-windows))
=C2=A0
=C2=A0(d= efun nlinum--face-height (face)
@@ -131,6 +144,36 @@ Linum mode i= s a buffer-local minor mode."
=C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 (point-min) = (point-max) '(fontified)))))
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0(current-buffer)))
=C2=A0
+(defun nlinum--current-line-update ()
+ =C2=A0"Upd= ate current line number, flush text properties for last and current line.&q= uot;
+ =C2=A0(setq nlinum--last-line nlinum--current-line)
<= div>+ =C2=A0;; (setq nlinum--current-line (nlinum--line-number-at-pos)) ; d= oes not work
+ =C2=A0(setq nlinum--current-line (line-number-at-p= os)) ; works
+ =C2=A0;; (setq nlinum--current-line (string-to-num= ber (format-mode-line "%l"))) ; works
+
+ =C2= =A0;; Flush the text properties only if the point has changed lines.
<= div>+ =C2=A0(when (not (eq nlinum--current-line nlinum--last-line))
+ =C2=A0 =C2=A0(let* ((line-diff (- nlinum--last-line nlinum--current-li= ne))
+ =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 (last-line-beg (line-be= ginning-position line-diff))
+ =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0= (last-line-end (line-end-position line-diff))
+ =C2=A0 =C2=A0 = =C2=A0 =C2=A0 =C2=A0 ;; (curr-line-beg (line-beginning-position))
+ =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 ;; (curr-line-end (line-end-position)= )
+ =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 )
+ =C2=A0 =C2= =A0 =C2=A0;; (message "last:%d, curr:%d" nlinum--last-line nlinum= --current-line)
+ =C2=A0 =C2=A0 =C2=A0(let* ((start (window-start= )) ; works
+ =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 (end (wind= ow-end))
+ =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 (out-of-rang= e-p (< (point-max) end)))
+ =C2=A0 =C2=A0 =C2=A0 =C2=A0(when o= ut-of-range-p
+ =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0(setq start (po= int-min))
+ =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0(setq end (point-ma= x)))
+ =C2=A0 =C2=A0 =C2=A0 =C2=A0(with-silent-modifications
+ =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0(remove-text-properties start end= '(fontified))))
+ =C2=A0 =C2=A0 =C2=A0;; (with-silent-modifi= cations ; does not work
+ =C2=A0 =C2=A0 =C2=A0;; =C2=A0 (remove-t= ext-properties last-line-beg last-line-end '(fontified))
+ = =C2=A0 =C2=A0 =C2=A0;; =C2=A0 ;; (remove-text-properties curr-line-beg curr= -line-end '(fontified))
+ =C2=A0 =C2=A0 =C2=A0;; =C2=A0 )
+ =C2=A0 =C2=A0 =C2=A0)))
+
=C2=A0;; (defun nlin= um--ol-count ()
=C2=A0;; =C2=A0 (let ((i 0))
=C2=A0;; = =C2=A0 =C2=A0 (dolist (ol (overlays-in (point-min) (point-max)))
= @@ -215,11 +258,16 @@ Used by the default `nlinum-format-function'.&quo= t;
=C2=A0
=C2=A0(defvar nlinum-format-function
=C2=A0 =C2=A0(lambda (line width)
- =C2=A0 =C2=A0(let ((str (fo= rmat nlinum-format line)))
+ =C2=A0 =C2=A0(let* ((is-current-line= (=3D line nlinum--current-line))
+ =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 (str (format nlinum-format line)))
=C2=A0 =C2=A0 =C2=A0 = =C2=A0(when (< (length str) width)
=C2=A0 =C2=A0 =C2=A0 =C2=A0= =C2=A0;; Left pad to try and right-align the line-numbers.
=C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0(setq str (concat (make-string (- width (len= gth str)) ?\ ) str)))
- =C2=A0 =C2=A0 =C2=A0(put-text-property 0 = width 'face 'linum str)
+ =C2=A0 =C2=A0 =C2=A0(put-text-p= roperty 0 width 'face
+ =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 (if is-current-line
<= div>+ =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0= =C2=A0 =C2=A0 =C2=A0 =C2=A0 'nlinum-current-line-face
+ =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 =C2=A0 'linum)
+ =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 str)
=C2=A0 =C2= =A0 =C2=A0 =C2=A0str))
=C2=A0 =C2=A0"Function to build the s= tring representing the line number.
=C2=A0Takes 2 arguments LINE = and WIDTH, both of them numbers, and should return
=3D=3D=3D=3D= =3D

Thanks.
--

Kaushal Modi

--001a1134fc8cbc7a510537e170d9--