7

I would like to be able to easily select a region of text from Emacs and then paste it into another app or browser - with all the extra fill-paragraph newlines removed so that the paragraph display in the other app can work properly.

The unfill-region function in the unfill package seems fine for this, but further work is needed to automate this properly. Before I do that, does this already exist?

3 Answers 3

7

I use the following for this:

(defun my-copy-simple (beg end)
  "Save the current region to the kill ring after stripping extra whitespace and new lines"
  (interactive "r")
  (copy-region-as-kill beg end)
  (with-temp-buffer 
    (yank)
    (goto-char 0)
    (while (looking-at "[ \t\n]")
      (delete-char 1))
    (compact-uncompact-block)
    (mark-whole-buffer)
    (kill-region (point-min) (point-max))))

This depends on the following function, which I've been using for a while as a replacement for the default M-q fill-paragraph. I didn't note where it came from, I think it was Xah Lee's?

(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)) ) ) )
3
  • 2
    i think parts can be improved. see gist.github.com/xahlee/d364cbbff9b3abd12d29 don't really need compact-uncompact-block since it does toggle.
    – Xah Lee
    Commented Oct 11, 2014 at 17:19
  • Thanks for this, Tyler and @XahLee. Looks just like what I need.
    – jmay
    Commented Oct 12, 2014 at 23:32
  • 1
    @xahless it doesn't need compact-uncompact-block, but if you already have it you might as well use it. I hardly ever remember to use my-copy-simple, but c-u-b is indispensable now!
    – Tyler
    Commented Oct 13, 2014 at 1:49
3

If you only want to remove newlines, then use replace-regexp-in-string on the result of buffer-substring to remove them.

If you want to remove all extra (typically "insignificant") whitespace, then try function ni-buffer-substring-collapsed-visible from library narrow-indirect.el.

It returns the buffer content between two positions, but with whitespace collapsed (extra whitespace removed, including newlines).

And if you also use library `subr+.el' then invisible text is also removed.

1

There is a package called "unfill.el" for this purpose: https://github.com/purcell/unfill

It comes with an unfill-toggle and unfill-region command.

Someone also posted code to "unfill" a paragraph on the EmacsWiki: https://www.emacswiki.org/emacs/UnfillParagraph

;;; Stefan Monnier <foo at acm.org>. It is the opposite of fill-paragraph    
(defun unfill-paragraph (&optional region)
  "Takes a multi-line paragraph and makes it into a single line of text."
  (interactive (progn (barf-if-buffer-read-only) '(t)))
  (let ((fill-column (point-max))
        ;; This would override `fill-column' if it's an integer.
        (emacs-lisp-docstring-fill-column t))
    (fill-paragraph nil region)))

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.