3

I'd like to be able to quickly "shuffle" the order in which all paragraphs in a region occur. Can this be easily accomplished in emacs?

For example, consider the following region.

Hello world.

This is the original second paragraph
and it contains two lines.

This is the original third paragraph and
it contains three
lines

Paragraph number four.

Running my desired command would result in a random reordering of these four paragraphs. The output might be something like

This is the original third paragraph and
it contains three
lines

Hello world.

Paragraph number four.

This is the original second paragraph
and it contains two lines.
1

Adapted from sort-paragraphs:

(defun sort-paragraphs-randomly (beg end)
  (interactive (if (use-region-p)
                   (list (region-beginning) (region-end))
                 (list (point-min) (point-max))))
  (save-excursion
    (save-restriction
      (narrow-to-region beg end)
      (goto-char (point-min))
      (sort-subr nil
                 (lambda ()
                   (while (and (not (eobp)) (looking-at paragraph-separate))
                     (forward-line 1)))
      'forward-paragraph
      nil nil 
      (lambda (_ _)
        (= (random 2) 0))))))
1

Edt. For short answer, look at @lawlist answer.

For explicit one, kinda. you may repeat the following sequence

(mark-paragraph)
(kill-region)
(backward-paragraph) || (forward-paragraph)
(yank)

while if in the leaf or root paragraph and there is no newline at the beginning and end do

(backward-paragraph) || (forward-paragraph)     ;; Respectively (leaf || root)
(newline)

Ow.. and if this happened to be the leaf then also do

(previous-line)
1

First create a list of paragraphs in the region. Then 1. shuffle the list, 2. delete the region, and 3. insert the shuffled list. The function below is a modified version of the shuffle-list function found here (thanks to lawlist for the link). Also, to get the correct spacing between paragraphs, you have to start with the cursor on the line above the first paragraph and end on the line below the last paragraph.

(defun shuffle (list)
  (let ((i (1- (length list))))
    (while (>= i 0)
      (let ((rand (random (1+ i)))
            (orig (nth i list)))
        (setcar (nthcdr i list) (nth rand list))
        (setcar (nthcdr rand list) orig)
        (setq i (1- i)))))
  list)

(defun shuffle-paragraphs (beg end)
  (interactive "r")
  (let* ((region (buffer-substring beg end))
         (list (split-string region org-element-paragraph-separate t))
         (shuffle (shuffle list)))
    (delete-region beg end)
    (cl-loop for par in shuffle
             do (insert par))))

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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