;To: unix-emacs@bbn.com ;Date: 16 May 89 17:01:35 GMT ;From: Martin Neitzel ;Sender: arpa-unix-emacs-request@bbn.com ;Subject: gin-mode.el, witchcraft for fill-prefix ;Organization: TU Braunschweig,Informatik,West Germany ;Source-Info: From (or Sender) name not authenticated. ; ;[a description of gin-mode follows the copyright stuff.] ; ;Please note: ;This is my first self-made minor-mode. It runs quite smoothly here ;for some weeks now, but some parts of the code at least *look* arkward ;to me. Everything is based on the suggestions given in the old '88 ;version of the elisp manual. It was a big help. If something with ;gin-mode.el is wrong, it might be wise to extend the manual, but any ;blame goes to me, of course. ; ; Martin Neitzel ;; gin-mode.el -- Set up minor mode with guess-indent stuff. ;; Copyright (C) Martin Neitzel, May 1989 ;; This file is not yet part of GNU Emacs. ;; GNU Emacs is distributed in the hope that it will be useful, ;; but WITHOUT ANY WARRANTY. No author or distributor ;; accepts responsibility to anyone for the consequences of using it ;; or for whether it serves any particular purpose or works at all, ;; unless he says so in writing. Refer to the GNU Emacs General Public ;; License for full details. ;; Everyone is granted permission to copy, modify and redistribute ;; GNU Emacs, but only under the conditions described in the ;; GNU Emacs General Public License. A copy of this license is ;; supposed to have been given to you along with GNU Emacs so you ;; can know your rights and responsibilities. It should be in a ;; file named COPYING. Among other things, the copyright notice ;; and this notice must be preserved on all copies. ;; SUMMARY ;; ;; Gnu Emacs supports filling of paragraphs and wrapping of lines with a ;; settable string to be used for the left margin, the variable ;; ``fill-prefix''. Setting this variable by hand is fine, but can ;; become mildly annoying if it has to be changed often in a document. ;; However, the appropriate value for fill-prefix can be derived from ;; the layout of the current line in almost all cases. ;; ;; This is a minor mode that ``guesses'' the indentation to be used ;; for (auto-) filling. It has proven to be very handy in all text-mode ;; variants. It uses a simple but effective heuristic to guess a ;; fill-prefix based on the current line and two (configurable) regular ;; expressions. I almost never have to use "^X." explicitly anymore. ;; ;; The two regexps control ;; ;; * what line beginnings have to be taken as "fill-prefix" (my ;; standard setup recognizes initial white space and typical ;; mail-prefixes like ">" or "name> "). ;; ;; * what line beginnings are really hanging indents. The ;; standard setup recognizes the stars used right here, ;; enumerations, and some more... ;; Change History: ;; Nov 9, 1990 - Ralph P.Sobek - Added gin-fill-region. ;; The guessing stuff (provide 'gin-mode) (defvar gin-left-hang-indent-re "\\s *\\([-*]\\|([a-zA-Z0-9])\\|[a-zA-Z0-9]\\.?:]?\\)\\s +" "*Regexp that defines a hanging indent of a paragraph. If it is seen by gin-guess-prefix, the next lines are indented with white space beyond the hanging indent. Setting this variable makes it buffer-local.") (defvar gin-retain-indent-re "[a-zA-Z]*>+[ \t]*\\|[ \t]+" "*Regexp that defines how a fill-prefix can look like. If such a string is seen by gin-guess-prefix in the current line, the next line will be indented with it, too. Setting this variable makes it buffer-local.") (defun gin-guess-prefix () "Try to figure out the prefix for the next line." (save-excursion (beginning-of-line) (cond ((looking-at gin-left-hang-indent-re) (let ((beg (point)) indent-size (indent-prefix "")) (re-search-forward gin-left-hang-indent-re) (setq indent-size (current-column)) ;; First gather tabs as needed ... (if indent-tabs-mode (while (>= indent-size tab-width) (setq indent-prefix (concat indent-prefix "\t")) (setq indent-size (- indent-size tab-width)))) ;; ... then append the rest as spaces: (while (> indent-size 0) (setq indent-prefix (concat indent-prefix " ")) (setq indent-size (1- indent-size))) indent-prefix)) ((looking-at gin-retain-indent-re) (buffer-substring (match-beginning 0) (match-end 0))) (t "")))) ;; Replacements for old functions dealing with the fill-prefix. ;; Their function values are stuffed into the original symbols. (defun gin-fill-paragraph (arg) "fill-paragraph in Gin mode, tries to guess the appropriate fill-prefix. With arg, also justify." (interactive "P") (if gin-mode (let ((gin-fill-prefix (gin-guess-prefix)) end) (save-excursion (forward-paragraph) (or (bolp) (newline 1)) (setq end (point)) (backward-paragraph) (let ((fill-prefix gin-fill-prefix)) (fill-region-as-paragraph (point) end arg)))) (funcall 'gin-old-fill-paragraph arg))) (defun gin-fill-region (from to &optional justify-flag) "fill-region in Gin mode, tries to guess the appropriate fill-prefix. Prefix arg (non-nil third arg, if called from program) means justify as well." (interactive "r\nP") (if gin-mode (let ((gin-fill-prefix (gin-guess-prefix))) (save-restriction (narrow-to-region from to) (goto-char (point-min)) (while (not (eobp)) (let* ((initial (point)) (end (progn (forward-paragraph 1) (point))) (fill-prefix gin-fill-prefix)) (forward-paragraph -1) (if (>= (point) initial) (fill-region-as-paragraph (point) end justify-flag)) (goto-char end))))) (funcall 'gin-old-fill-region from to justify-flag))) (defun gin-do-auto-fill() (if gin-mode (let ((fill-prefix (gin-guess-prefix))) (funcall 'gin-old-do-auto-fill)) (funcall 'gin-old-do-auto-fill))) ;; When loaded for the first time, install our minor mode indicator (defconst gin-old-fill-paragraph nil "Keeps the true fill-paragraph function during Gin mode.") (defconst gin-old-fill-region nil "Keeps the true fill-region function during Gin mode.") (defconst gin-old-do-auto-fill nil "Keeps the true do-auto-fill function during Gin mode.") (defun gin-overlay-functions() "Undermine emacs with Gin stuff." (fset 'fill-paragraph (symbol-function 'gin-fill-paragraph)) (fset 'fill-region (symbol-function 'gin-fill-region)) (fset 'do-auto-fill (symbol-function 'gin-do-auto-fill))) (defun gin-restore-originals () "Throw gin-mode functions out everywhere." (fset 'fill-paragraph (symbol-function 'gin-old-fill-paragraph)) (fset 'fill-region (symbol-function 'gin-old-fill-region)) (fset 'do-auto-fill (symbol-function 'gin-old-do-auto-fill))) (if (boundp 'gin-mode) nil (setq minor-mode-alist (cons '(gin-mode " Gin") minor-mode-alist)) (make-variable-buffer-local 'gin-mode) (set-default 'gin-mode nil) (make-variable-buffer-local 'gin-left-hang-indent-re) (make-variable-buffer-local 'gin-retain-indent-re) (fset 'gin-old-fill-paragraph (symbol-function 'fill-paragraph)) (fset 'gin-old-fill-region (symbol-function 'fill-region)) (fset 'gin-old-do-auto-fill (symbol-function 'do-auto-fill)) (gin-overlay-functions)) (defun gin-mode (arg) "Minor mode to guess indentations. Toggle gin-mode, or turn it on iff optional ARG is positiv. Gin mode adds the capability to \"guess\" a suitable indent for filling based on the current line. The line is matched against the two regexps 'gin-left-hang-indent-re' and 'gin-retain-indent-re', see their documentation. When Gin mode is active, auto-filling, fill-paragraph, and fill-region will both use a \"guessed\" value as fill-prefix." (interactive "P") (setq gin-mode (if (null arg) (not gin-mode) (> (prefix-numeric-value arg) 0))) (set-buffer-modified-p (buffer-modified-p)))