'Function to Explode paragraph into org-bullets by sentences

I am trying to write a simple Elisp Emacs function that takes a paragraph (point indicated by [X]) and expands it into a series of bullet points with each bullet containing a sentence.

much more useful, especially with huge windows. In my experience, it slows down redraw a little bit, but it’s worth it.There are two ways to enable it: the first is with M-x visual-line-mode[X] (for those with real menus, apparently Options->Line Wrapping in this Buffer->Word Wrap), which will give you a minor mode “wrap” in the mode line.

and returns

+ much more useful, especially with huge windows. 
+ In my experience, it slows down redraw a little bit, but it’s worth it.
+ There are two ways to enable it: the first is with M-x visual-line-mode[X] (for those with real menus, apparently Options->Line Wrapping in this Buffer->Word Wrap), which will give you a minor mode “wrap” in the mode line.

Here is what I have so far:

(defun jds/explode ()
  "explode paragraph, more documentation needed"
  (interactive)
  (save-excursion
    (let ((bop (copy-marker (progn (backward-paragraph) (point))))
          (eop (copy-marker (progn (forward-paragraph) (point)))))
          (goto-char bop)
          (back-to-indentation) ;; goto first non-whitespace character
          (if (re-search-forward "^[:blank:]*[+-x] " nil t) nil (insert "+ "))
          (while (< (point) eop)
            (forward-sentence)
            (forward-whitespace 1)
            (unless (>= (point) eop)
              (org-meta-return)))))))))

But this just seems to run but not do anything. I think the problem may be that the backward-paragraph function may not be putting the point on the first non-black character (the m in much). But that said, my Elisp is very weak and I am struggling to figure out the problem.



Solution 1:[1]

Turns out this works - just needed to add +/-1 to point

(defun jds/explode ()
  "explode paragraph, more documentation needed"
  (interactive)
  (save-excursion
    (let ((bop (copy-marker (progn (backward-paragraph) (+ (point) 1))))
          (eop (copy-marker (progn (forward-paragraph) (- (point) 1)))))
          (goto-char bop)
          (if (looking-at-p "^[:blank:]*[+-x] ") nil (insert "+ "))
          (while (< (point) eop)
            (forward-sentence)
            (forward-whitespace 1)
            (unless (>= (point) eop)
              (org-meta-return))))))

Solution 2:[2]

  (defun explode-paragraph ()
    "Explode paragraph. If run twice it changes list marker."
    (interactive)
    (save-mark-and-excursion
      (let ((bop (copy-marker (progn (backward-paragraph) (1+ (point)))))
            (eop (copy-marker (progn (forward-paragraph)  (point)))))
        (goto-char bop)
        (if (looking-at-p "^\s*[\-\+x] ") nil (insert "+ "))
        (while (< (point) eop)
          (forward-sentence)
          (forward-whitespace 1)
          (unless (>= (point) eop)
            (org-meta-return))))))

I extended your implementation to work for my use-case. I changed a couple of things:

  • I changed [:blank:] to \s because it was matching on lines under a header (if anyone knows why this is I'd be happy to be educated).
  • I used the (+1 (point) notation and removed the -1 from the eop, as I didn't find it necessary.
  • I escaped the special symbols inside [...] because -x was matching lines starting with 'A'.

In my own version of this function I have the first line (summary sentence) a level up from the other sentences, but I think this should cover most cases for its original intended purpose.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 jds
Solution 2 cachora