Emacs's Line Wrap Commands: fill-region, unfill-region, compact-uncompact-block

, , …,

Emacs has a command fill-paragraphAlt+q】 that does hard-wrap of current paragraph (it inserts a newline char at every ≈70 chars.). This command is especially useful when writing plain English such as email. Emacs also has fill-region, which acts on a text selection. However, there are some usability problems with these commands. This page discuss the problems and some suggestions.

One frequently asked question is how to “unfill” — do inverse of fill-paragraph. Technically, this means replacing newline char by space. Emacs does not have a built-in command for this. The typical answer to this question, is to set the cut-width to a huge number (⁖ set fill-column to 10001000), then call fill-paragraph, then set fill-column back to previous value. This is inconvenient.

If you need to reformat several paragraphs, you need to call fill-region. There is no keyboard shortcut for it.

In the following, we suggest a command to automatically toggle “fill” or “unfill” on the current paragraph. If there is a text selection, then the command automatically works on the region.

Here is a implementation:

(defun compact-uncompact-block ()
  "Remove or add line ending chars on current paragraph.
This command is similar to a toggle of `fill-paragraph'.
When there is a text selection, act on the region."
  (interactive)

  ;; This command symbol has a property “'stateIsCompact-p”.
  (let (currentStateIsCompact (bigFillColumnVal 90002000) (deactivate-mark nil))
    ;; 90002000 is just random. you can use `most-positive-fixnum'

    (save-excursion
      ;; Determine whether the text is currently compact.
      (setq currentStateIsCompact
            (if (eq last-command this-command)
                (get this-command 'stateIsCompact-p)
              (if (> (- (line-end-position) (line-beginning-position)) fill-column) t nil) ) )

      (if (region-active-p)
          (if currentStateIsCompact
              (fill-region (region-beginning) (region-end))
            (let ((fill-column bigFillColumnVal))
              (fill-region (region-beginning) (region-end))) )
        (if currentStateIsCompact
            (fill-paragraph nil)
          (let ((fill-column bigFillColumnVal))
            (fill-paragraph nil)) ) )

      (put this-command 'stateIsCompact-p (if currentStateIsCompact nil t)) ) ) )

This command is part of ErgoEmacs Keybinding. The command name is ergoemacs-compact-uncompact-block.

One improvement is to make the command do source code formatting in a smart way when the current buffer is in a programing language mode. (like C-lint, HTML-lint, JSLint, etc.) It should toggle the formatting between a compact and non-compact style. The compact style will mostly likely be single line when possible, especially useful for functional languages such as lisp.

blog comments powered by Disqus