Emacs: Move Cursor by Paragraph or Text Block

By Xah Lee. Date: . Last updated: .

This pages shows you 2 emacs commands to move cursor by text block (paragraph) in a predictable way across major modes.

Emacs has commands forward-paragraphCtrl+】 and backward-paragraphCtrl+】. The problem with these is that the definition of “paragraph” in emacs is not predictable; it depends on what mode you are in. For example, in text-mode, a paragraph is 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.) (info "(elisp) Syntax Tables")

The following commands let you move by paragraph in a predictable way, regardless what major mode you are in.

(defun xah-forward-block (&optional φn)
  "Move cursor forward to the beginning of next text block.
A text block is separated by blank lines.
In most major modes, this is similar to `forward-paragraph', but this command's behavior is the same regardless of syntax table."
  (interactive "p")
  (let ((φn (if (null φn) 1 φn)))
    (search-forward-regexp "\n[\t\n ]*\n+" nil "NOERROR" φn)))

(defun xah-backward-block (&optional φn)
  "Move cursor backward to previous text block.
See: `xah-forward-block'"
  (interactive "p")
  (let ((φn (if (null φn) 1 φn))
        (ξi 1))
    (while (<= ξi φn)
      (if (search-backward-regexp "\n[\t\n ]*\n+" nil "NOERROR")
          (progn (skip-chars-backward "\n\t "))
        (progn (goto-char (point-min))
               (setq ξi φn)))
      (setq ξi (1+ ξi)))))

Note: these commands are in ergoemacs-mode and my versions are in xah fly keys.

You can bind the emacs default keys to it:

(global-set-key (kbd "<C-up>") 'xah-backward-block)
(global-set-key (kbd "<C-down>") 'xah-forward-block)

But more efficient, is:

(global-set-key (kbd "<prior>") 'xah-backward-block)
(global-set-key (kbd "<next>") 'xah-forward-block)

This makes the 【⇞ Page △】 & 【⇟ Page ▽】 keys do move by block. This is more efficient use of keys, because:

  1. moving by block is more frequently needed than by screen. 〔➤see Keybinding Design: Dedicated keys, Special Buttons, Extra Keys
  2. Single key for operation is better than key combination of 2 keys. 〔➤see Banish Key Chords
  3. paging by screen is more efficiently done with mouse scroll wheel. 〔➤see Emacs Keybinding Efficiency: Page Up/Down and Pigeon Hole Principle

Note: a even more efficient keybinding is to combine beginning-of-lineend-of-line commands with it. See: Emacs Lisp: Move Cursor to Beginning of Line/Block.

Like it? Buy Xah Emacs Tutorial. Thanks.