Emacs Lisp: fill/unfill-region Toggle, compact-uncompact-block

Buy Xah Emacs Tutorial. Master emacs benefits for life.
, , …,

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."

  ;; 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'

      ;; 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 (use-region-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.

Like it? Buy Xah Emacs Tutorial.
blog comments powered by Disqus