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?

sanityinc
  • 2,871
  • 13
  • 17
jmay
  • 363
  • 2
  • 9

3 Answers3

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)) ) ) )
Tyler
  • 21,719
  • 1
  • 52
  • 92
  • 2
    i think parts can be improved. see https://gist.github.com/xahlee/d364cbbff9b3abd12d29 don't really need compact-uncompact-block since it does toggle. – Xah Lee Oct 11 '14 at 17:19
  • Thanks for this, Tyler and @XahLee. Looks just like what I need. – jmay Oct 12 '14 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 Oct 13 '14 at 01: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.

Drew
  • 75,699
  • 9
  • 109
  • 225
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)))