Messing around with emacs again
This commit is contained in:
parent
444e503cad
commit
d529315a4d
138 changed files with 1301 additions and 3060 deletions
981
site-lisp/filladapt.el
Normal file
981
site-lisp/filladapt.el
Normal file
|
|
@ -0,0 +1,981 @@
|
|||
;;; Adaptive fill
|
||||
;;; Copyright (C) 1989, 1995-1998 Kyle E. Jones
|
||||
;;;
|
||||
;;; 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 2, 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.
|
||||
;;;
|
||||
;;; A copy of the GNU General Public License can be obtained from this
|
||||
;;; program's author (send electronic mail to kyle@uunet.uu.net) or from
|
||||
;;; the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA
|
||||
;;; 02139, USA.
|
||||
;;;
|
||||
;;; Send bug reports to kyle_jones@wonderworks.com
|
||||
|
||||
;; LCD Archive Entry:
|
||||
;; filladapt|Kyle Jones|kyle_jones@wonderworks.com|
|
||||
;; Minor mode to adaptively set fill-prefix and overload filling functions|
|
||||
;; 28-February-1998|2.12|~/packages/filladapt.el|
|
||||
|
||||
;; These functions enhance the default behavior of Emacs' Auto Fill
|
||||
;; mode and the commands fill-paragraph, lisp-fill-paragraph,
|
||||
;; fill-region-as-paragraph and fill-region.
|
||||
;;
|
||||
;; The chief improvement is that the beginning of a line to be
|
||||
;; filled is examined and, based on information gathered, an
|
||||
;; appropriate value for fill-prefix is constructed. Also the
|
||||
;; boundaries of the current paragraph are located. This occurs
|
||||
;; only if the fill prefix is not already non-nil.
|
||||
;;
|
||||
;; The net result of this is that blurbs of text that are offset
|
||||
;; from left margin by asterisks, dashes, and/or spaces, numbered
|
||||
;; examples, included text from USENET news articles, etc. are
|
||||
;; generally filled correctly with no fuss.
|
||||
;;
|
||||
;; Since this package replaces existing Emacs functions, it cannot
|
||||
;; be autoloaded. Save this in a file named filladapt.el in a
|
||||
;; Lisp directory that Emacs knows about, byte-compile it and put
|
||||
;; (require 'filladapt)
|
||||
;; in your .emacs file.
|
||||
;;
|
||||
;; Note that in this release Filladapt mode is a minor mode and it is
|
||||
;; _off_ by default. If you want it to be on by default, use
|
||||
;; (setq-default filladapt-mode t)
|
||||
;;
|
||||
;; M-x filladapt-mode toggles Filladapt mode on/off in the current
|
||||
;; buffer.
|
||||
;;
|
||||
;; Use
|
||||
;; (add-hook 'text-mode-hook 'turn-on-filladapt-mode)
|
||||
;; to have Filladapt always enabled in Text mode.
|
||||
;;
|
||||
;; Use
|
||||
;; (add-hook 'c-mode-hook 'turn-off-filladapt-mode)
|
||||
;; to have Filladapt always disabled in C mode.
|
||||
;;
|
||||
;; In many cases, you can extend Filladapt by adding appropriate
|
||||
;; entries to the following three `defvar's. See `postscript-comment'
|
||||
;; or `texinfo-comment' as a sample of what needs to be done.
|
||||
;;
|
||||
;; filladapt-token-table
|
||||
;; filladapt-token-match-table
|
||||
;; filladapt-token-conversion-table
|
||||
|
||||
(and (featurep 'filladapt)
|
||||
(error "filladapt cannot be loaded twice in the same Emacs session."))
|
||||
|
||||
(provide 'filladapt)
|
||||
|
||||
(defvar filladapt-version "2.12"
|
||||
"Version string for filladapt.")
|
||||
|
||||
;; BLOB to make custom stuff work even without customize
|
||||
(eval-and-compile
|
||||
(condition-case ()
|
||||
(require 'custom)
|
||||
(error nil))
|
||||
(if (and (featurep 'custom) (fboundp 'custom-declare-variable))
|
||||
nil ;; We've got what we needed
|
||||
;; We have the old custom-library, hack around it!
|
||||
(defmacro defgroup (&rest args)
|
||||
nil)
|
||||
(defmacro defcustom (var value doc &rest args)
|
||||
(` (defvar (, var) (, value) (, doc))))))
|
||||
|
||||
(defgroup filladapt nil
|
||||
"Enhanced filling"
|
||||
:group 'fill)
|
||||
|
||||
(defvar filladapt-mode nil
|
||||
"Non-nil means that Filladapt minor mode is enabled.
|
||||
Use the filladapt-mode command to toggle the mode on/off.")
|
||||
(make-variable-buffer-local 'filladapt-mode)
|
||||
|
||||
(defcustom filladapt-mode-line-string " Filladapt"
|
||||
"*String to display in the modeline when Filladapt mode is active.
|
||||
Set this to nil if you don't want a modeline indicator for Filladapt."
|
||||
:type 'string
|
||||
:group 'filladapt)
|
||||
|
||||
(defcustom filladapt-fill-column-tolerance nil
|
||||
"*Tolerate filled paragraph lines ending this far from the fill column.
|
||||
If any lines other than the last paragraph line end at a column
|
||||
less than fill-column - filladapt-fill-column-tolerance, fill-column will
|
||||
be adjusted using the filladapt-fill-column-*-fuzz variables and
|
||||
the paragraph will be re-filled until the tolerance is achieved
|
||||
or filladapt runs out of fuzz values to try.
|
||||
|
||||
A nil value means behave normally, that is, don't try refilling
|
||||
paragraphs to make filled line lengths fit within any particular
|
||||
range."
|
||||
:type '(choice (const nil)
|
||||
integer)
|
||||
:group 'filladapt)
|
||||
|
||||
(defcustom filladapt-fill-column-forward-fuzz 5
|
||||
"*Try values from fill-column to fill-column plus this variable
|
||||
when trying to make filled paragraph lines fall with the tolerance
|
||||
range specified by filladapt-fill-column-tolerance."
|
||||
:type 'integer
|
||||
:group 'filladapt)
|
||||
|
||||
(defcustom filladapt-fill-column-backward-fuzz 5
|
||||
"*Try values from fill-column to fill-column minus this variable
|
||||
when trying to make filled paragraph lines fall with the tolerance
|
||||
range specified by filladapt-fill-column-tolerance."
|
||||
:type 'integer
|
||||
:group 'filladapt)
|
||||
|
||||
;; install on minor-mode-alist
|
||||
(or (assq 'filladapt-mode minor-mode-alist)
|
||||
(setq minor-mode-alist (cons (list 'filladapt-mode
|
||||
'filladapt-mode-line-string)
|
||||
minor-mode-alist)))
|
||||
|
||||
(defcustom filladapt-token-table
|
||||
'(
|
||||
;; this must be first
|
||||
("^" beginning-of-line)
|
||||
;; Included text in news or mail replies
|
||||
(">+" citation->)
|
||||
;; Included text generated by SUPERCITE. We can't hope to match all
|
||||
;; the possible variations, your mileage may vary.
|
||||
("\\(\\w\\|[0-9]\\)[^'`\"< \t\n]*>[ \t]*" supercite-citation)
|
||||
;; Lisp comments
|
||||
(";+" lisp-comment)
|
||||
;; UNIX shell comments
|
||||
("#+" sh-comment)
|
||||
;; Postscript comments
|
||||
("%+" postscript-comment)
|
||||
;; C++ comments
|
||||
("///*" c++-comment)
|
||||
;; Texinfo comments
|
||||
("@c[ \t]" texinfo-comment)
|
||||
("@comment[ \t]" texinfo-comment)
|
||||
;; Bullet types.
|
||||
;;
|
||||
;; LaTex \item
|
||||
;;
|
||||
("\\\\item[ \t]" bullet)
|
||||
;;
|
||||
;; 1. xxxxx
|
||||
;; xxxxx
|
||||
;;
|
||||
("[0-9]+\\.[ \t]" bullet)
|
||||
;;
|
||||
;; 2.1.3 xxxxx xx x xx x
|
||||
;; xxx
|
||||
;;
|
||||
("[0-9]+\\(\\.[0-9]+\\)+[ \t]" bullet)
|
||||
;;
|
||||
;; a. xxxxxx xx
|
||||
;; xxx xxx
|
||||
;;
|
||||
("[A-Za-z]\\.[ \t]" bullet)
|
||||
;;
|
||||
;; 1) xxxx x xx x xx or (1) xx xx x x xx xx
|
||||
;; xx xx xxxx xxx xx x x xx x
|
||||
;;
|
||||
("(?[0-9]+)[ \t]" bullet)
|
||||
;;
|
||||
;; a) xxxx x xx x xx or (a) xx xx x x xx xx
|
||||
;; xx xx xxxx xxx xx x x xx x
|
||||
;;
|
||||
("(?[A-Za-z])[ \t]" bullet)
|
||||
;;
|
||||
;; 2a. xx x xxx x x xxx
|
||||
;; xxx xx x xx x
|
||||
;;
|
||||
("[0-9]+[A-Za-z]\\.[ \t]" bullet)
|
||||
;;
|
||||
;; 1a) xxxx x xx x xx or (1a) xx xx x x xx xx
|
||||
;; xx xx xxxx xxx xx x x xx x
|
||||
;;
|
||||
("(?[0-9]+[A-Za-z])[ \t]" bullet)
|
||||
;;
|
||||
;; - xx xxx xxxx or * xx xx x xxx xxx
|
||||
;; xxx xx xx x xxx x xx x x x
|
||||
;;
|
||||
("[-~*+]+[ \t]" bullet)
|
||||
;;
|
||||
;; o xx xxx xxxx xx x xx xxx x xxx xx x xxx
|
||||
;; xxx xx xx
|
||||
;;
|
||||
("o[ \t]" bullet)
|
||||
;; don't touch
|
||||
("[ \t]+" space)
|
||||
("$" end-of-line)
|
||||
)
|
||||
"Table of tokens filladapt knows about.
|
||||
Format is
|
||||
|
||||
((REGEXP SYM) ...)
|
||||
|
||||
filladapt uses this table to build a tokenized representation of
|
||||
the beginning of the current line. Each REGEXP is matched
|
||||
against the beginning of the line until a match is found.
|
||||
Matching is done case-sensitively. The corresponding SYM is
|
||||
added to the list, point is moved to (match-end 0) and the
|
||||
process is repeated. The process ends when there is no REGEXP in
|
||||
the table that matches what is at point."
|
||||
:type '(repeat (list regexp symbol))
|
||||
:group 'filladapt)
|
||||
|
||||
(defcustom filladapt-not-token-table
|
||||
'(
|
||||
"[Ee]\\.g\\.[ \t,]"
|
||||
"[Ii]\\.e\\.[ \t,]"
|
||||
;; end-of-line isn't a token if whole line is empty
|
||||
"^$"
|
||||
)
|
||||
"List of regexps that can never be a token.
|
||||
Before trying the regular expressions in filladapt-token-table,
|
||||
the regexps in this list are tried. If any regexp in this list
|
||||
matches what is at point then the token generator gives up and
|
||||
doesn't try any of the regexps in filladapt-token-table.
|
||||
|
||||
Regexp matching is done case-sensitively."
|
||||
:type '(repeat regexp)
|
||||
:group 'filladapt)
|
||||
|
||||
(defcustom filladapt-token-match-table
|
||||
'(
|
||||
(citation-> citation->)
|
||||
(supercite-citation supercite-citation)
|
||||
(lisp-comment lisp-comment)
|
||||
(sh-comment sh-comment)
|
||||
(postscript-comment postscript-comment)
|
||||
(c++-comment c++-comment)
|
||||
(texinfo-comment texinfo-comment)
|
||||
(bullet)
|
||||
(space bullet space)
|
||||
(beginning-of-line beginning-of-line)
|
||||
)
|
||||
"Table describing what tokens a certain token will match.
|
||||
|
||||
To decide whether a line belongs in the current paragraph,
|
||||
filladapt creates a token list for the fill prefix of both lines.
|
||||
Tokens and the columns where tokens end are compared. This table
|
||||
specifies what a certain token will match.
|
||||
|
||||
Table format is
|
||||
|
||||
(SYM [SYM1 [SYM2 ...]])
|
||||
|
||||
The first symbol SYM is the token, subsequent symbols are the
|
||||
tokens that SYM will match."
|
||||
:type '(repeat (repeat symbol))
|
||||
:group 'filladapt)
|
||||
|
||||
(defcustom filladapt-token-match-many-table
|
||||
'(
|
||||
space
|
||||
)
|
||||
"List of tokens that can match multiple tokens.
|
||||
If one of these tokens appears in a token list, it will eat all
|
||||
matching tokens in a token list being matched against it until it
|
||||
encounters a token that doesn't match or a token that ends on
|
||||
a greater column number."
|
||||
:type '(repeat symbol)
|
||||
:group 'filladapt)
|
||||
|
||||
(defcustom filladapt-token-paragraph-start-table
|
||||
'(
|
||||
bullet
|
||||
)
|
||||
"List of tokens that indicate the start of a paragraph.
|
||||
If parsing a line generates a token list containing one of
|
||||
these tokens, then the line is considered to be the start of a
|
||||
paragraph."
|
||||
:type '(repeat symbol)
|
||||
:group 'filladapt)
|
||||
|
||||
(defcustom filladapt-token-conversion-table
|
||||
'(
|
||||
(citation-> . exact)
|
||||
(supercite-citation . exact)
|
||||
(lisp-comment . exact)
|
||||
(sh-comment . exact)
|
||||
(postscript-comment . exact)
|
||||
(c++-comment . exact)
|
||||
(texinfo-comment . exact)
|
||||
(bullet . spaces)
|
||||
(space . exact)
|
||||
(end-of-line . exact)
|
||||
)
|
||||
"Table that specifies how to convert a token into a fill prefix.
|
||||
Table format is
|
||||
|
||||
((SYM . HOWTO) ...)
|
||||
|
||||
SYM is the symbol naming the token to be converted.
|
||||
HOWTO specifies how to do the conversion.
|
||||
`exact' means copy the token's string directly into the fill prefix.
|
||||
`spaces' means convert all characters in the token string that are
|
||||
not a TAB or a space into spaces and copy the resulting string into
|
||||
the fill prefix."
|
||||
:type '(repeat (cons symbol (choice (const exact)
|
||||
(const spaces))))
|
||||
:group 'filladapt)
|
||||
|
||||
(defvar filladapt-function-table
|
||||
(let ((assoc-list
|
||||
(list (cons 'fill-paragraph (symbol-function 'fill-paragraph))
|
||||
(cons 'fill-region (symbol-function 'fill-region))
|
||||
(cons 'fill-region-as-paragraph
|
||||
(symbol-function 'fill-region-as-paragraph))
|
||||
(cons 'do-auto-fill (symbol-function 'do-auto-fill)))))
|
||||
;; v18 Emacs doesn't have lisp-fill-paragraph
|
||||
(if (fboundp 'lisp-fill-paragraph)
|
||||
(nconc assoc-list
|
||||
(list (cons 'lisp-fill-paragraph
|
||||
(symbol-function 'lisp-fill-paragraph)))))
|
||||
assoc-list )
|
||||
"Table containing the old function definitions that filladapt usurps.")
|
||||
|
||||
(defcustom filladapt-fill-paragraph-post-hook nil
|
||||
"Hooks run after filladapt runs fill-paragraph."
|
||||
:type 'hook
|
||||
:group 'filladapt)
|
||||
|
||||
(defvar filladapt-inside-filladapt nil
|
||||
"Non-nil if the filladapt version of a fill function executing.
|
||||
Currently this is only checked by the filladapt version of
|
||||
fill-region-as-paragraph to avoid this infinite recursion:
|
||||
|
||||
fill-region-as-paragraph -> fill-paragraph -> fill-region-as-paragraph ...")
|
||||
|
||||
(defcustom filladapt-debug nil
|
||||
"Non-nil means filladapt debugging is enabled.
|
||||
Use the filladapt-debug command to turn on debugging.
|
||||
|
||||
With debugging enabled, filladapt will
|
||||
|
||||
a. display the proposed indentation with the tokens highlighted
|
||||
using filladapt-debug-indentation-face-1 and
|
||||
filladapt-debug-indentation-face-2.
|
||||
b. display the current paragraph using the face specified by
|
||||
filladapt-debug-paragraph-face."
|
||||
:type 'boolean
|
||||
:group 'filladapt)
|
||||
|
||||
(if filladapt-debug
|
||||
(add-hook 'post-command-hook 'filladapt-display-debug-info-maybe))
|
||||
|
||||
(defvar filladapt-debug-indentation-face-1 'highlight
|
||||
"Face used to display the indentation when debugging is enabled.")
|
||||
|
||||
(defvar filladapt-debug-indentation-face-2 'secondary-selection
|
||||
"Another face used to display the indentation when debugging is enabled.")
|
||||
|
||||
(defvar filladapt-debug-paragraph-face 'bold
|
||||
"Face used to display the current paragraph when debugging is enabled.")
|
||||
|
||||
(defvar filladapt-debug-indentation-extents nil)
|
||||
(make-variable-buffer-local 'filladapt-debug-indentation-extents)
|
||||
(defvar filladapt-debug-paragraph-extent nil)
|
||||
(make-variable-buffer-local 'filladapt-debug-paragraph-extent)
|
||||
|
||||
;; kludge city, see references in code.
|
||||
(defvar filladapt-old-line-prefix)
|
||||
|
||||
(defun do-auto-fill ()
|
||||
(catch 'done
|
||||
(if (and filladapt-mode (null fill-prefix))
|
||||
(save-restriction
|
||||
(let ((paragraph-ignore-fill-prefix nil)
|
||||
;; if the user wanted this stuff, they probably
|
||||
;; wouldn't be using filladapt-mode.
|
||||
(adaptive-fill-mode nil)
|
||||
(adaptive-fill-regexp nil)
|
||||
;; need this or Emacs 19 ignores fill-prefix when
|
||||
;; inside a comment.
|
||||
(comment-multi-line t)
|
||||
(filladapt-inside-filladapt t)
|
||||
fill-prefix retval)
|
||||
(if (filladapt-adapt nil nil)
|
||||
(progn
|
||||
(setq retval (filladapt-funcall 'do-auto-fill))
|
||||
(throw 'done retval))))))
|
||||
(filladapt-funcall 'do-auto-fill)))
|
||||
|
||||
(defun filladapt-fill-paragraph (function arg)
|
||||
(catch 'done
|
||||
(if (and filladapt-mode (null fill-prefix))
|
||||
(save-restriction
|
||||
(let ((paragraph-ignore-fill-prefix nil)
|
||||
;; if the user wanted this stuff, they probably
|
||||
;; wouldn't be using filladapt-mode.
|
||||
(adaptive-fill-mode nil)
|
||||
(adaptive-fill-regexp nil)
|
||||
;; need this or Emacs 19 ignores fill-prefix when
|
||||
;; inside a comment.
|
||||
(comment-multi-line t)
|
||||
fill-prefix retval)
|
||||
(if (filladapt-adapt t nil)
|
||||
(progn
|
||||
(if filladapt-fill-column-tolerance
|
||||
(let* ((low (- fill-column
|
||||
filladapt-fill-column-backward-fuzz))
|
||||
(high (+ fill-column
|
||||
filladapt-fill-column-forward-fuzz))
|
||||
(old-fill-column fill-column)
|
||||
(fill-column fill-column)
|
||||
(lim (- high low))
|
||||
(done nil)
|
||||
(sign 1)
|
||||
(delta 0))
|
||||
(while (not done)
|
||||
(setq retval (filladapt-funcall function arg))
|
||||
(if (filladapt-paragraph-within-fill-tolerance)
|
||||
(setq done 'success)
|
||||
(setq delta (1+ delta)
|
||||
sign (* sign -1)
|
||||
fill-column (+ fill-column (* delta sign)))
|
||||
(while (and (<= delta lim)
|
||||
(or (< fill-column low)
|
||||
(> fill-column high)))
|
||||
(setq delta (1+ delta)
|
||||
sign (* sign -1)
|
||||
fill-column (+ fill-column
|
||||
(* delta sign))))
|
||||
(setq done (> delta lim))))
|
||||
;; if the paragraph lines never fell
|
||||
;; within the tolerances, refill using
|
||||
;; the old fill-column.
|
||||
(if (not (eq done 'success))
|
||||
(let ((fill-column old-fill-column))
|
||||
(setq retval (filladapt-funcall function arg)))))
|
||||
(setq retval (filladapt-funcall function arg)))
|
||||
(run-hooks 'filladapt-fill-paragraph-post-hook)
|
||||
(throw 'done retval))))))
|
||||
;; filladapt-adapt failed, so do fill-paragraph normally.
|
||||
(filladapt-funcall function arg)))
|
||||
|
||||
(defun fill-paragraph (arg)
|
||||
"Fill paragraph at or after point. Prefix arg means justify as well.
|
||||
|
||||
(This function has been overloaded with the `filladapt' version.)
|
||||
|
||||
If `sentence-end-double-space' is non-nil, then period followed by one
|
||||
space does not end a sentence, so don't break a line there.
|
||||
|
||||
If `fill-paragraph-function' is non-nil, we call it (passing our
|
||||
argument to it), and if it returns non-nil, we simply return its value."
|
||||
(interactive "*P")
|
||||
(let ((filladapt-inside-filladapt t))
|
||||
(filladapt-fill-paragraph 'fill-paragraph arg)))
|
||||
|
||||
(defun lisp-fill-paragraph (&optional arg)
|
||||
"Like \\[fill-paragraph], but handle Emacs Lisp comments.
|
||||
|
||||
(This function has been overloaded with the `filladapt' version.)
|
||||
|
||||
If any of the current line is a comment, fill the comment or the
|
||||
paragraph of it that point is in, preserving the comment's indentation
|
||||
and initial semicolons."
|
||||
(interactive "*P")
|
||||
(let ((filladapt-inside-filladapt t))
|
||||
(filladapt-fill-paragraph 'lisp-fill-paragraph arg)))
|
||||
|
||||
(defun fill-region-as-paragraph (beg end &optional justify
|
||||
nosqueeze squeeze-after)
|
||||
"Fill the region as one paragraph.
|
||||
|
||||
(This function has been overloaded with the `filladapt' version.)
|
||||
|
||||
It removes any paragraph breaks in the region and extra newlines at the end,
|
||||
indents and fills lines between the margins given by the
|
||||
`current-left-margin' and `current-fill-column' functions.
|
||||
It leaves point at the beginning of the line following the paragraph.
|
||||
|
||||
Normally performs justification according to the `current-justification'
|
||||
function, but with a prefix arg, does full justification instead.
|
||||
|
||||
From a program, optional third arg JUSTIFY can specify any type of
|
||||
justification. Fourth arg NOSQUEEZE non-nil means not to make spaces
|
||||
between words canonical before filling. Fifth arg SQUEEZE-AFTER, if non-nil,
|
||||
means don't canonicalize spaces before that position.
|
||||
|
||||
If `sentence-end-double-space' is non-nil, then period followed by one
|
||||
space does not end a sentence, so don't break a line there."
|
||||
(interactive "*r\nP")
|
||||
(if (and filladapt-mode (not filladapt-inside-filladapt))
|
||||
(save-restriction
|
||||
(narrow-to-region beg end)
|
||||
(let ((filladapt-inside-filladapt t)
|
||||
line-start last-token)
|
||||
(goto-char beg)
|
||||
(while (equal (char-after (point)) ?\n)
|
||||
(delete-char 1))
|
||||
(end-of-line)
|
||||
(while (zerop (forward-line))
|
||||
(if (setq last-token
|
||||
(car (filladapt-tail (filladapt-parse-prefixes))))
|
||||
(progn
|
||||
(setq line-start (point))
|
||||
(move-to-column (nth 1 last-token))
|
||||
(delete-region line-start (point))))
|
||||
;; Dance...
|
||||
;;
|
||||
;; Do this instead of (delete-char -1) to keep
|
||||
;; markers on the correct side of the whitespace.
|
||||
(goto-char (1- (point)))
|
||||
(insert " ")
|
||||
(delete-char 1)
|
||||
|
||||
(end-of-line))
|
||||
(goto-char beg)
|
||||
(fill-paragraph justify))
|
||||
;; In XEmacs 19.12 and Emacs 18.59 fill-region relies on
|
||||
;; fill-region-as-paragraph to do this. If we don't do
|
||||
;; it, fill-region will spin in an endless loop.
|
||||
(goto-char (point-max)))
|
||||
(condition-case nil
|
||||
;; five args for Emacs 19.31
|
||||
(filladapt-funcall 'fill-region-as-paragraph beg end
|
||||
justify nosqueeze squeeze-after)
|
||||
(wrong-number-of-arguments
|
||||
(condition-case nil
|
||||
;; four args for Emacs 19.29
|
||||
(filladapt-funcall 'fill-region-as-paragraph beg end
|
||||
justify nosqueeze)
|
||||
;; three args for the rest of the world.
|
||||
(wrong-number-of-arguments
|
||||
(filladapt-funcall 'fill-region-as-paragraph beg end justify)))))))
|
||||
|
||||
(defun fill-region (beg end &optional justify nosqueeze to-eop)
|
||||
"Fill each of the paragraphs in the region.
|
||||
|
||||
(This function has been overloaded with the `filladapt' version.)
|
||||
|
||||
Prefix arg (non-nil third arg, if called from program) means justify as well.
|
||||
|
||||
Noninteractively, fourth arg NOSQUEEZE non-nil means to leave
|
||||
whitespace other than line breaks untouched, and fifth arg TO-EOP
|
||||
non-nil means to keep filling to the end of the paragraph (or next
|
||||
hard newline, if `use-hard-newlines' is on).
|
||||
|
||||
If `sentence-end-double-space' is non-nil, then period followed by one
|
||||
space does not end a sentence, so don't break a line there."
|
||||
(interactive "*r\nP")
|
||||
(if (and filladapt-mode (not filladapt-inside-filladapt))
|
||||
(save-restriction
|
||||
(narrow-to-region beg end)
|
||||
(let ((filladapt-inside-filladapt t)
|
||||
start)
|
||||
(goto-char beg)
|
||||
(while (not (eobp))
|
||||
(setq start (point))
|
||||
(while (and (not (eobp)) (not (filladapt-parse-prefixes)))
|
||||
(forward-line 1))
|
||||
(if (not (equal start (point)))
|
||||
(progn
|
||||
(save-restriction
|
||||
(narrow-to-region start (point))
|
||||
(fill-region start (point) justify nosqueeze to-eop)
|
||||
(goto-char (point-max)))
|
||||
(if (and (not (bolp)) (not (eobp)))
|
||||
(forward-line 1))))
|
||||
(if (filladapt-parse-prefixes)
|
||||
(progn
|
||||
(save-restriction
|
||||
;; for the clipping region
|
||||
(filladapt-adapt t t)
|
||||
(fill-paragraph justify)
|
||||
(goto-char (point-max)))
|
||||
(if (and (not (bolp)) (not (eobp)))
|
||||
(forward-line 1)))))))
|
||||
(condition-case nil
|
||||
(filladapt-funcall 'fill-region beg end justify nosqueeze to-eop)
|
||||
(wrong-number-of-arguments
|
||||
(condition-case nil
|
||||
(filladapt-funcall 'fill-region beg end justify nosqueeze)
|
||||
(wrong-number-of-arguments
|
||||
(filladapt-funcall 'fill-region beg end justify)))))))
|
||||
|
||||
(defvar zmacs-region-stays) ; for XEmacs
|
||||
|
||||
(defun filladapt-mode (&optional arg)
|
||||
"Toggle Filladapt minor mode.
|
||||
With arg, turn Filladapt mode on iff arg is positive. When
|
||||
Filladapt mode is enabled, auto-fill-mode and the fill-paragraph
|
||||
command are both smarter about guessing a proper fill-prefix and
|
||||
finding paragraph boundaries when bulleted and indented lines and
|
||||
paragraphs are used."
|
||||
(interactive "P")
|
||||
;; don't deactivate the region.
|
||||
(setq zmacs-region-stays t)
|
||||
(setq filladapt-mode (or (and arg (> (prefix-numeric-value arg) 0))
|
||||
(and (null arg) (null filladapt-mode))))
|
||||
(if (fboundp 'force-mode-line-update)
|
||||
(force-mode-line-update)
|
||||
(set-buffer-modified-p (buffer-modified-p))))
|
||||
|
||||
(defun turn-on-filladapt-mode ()
|
||||
"Unconditionally turn on Filladapt mode in the current buffer."
|
||||
(filladapt-mode 1))
|
||||
|
||||
(defun turn-off-filladapt-mode ()
|
||||
"Unconditionally turn off Filladapt mode in the current buffer."
|
||||
(filladapt-mode -1))
|
||||
|
||||
(defun filladapt-funcall (function &rest args)
|
||||
"Call the old definition of a function that filladapt has usurped."
|
||||
(apply (cdr (assoc function filladapt-function-table)) args))
|
||||
|
||||
(defun filladapt-paragraph-start (list)
|
||||
"Returns non-nil if LIST contains a paragraph starting token.
|
||||
LIST should be a token list as returned by filladapt-parse-prefixes."
|
||||
(catch 'done
|
||||
(while list
|
||||
(if (memq (car (car list)) filladapt-token-paragraph-start-table)
|
||||
(throw 'done t))
|
||||
(setq list (cdr list)))))
|
||||
|
||||
(defun filladapt-parse-prefixes ()
|
||||
"Parse all the tokens after point and return a list of them.
|
||||
The tokens regular expressions are specified in
|
||||
filladapt-token-table. The list returned is of this form
|
||||
|
||||
((SYM COL STRING) ...)
|
||||
|
||||
SYM is a token symbol as found in filladapt-token-table.
|
||||
COL is the column at which the token ended.
|
||||
STRING is the token's text."
|
||||
(save-excursion
|
||||
(let ((token-list nil)
|
||||
(done nil)
|
||||
(old-point (point))
|
||||
(case-fold-search nil)
|
||||
token-table not-token-table moved)
|
||||
(catch 'done
|
||||
(while (not done)
|
||||
(setq not-token-table filladapt-not-token-table)
|
||||
(while not-token-table
|
||||
(if (looking-at (car not-token-table))
|
||||
(throw 'done t))
|
||||
(setq not-token-table (cdr not-token-table)))
|
||||
(setq token-table filladapt-token-table
|
||||
done t)
|
||||
(while token-table
|
||||
(if (null (looking-at (car (car token-table))))
|
||||
(setq token-table (cdr token-table))
|
||||
(goto-char (match-end 0))
|
||||
(setq token-list (cons (list (nth 1 (car token-table))
|
||||
(current-column)
|
||||
(buffer-substring
|
||||
(match-beginning 0)
|
||||
(match-end 0)))
|
||||
token-list)
|
||||
moved (not (eq (point) old-point))
|
||||
token-table (if moved nil (cdr token-table))
|
||||
done (not moved)
|
||||
old-point (point))))))
|
||||
(nreverse token-list))))
|
||||
|
||||
(defun filladapt-tokens-match-p (list1 list2)
|
||||
"Compare two token lists and return non-nil if they match, nil otherwise.
|
||||
The lists are walked through in lockstep, comparing tokens.
|
||||
|
||||
When two tokens A and B are compared, they are considered to
|
||||
match if
|
||||
|
||||
1. A appears in B's list of matching tokens or
|
||||
B appears in A's list of matching tokens
|
||||
and
|
||||
2. A and B both end at the same column
|
||||
or
|
||||
A can match multiple tokens and ends at a column > than B
|
||||
or
|
||||
B can match multiple tokens and ends at a column > than A
|
||||
|
||||
In the case where the end columns differ the list pointer for the
|
||||
token with the greater end column is not moved forward, which
|
||||
allows its current token to be matched against the next token in
|
||||
the other list in the next iteration of the matching loop.
|
||||
|
||||
All tokens must be matched in order for the lists to be considered
|
||||
matching."
|
||||
(let ((matched t)
|
||||
(done nil))
|
||||
(while (and (not done) list1 list2)
|
||||
(let* ((token1 (car (car list1)))
|
||||
(token1-matches-many-p
|
||||
(memq token1 filladapt-token-match-many-table))
|
||||
(token1-matches (cdr (assq token1 filladapt-token-match-table)))
|
||||
(token1-endcol (nth 1 (car list1)))
|
||||
(token2 (car (car list2)))
|
||||
(token2-matches-many-p
|
||||
(memq token2 filladapt-token-match-many-table))
|
||||
(token2-matches (cdr (assq token2 filladapt-token-match-table)))
|
||||
(token2-endcol (nth 1 (car list2)))
|
||||
(tokens-match (or (memq token1 token2-matches)
|
||||
(memq token2 token1-matches))))
|
||||
(cond ((not tokens-match)
|
||||
(setq matched nil
|
||||
done t))
|
||||
((and token1-matches-many-p token2-matches-many-p)
|
||||
(cond ((= token1-endcol token2-endcol)
|
||||
(setq list1 (cdr list1)
|
||||
list2 (cdr list2)))
|
||||
((< token1-endcol token2-endcol)
|
||||
(setq list1 (cdr list1)))
|
||||
(t
|
||||
(setq list2 (cdr list2)))))
|
||||
(token1-matches-many-p
|
||||
(cond ((= token1-endcol token2-endcol)
|
||||
(setq list1 (cdr list1)
|
||||
list2 (cdr list2)))
|
||||
((< token1-endcol token2-endcol)
|
||||
(setq matched nil
|
||||
done t))
|
||||
(t
|
||||
(setq list2 (cdr list2)))))
|
||||
(token2-matches-many-p
|
||||
(cond ((= token1-endcol token2-endcol)
|
||||
(setq list1 (cdr list1)
|
||||
list2 (cdr list2)))
|
||||
((< token2-endcol token1-endcol)
|
||||
(setq matched nil
|
||||
done t))
|
||||
(t
|
||||
(setq list1 (cdr list1)))))
|
||||
((= token1-endcol token2-endcol)
|
||||
(setq list1 (cdr list1)
|
||||
list2 (cdr list2)))
|
||||
(t
|
||||
(setq matched nil
|
||||
done t)))))
|
||||
(and matched (null list1) (null list2)) ))
|
||||
|
||||
(defun filladapt-make-fill-prefix (list)
|
||||
"Build a fill-prefix for a token LIST.
|
||||
filladapt-token-conversion-table specifies how this is done."
|
||||
(let ((prefix-list nil)
|
||||
(conversion-spec nil))
|
||||
(while list
|
||||
(setq conversion-spec (cdr (assq (car (car list))
|
||||
filladapt-token-conversion-table)))
|
||||
(cond ((eq conversion-spec 'spaces)
|
||||
(setq prefix-list
|
||||
(cons
|
||||
(filladapt-convert-to-spaces (nth 2 (car list)))
|
||||
prefix-list)))
|
||||
((eq conversion-spec 'exact)
|
||||
(setq prefix-list
|
||||
(cons
|
||||
(nth 2 (car list))
|
||||
prefix-list))))
|
||||
(setq list (cdr list)))
|
||||
(apply (function concat) (nreverse prefix-list)) ))
|
||||
|
||||
(defun filladapt-paragraph-within-fill-tolerance ()
|
||||
(catch 'done
|
||||
(save-excursion
|
||||
(let ((low (- fill-column filladapt-fill-column-tolerance))
|
||||
(shortline nil))
|
||||
(goto-char (point-min))
|
||||
(while (not (eobp))
|
||||
(if shortline
|
||||
(throw 'done nil)
|
||||
(end-of-line)
|
||||
(setq shortline (< (current-column) low))
|
||||
(forward-line 1)))
|
||||
t ))))
|
||||
|
||||
(defun filladapt-convert-to-spaces (string)
|
||||
"Return a copy of STRING, with all non-tabs and non-space changed to spaces."
|
||||
(let ((i 0)
|
||||
(space-list '(?\ ?\t))
|
||||
(space ?\ )
|
||||
(lim (length string)))
|
||||
(setq string (copy-sequence string))
|
||||
(while (< i lim)
|
||||
(if (not (memq (aref string i) space-list))
|
||||
(aset string i space))
|
||||
(setq i (1+ i)))
|
||||
string ))
|
||||
|
||||
(defun filladapt-adapt (paragraph debugging)
|
||||
"Set fill-prefix based on the contents of the current line.
|
||||
|
||||
If the first arg PARAGRAPH is non-nil, also set a clipping region
|
||||
around the current paragraph.
|
||||
|
||||
If the second arg DEBUGGING is non-nil, don't do the kludge that's
|
||||
necessary to make certain paragraph fills work properly."
|
||||
(save-excursion
|
||||
(beginning-of-line)
|
||||
(let ((token-list (filladapt-parse-prefixes))
|
||||
curr-list done)
|
||||
(if (null token-list)
|
||||
nil
|
||||
(setq fill-prefix (filladapt-make-fill-prefix token-list))
|
||||
(if paragraph
|
||||
(let (beg end)
|
||||
(if (filladapt-paragraph-start token-list)
|
||||
(setq beg (point))
|
||||
(save-excursion
|
||||
(setq done nil)
|
||||
(while (not done)
|
||||
(cond ((not (= 0 (forward-line -1)))
|
||||
(setq done t
|
||||
beg (point)))
|
||||
((not (filladapt-tokens-match-p
|
||||
token-list
|
||||
(setq curr-list (filladapt-parse-prefixes))))
|
||||
(forward-line 1)
|
||||
(setq done t
|
||||
beg (point)))
|
||||
((filladapt-paragraph-start curr-list)
|
||||
(setq done t
|
||||
beg (point)))))))
|
||||
(save-excursion
|
||||
(setq done nil)
|
||||
(while (not done)
|
||||
(cond ((not (= 0 (progn (end-of-line) (forward-line 1))))
|
||||
(setq done t
|
||||
end (point)))
|
||||
((not (filladapt-tokens-match-p
|
||||
token-list
|
||||
(setq curr-list (filladapt-parse-prefixes))))
|
||||
(setq done t
|
||||
end (point)))
|
||||
((filladapt-paragraph-start curr-list)
|
||||
(setq done t
|
||||
end (point))))))
|
||||
(narrow-to-region beg end)
|
||||
;; Multiple spaces after the bullet at the start of
|
||||
;; a hanging list paragraph get squashed by
|
||||
;; fill-paragraph. We kludge around this by
|
||||
;; replacing the line prefix with the fill-prefix
|
||||
;; used by the rest of the lines in the paragraph.
|
||||
;; fill-paragraph will not alter the fill prefix so
|
||||
;; we win. The post hook restores the old line prefix
|
||||
;; after fill-paragraph has been called.
|
||||
(if (and paragraph (not debugging))
|
||||
(let (col)
|
||||
(setq col (nth 1 (car (filladapt-tail token-list))))
|
||||
(goto-char (point-min))
|
||||
(move-to-column col)
|
||||
(setq filladapt-old-line-prefix
|
||||
(buffer-substring (point-min) (point)))
|
||||
(delete-region (point-min) (point))
|
||||
(insert fill-prefix)
|
||||
(add-hook 'filladapt-fill-paragraph-post-hook
|
||||
'filladapt-cleanup-kludge-at-point-min)))))
|
||||
t ))))
|
||||
|
||||
(defun filladapt-cleanup-kludge-at-point-min ()
|
||||
"Cleanup the paragraph fill kludge.
|
||||
See filladapt-adapt."
|
||||
(save-excursion
|
||||
(goto-char (point-min))
|
||||
(insert filladapt-old-line-prefix)
|
||||
(delete-char (length fill-prefix))
|
||||
(remove-hook 'filladapt-fill-paragraph-post-hook
|
||||
'filladapt-cleanup-kludge-at-point-min)))
|
||||
|
||||
(defun filladapt-tail (list)
|
||||
"Returns the last cons in LIST."
|
||||
(if (null list)
|
||||
nil
|
||||
(while (consp (cdr list))
|
||||
(setq list (cdr list)))
|
||||
list ))
|
||||
|
||||
(defun filladapt-delete-extent (e)
|
||||
(if (fboundp 'delete-extent)
|
||||
(delete-extent e)
|
||||
(delete-overlay e)))
|
||||
|
||||
(defun filladapt-make-extent (beg end)
|
||||
(if (fboundp 'make-extent)
|
||||
(make-extent beg end)
|
||||
(make-overlay beg end)))
|
||||
|
||||
(defun filladapt-set-extent-endpoints (e beg end)
|
||||
(if (fboundp 'set-extent-endpoints)
|
||||
(set-extent-endpoints e beg end)
|
||||
(move-overlay e beg end)))
|
||||
|
||||
(defun filladapt-set-extent-property (e prop val)
|
||||
(if (fboundp 'set-extent-property)
|
||||
(set-extent-property e prop val)
|
||||
(overlay-put e prop val)))
|
||||
|
||||
(defun filladapt-debug ()
|
||||
"Toggle filladapt debugging on/off in the current buffer."
|
||||
;; (interactive)
|
||||
(make-local-variable 'filladapt-debug)
|
||||
(setq filladapt-debug (not filladapt-debug))
|
||||
(if (null filladapt-debug)
|
||||
(progn
|
||||
(mapcar (function (lambda (e) (filladapt-set-extent-endpoints e 1 1)))
|
||||
filladapt-debug-indentation-extents)
|
||||
(if filladapt-debug-paragraph-extent
|
||||
(progn
|
||||
(filladapt-delete-extent filladapt-debug-paragraph-extent)
|
||||
(setq filladapt-debug-paragraph-extent nil)))))
|
||||
(add-hook 'post-command-hook 'filladapt-display-debug-info-maybe))
|
||||
|
||||
(defun filladapt-display-debug-info-maybe ()
|
||||
(cond ((null filladapt-debug) nil)
|
||||
(fill-prefix nil)
|
||||
(t
|
||||
(if (null filladapt-debug-paragraph-extent)
|
||||
(let ((e (filladapt-make-extent 1 1)))
|
||||
(filladapt-set-extent-property e 'detachable nil)
|
||||
(filladapt-set-extent-property e 'evaporate nil)
|
||||
(filladapt-set-extent-property e 'face
|
||||
filladapt-debug-paragraph-face)
|
||||
(setq filladapt-debug-paragraph-extent e)))
|
||||
(save-excursion
|
||||
(save-restriction
|
||||
(let ((ei-list filladapt-debug-indentation-extents)
|
||||
(ep filladapt-debug-paragraph-extent)
|
||||
(face filladapt-debug-indentation-face-1)
|
||||
fill-prefix token-list)
|
||||
(if (null (filladapt-adapt t t))
|
||||
(progn
|
||||
(filladapt-set-extent-endpoints ep 1 1)
|
||||
(while ei-list
|
||||
(filladapt-set-extent-endpoints (car ei-list) 1 1)
|
||||
(setq ei-list (cdr ei-list))))
|
||||
(filladapt-set-extent-endpoints ep (point-min) (point-max))
|
||||
(beginning-of-line)
|
||||
(setq token-list (filladapt-parse-prefixes))
|
||||
(message "(%s)" (mapconcat (function
|
||||
(lambda (q) (symbol-name (car q))))
|
||||
token-list
|
||||
" "))
|
||||
(while token-list
|
||||
(if ei-list
|
||||
(setq e (car ei-list)
|
||||
ei-list (cdr ei-list))
|
||||
(setq e (filladapt-make-extent 1 1))
|
||||
(filladapt-set-extent-property e 'detachable nil)
|
||||
(filladapt-set-extent-property e 'evaporate nil)
|
||||
(setq filladapt-debug-indentation-extents
|
||||
(cons e filladapt-debug-indentation-extents)))
|
||||
(filladapt-set-extent-property e 'face face)
|
||||
(filladapt-set-extent-endpoints e (point)
|
||||
(progn
|
||||
(move-to-column
|
||||
(nth 1
|
||||
(car token-list)))
|
||||
(point)))
|
||||
(if (eq face filladapt-debug-indentation-face-1)
|
||||
(setq face filladapt-debug-indentation-face-2)
|
||||
(setq face filladapt-debug-indentation-face-1))
|
||||
(setq token-list (cdr token-list)))
|
||||
(while ei-list
|
||||
(filladapt-set-extent-endpoints (car ei-list) 1 1)
|
||||
(setq ei-list (cdr ei-list))))))))))
|
||||
Loading…
Add table
Add a link
Reference in a new issue