From: bobg@zindigo.z-code.COM (Bob Glickstein)
Newsgroups: gnu.emacs.sources
Subject: intelligent-fill-paragraph (was Re: Mail enhancements, was Re: How to get '>' with C-c C-y in rmail-mode)
Date: 16 Oct 92 01:48:46 GMT
Article-I.D.: zindigo.9210160848.ZM5324
Reply-To: Bob Glickstein <bobg@z-code.z-code.com>
Distribution: gnu
Organization: Z-Code Software Corp., Marin County, CA

On Oct 15,  3:22pm, Barry A. Warsaw wrote:
> Yup, supercite is what you want. It does all the extracting of author
> names automatically, plus it provides "header rewrite functions" which
> put in the attribution line(s) (the "CL" == ... line above).

While you're at it, you might want to try my
"intelligent-fill-paragraph" function below, which is primarily useful
for refilling paragraphs cited with supercite or C-c C-y.  It
magically determines the fill-prefix for the paragraph.  To refill
text that looks like this:

----------------
In article foo, bar@baz wrote:
XX> arnings maticeborely
XX> cigaflextreatancannive brainwards minity remics februs madm den nierchesignosebolar skullipotes immitmanum girl
XX> clouisexecustinuo bikiano defactionary lebandiwordinglandrox
YY>> runnecerthearelia libalarciblens sliper bouringbor hildouringle mate
YY>> cleaveyork hously
YY>> ovat ged putth mulhu entionessoldher nooneragglycereferode moducedes royed hearmist ale achief atted
----------------

first open blank lines between regions of differing prefixes (so that
forward-paragraph and backward-paragraph, which are used by
intelligent-fill-paragraph, can correctly delimit the region):

----------------
In article foo, bar@baz wrote:

XX> arnings maticeborely
XX> cigaflextreatancannive brainwards minity remics februs madm den nierchesignosebolar skullipotes immitmanum girl
XX> clouisexecustinuo bikiano defactionary lebandiwordinglandrox

YY>> runnecerthearelia libalarciblens sliper bouringbor hildouringle mate
YY>> cleaveyork hously
YY>> ovat ged putth mulhu entionessoldher nooneragglycereferode moducedes royed hearmist ale achief atted
----------------

then place the cursor in the paragraph you wish to fill, and do it.

----------------
In article foo, bar@baz wrote:

XX> arnings maticeborely cigaflextreatancannive brainwards minity
XX> remics februs madm den nierchesignosebolar skullipotes immitmanum
XX> girl clouisexecustinuo bikiano defactionary lebandiwordinglandrox

YY>> runnecerthearelia libalarciblens sliper bouringbor hildouringle
YY>> mate cleaveyork hously ovat ged putth mulhu entionessoldher
YY>> nooneragglycereferode moducedes royed hearmist ale achief atted
----------------

"intelligent-fill-paragraph" can be disabled for a particular buffer
with M-x set-variable RET intelligent-fill-enable RET nil RET (in
which case it behaves exactly like fill-paragraph).



(defun common-prefix (str1 str2)
  (let ((i 0))
    (while (and (< i (length str1))
		(< i (length str2))
		(= (aref str1 i)
		   (aref str2 i)))
      (setq i (+ i 1)))
    (if (> i 0)
	(substring str1 0 i)
      nil)))

(defun split-at-newlines (str)
  (let ((s str)
	(result '())
	nl)
    (while (not (string= s ""))
      (setq nl (string-match "\n" s))
      (if nl (progn (setq result (cons (substring s 0 nl) result))
		    (setq s (substring s (+ nl 1))))
	(setq result (cons s result))
	(setq s "")))
    (reverse result)))

(defun paragraph-common-prefix ()
  (save-excursion
    (let* ((pend (save-excursion (forward-paragraph)
				 (point)))
	   (pstart (if (= (point) (point-min))
		       (point)
		     (backward-paragraph)
		     (point))))
      (if (looking-at "$")
	  (forward-char 1))
      (if (>= (point) pend) nil
	(let ((line2 (point)))
	  (goto-char pend)
	  (if (looking-at "^")
	      (backward-char 1))
	  (if (>= line2 (point)) nil
	    (let* ((lines (split-at-newlines (buffer-substring line2 
							       (point))))
		   (prefix (car lines)))
	      (setq lines (cdr lines))
	      (if (not lines)
		  nil
		(while (and prefix lines)
		  (setq prefix (common-prefix prefix (car lines)))
		  (setq lines (cdr lines)))
		prefix))))))))
	      
(defun isalnum (c)			; tabs and spaces are alphanumeric (!)
  (or (and (>= c ?A)
	   (<= c ?Z))
      (and (>= c ?a)
	   (<= c ?z))
      (and (>= c ?0)
	   (<= c ?9))
      (= c 32)
      (= c 9)))

(defun string-alnum-p (str)
  (let ((i 0)
	(l (length str))
	(result t))
    (while (and result (< i l))
      (setq result (isalnum (aref str i)))
      (setq i (1+ i)))
    result))

(defvar intelligent-fill-enable t
  "*Controls whether intelligent filling is enabled for this buffer.")

(make-variable-buffer-local 'intelligent-fill-enable)

(defun intelligent-fill-paragraph (arg)
  "Fill paragraph, temporarily setting fill-prefix to this paragraph's
automagically-determined fill prefix.  Prefix ARG means justify as well."
  (interactive "*P")
  (if (not intelligent-fill-enable)
      (fill-paragraph arg)
    (let* ((possible-fill-prefix (paragraph-common-prefix)))
      (if (and possible-fill-prefix
	       (not (string-alnum-p possible-fill-prefix)))
	  nil
	(setq possible-fill-prefix fill-prefix))
      (let ((fill-prefix possible-fill-prefix))
	(fill-paragraph arg)))))

(define-key global-map "\C-xf" 'intelligent-fill-paragraph)
;; ...or whatever keybinding floats your boat



-- 
Bob Glickstein
Z-Code Software Corp.
4340 Redwood Highway  Suite B-50
San Rafael, CA  94903
(415) 499-8649
Newsgroups: gnu.emacs.sources