Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Relative Line Numbers In Emacs

Does anyone know how if something like this Vim Relative Line Numbers exists for emacs? I use vimpulse, and man, that would be super handy to have! I know some lisp, so if it doesn't, I could try to make my own, if I got a point in the right direction.

Update: Thanks to the correct response, I came up with this, that will show 1 for the current line, and -1 for the previous line, for combining with vimpulse yanks and deletes.

Thanks a ton to all who helped! I know it is not exactly what Vim does, but what good is the Relative line numbers in vim that start at zero?? Silly vim.

(defvar my-linum-current-line-number 0)  (setq linum-format 'my-linum-relative-line-numbers)  (defun my-linum-relative-line-numbers (line-number)   (let ((test2 (1+ (- line-number my-linum-current-line-number))))     (propertize      (number-to-string (cond ((<= test2 0) (1- test2))                              ((> test2 0) test2)))      'face 'linum)))  (defadvice linum-update (around my-linum-update)   (let ((my-linum-current-line-number (line-number-at-pos)))     ad-do-it)) (ad-activate 'linum-update) 
like image 726
Steve Avatar asked Jul 29 '11 14:07

Steve


People also ask

How do I set line numbers in Emacs?

By default, Emacs displays the current line number of the point in the mode line. You can toggle this feature off or on with the command M-x line-number-mode , or by setting the variable line-number-mode .

How do I show line numbers in vi?

Press the Esc key if you are currently in insert or append mode. Press : (the colon). The cursor should reappear at the lower left corner of the screen next to a : prompt. A column of sequential line numbers will then appear at the left side of the screen.

What is relative number in Vim?

When you display relative numbers in Vim, each line is numbered by its distance from the cursor. Take a look at the position of the cursor in the image above. This position is marked as 0. Accordingly, lines above and under the cursor are labeled as 1, the next ones 2 and so on.


2 Answers

In Emacs 26.1, there's a built-in line number mode (display-line-numbers-mode). Enable it and set (setq display-line-numbers 'relative) to use relative line numbers.

like image 194
Aethanyc Avatar answered Oct 09 '22 04:10

Aethanyc


(2012-03-16: line numbers are now right-aligned, and displayed in the correct face.)

The problem here is that by the time a custom linum-format function is called, point has already been moved (by linum-update-window) to the line in question, so we can no longer use it to establish the difference between the two lines; it would just print a zero for every line.

There is a linum-before-numbering-hook, but this is run after point has been moved to the start of the buffer, so that's not useful for our purpose.

The following code solves the problem by using advice for linum-update to store the current line number, so that it will be available to the custom linum-format function.

To right-align the numbers I initially used a hard-coded format string of %3d on the basis that a single window showing more than 100 lines of code was not terribly likely. If you're a fan of follow-mode, however (or simply have multiple windows on the same buffer), that circumstance becomes exceedingly likely; so the code now calculates the number of columns required dynamically. The use of linum-before-numbering-hook makes this more efficient than the approach taken by the default dynamic linum format.

Note that if you comment out the add-hook, the faster non-dynamic approach is used.

(defvar my-linum-format-string "%3d")  (add-hook 'linum-before-numbering-hook 'my-linum-get-format-string)  (defun my-linum-get-format-string ()   (let* ((width (1+ (length (number-to-string                              (count-lines (point-min) (point-max))))))          (format (concat "%" (number-to-string width) "d")))     (setq my-linum-format-string format)))  (defvar my-linum-current-line-number 0)  (setq linum-format 'my-linum-relative-line-numbers)  (defun my-linum-relative-line-numbers (line-number)   (let ((offset (- line-number my-linum-current-line-number)))     (propertize (format my-linum-format-string offset) 'face 'linum)))  (defadvice linum-update (around my-linum-update)   (let ((my-linum-current-line-number (line-number-at-pos)))     ad-do-it)) (ad-activate 'linum-update) 
like image 26
phils Avatar answered Oct 09 '22 02:10

phils