4

next-line is very slow, and this is creating problems. I'll give some background then explain why.

By default, linum.el treats a wrapped line as a single line, and it takes into account hidden lines when numbering. I need it to number visual lines only - i.e. it should ignore hidden lines, and count wrapped lines as multiple lines.

For example, this is how it works by default:

1 This is a line. 2 This is a long line which has been auto-wrapped >by emacs. 3 This is another line. 

This is the behaviour I want:

1 This is a line. 2 This is a long line which has been auto-wrapped 3>by emacs. 4 This is another line. 

I have this behaviour working, but it's very slow. By default, linum.el uses forward-line to number each line. This is the code that actually moves down by one line and increments the line counter:

(let ((inhibit-point-motion-hooks t)) (forward-line)) (setq line (1+ line)) 

I modified it to use next-line:

(let ((inhibit-point-motion-hooks t)) ;; (forward-line) (next-line)) (setq line (1+ line)) 

This works, but next-line is very slow in comparison to forward-line. Line numbers must be updated frequently so this slows down Emacs considerably.

I don't actually need to number every line. I am happy to use forward-line and number only the beginning of lines, as so:

1 This is a line. 2 This is a long line which has been auto-wrapped >by emacs. 4 This is another line. 

But if I want to do this, I need to be able to check how many screen lines I moved when I called forward-line.

Does anyone have any ideas on how to solve this?

1 Answer 1

2

After delving into the source for next-line, I found a solution.

line-move-visual is the command I want. next-line is an interactive command with side effects that does a lot of unnecessary things, line-move-visual has the core behaviour I'm looking for.

This is the relevant passage after modification:

(let ((inhibit-point-motion-hooks t)) ;; (forward-line) (line-move-visual 1 t)) (setq line (1+ line)) 

This is the full spec for the command:

(line-move-visual ARG &optional NOERROR) 

Suppressing errors is necessary to prevent it dinging when it reaches the end of a buffer.

After some testing it's still a lot slower than forward-line, but it's fast enough to be usable if I delay updates until I'm idling.

4
  • 1
    What you are probably really after is just vertical-motion, since you don't care about goal columns and so forth to handle just line-numbering. The goal columns and so forth are for moving interactively and maintaining the cursor in what appears to be a vertical line when moving over wrapped lines . . . . Type: M-x describe-function RET vertical-motion RET to read more about how that function works. Commented Sep 13, 2016 at 1:02
  • 1
    vertical-motion is costly time-wise -- there is no way around it. If you open up line-move-visual, you'll see it uses vertical-motion and just adds stuff that you don't need for your current project. Unfortunately, Emacs does not have the ability to properly operate on just the visible window from window-start to window-end in all cases. I modified the C-source-code in a custom-build of Emacs to add that feature, but it may never make its way into the mainstream Emacs. There was recent talk of a post-redisplay-hook, but it may or may not ever come to fruition. Commented Sep 13, 2016 at 1:11
  • 1
    You can obtain speed enhancements of linum-mode (in large buffers) by replacing count-lines / line-number-at-pos with (save-excursion (goto-char (point-max)) (format-mode-line "%l")) with some exceptions: emacs.stackexchange.com/questions/3821/… The Emacs team does not care about linum-mode and would prefer that everyone just use Stefan's nlinum-mode -- so there will never be any formal improvements of linum-mode. I haven't really posted much about how to improve linum-mode, but the above is one of them. Commented Sep 13, 2016 at 1:24
  • Thank you! These comments are super helpful. I'll have a look at nlinum. Commented Sep 13, 2016 at 12:27

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.