ErgoEmacsEmacsLispBlogEmacsLispBuy Tutorial
Web Hosting by 1&1

Emacs: How to Move Around Source Code Section (^L) and Text Blocks

Xah Lee, ,

This page gives you some tips for moving cursor around sections in source code in emacs lisp, and also commands to navigate paragraphs.

Displaying Form Feed Character as Line

Emacs lisp uses the Form Feed character (Form Feed; ASCII 12) as source code section marker. It is displayed as “^L”.

emacs page break lines mode screenshot 2012-11-15
Emacs page-break-lines-mode screenshot

You can make emacs display the Form Feed character as a horizontal line. You need to install Steve Purcell's 〔page-break-lines.el〕. It's in MELPA package repository. 〔☛ A Guide on Emacs 24 Package System

Typing the Form Feed Character

In emacs, you can type the char by pressing 【Ctrl+q】 then 【Ctrl+l】. 〔☛ Emacs's Key Notations Explained (/r, ^M, C-m, RET, <return>, M-, meta)

Keys for Navigating Source Code Section

Emacs has keys to jump to the Form Feed char. By default, the keys are:

It's hard to use and hard to remember. You can set a more convenient key. For example:

;; keys for moving to prev/next code section (Form Feed; ^L)
(global-set-key (kbd "<C-M-prior>") 'backward-page) ; Ctrl+Alt+PageUp
(global-set-key (kbd "<C-M-next>") 'forward-page)   ; Ctrl+Alt+PageDown

Using 【Ctrl+Alt】 makes it consistent with the default keys to navigate lisp code. 〔☛ How to Edit Lisp Code with Emacs

Emacs Lisp Commands to Navigate Paragraphs

Emacs has commands forward-paragraphCtrl+】 and backward-paragraphCtrl+】. The problem with these is that the definition of “paragraph” in emacs is not well defined; it depends on what mode you are in. For example, in text-mode, a paragraph is basically a text block separated by newline characters. But in html-mode, it moves by some weird way. (copy source code of this page then paste in emacs, turn on html-mode and try to move by paragraph.)

Technically, this is because the notion of “paragraph” in emacs is dependent on emacs's syntax table. (emacs's syntax table is a elementary system that categorize characters into semantic categories. From my experience in the past few years, i don't think it is a good system, and i think emacs could do without.) (info "(elisp) Syntax Tables")

Moving by Text Blocks in a Consistent Way: “forward-block” and “backward-block”

The following commands lets you move by paragraph in a consistent way regardless of syntax table.

(defun forward-block ()
  "Move cursor forward to next occurrence of double newline character.
In most major modes, this is the same as `forward-paragraph', however, this command's behavior is the same regardless of syntax table."
  (interactive)
  (skip-chars-forward "\n")
  (when (not (search-forward-regexp "\n[[:blank:]]*\n" nil t))
    (goto-char (point-max)) ) )

(defun backward-block ()
  "Move cursor backward to previous occurrence of double newline char.
See: `forward-block'"
  (interactive)
  (skip-chars-backward "\n")
  (when (not (search-backward-regexp "\n[[:blank:]]*\n" nil t))
    (goto-char (point-min))
    )
  )

You can assign a key like this:

(global-set-key (kbd "<C-up>") 'backward-block) ; Ctrl+↑
(global-set-key (kbd "<C-down>") 'forward-block) ; Ctrl+↓

This way, when you press a key to move by “paragraph”, the cursor movement is predictable.

For a detailed discussion of using the Form Feed character as page section marker, see: Emacs Form Feed (^L) Display Suggestion and Tips.

Thanks to Steve Purcell ( https://twitter.com/sanityinc ) for tips.

blog comments powered by Disqus