如何在“nlinum-mode”中突出当前行号

时间:2021-12-21 17:28:50

I am writing a minor mode to highlight the current line number when using nlinum-mode (written by @Stefan), and I got everything working except when the cursor is on the first line at the top of the window.

我在使用nlin -mode(由@Stefan编写)时编写了一个小模式来突出显示当前行号,除了光标在窗口顶部的第一行之外,我让所有的东西都能工作。

The code for nlinum-mode can be found here: http://elpa.gnu.org/packages/nlinum.html

nlin模式的代码可以在这里找到:http://elpa.gnu.org/packages/nlinum.html

Any assistance in figuring out why this doesn't work (i.e., when the cursor is on the first line at the top of the window) would be greatly appreciated.

任何有助于弄清楚为什么这不起作用的帮助。,当光标在窗口顶部的第一行时),我们将非常感激。

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; M-x hl-nlinum-mode

(defvar nlinum-highlight-current-line-number-string nil
  "An overlay string used to highlight the current line number.")
(make-variable-buffer-local 'nlinum-highlight-current-line-number-string)

(defvar nlinum-highlight-p nil
  "Set to non-`nil` when overlay is present, and `nil` when not present.")
(make-variable-buffer-local 'nlinum-highlight-p)

(defface ln-active-face
  '((t (:foreground "black" :background "#eab700" :bold nil :italic nil
      :underline nil :box nil :overline nil)))
  "Face for `ln-active-face`."
  :group 'linum)

(defface ln-inactive-face
  '((t (:foreground "SteelBlue" :background "black" :bold t :italic nil
      :underline nil :box nil :overline nil)))
  "Face for `ln-active-face`."
  :group 'linum)

(defun hl-nlinum-remove-overlay ()
  (when nlinum-highlight-p
    (remove-overlays (point-min) (point-max)
      'before-string nlinum-highlight-current-line-number-string)
    (setq nlinum-highlight-p nil)))

(defun nlinum-highlight-current-line-number ()
  (when nlinum-mode
    (hl-nlinum-remove-overlay)
    (let* (
        (pbol (point-at-bol))
        (line (nlinum--line-number-at-pos))
        (line-mod
          (cond
            ((eq nlinum--width 2)
              (cond
                ((< line 10)
                  (concat " " (format "%s" line)))
                (t (format "%s" line))))
            ((eq nlinum--width 3)
              (cond
                ((< line 10)
                  (concat "  " (format "%s" line)))
                ((and
                    (> line 9)
                    (< line 100))
                  (concat " " (format "%s" line)))
                (t (format "%s" line))))
            ((eq nlinum--width 4)
              (cond
                ((< line 10)
                  (concat "   " (format "%s" line)))
                ((and
                    (> line 9)
                    (< line 100))
                  (concat "  " (format "%s" line)))
                ((and
                    (> line 99)
                    (< line 1000))
                  (concat " " (format "%s" line)))
                (t (format "%s" line))))
            (t (format "%s" line))))
        (str (propertize line-mod 'face 'ln-active-face) )
        (final-line-number (propertize " " 'display `((margin left-margin) ,str))))
      (setq nlinum-highlight-current-line-number-string final-line-number)
      (overlay-put (make-overlay pbol pbol)
        'before-string nlinum-highlight-current-line-number-string)
      (setq nlinum-highlight-p t))))

(define-minor-mode hl-nlinum-mode
"A minor-mode for highlighting the current line number when nlinum-mode is active."
  :init-value nil
  :lighter " HL#"
  :keymap nil
  :global nil
  :group 'linum
  (cond
    (hl-nlinum-mode
      (when (not nlinum-mode)
         (nlinum-mode 1))
      (add-hook 'post-command-hook #'nlinum-highlight-current-line-number nil t))
    (t
      (remove-hook 'post-command-hook #'nlinum-highlight-current-line-number t)
      (remove-overlays (point-min) (point-max)
        'before-string nlinum-highlight-current-line-number-string))))

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

2 个解决方案

#1


2  

The problem is probably in your call to (hl-nlinum-remove-overlay). I'm not completely sure I understand the way your code is expected to work, but here's my analysis: the main issue you have is that you want your overlay to replace nlinum's, but doing it from post-command-hook won't always work, because nlinum adds its overlays via jit-lock which is typically run by redisplay, i.e. after post-command-hook.

问题可能出在调用(hl- nlinm -remove-overlay)中。我不完全确定我理解你的代码的方式将工作,但这是我的分析:你的主要问题是,你想让你的叠加来取代nlinum,但这样做从post-command-hook不总是有效,因为通过jit-lock nlinum增加了其覆盖通常是由重新显示,即post-command-hook之后。

I think you can fix this problem by calling jit-lock-fontify-now on the current line in nlinum-highlight-current-line-number. Whether that will fix your "first line is wrong", I'm not sure, tho.

我认为您可以通过在nlin -highlight-current-line-number中的当前行上调用jit-lock-fonti -now来解决这个问题。我不确定这是否会修正你的“第一行是错误的”。

This said, I think your code shouldn't try to replace nlinum's overlay. Instead it should go and modify nlinum's overlay. I.e.:

这就是说,我认为您的代码不应该试图替换nlinum的覆盖。相反,它应该去修改nlinum的覆盖。例如:

  • Call jit-lock-fontify-now
  • 叫jit-lock-fontify-now
  • Then look for nlinum's overlay on the current line
  • 然后在当前线上寻找nlinum的覆盖
  • If it's a different overlay than the last one (which you stashed in a hl-nlinum--last-overlay), then un-modify the last overlay.
  • 如果它的覆盖层与上一个不同(你把它藏在hl-nlinum——last-overlay),然后取消修改最后一个覆盖层。
  • Finally, modify the current line's overlay with something like the code below.
  • 最后,用如下代码修改当前行的覆盖。

If ol is nlinum's current line's overlay, you should be able to modify it with something like:

如果ol是nlinum当前行的覆盖,您应该能够修改如下内容:

(let* ((spc (overlay-get ol 'before-string))
       (disp (get-text-property 0 'display spc))
       (str (nth 1 disp)))
  (put-text-property 0 (length str) 'face 'foo str))

#2


3  

You can enable highlighting the current line number in version 1.7 of nlinum package by setting this in your config:

通过在配置中设置,可以在nlinum包的1.7版本中突出显示当前行号:

(setq nlinum-highlight-current-line t)

#1


2  

The problem is probably in your call to (hl-nlinum-remove-overlay). I'm not completely sure I understand the way your code is expected to work, but here's my analysis: the main issue you have is that you want your overlay to replace nlinum's, but doing it from post-command-hook won't always work, because nlinum adds its overlays via jit-lock which is typically run by redisplay, i.e. after post-command-hook.

问题可能出在调用(hl- nlinm -remove-overlay)中。我不完全确定我理解你的代码的方式将工作,但这是我的分析:你的主要问题是,你想让你的叠加来取代nlinum,但这样做从post-command-hook不总是有效,因为通过jit-lock nlinum增加了其覆盖通常是由重新显示,即post-command-hook之后。

I think you can fix this problem by calling jit-lock-fontify-now on the current line in nlinum-highlight-current-line-number. Whether that will fix your "first line is wrong", I'm not sure, tho.

我认为您可以通过在nlin -highlight-current-line-number中的当前行上调用jit-lock-fonti -now来解决这个问题。我不确定这是否会修正你的“第一行是错误的”。

This said, I think your code shouldn't try to replace nlinum's overlay. Instead it should go and modify nlinum's overlay. I.e.:

这就是说,我认为您的代码不应该试图替换nlinum的覆盖。相反,它应该去修改nlinum的覆盖。例如:

  • Call jit-lock-fontify-now
  • 叫jit-lock-fontify-now
  • Then look for nlinum's overlay on the current line
  • 然后在当前线上寻找nlinum的覆盖
  • If it's a different overlay than the last one (which you stashed in a hl-nlinum--last-overlay), then un-modify the last overlay.
  • 如果它的覆盖层与上一个不同(你把它藏在hl-nlinum——last-overlay),然后取消修改最后一个覆盖层。
  • Finally, modify the current line's overlay with something like the code below.
  • 最后,用如下代码修改当前行的覆盖。

If ol is nlinum's current line's overlay, you should be able to modify it with something like:

如果ol是nlinum当前行的覆盖,您应该能够修改如下内容:

(let* ((spc (overlay-get ol 'before-string))
       (disp (get-text-property 0 'display spc))
       (str (nth 1 disp)))
  (put-text-property 0 (length str) 'face 'foo str))

#2


3  

You can enable highlighting the current line number in version 1.7 of nlinum package by setting this in your config:

通过在配置中设置,可以在nlinum包的1.7版本中突出显示当前行号:

(setq nlinum-highlight-current-line t)