emacs-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: Patch to highlight current line number [nlinum.el]


From: Kaushal Modi
Subject: Re: Patch to highlight current line number [nlinum.el]
Date: Tue, 19 Jul 2016 05:00:03 +0000



On Mon, Jul 18, 2016 at 8:32 PM Stefan Monnier <address@hidden> wrote:
They do.  But (line-beginning-position 1) gives the line-beg of current
line, and (line-beginning-position 0) gives line-beg of previous line,
and (line-beginning-position -1) gives line-beg of the line before that.

Duh, yeah. I somehow missed that earlier in hasty re-evals. Thanks, I got rid of those save-excursions in nlinum--current-line-update.
 
> Using line numbers came just intuitively.  I will anyways need to get line
> numbers to calculate the line diffs.

Why do you need line-diff?

I need the line-diff to get the line begin/end positions for the last-line. line-begining/end-position functions accept 'delta' as arguments.

=====
        (if (natnump line-diff)
            (progn
              (setq beg (line-beginning-position)) ; beginning of the current line
              (setq end (line-end-position (1+ line-diff))) ; end of the last line
              ;; Handle the case of blank lines too.
              (setq end (min (point-max) (1+ end))))
          ;; If point is moving downwards
          (setq beg (line-beginning-position (1+ line-diff))) ; beginning of the last line
          (setq end (line-end-position)) ; end of the current line
          ;; Handle the case of blank lines too.
          (setq end (min (point-max) (1+ end))))
=====
 
> So I cannot think of a way using just positions.

That's because you haven't spent enough time hacking on Elisp yet ;-)

Yes, getting better. My future commit could be an improvement upon this.

   (progn
     (forward-line -2)
     (insert "a\nb\n")
     (forward-line -4))

That case worked fine too.
 
> Also, I do not know how to do it using just markers :)

Ideally, I'd keep a global var
nlinum--last-current-line-highlighted-overlay which (as its name
implies) keeps track of the overlay that holds the (one and only, tho we
could make it more robust and make it into a list, just in case) line
number highlighted as "current".  Then in nlinum--current-line-update
you just remove-text-properties at the position of this overlay (plus at
the position of point).

Now, there's a problem with this, because the code which creates the
overlay doesn't know whether that's the "current-line-highlighted"
overlay or not: this decision is made in nlinum-format-function which
just returns the string that should be put into the overlay.
And nlinum-format-function is meant to be somewhat customized (that's
why it's a var) so we really don't know what happens with the string
we return.  It could be put into an overlay as-is but it could just as
well be replaced with something else.

But it's probably sufficient to change nlinum-format-function so it just
sets a global nlinum--last-current-line-highlighted-marker to (point)
and then in the post-command-hook when that marker points somewhere,
just remove-text-properties between
nlinum--last-current-line-highlighted-marker and (1+
nlinum--last-current-line-highlighted-marker).

I sort of understood the thought process. I will work on that in near future.
 
Looks good, feel free to install it.

Thanks. I have attached updated patch with the email with new defgroup nlinum, changes in defcustom groups and nlinum--current-line-update update. 

> -(require 'linum)                        ;For its face.
> +(require 'linum) ; For its face.

I have fixed this.
 
Hmm... M-; doesn't agree with this comment indentation.
How did you get that? 

I used to manually do C-e SPC ;. Now I am starting to do "M-;".
 
If you want this indentation (I don't have an
opinion on that one), feel free to do it, but do it with ";;" so M-;
will place it as you want.

> +(defcustom nlinum-highlight-current-line nil
> +  "Whether the current line number should be highlighted.
> +When non-nil, the current line number is highlighted in
> `nlinum-current-line'
> +face. "
> +  :group 'nlinum
> +  :type 'boolean)

Hmm... we don't have an `nlinum' group yet, AFAIK.
Feel free to add one, and then we can drop the ":group 'nlinum"
args altogether.

Otherwise, we can simply keep using the `linum' group.

OK, I have defined an nlinum group.

One reason was that it looked like the nlinum group was anyways autogenerated when gloabl-nlinum-mode was created. It just wasn't formally defined. So it was missing the description. On evaluating "(customize-group 'nlinum)", it gave:

-----
Nlinum group:  Group definition missing. 
       State : visible group members are all at standard values.
   
Show Value Global Nlinum Mode 
   Non-nil if Global Nlinum mode is enabled. More
-----

===== patch follows

From 06e4209cea3a860c3329d3f885605736fb414e48 Mon Sep 17 00:00:00 2001
From: Kaushal Modi <address@hidden>
Date: Mon, 18 Jul 2016 17:42:45 -0400
Subject: [PATCH] Add ability to highlight current line number

* nlinum.el (nlinum-highlight-current-line): New defcustom to enable
highlighting current line number when non-nil (default is nil).
        (nlinum-current-line): New face for highlighting the current
line number.
---
 packages/nlinum/nlinum.el | 87 +++++++++++++++++++++++++++++++++++++++++------
 1 file changed, 76 insertions(+), 11 deletions(-)

diff --git a/packages/nlinum/nlinum.el b/packages/nlinum/nlinum.el
index 98c9cbc..79f6891 100644
--- a/packages/nlinum/nlinum.el
+++ b/packages/nlinum/nlinum.el
@@ -4,7 +4,7 @@
 
 ;; Author: Stefan Monnier <address@hidden>
 ;; Keywords: convenience
-;; Version: 1.6
+;; Version: 1.7
 
 ;; This program is free software; you can redistribute it and/or modify
 ;; it under the terms of the GNU General Public License as published by
@@ -26,6 +26,11 @@
 
 ;;; News:
 
+;; v1.7:
+;; - Add ability to highlight current line number.
+;; - New custom variable `nlinum-highlight-current-line' and
+;;   face `nlinum-current-line'.
+
 ;; v1.3:
 ;; - New custom variable `nlinum-format'.
 ;; - Change in calling convention of `nlinum-format-function'.
@@ -36,11 +41,32 @@
 
 ;;; Code:
 
-(require 'linum)                        ;For its face.
+(require 'linum)                        ; for its face
+
+(defgroup nlinum nil
+  "Show line numbers in the margin, (hopefully) more efficiently."
+  :group 'convenience
+  :prefix "nlinum")
+
+(defcustom nlinum-highlight-current-line nil
+  "Whether the current line number should be highlighted.
+When non-nil, the current line number is highlighted in `nlinum-current-line'
+face. "
+  :group 'nlinum
+  :type 'boolean)
+
+(defface nlinum-current-line
+  '((t :inherit linum :weight bold))
+  "Face for displaying current line."
+  :group 'nlinum)
 
 (defvar nlinum--width 2)
 (make-variable-buffer-local 'nlinum--width)
 
+(defvar nlinum--current-line 0
+  "Store current line number.")
+(make-variable-buffer-local 'nlinum--current-line)
+
 ;; (defvar nlinum--desc "")
 
 ;;;###autoload
@@ -53,9 +79,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 +91,13 @@ 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)
+    (if nlinum-highlight-current-line
+        (add-hook 'post-command-hook #'nlinum--current-line-update nil :local)
+      (remove-hook 'post-command-hook #'nlinum--current-line-update :local))
+    (jit-lock-register #'nlinum--region :contextual))
   (nlinum--setup-windows))
 
 (defun nlinum--face-height (face)
@@ -131,6 +161,35 @@ Linum mode is a buffer-local minor mode."
                          (point-min) (point-max) '(fontified)))))
                   (current-buffer)))
 
+(defun nlinum--current-line-update ()
+  "Update current line number."
+  (let ((last-line nlinum--current-line))
+    (setq nlinum--current-line (save-excursion
+                                 (unless (bolp)
+                                   (forward-line 0))
+                                 (nlinum--line-number-at-pos)))
+
+    (let ((line-diff (- last-line nlinum--current-line))
+          beg end)
+      ;; Remove the text properties only if the current line has changed
+      (when (not (zerop line-diff))
+        ;; If point is moving upwards
+        (if (natnump line-diff)
+            (progn
+              (setq beg (line-beginning-position)) ; beginning of the current line
+              (setq end (line-end-position (1+ line-diff))) ; end of the last line
+              ;; Handle the case of blank lines too.
+              (setq end (min (point-max) (1+ end))))
+          ;; If point is moving downwards
+          (setq beg (line-beginning-position (1+ line-diff))) ; beginning of the last line
+          (setq end (line-end-position)) ; end of the current line
+          ;; Handle the case of blank lines too.
+          (setq end (min (point-max) (1+ end))))
+        ;; (message "curr-line:%d [beg/end:%d/%d] -- last-line:%d"
+        ;;          nlinum--current-line beg end last-line)
+        (with-silent-modifications
+          (remove-text-properties beg end '(fontified)))))))
+
 ;; (defun nlinum--ol-count ()
 ;;   (let ((i 0))
 ;;     (dolist (ol (overlays-in (point-min) (point-max)))
@@ -215,11 +274,17 @@ 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 (and nlinum-highlight-current-line
+                                  is-current-line)
+                             'nlinum-current-line
+                           '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
-- 
2.6.0.rc0.24.gec371ff
--

Kaushal Modi


reply via email to

[Prev in Thread] Current Thread [Next in Thread]