HomeMathComputingArtsWordsLiteratureMusictwitter facebook webfeed

All About Processing Lines in Emacs Lisp

Advertise Here For Profit

Xah Lee, 2010-06-08

This page discuss issues about which emacs lisp functions to use for processing lines. e.g. move cursor to end of line, to next line, grabbing the current line, etc. If you don't know elisp, first take a look at Emacs Lisp Basics.

In emacs, there are lots of ways to move or grab lines. In particular, in the first few years of my elisp experience, i find it confusing. Here are some functions or variables that are related to lines:

line-beginning-position, line-end-position
move-beginning-of-line, move-end-of-line
next-line, previous-line
forward-line
(search-forward "\n"), (search-backward "\n")
line-move-visual
(thing-at-point 'line)

Do you know the differences? Also, there are issues such as:

Get Line Beginning/Ending Position

To get the position of line beginning/ending position, use:

(setq p1 (line-beginning-position) )
(setq p2 (line-end-position) )

These are written in C.

Move to Beginning/End of a Line

To move cursor to beginning or end of a line, use:

(beginning-of-line) ; better than (goto-char (line-beginning-position))
(end-of-line)       ; better than (goto-char (line-end-position))

These are written in C. So, they are much faster than other functions that are written in elisp.

They don't have problems when the line is at the beginning of buffer or end.

They work by EOL (end of line) character. That is, not screen line.

Do not use (search-forward "\n") for moving cursor to end of line. Because you'll have special cases if the line is at the end of buffer and doesn't have a EOL. It is also slower.

Do not use “move-beginning-of-line” or “move-end-of-line”. Because these are designed for interactive use.

Move to Previous/Next Line

To move by line, use:

(forward-line 1)
(forward-line -1)

Do not use “next-line” or “previous-line”. Because these are for interactive use. Their behavior changes depending on the variable “line-move-visual”.

Grab the Current Line

To grab current line, use:

(let (p1 p2 myLine)
  (setq p1 (line-beginning-position) )
  (setq p2 (line-end-position) )
  (setq myLine (buffer-substring-no-properties p1 p2))
)

Do not use (thing-at-point 'line), because “thing-at-point” have problems when the line is at the end of buffer. Normally, thing-at-point will include the EOL char, but if the line is at the end of buffer, then it won't. So, if you use it, you have to do extra work to detect special cases. Also, “thing-at-point” is complex elisp code and is slower. (See: Emacs thing-at-point and Chaining Functions)

Get All Lines In a File Into a List

See: Process a File line-by-line in Emacs Lisp.

Screen Lines

If you want to move cursor across lines as defined by the screen, you can use these.

next-line, previous-line
line-move-visual

“line-move-visual” is a variable that controls whether “next-line” and “previous-line” move by EOL or screen.

Misc

Note that in emacs buffer, all EOL are represented by "\n" in elisp.

So, if you need to use (search-forward "\n"), you don't have to worry about whether the file uses unix or Windows line endings. (See: Emacs Line Return and Windows, Unix, Mac, All That ^M ^J ^L.)

Thanks to Uday S Reddy and Alan Mackenzie for some tips.

blog comments powered by Disqus