Относительные номера строк в Emacs

Кто-нибудь знает, как, если что-то вроде этого Vim Relative Line Numbers существует для emacs? Я использую vimpulse, и это было бы очень удобно! Я знаю немного шепелявости, поэтому, если это не так, я мог бы попытаться сделать свой собственный, если бы я понял правильное направление.

Обновление: Благодаря правильному ответу я придумал это, которое будет показывать 1 для текущей строки и -1 для предыдущей строки, для объединения с вимпульсом дергает и удаляет.

Большое спасибо всем, кто помог! Я знаю, что это не совсем то, что делает Vim, но что хорошего в относительных номерах строк в 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)

person Steve    schedule 29.07.2011    source источник
comment
Как сказал Стив, он использует vimpulse в Emacs. emacswiki.org/emacs/Vimpulse   -  person phils    schedule 29.07.2011
comment
@phils - ах, спасибо, пропустил этот кусок поста.   -  person jtahlborn    schedule 29.07.2011
comment
Стив, я позволил себе обновить вашу версию, исправив ошибку, чтобы использовать правильное лицо для вывода функции в формате linum.   -  person phils    schedule 13.03.2012
comment
Кстати: Что касается такой функции относительного номера строки, как она должна вести себя, когда буфер отображается в нескольких окнах: должны ли другие окна отображать номера строк относительно их соответствующих точек или точки в текущем выбранном окне (и если да, что должно произойти, если ни одно из окон буфера не является выбранным окном)?   -  person Stefan    schedule 29.09.2015


Ответы (5)


(2012-03-16: номера строк теперь выравниваются по правому краю и отображаются правильным шрифтом.)

Проблема здесь в том, что к моменту вызова пользовательской функции linum-format точка уже была перемещена (на linum-update-window) в рассматриваемую линию, поэтому мы больше не можем использовать ее для установления разницы между двумя линиями; он просто печатал бы ноль для каждой строки.

Есть linum-before-numbering-hook, но он запускается после того, как точка была перемещена в начало буфера, так что это бесполезно для нашей цели.

Следующий код решает проблему, используя совет для linum-update для сохранения текущего номера строки, чтобы он был доступен для пользовательской функции linum-format.

Чтобы выровнять числа по правому краю, я изначально использовал жестко заданную строку формата %3d на том основании, что одно окно, показывающее более 100 строк кода, маловероятно. Однако, если вы являетесь поклонником follow-mode (или просто имеете несколько окон в одном и том же буфере), это обстоятельство становится чрезвычайно вероятным; поэтому код теперь вычисляет количество необходимых столбцов динамически. Использование linum-before-numbering-hook делает это более эффективным, чем подход, принятый по умолчанию форматом dynamic linum.

Обратите внимание, что если вы закомментируете add-hook, будет использован более быстрый нединамический подход.

(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)
person phils    schedule 03.08.2011
comment
Два вопроса. Как я могу иметь отрицательные номера строк без префикса -? И как я могу избежать того, чтобы номера строк получали одинаковые настройки лица в строке, которую они представляют? Например, номера строк для закомментированных строк окрашиваются в тот же цвет, что и сами комментарии. - person jimeh; 13.03.2012
comment
Чтобы удалить знак минус, просто вызовите abs, чтобы получить абсолютное значение числа. то есть: (number-to-string (abs (- line-number my-linum-current-line-number))) - person phils; 13.03.2012
comment
Что касается второго вопроса, в моем коде отсутствовала хитрость: когда linum-format является функцией, возвращаемое значение не соответствует автоматически linum face. Я обновил код выше, чтобы позаботиться об этом. Затем вы можете M-x customize-group RET linum RET, если хотите изменить лицо дальше. - person phils; 13.03.2012
comment
Спасибо, отлично работает :)... У меня только один последний вопрос, как вы выравниваете по правому или левому краю номера строк? Например, здесь номера строк выровнены по левому краю: cl.ly/2J1i1T2B0Q0N13181g24 - person jimeh; 14.03.2012
comment
Еще раз спасибо :D... Я добавил вызов abs, так как считаю, что отрицательные числа выглядят странно. И мне кажется, что follow-mode будет проблемой, только если вы можете вывести на экран 1000 или более строк одновременно. Но тогда это может быть из-за того, что я удалил символ -... лол - person jimeh; 20.03.2012
comment
Я взял этот код и написал relative-linum.el в EmacsWiki, чтобы другие могли его использовать. Проверьте это: emacswiki.org/emacs/relative-linum.el . Я надеюсь, что это нормально :) - person Wilfred Hughes; 11.07.2012
comment
Конечно (если вы добавите phils после URL-адреса stackoverflow, это будет нормально для атрибуции), за исключением того, что я могу только предложить удалить то, что вы добавили к нему: ваша relative-linum-jump в основном идентична функции forward-line, которую она вызывает, и поэтому не на самом деле не служат цели; и вы затираете привязку, которую не должны использовать. - person phils; 11.07.2012
comment
Решение работает, к сожалению, оно также вызывает много раздражающих миганий (я думаю, медленная перерисовка) при перемещении курсора, по крайней мере, в Emacs24 + Windows. В конечном счете, это то, что, вероятно, должно быть реализовано в ядре. - person juanjux; 12.09.2014
comment
juanjux: Попробуйте запустить emacs -Q и посмотрите, сохраняется ли эта проблема после загрузки этого кода. В то время, когда я это писал, это было на самом деле более эффективно, чем linum по умолчанию (но я думаю, что это было решено в промежуточный период). В любом случае, я был бы удивлен, если бы у вас возникли проблемы с этим кодом, которых не было с немодифицированным linum? Попробуйте байтовую компиляцию кода, если вы еще этого не сделали. Вы также можете исследовать пакет nlinum, который был написан сопровождающим Emacs, чтобы стать более эффективной заменой linum. - person phils; 12.09.2014
comment
Я не знаю, сработает ли это для вашего ответа, но я получил значительное увеличение скорости в пользовательском второстепенном режиме, используя: (save-excursion (goto-char (point-max)) (format-mode-line "%l")) вместо count-lines, что вызывает замедление в больших буферах. emacs.stackexchange.com/a/3822/2287 У вас есть несколько вхождений в ответе в его нынешнем виде - - т. е. line-number-at-pos опирается на count-lines, и у вас также есть count-lines отдельно. - person lawlist; 29.09.2015

В Emacs 26.1 есть встроенный режим номеров строк (display-line-numbers-mode). Включите его и установите (setq display-line-numbers 'relative) для использования относительных номеров строк.

person Aethanyc    schedule 27.01.2019
comment
Для меня (setq display-line-numbers-type 'relative) включил его глобально. (Эмакс 26.3) - person loki; 11.01.2021
comment
@loki display-line-numbers-type отлично работает - person rox; 11.05.2021

Я только что наткнулся на код Скотта Джейдерхольма для этого и вспомнил, что видел этот вопрос, поэтому решил опубликовать ссылку на соответствующие строки в его .emacs.

Обновление: если вы используете MELPA (а так и должно быть!), просто Mx package-install RET linum-relative.

person sanityinc    schedule 24.10.2011
comment
Наиболее полной и современной библиотекой, обеспечивающей эту функциональность, на самом деле является linum-relative., для которого Melpa предоставляет моментальный снимок пакета ELPA. - person sanityinc; 10.12.2012
comment
@sanityinc linum-relative у меня не устанавливается из melpa с помощью package.el или el-get. Как вы заставили его работать? - person Sam Hasler; 06.02.2013
comment
@Sam Установка linum-relative из Melpa у меня отлично работает. Что вы имеете в виду под не устанавливает? Вы получаете сообщение об ошибке или не видите его в своих списках пакетов? - person sanityinc; 07.02.2013
comment
Те же проблемы с перерисовкой на emacs24 + windows, что и на коде Фила. - person juanjux; 12.09.2014
comment
PS: но отлично работает на графическом интерфейсе и консоли Linux, проблема, похоже, только в Windows Emacs. - person juanjux; 12.09.2014
comment
linum-mode работает очень, очень и очень медленно для моих оргфайлов, которые немного больше. display-line-number-mode похоже решает эту проблему. - person Student; 08.12.2019

Кстати, если вы хотите перейти только к определенной строке, ace-jump- mode предоставляет команду ace-jump-line-mode, которая позволяет перейти к определенной строке, видимой на экране. Однако он использует буквы, а не цифры для строк:

скриншот ace-jump-mode

person Wilfred Hughes    schedule 30.01.2014

Посмотрите на M-x linum-mode и переменную linum-format.

linum-format — это переменная, определенная в linum.el.
Ее значение является динамическим.

Документация:

Формат, используемый для отображения номеров строк.
Либо строка формата, такая как "%7d", `динамическая' для адаптации ширины по мере необходимости, либо функция, которая вызывается с номером строки в качестве аргумента и должна возвращать строку для будет отображаться в этой строке.
См. также `linum-before-numbering-hook'.

person aartist    schedule 29.07.2011
comment
Ах, я не видел этого раньше, что я могу просто дать ему функцию для создания строки, показанной в строке... хороший звонок, я мог бы попробовать сделать свой собственный на этих выходных. - person Steve; 29.07.2011