tom@ssd.harris.com (Tom Horsley) (09/08/89)
Someone was asking about formatting paragraphs with hanging indents. This is
a package I wrote which I now use to do all my paragraph filling. It uses
several empirical rules to recognize a "paragraph" which seem to work well
in practice, at least for the sorts of things I am always typing.
For instance:
/* This is a sample C comment to be formatted by paraform
* this version is
* very ragged, but it will come out nicely filled
* once formatted.
*/
1) This is another sort of
paragraph, which can be filled by paraform with no mode
changes or variable settings required
since filling
the C comment.
becomes:
/* This is a sample C comment to be formatted by paraform this version is
* very ragged, but it will come out nicely filled once formatted.
*/
1) This is another sort of paragraph, which can be filled by paraform with
no mode changes or variable settings required since filling the C
comment.
The requirement for paraform to figure out what goes on is that in both of
the above examples, the cursor was sitting on the 'T' in the first word
(This) in each paragraph when it was filled.
I replaced the standard fill paragraph key binding with this, but people who
normally fill paragraphs with the cursor sitting at the end may not want to
do that, paraform only works with the cursor on the first character of the
paragraph, also it cannot work at all if you want paragraphs with the first
line indented.
-------------------cut here for paraform.el------------------------------
;; This is a paragraph formatting command that combines many elements
;; of the standard paragraph formatting routines in a more convenient
;; to use functionality than the standard fill-paragraph command of
;; emacs - this is NOT a functional replacement - it behaves
;; differently.
;;
;; The primary improvement is in the area of formatting text with
;; hanging indents. You MUST put the cursor on the first character of
;; the paragraph. If there is text to the left of the cursor, it is
;; assumed to be the paragraph label. It searches down from the first
;; character for a line that does not look like it belongs to the
;; paragraph. The criteria are:
;;
;; 1) The end of the buffer is hit.
;; 2) The line is not long enough.
;; 3) The line has white space in the cursor column.
;; 4) The prefix is not identical to the prefix of the second line
;; (for lines beyond the second line).
;;
;; The area defined by this match criteria is formatted. The first
;; line remains prefixed by the first line prefix, any additional
;; lines are prefixed by the second line prefix.
;;
;; With a prefix arg it will right justify the text.
(defun paraform (prf)
"Format a paragraph starting at point the cursor is on. Anything to
the left of the cursor is interpreted as a prefix for line 1 of the
paragraph. The paragraph ends at the first line following the cursor
line which contains white space in the cursor column, or does not
match the previous lines. Any prefix on the second line of the
paragraph is used as a fill prefix for all remaining lines. A prefix
argument right justifies the paragraph. The variable fill-column
determines where the right margin is."
(interactive "P")
(let
(
(start-pos (point))
(start-col (current-column))
(orig-fill-column fill-column)
(orig-fill-prefix fill-prefix)
(first-line-prefix
(buffer-substring
(save-excursion (beginning-of-line 1) (point))
(point)
)
)
(second-line-prefix nil)
(delete-final-newline nil)
start-marker
end-marker
)
; Make sure this file has a final newline (otherwise while
; loop below might infinite loop).
(if (/= (char-after (1- (point-max))) ?\n)
(save-excursion
(goto-char (point-max))
(insert "\n")
(setq delete-final-newline t)
)
)
; Insert a blank line above this so it looks like start
; of paragraph. Record the newline position in start-marker.
(save-excursion
(beginning-of-line 1)
(insert "\n")
(backward-char 1)
(setq start-marker (point-marker))
)
; Delete the first line prefix
(delete-region (save-excursion (beginning-of-line 1) (point)) (point))
; This loop moves to first line after paragraph
(while
(and (equal (forward-line 1) 0)
(equal (move-to-column start-col) start-col)
(looking-at "[^ \t\n]")
(or (not second-line-prefix)
(equal second-line-prefix
(buffer-substring
(save-excursion (beginning-of-line 1) (point))
(point)
)
)
)
)
; remember second line prefix
(if second-line-prefix
nil
(setq second-line-prefix
(buffer-substring
(save-excursion
(beginning-of-line 1)
(point)
)
(point)
)
)
)
; delete prefix of each line in paragraph
(delete-region
(save-excursion (beginning-of-line 1) (point))
(point)
)
)
; get a marker to blank line at end of paragraph
(beginning-of-line 1)
(insert "\n")
(backward-char 1)
(setq end-marker (point-marker))
; go fill the paragraph
(goto-char (marker-position start-marker))
(forward-line 1)
(setq fill-column (- fill-column start-col))
(setq fill-prefix nil)
(fill-paragraph prf)
(setq fill-column orig-fill-column)
(setq fill-prefix orig-fill-prefix)
; if only 1 line, use same prefix for all.
(if second-line-prefix
nil
(setq second-line-prefix first-line-prefix)
)
; Insert first line prefix at first line and
; second line prefix in all other lines.
(goto-char (marker-position start-marker))
(set-marker start-marker nil)
(delete-char 1)
(insert first-line-prefix)
(while
(and (equal (forward-line 1) 0)
(< (point) (marker-position end-marker))
)
(insert second-line-prefix)
)
(set-marker end-marker nil)
(delete-char 1)
; Leave buffer terminated the way we found it.
(if delete-final-newline
(save-excursion
(goto-char (point-max))
(backward-delete-char 1 nil)
)
)
; go back to the beginning of the paragraph
(goto-char start-pos)
)
)
-------------------cut here, end of paraform.el------------------------------
--
=====================================================================
usenet: tahorsley@ssd.harris.com USMail: Tom Horsley
compuserve: 76505,364 511 Kingbird Circle
genie: T.HORSLEY Delray Beach, FL 33444
======================== Aging: Just say no! ========================