home *** CD-ROM | disk | FTP | other *** search
- ;;;; -*-Emacs-Lisp-*- Enhancements to Kyle Jones' Adaptive Fill Package
- ;;;; Written by Eric Eide, last modified on March 8, 1993.
- ;;;; (C) Copyright 1992, 1993, Eric Eide and the University of Utah
- ;;;;
- ;;;; COPYRIGHT NOTICE
- ;;;;
- ;;;; This program is free software; you can redistribute it and/or modify it
- ;;;; under the terms of the GNU General Public License as published by the Free
- ;;;; Software Foundation; either version 1, or (at your option) any later
- ;;;; version.
- ;;;;
- ;;;; This program is distributed in the hope that it will be useful, but
- ;;;; WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
- ;;;; or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- ;;;; for more details.
- ;;;;
- ;;;; You should have received a copy of the GNU General Public License along
- ;;;; with this program; if not, write to the Free Software Foundation, Inc.,
- ;;;; 675 Mass Ave, Cambridge, MA 02139, USA.
-
- ;;;; AUTHORS
- ;;;;
- ;;;; This set of functions was written by Eric Eide (eeide@cs.utah.edu) but is
- ;;;; very heavily based on Kyle Jones' "filladapt" package and the standard GNU
- ;;;; Emacs code.
- ;;;;
- ;;;; Addresses:
- ;;;;
- ;;;; Eric Eide (eeide@cs.utah.edu)
- ;;;; University of Utah
- ;;;; 3190 Merrill Engineering Building
- ;;;; Salt Lake City, Utah 84112
- ;;;;
- ;;;; Kyle Jones (kyle@crystal.wonderworks.com)
- ;;;;
- ;;;; Kyle Jones' "filladapt" package is Copyright (C) 1989 by Kyle E. Jones.
- ;;;; It is distributed under the terms of the GNU General Public License.
-
- ;;;; LISP CODE DIRECTORY INFORMATION
- ;;;;
- ;;;; LCD Archive Entry:
- ;;;; fa-extras|Eric Eide|eeide@cs.utah.edu|
- ;;;; Enhancements to Kyle Jones' "filladapt"; hanging lists in Lisp comments|
- ;;;; 08-Mar-1993||~/packages/fa-extras.el.Z|
-
- ;;;; SUMMARY
- ;;;;
- ;;;; This file enhances Kyle Jones' "filladapt" package to properly indent
- ;;;; hanging paragraphs in more circumstances. The whitespace that insets a
- ;;;; hanging paragraph may now contain both spaces and TABs. Hanging
- ;;;; paragraphs within Lisp comments are also handled correctly. Examples:
- ;;;;
- ;;;; ;; + This text is ;; 1. This text is ;; (a) This text is
- ;;;; ;; filled. ;; filled. ;; filled.
- ;;;;
- ;;;; This file redefines the function filladapt-hanging-list from Kyle Jones'
- ;;;; "filladapt" package. This file also redefines the standard GNU Emacs
- ;;;; functions indent-new-comment-line (from "simple.el"), fill-region-as-
- ;;;; paragraph (from "fill.el"), and lisp-mode-variables (from "lisp-mode.el").
- ;;;; All required slight modifications to better handle comments.
- ;;;;
- ;;;; To use this file, simply load it after Kyle Jones' "filladapt" package has
- ;;;; been loaded.
-
-
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
- ;;;;
- ;;;; Here are the global variable declarations.
- ;;;;
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-
- ;; This new filladapt table contains three new entries: the ones that refer to
- ;; the function filladapt-hanging-list-in-lisp-comment. Also, the regular
- ;; expressions associated with filladapt-supercite-included-text and filladapt-
- ;; hanging-list are slightly modified.
-
- (setq filladapt-prefix-table
- '(
- ;; Included text in news or mail replies
- ("[ \t]*\\(>+ *\\)+" . filladapt-normal-included-text)
- ;; Included text generated by SUPERCITE. We can't hope to match all
- ;; the possible variations, your mileage may vary.
- ("[ \t]*[^'`\"< \t]*> *" . filladapt-supercite-included-text)
- ;; These are the new entries for handling hanging lists within Lisp
- ;; comments.
- ("\\([ \t]*\\(;[ \t]*\\)*;\\)[ \t]*(?\\([0-9]+[a-z]?\\|[a-z]\\))[ \t]+" .
- filladapt-hanging-list-in-lisp-comment)
- ("\\([ \t]*\\(;[ \t]*\\)*;\\)[ \t]*\\([0-9]+[a-z]?\\|[a-z]\\)\\.[ \t]+" .
- filladapt-hanging-list-in-lisp-comment)
- ("\\([ \t]*\\(;[ \t]*\\)*;\\)[?!~*+--- \t]+[ \t]" . ;; See NOTE below.
- filladapt-hanging-list-in-lisp-comment)
- ;; Lisp comments
- ("[ \t]*\\(;+[ \t]*\\)+" . filladapt-lisp-comment)
- ;; UNIX shell comments
- ("[ \t]*\\(#+[ \t]*\\)+" . filladapt-sh-comment)
- ;; Postscript comments
- ("[ \t]*\\(%+[ \t]*\\)+" . filladapt-postscript-comment)
- ;; C++ comments
- ("[ \t]*//[/ \t]*" . filladapt-c++-comment)
- ;; Lists with hanging indents, e.g.
- ;; 1. xxxxx or * xxxxx etc.
- ;; xxxxx xxx
- ("[ \t]*(?\\([0-9]+[a-z]?\\|[a-z]\\))[ \t]+" . filladapt-hanging-list)
- ("[ \t]*\\([0-9]+[a-z]?\\|[a-z]\\)\\.[ \t]+" . filladapt-hanging-list)
- ("[?!~*+--- \t]*[ \t]" . filladapt-hanging-list)
- ;; This keeps normal paragraphs from interacting unpleasantly with
- ;; the types given above.
- ("[^ \t/#%?!~*+---]" . filladapt-normal)
- ))
-
- ;; NOTE that the indicated regular expression for hanging lists in Lisp
- ;; comments sometimes does the "wrong thing" in unusual circumstances. For
- ;; example, it will cause the following two lines to be filled "incorrectly":
- ;;
- ;; ;; This is line one.
- ;; ;; This is line two.
- ;;
- ;; The regular expression matches ";; " and filladapt-hanging-list-in-lisp-
- ;; comment believes that it is the prefix. The filler then fills the comments
- ;; as:
- ;;
- ;; ;; This is line one. ;; This is line two.
- ;;
- ;; (NOTE the embedded semicolons.) However, the following lines will be filled
- ;; "correctly" because there is only one space between the semicolons:
- ;;
- ;; ;; This is line one.
- ;; ;; This is line two.
- ;;
- ;; These lines will be filled by filladapt-lisp-comment as:
- ;;
- ;; ;; This is line one. This is line two.
- ;;
- ;; So be careful how you nest your semicolons.
-
-
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
- ;;;;
- ;;;; Here are the functions that allow one to fill hanging paragraphs.
- ;;;;
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-
- (defun filladapt-looking-at (regexp width)
- ;; This function returns t if point is at the beginning of the given regular
- ;; expression and the width (not length!) of the matching text is equal to
- ;; the specified width.
- (if (looking-at regexp)
- (let ((looking-at-width (- (save-excursion
- (goto-char (match-end 0))
- (current-column))
- (if (bolp)
- 0
- (current-column)))))
- (= looking-at-width width))
- nil))
-
- (defun filladapt-make-whitespace (start-column width)
- ;; Make a string of whitespace containing TABs and spaces.
- (if indent-tabs-mode
- (let* ((end-column (+ start-column width))
- (tabs-before-start (/ start-column tab-width))
- (tabs-before-end (/ end-column tab-width))
- (tabs (- tabs-before-end tabs-before-start))
- (spaces (if (> tabs 0)
- (% end-column tab-width)
- width))
- (whitespace (make-string (+ tabs spaces) ?\ )))
- ;; Special case: don't use only one TAB to go one space.
- (if (and (= tabs 1) (= (+ tabs spaces) width))
- (setq tabs 0
- spaces (1+ spaces)))
- ;; Fill in the whitespace string with the required TABs.
- (let ((index 0))
- (while (> tabs 0)
- (aset whitespace index ?\t)
- (setq index (1+ index)
- tabs (1- tabs))))
- whitespace)
- ;; indent-tabs-mode is nil; only use spaces.
- (make-string width ?\ )))
-
- ;;; The function below is a replacement for the function filladapt-hanging-list
- ;;; from Kyle Jones' "filladapt" package. This new filladapt-hanging-list
- ;;; understands whitespace that contains both spaces and TABs.
-
- (defun filladapt-hanging-list (paragraph)
- (let (prefix match match-width beg end)
- (setq match-width (save-excursion (goto-char (match-end 0))
- (current-column)))
- (setq prefix (filladapt-make-whitespace 0 match-width))
- (if paragraph
- (progn
- (setq match (buffer-substring (match-beginning 0) (match-end 0)))
- (if (string-match "^[ \t]+$" match)
- (save-excursion
- (while (and (not (bobp))
- (filladapt-looking-at "[ \t]*" match-width))
- (forward-line -1))
- (if (or (filladapt-looking-at
- "[ \t]*(?\\([0-9]+[a-z]?\\|[a-z]\\))[ \t]+"
- match-width)
- (filladapt-looking-at
- "[ \t]*\\([0-9]+[a-z]?\\|[a-z]\\)\\.[ \t]+"
- match-width)
- (filladapt-looking-at
- "[ \t]*[?!~*+---]+[ \t]+"
- match-width))
- (setq beg (point))
- (setq beg (progn (forward-line 1) (point)))))
- (setq beg (point)))
- (save-excursion
- (goto-char beg)
- (forward-line)
- (while (filladapt-looking-at "[ \t]*" match-width)
- (replace-match prefix nil t)
- (forward-line))
- (setq end (point)))
- (narrow-to-region beg end)))
- (setq fill-prefix prefix)))
-
- ;;; filladapt-hanging-list-in-lisp-comment started as a merger of the functions
- ;;; filladapt-lisp-comment and filladapt-hanging-list (both from Kyle Jones'
- ;;; "filladapt" package). But it became much more complicated when I taught it
- ;;; to understand whitespace containing both spaces and TABs.
-
- (defun filladapt-hanging-list-in-lisp-comment (paragraph)
- (let (prefix match
- match-width ;; The width of the entire match.
- leading-whitespace-width ;; ...of the whitespace before the semicolons
- to-last-semicolon-width ;; ...of the text between bol and the last ;.
- comment-semicolons ;; The text from the first ; to the last ;.
- matching-prefix-regexp ;; Regexp for finding prefixes "like" prefix.
- beg end)
- (save-excursion
- (setq match-width (progn (goto-char (match-end 0))
- (current-column))
- leading-whitespace-width (progn (goto-char (match-beginning 2))
- (current-column))
- to-last-semicolon-width (progn (goto-char (match-end 1))
- (current-column))
- comment-semicolons (buffer-substring (match-beginning 2)
- (match-end 1))))
- (setq prefix
- (concat
- (filladapt-make-whitespace 0 leading-whitespace-width)
- comment-semicolons
- (filladapt-make-whitespace to-last-semicolon-width
- (- match-width to-last-semicolon-width))
- ))
- (if paragraph
- (progn
- (setq paragraph-separate (concat "^" prefix "[ \t]*;\\|^"
- (filladapt-negate-string prefix))
- match (buffer-substring (match-beginning 0) (match-end 0))
- matching-prefix-regexp (concat "[ \t]*"
- (regexp-quote
- comment-semicolons)
- "[ \t]*"))
- (if (string-match "^[ \t]*\\(;[ \t]*\\)*;[ \t]+$" match)
- (save-excursion
- (while (and (not (bobp))
- ;; I need two regular expressions here because I
- ;; want the leading whitespace to be of a certain
- ;; width. I can't check that without two calls to
- ;; filladapt-looking-prefix -- unless I change that
- ;; function to accept more arguments.
- (filladapt-looking-at "[ \t]*"
- leading-whitespace-width)
- (filladapt-looking-at matching-prefix-regexp
- match-width))
- (forward-line -1))
- (if (or
- (filladapt-looking-at
- "\\([ \t]*\\(;[ \t]*\\)*;\\)[ \t]*(?\\([0-9]+[a-z]?\\|[a-z]\\)[ \t]+"
- match-width)
- (filladapt-looking-at
- "\\([ \t]*\\(;[ \t]*\\)*;\\)[ \t]*\\([0-9]+[a-z]?\\|[a-z]\\)\\.[ \t]+"
- match-width)
- (filladapt-looking-at
- "\\([ \t]*\\(;[ \t]*\\)*;\\)[ \t]*[?!~*+---]+[ \t]+"
- match-width))
- (setq beg (point))
- (setq beg (progn (forward-line 1) (point)))))
- (setq beg (point)))
- (save-excursion
- (goto-char beg)
- (forward-line)
- (while (and (filladapt-looking-at "[ \t]*"
- leading-whitespace-width)
- (filladapt-looking-at matching-prefix-regexp
- match-width))
- (replace-match prefix nil t)
- (forward-line))
- (setq end (point)))
- (narrow-to-region beg end)))
- (setq fill-prefix prefix)))
-
-
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
- ;;;;
- ;;;; Here are the new versions of the standard GNU Emacs functions indent-new-
- ;;;; comment-line, fill-region-as-paragraph, and lisp-mode-variables.
- ;;;;
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-
- ;;; This version of indent-new-comment-line (originally from "simple.el" in GNU
- ;;; Emacs 18.58) has been modified to work better when a fill prefix has been
- ;;; specified for filling a comment. The changed line is marked with my
- ;;; initials (ENE).
-
- (defun indent-new-comment-line ()
- "Break line at point and indent, continuing comment if presently within one.
- The body of the continued comment is indented under the previous comment line."
- (interactive "*")
- (let (comcol comstart)
- (skip-chars-backward " \t")
- (delete-region (point)
- (progn (skip-chars-forward " \t")
- (point)))
- (insert ?\n)
- (save-excursion
- (if (and comment-start-skip
- (let ((opoint (point)))
- (forward-line -1)
- (re-search-forward comment-start-skip opoint t)))
- ;; The old line is a comment.
- ;; Set WIN to the pos of the comment-start.
- ;; But if the comment is empty, look at preceding lines
- ;; to find one that has a nonempty comment.
- (let ((win (match-beginning 0)))
- (while (and (eolp) (not (bobp))
- (let (opoint)
- (beginning-of-line)
- (setq opoint (point))
- (forward-line -1)
- (re-search-forward comment-start-skip opoint t)))
- (setq win (match-beginning 0)))
- ;; Indent this line like what we found.
- (goto-char win)
- (setq comcol (current-column))
- (setq comstart (buffer-substring (point) (match-end 0))))))
- (if (and comcol (not fill-prefix)) ;; ENE: Changed this test.
- (let ((comment-column comcol)
- (comment-start comstart)
- (comment-end comment-end))
- (and comment-end (not (equal comment-end ""))
- (if (not comment-multi-line)
- (progn
- (forward-char -1)
- (insert comment-end)
- (forward-char 1))
- (setq comment-column (+ comment-column (length comment-start))
- comment-start "")))
- (if (not (eolp))
- (setq comment-end ""))
- (insert ?\n)
- (forward-char -1)
- (indent-for-comment)
- (delete-char 1))
- (if fill-prefix
- (insert fill-prefix)
- (indent-according-to-mode)))))
-
- ;;; This version of fill-region-as-paragraph (originally from "fill.el" in GNU
- ;;; Emacs 18.58) has been modified to skip past the comment start (if present)
- ;;; on the first line of the paragraph to be filled. The added form is marked
- ;;; with my initials (ENE).
-
- (defun fill-region-as-paragraph (from to &optional justify-flag)
- "Fill region as one paragraph: break lines to fit fill-column.
- Prefix arg means justify too.
- >From program, pass args FROM, TO and JUSTIFY-FLAG."
- (interactive "r\nP")
- (save-restriction
- (narrow-to-region from to)
- (goto-char (point-min))
- (skip-chars-forward "\n")
- (narrow-to-region (point) (point-max))
- (setq from (point))
- (let ((fpre (and fill-prefix (not (equal fill-prefix ""))
- (regexp-quote fill-prefix))))
- ;; Delete the fill prefix from every line except the first.
- ;; The first line may not even have a fill prefix.
- (and fpre
- (progn
- (if (>= (length fill-prefix) fill-column)
- (error "fill-prefix too long for specified width"))
- (goto-char (point-min))
- (forward-line 1)
- (while (not (eobp))
- (if (looking-at fpre)
- (delete-region (point) (match-end 0)))
- (forward-line 1))
- (goto-char (point-min))
- (and (looking-at fpre) (forward-char (length fill-prefix)))
- (setq from (point)))))
- ;; from is now before the text to fill,
- ;; but after any fill prefix on the first line.
-
- ;; Make sure sentences ending at end of line get an extra space.
- (goto-char from)
- (while (re-search-forward "[.?!][])""']*$" nil t)
- (insert ? ))
- ;; Then change all newlines to spaces.
- (subst-char-in-region from (point-max) ?\n ?\ )
- ;; Flush excess spaces, except in the paragraph indentation.
- (goto-char from)
- (skip-chars-forward " \t")
- ;; ENE: Added the following "if" form to move past the comment start.
- (if (and comment-start-skip
- (looking-at comment-start-skip))
- (goto-char (match-end 0)))
- (while (re-search-forward " *" nil t)
- (delete-region
- (+ (match-beginning 0)
- (if (save-excursion
- (skip-chars-backward " ])\"'")
- (memq (preceding-char) '(?. ?? ?!)))
- 2 1))
- (match-end 0)))
- (goto-char (point-max))
- (delete-horizontal-space)
- (insert " ")
- (goto-char (point-min))
- (let ((prefixcol 0))
- (while (not (eobp))
- (move-to-column (1+ fill-column))
- (if (eobp)
- nil
- ;; Move back to start of word.
- (skip-chars-backward "^ \n")
- (if (if (zerop prefixcol) (bolp) (>= prefixcol (current-column)))
- ;; Move back over whitespace before the word.
- (skip-chars-forward "^ \n")
- ;; Normally, move back over the single space between the words.
- (forward-char -1)))
- ;; Replace all whitespace here with one newline.
- ;; Insert before deleting, so we don't forget which side of
- ;; the whitespace point or markers used to be on.
- (skip-chars-backward " ")
- (insert ?\n)
- (delete-horizontal-space)
- ;; Insert the fill prefix at start of each line.
- ;; Set prefixcol so whitespace in the prefix won't get lost.
- (and (not (eobp)) fill-prefix (not (equal fill-prefix ""))
- (progn
- (insert fill-prefix)
- (setq prefixcol (current-column))))
- ;; Justify the line just ended, if desired.
- (and justify-flag (not (eobp))
- (progn
- (forward-line -1)
- (justify-current-line)
- (forward-line 1)))))))
-
- ;;; This version of lisp-mode-variables (originally from "lisp-mode.el" in GNU
- ;;; Emacs 18.58) has been modified to set comment-start-skip to ";+[ \t]*".
- ;;; (Should it be ";[; \t]*"? Simply ";+[ \t]*" seems to be good enough.) The
- ;;; changed line is marked with my initials (ENE).
-
- (defun lisp-mode-variables (lisp-syntax)
- (cond (lisp-syntax
- (if (not lisp-mode-syntax-table)
- (progn (setq lisp-mode-syntax-table
- (copy-syntax-table emacs-lisp-mode-syntax-table))
- (modify-syntax-entry ?\| "\" "
- lisp-mode-syntax-table)
- (modify-syntax-entry ?\[ "_ "
- lisp-mode-syntax-table)
- (modify-syntax-entry ?\] "_ "
- lisp-mode-syntax-table)))
- (set-syntax-table lisp-mode-syntax-table)))
- (setq local-abbrev-table lisp-mode-abbrev-table)
- (make-local-variable 'paragraph-start)
- (setq paragraph-start (concat "^$\\|" page-delimiter))
- (make-local-variable 'paragraph-separate)
- (setq paragraph-separate paragraph-start)
- (make-local-variable 'paragraph-ignore-fill-prefix)
- (setq paragraph-ignore-fill-prefix t)
- (make-local-variable 'indent-line-function)
- (setq indent-line-function 'lisp-indent-line)
- (make-local-variable 'comment-start)
- (setq comment-start ";")
- (make-local-variable 'comment-start-skip)
- (setq comment-start-skip ";+[ \t]*") ;; ENE: Used to be ";+ *".
- (make-local-variable 'comment-column)
- (setq comment-column 40)
- (make-local-variable 'comment-indent-hook)
- (setq comment-indent-hook 'lisp-comment-indent))
-
- ;; End of file.
-