0

This question applies in the context of all line numbering implementations I've tried, including line-number, nlinum, and linum, so I have a feeling that the answer will have something to do with Emacs internals, especially with the abstraction of buffers.

Getting on with it... Let's say I have a buffer with the following content (leading digits represent line numbers, not buffer content):

1 foo
2 bar
3 baz
4 quux

If I were to do a narrow-to-region on the last two lines, I'd end up with a narrowed buffer like this:

1 baz
2 quux

But what I really want is this:

3 baz
4 quux

Is there any way to accomplish that last case? I'm willing to redefine or advise internal Emacs constructs to get this to work and deal with the consequences as they arise.


EDIT: As pointed out in the comments, this question seems to invalidate my own as a duplicate. Let me add a couple of points that will hopefully add some distinction:

  1. I am most interested in a solution that is agnostic to line numbering package. Something that will work for line-number, nlinum, and linum without needing to customize each one.
  2. I would also settle for a fix that only works with line-number, as that is the package that I use (given that it ships with Emacs 26.1 and is more performant than the other two options).

If you feel like further edits are necessary, or if voting to close is most appropriate, no hard feelings from me.


EDIT: Thanks for the answers! This is now my line numbering setup:

(defun with-absolute-line-numbers (fun &rest args)
  "Let `line-number-at-pos' always output absolute line numbers."
  (cl-letf*
      ((old-line-number-at-pos (symbol-function 'line-number-at-pos))
       ((symbol-function 'line-number-at-pos)
        (lambda (&optional pos absolute)
          (funcall old-line-number-at-pos pos t))))
    (apply fun args)))

;;; Line numbering config
(if (>= emacs-major-version 26)

    ;; Disregard narrowing when displaying line numbers
    (setq-default display-line-numbers-widen t)

  ;; Same, but for [n]linum
  (advice-add 'linum-update-window :around #'with-absolute-line-numbers)
  (advice-add 'nlinum--line-number-at-pos :around #'with-absolute-line-numbers)

  ;; Use nice formatting for [n]linum
  (setq linum-format "%3d ")
  (setq nlinum-format " %d "))
  • Here is a link to a modification of the Lisp version of line numbers: emacs.stackexchange.com/questions/24833/… – lawlist Mar 26 at 3:00
  • @lawlist Thanks, that certainly makes this question look like a duplicate, doesn't it? I will edit this question to make it more distinct. – Sam Mar 26 at 12:57
3

Specifically for the built-in line-number support in Emacs 26.1:

display-line-numbers-widen is a variable defined in `xdisp.c'.
Its value is nil

  Automatically becomes buffer-local when set.
  Calls these functions when changed: (#<subr set-buffer-redisplay>)

Documentation:
Non-nil means display line numbers disregarding any narrowing.
  • By golly, you've done it! Works perfectly. – Sam Mar 26 at 15:27
1

For both linum and nlinum you can probably get what you want by advising line-number-at-pos to force its absolute arg to be non-nil. Of course, that will affect more than just linum and nlinum.

But for line-number I can't think of a way to make it do what you want without changing the C code, sorry.

(advice-add 'line-number-at-pos :around
            (lambda (orig-fun &optional pos _absolute)
              (funcall orig-fun pos t)))

BTW, for nlinum-mode you can also (setq nlinum-widen t) if you're using nlinum-mode≥1.9.

  • Thank you much! Your answer combined with the accepted one addresses all three cases. Can't complain :) – Sam Mar 26 at 15:29
  • 1
    Do not do that! The consequences of advising line-number-at-pos are unforeseeable! When you are hit by the consequences you will not remember that they are due to the advice. – Tobias Mar 26 at 15:47
1

Stefan's answer leads the way. But you should absolutely not globally advise line-number-at-pos.

The consequences of advising line-number-at-pos are unforeseeable! When you are hit by the consequences you will not remember that they are due to the advice. Furthermore, the consequences can be indirect because narrowing, point, and line-number-at-pos do all also work without any direct effect in the user interface. For an instance it might be that some version control package does not work anymore reliable or stuff like that.

A local advice for each of the line-numbering packages is much better.

1st) Determine what function of the package in question calls line-number-at-pos. If there is an option for the ABSOLUTE argument of line-number-at-pos in that function you are almost certainly done. Just use that option.

2nd) If there is no option for the ABSOLUTE argument of line-number-at-pos use the advice with-absolute-line-numbers as defined in the following Elisp snippet. The usage of with-absolute-line-numbers is demonstrated for linum-mode in the snippet.

(defun with-absolute-line-numbers (fun &rest args)
  "Let `line-number-at-pos' always output absolute line numbers."
  (cl-letf* ((old-line-number-at-pos (symbol-function 'line-number-at-pos))
         ((symbol-function 'line-number-at-pos)
          (lambda (&optional pos absolute)
        (funcall old-line-number-at-pos pos t))))
    (apply fun args)
    ))

(advice-add 'linum-update-window :around #'with-absolute-line-numbers)
  • Your points are taken and I really like your approach! Would have never thought of that cl-letf* bit. I'll update my config as such. – Sam Mar 26 at 16:56

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.