how to collapse whitespaces in a region?

You can deal with your rectangle requirements using cua-mode's rectangle editing facilities*.

  1. M-x cua-selection-mode RET or (cua-selection-mode 1)
    (myself, I have this enabled permanently).

  2. Mark the rectangle within which you wish to collapse the whitespace, using C-RET and the normal movement keys.

  3. Call cua-replace-in-rectangle:
    M-r \s-+ RET SPC RET

  4. C-RET again to end rectangle editing.

(*) This won't work if you need fields to the right of the rectangle to remain aligned, as in that case you would need to insert new spaces to compensate for the ones which were removed. You could use 2C-split and 2C-merge or just kill/yank the right-most rectangle to work around that.


Not really answering your question but there is

 M-SPC runs the command just-one-space, which is an interactive
 compiled Lisp function in `simple.el'.

 It is bound to M-SPC.

 (just-one-space &optional N)

 Delete all spaces and tabs around point, leaving one space (or N spaces).

 [back]

which is useful when you want to delete whitespace in one off cases. It might be suitable for a macro case where the deletions are at random lines with no fixed pattern.


This function should do the trick:

(defun just-one-space-in-region (beg end)
  "replace all whitespace in the region with single spaces"
  (interactive "r")
  (save-excursion
    (save-restriction
      (narrow-to-region beg end)
      (goto-char (point-min))
      (while (re-search-forward "\\s-+" nil t)
        (replace-match " ")))))

And, since the question was updated to apply to spaces in a rectangle, try this:

(require 'rect)  
(defun just-one-space-in-rect-line (start end)
  (save-restriction
    (save-match-data
      (narrow-to-region (+ (point) start)
                        (+ (point) end))
      (while (re-search-forward "\\s-+" nil t)
        (replace-match " ")))))
(defun just-one-space-in-rect (start end)
  "replace all whitespace in the rectangle with single spaces"
  (interactive "r")
  (apply-on-rectangle 'just-one-space-in-rect-line start end))