ErgoEmacsEmacsLispBlogEmacsLispBuy Tutorial
Web Hosting by 1&1

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

Xah Lee, , …,

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 email or plain text based report. 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 reverse 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.

When user needs to break lines for several paragraphs of text, she need to call fill-region. There is no keyboard shortcut for it. It would be nice, if the hard-wrap command will automatically work on a text selection if it exists.

In the following, we suggest a command “compact-uncompact-block”. It does “fill” or “unfill” on the current paragraph. If there is a text selection, then the command automatically works on the region. This way, there is one single command with one single shortcut to remember.

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 4333999) (deactivate-mark nil))

    (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 compact-uncompact-block command is part of ErgoEmacs Keybinding.

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.

blog comments powered by Disqus