;;
;;  Emacs Lisp tutorial:
;;
;;   - http://www.gnu.org/manual/emacs-lisp-intro/emacs-lisp-intro.html
;;     "Programming in Emacs Lisp"
;;     by Robert J. Chassell.
;; -------------------------------------------
;;
;; See example input/output:  - rjc_fill__before.txt
;;                            - rjc_fill__after.txt

;; Using the function would be something like this:
;;  - visit text that needs formatting in an Emacs buffer
;;  - load function into memory (if not already there)
;;  - make sure any "<p>" tags really are at beginning of paragraph
;;  - add "<p>" tags at beginning of paragraphs that need them
;;  - execute function
;;  - save modified buffer, or send email, or...
;;
;;
(defun rjc-formatter-paragraphs (args)
  "Simple formatting based on <p> tags: add newsline(s), indent and fill"
  (interactive "p")
  (let (
	(my-indentation nil)
	(my-point nil)
	(my-point-end nil)
	(paragraph-tag "<[pP]>")
	(paragraph-tag-length 3))
    (save-excursion
      (save-restriction
	(beginning-of-buffer)
	(while (search-forward-regexp paragraph-tag nil t)
	  (backward-delete-char paragraph-tag-length)
	  (setq my-point (point))
					; Conditionally insert 1st newline.
					; Capture indentation with parentheses.
	  (search-backward-regexp "\n\\([ \t]*\\)" nil t)
	  (setq my-point-end (match-end 0)) (goto-char my-point)
	  (if (= my-point my-point-end)
	      nil
	    (newline 1))
					; Calculate indentation.
	  (setq my-indentation "")
	  (if (not (match-string 1))
	      nil
	    (setq n (length (match-string 1)))
	    (while (> n 0)
	      (setq my-indentation (concat my-indentation " "))
	      (setq n (- n 1))))
					; Conditionally insert 2nd newline.
	  (search-backward-regexp "\n[ \t]*\n[ \t]*" nil t)
	  (setq my-point-end (match-end 0)) (goto-char my-point)
	  (if (not (= my-point my-point-end))
	      (newline 1)
	    nil)
					; Insert indentation (could be "").
	  (insert my-indentation)
					; Fill all paragraphs except for last.
	  (let ((beg (point)))
	    (if (search-forward-regexp paragraph-tag nil t)
		(fill-region beg (match-beginning 0))
	      nil)
	    (goto-char beg)))
					; Unconditionally fill last paragraph.
	(fill-paragraph nil)))))