diff options
| author | Juanma Barranquero | 2003-05-30 23:31:15 +0000 |
|---|---|---|
| committer | Juanma Barranquero | 2003-05-30 23:31:15 +0000 |
| commit | 5e046f6d571737bb8cd115bf67f9ee76519ba3cb (patch) | |
| tree | c25147d32cbb72db4fb264c670f3cfb3b6f08af0 | |
| parent | 9d7aa1b1b6f7eb8d97c2cc620022a708d43398f2 (diff) | |
| download | emacs-5e046f6d571737bb8cd115bf67f9ee76519ba3cb.tar.gz emacs-5e046f6d571737bb8cd115bf67f9ee76519ba3cb.zip | |
Moved from lisp/.
| -rw-r--r-- | lisp/emacs-lisp/byte-run.el | 172 | ||||
| -rw-r--r-- | lisp/emacs-lisp/derived.el | 436 | ||||
| -rw-r--r-- | lisp/emacs-lisp/float-sup.el | 63 | ||||
| -rw-r--r-- | lisp/emacs-lisp/map-ynp.el | 264 | ||||
| -rw-r--r-- | lisp/emacs-lisp/regi.el | 258 | ||||
| -rw-r--r-- | lisp/emacs-lisp/timer.el | 479 | ||||
| -rw-r--r-- | lisp/emacs-lisp/warnings.el | 311 | ||||
| -rw-r--r-- | lisp/progmodes/which-func.el | 256 | ||||
| -rw-r--r-- | lisp/textmodes/enriched.el | 474 |
9 files changed, 2713 insertions, 0 deletions
diff --git a/lisp/emacs-lisp/byte-run.el b/lisp/emacs-lisp/byte-run.el new file mode 100644 index 00000000000..a28f89cd91a --- /dev/null +++ b/lisp/emacs-lisp/byte-run.el | |||
| @@ -0,0 +1,172 @@ | |||
| 1 | ;;; byte-run.el --- byte-compiler support for inlining | ||
| 2 | |||
| 3 | ;; Copyright (C) 1992 Free Software Foundation, Inc. | ||
| 4 | |||
| 5 | ;; Author: Jamie Zawinski <jwz@lucid.com> | ||
| 6 | ;; Hallvard Furuseth <hbf@ulrik.uio.no> | ||
| 7 | ;; Maintainer: FSF | ||
| 8 | ;; Keywords: internal | ||
| 9 | |||
| 10 | ;; This file is part of GNU Emacs. | ||
| 11 | |||
| 12 | ;; GNU Emacs is free software; you can redistribute it and/or modify | ||
| 13 | ;; it under the terms of the GNU General Public License as published by | ||
| 14 | ;; the Free Software Foundation; either version 2, or (at your option) | ||
| 15 | ;; any later version. | ||
| 16 | |||
| 17 | ;; GNU Emacs is distributed in the hope that it will be useful, | ||
| 18 | ;; but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 19 | ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 20 | ;; GNU General Public License for more details. | ||
| 21 | |||
| 22 | ;; You should have received a copy of the GNU General Public License | ||
| 23 | ;; along with GNU Emacs; see the file COPYING. If not, write to the | ||
| 24 | ;; Free Software Foundation, Inc., 59 Temple Place - Suite 330, | ||
| 25 | ;; Boston, MA 02111-1307, USA. | ||
| 26 | |||
| 27 | ;;; Commentary: | ||
| 28 | |||
| 29 | ;; interface to selectively inlining functions. | ||
| 30 | ;; This only happens when source-code optimization is turned on. | ||
| 31 | |||
| 32 | ;;; Code: | ||
| 33 | |||
| 34 | ;; Redefined in byte-optimize.el. | ||
| 35 | ;; This is not documented--it's not clear that we should promote it. | ||
| 36 | (fset 'inline 'progn) | ||
| 37 | (put 'inline 'lisp-indent-hook 0) | ||
| 38 | |||
| 39 | |||
| 40 | ;;; Interface to inline functions. | ||
| 41 | |||
| 42 | ;; (defmacro proclaim-inline (&rest fns) | ||
| 43 | ;; "Cause the named functions to be open-coded when called from compiled code. | ||
| 44 | ;; They will only be compiled open-coded when byte-compile-optimize is true." | ||
| 45 | ;; (cons 'eval-and-compile | ||
| 46 | ;; (mapcar '(lambda (x) | ||
| 47 | ;; (or (memq (get x 'byte-optimizer) | ||
| 48 | ;; '(nil byte-compile-inline-expand)) | ||
| 49 | ;; (error | ||
| 50 | ;; "%s already has a byte-optimizer, can't make it inline" | ||
| 51 | ;; x)) | ||
| 52 | ;; (list 'put (list 'quote x) | ||
| 53 | ;; ''byte-optimizer ''byte-compile-inline-expand)) | ||
| 54 | ;; fns))) | ||
| 55 | |||
| 56 | ;; (defmacro proclaim-notinline (&rest fns) | ||
| 57 | ;; "Cause the named functions to no longer be open-coded." | ||
| 58 | ;; (cons 'eval-and-compile | ||
| 59 | ;; (mapcar '(lambda (x) | ||
| 60 | ;; (if (eq (get x 'byte-optimizer) 'byte-compile-inline-expand) | ||
| 61 | ;; (put x 'byte-optimizer nil)) | ||
| 62 | ;; (list 'if (list 'eq (list 'get (list 'quote x) ''byte-optimizer) | ||
| 63 | ;; ''byte-compile-inline-expand) | ||
| 64 | ;; (list 'put x ''byte-optimizer nil))) | ||
| 65 | ;; fns))) | ||
| 66 | |||
| 67 | ;; This has a special byte-hunk-handler in bytecomp.el. | ||
| 68 | (defmacro defsubst (name arglist &rest body) | ||
| 69 | "Define an inline function. The syntax is just like that of `defun'." | ||
| 70 | (or (memq (get name 'byte-optimizer) | ||
| 71 | '(nil byte-compile-inline-expand)) | ||
| 72 | (error "`%s' is a primitive" name)) | ||
| 73 | (list 'prog1 | ||
| 74 | (cons 'defun (cons name (cons arglist body))) | ||
| 75 | (list 'eval-and-compile | ||
| 76 | (list 'put (list 'quote name) | ||
| 77 | ''byte-optimizer ''byte-compile-inline-expand)))) | ||
| 78 | |||
| 79 | (defun make-obsolete (fn new &optional when) | ||
| 80 | "Make the byte-compiler warn that FUNCTION is obsolete. | ||
| 81 | The warning will say that NEW should be used instead. | ||
| 82 | If NEW is a string, that is the `use instead' message. | ||
| 83 | If provided, WHEN should be a string indicating when the function | ||
| 84 | was first made obsolete, for example a date or a release number." | ||
| 85 | (interactive "aMake function obsolete: \nxObsoletion replacement: ") | ||
| 86 | (let ((handler (get fn 'byte-compile))) | ||
| 87 | (if (eq 'byte-compile-obsolete handler) | ||
| 88 | (setq handler (nth 1 (get fn 'byte-obsolete-info))) | ||
| 89 | (put fn 'byte-compile 'byte-compile-obsolete)) | ||
| 90 | (put fn 'byte-obsolete-info (list new handler when))) | ||
| 91 | fn) | ||
| 92 | |||
| 93 | (defun make-obsolete-variable (var new &optional when) | ||
| 94 | "Make the byte-compiler warn that VARIABLE is obsolete, | ||
| 95 | and NEW should be used instead. If NEW is a string, then that is the | ||
| 96 | `use instead' message. | ||
| 97 | If provided, WHEN should be a string indicating when the variable | ||
| 98 | was first made obsolete, for example a date or a release number." | ||
| 99 | (interactive | ||
| 100 | (list | ||
| 101 | (let ((str (completing-read "Make variable obsolete: " obarray 'boundp t))) | ||
| 102 | (if (equal str "") (error "")) | ||
| 103 | (intern str)) | ||
| 104 | (car (read-from-string (read-string "Obsoletion replacement: "))))) | ||
| 105 | (put var 'byte-obsolete-variable (cons new when)) | ||
| 106 | var) | ||
| 107 | |||
| 108 | (put 'dont-compile 'lisp-indent-hook 0) | ||
| 109 | (defmacro dont-compile (&rest body) | ||
| 110 | "Like `progn', but the body always runs interpreted (not compiled). | ||
| 111 | If you think you need this, you're probably making a mistake somewhere." | ||
| 112 | (list 'eval (list 'quote (if (cdr body) (cons 'progn body) (car body))))) | ||
| 113 | |||
| 114 | |||
| 115 | ;;; interface to evaluating things at compile time and/or load time | ||
| 116 | ;;; these macro must come after any uses of them in this file, as their | ||
| 117 | ;;; definition in the file overrides the magic definitions on the | ||
| 118 | ;;; byte-compile-macro-environment. | ||
| 119 | |||
| 120 | (put 'eval-when-compile 'lisp-indent-hook 0) | ||
| 121 | (defmacro eval-when-compile (&rest body) | ||
| 122 | "Like `progn', but evaluates the body at compile time. | ||
| 123 | The result of the body appears to the compiler as a quoted constant." | ||
| 124 | ;; Not necessary because we have it in b-c-initial-macro-environment | ||
| 125 | ;; (list 'quote (eval (cons 'progn body))) | ||
| 126 | (cons 'progn body)) | ||
| 127 | |||
| 128 | (put 'eval-and-compile 'lisp-indent-hook 0) | ||
| 129 | (defmacro eval-and-compile (&rest body) | ||
| 130 | "Like `progn', but evaluates the body at compile time and at load time." | ||
| 131 | ;; Remember, it's magic. | ||
| 132 | (cons 'progn body)) | ||
| 133 | |||
| 134 | (defun with-no-warnings (&optional first &rest body) | ||
| 135 | "Like `progn', but prevents compiler warnings in the body." | ||
| 136 | ;; The implementation for the interpreter is basically trivial. | ||
| 137 | (if body (car (last body)) | ||
| 138 | first)) | ||
| 139 | |||
| 140 | |||
| 141 | ;;; I nuked this because it's not a good idea for users to think of using it. | ||
| 142 | ;;; These options are a matter of installation preference, and have nothing to | ||
| 143 | ;;; with particular source files; it's a mistake to suggest to users | ||
| 144 | ;;; they should associate these with particular source files. | ||
| 145 | ;;; There is hardly any reason to change these parameters, anyway. | ||
| 146 | ;;; --rms. | ||
| 147 | |||
| 148 | ;; (put 'byte-compiler-options 'lisp-indent-hook 0) | ||
| 149 | ;; (defmacro byte-compiler-options (&rest args) | ||
| 150 | ;; "Set some compilation-parameters for this file. This will affect only the | ||
| 151 | ;; file in which it appears; this does nothing when evaluated, and when loaded | ||
| 152 | ;; from a .el file. | ||
| 153 | ;; | ||
| 154 | ;; Each argument to this macro must be a list of a key and a value. | ||
| 155 | ;; | ||
| 156 | ;; Keys: Values: Corresponding variable: | ||
| 157 | ;; | ||
| 158 | ;; verbose t, nil byte-compile-verbose | ||
| 159 | ;; optimize t, nil, source, byte byte-compile-optimize | ||
| 160 | ;; warnings list of warnings byte-compile-warnings | ||
| 161 | ;; Legal elements: (callargs redefine free-vars unresolved) | ||
| 162 | ;; file-format emacs18, emacs19 byte-compile-compatibility | ||
| 163 | ;; | ||
| 164 | ;; For example, this might appear at the top of a source file: | ||
| 165 | ;; | ||
| 166 | ;; (byte-compiler-options | ||
| 167 | ;; (optimize t) | ||
| 168 | ;; (warnings (- free-vars)) ; Don't warn about free variables | ||
| 169 | ;; (file-format emacs19))" | ||
| 170 | ;; nil) | ||
| 171 | |||
| 172 | ;;; byte-run.el ends here | ||
diff --git a/lisp/emacs-lisp/derived.el b/lisp/emacs-lisp/derived.el new file mode 100644 index 00000000000..8d152f391bc --- /dev/null +++ b/lisp/emacs-lisp/derived.el | |||
| @@ -0,0 +1,436 @@ | |||
| 1 | ;;; derived.el --- allow inheritance of major modes | ||
| 2 | ;;; (formerly mode-clone.el) | ||
| 3 | |||
| 4 | ;; Copyright (C) 1993, 1994, 1999, 2003 Free Software Foundation, Inc. | ||
| 5 | |||
| 6 | ;; Author: David Megginson (dmeggins@aix1.uottawa.ca) | ||
| 7 | ;; Maintainer: FSF | ||
| 8 | ;; Keywords: extensions | ||
| 9 | |||
| 10 | ;; This file is part of GNU Emacs. | ||
| 11 | |||
| 12 | ;; GNU Emacs is free software; you can redistribute it and/or modify | ||
| 13 | ;; it under the terms of the GNU General Public License as published by | ||
| 14 | ;; the Free Software Foundation; either version 2, or (at your option) | ||
| 15 | ;; any later version. | ||
| 16 | |||
| 17 | ;; GNU Emacs is distributed in the hope that it will be useful, | ||
| 18 | ;; but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 19 | ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 20 | ;; GNU General Public License for more details. | ||
| 21 | |||
| 22 | ;; You should have received a copy of the GNU General Public License | ||
| 23 | ;; along with GNU Emacs; see the file COPYING. If not, write to the | ||
| 24 | ;; Free Software Foundation, Inc., 59 Temple Place - Suite 330, | ||
| 25 | ;; Boston, MA 02111-1307, USA. | ||
| 26 | |||
| 27 | ;;; Commentary: | ||
| 28 | |||
| 29 | ;; GNU Emacs is already, in a sense, object oriented -- each object | ||
| 30 | ;; (buffer) belongs to a class (major mode), and that class defines | ||
| 31 | ;; the relationship between messages (input events) and methods | ||
| 32 | ;; (commands) by means of a keymap. | ||
| 33 | ;; | ||
| 34 | ;; The only thing missing is a good scheme of inheritance. It is | ||
| 35 | ;; possible to simulate a single level of inheritance with generous | ||
| 36 | ;; use of hooks and a bit of work -- sgml-mode, for example, also runs | ||
| 37 | ;; the hooks for text-mode, and keymaps can inherit from other keymaps | ||
| 38 | ;; -- but generally, each major mode ends up reinventing the wheel. | ||
| 39 | ;; Ideally, someone should redesign all of Emacs's major modes to | ||
| 40 | ;; follow a more conventional object-oriented system: when defining a | ||
| 41 | ;; new major mode, the user should need only to name the existing mode | ||
| 42 | ;; it is most similar to, then list the (few) differences. | ||
| 43 | ;; | ||
| 44 | ;; In the mean time, this package offers most of the advantages of | ||
| 45 | ;; full inheritance with the existing major modes. The macro | ||
| 46 | ;; `define-derived-mode' allows the user to make a variant of an existing | ||
| 47 | ;; major mode, with its own keymap. The new mode will inherit the key | ||
| 48 | ;; bindings of its parent, and will, in fact, run its parent first | ||
| 49 | ;; every time it is called. For example, the commands | ||
| 50 | ;; | ||
| 51 | ;; (define-derived-mode hypertext-mode text-mode "Hypertext" | ||
| 52 | ;; "Major mode for hypertext.\n\n\\{hypertext-mode-map}" | ||
| 53 | ;; (setq case-fold-search nil)) | ||
| 54 | ;; | ||
| 55 | ;; (define-key hypertext-mode-map [down-mouse-3] 'do-hyper-link) | ||
| 56 | ;; | ||
| 57 | ;; will create a function `hypertext-mode' with its own (sparse) | ||
| 58 | ;; keymap `hypertext-mode-map.' The command M-x hypertext-mode will | ||
| 59 | ;; perform the following actions: | ||
| 60 | ;; | ||
| 61 | ;; - run the command (text-mode) to get its default setup | ||
| 62 | ;; - replace the current keymap with 'hypertext-mode-map,' which will | ||
| 63 | ;; inherit from 'text-mode-map'. | ||
| 64 | ;; - replace the current syntax table with | ||
| 65 | ;; 'hypertext-mode-syntax-table', which will borrow its defaults | ||
| 66 | ;; from the current text-mode-syntax-table. | ||
| 67 | ;; - replace the current abbrev table with | ||
| 68 | ;; 'hypertext-mode-abbrev-table', which will borrow its defaults | ||
| 69 | ;; from the current text-mode-abbrev table | ||
| 70 | ;; - change the mode line to read "Hypertext" | ||
| 71 | ;; - assign the value 'hypertext-mode' to the 'major-mode' variable | ||
| 72 | ;; - run the body of commands provided in the macro -- in this case, | ||
| 73 | ;; set the local variable `case-fold-search' to nil. | ||
| 74 | ;; | ||
| 75 | ;; The advantages of this system are threefold. First, text mode is | ||
| 76 | ;; untouched -- if you had added the new keystroke to `text-mode-map,' | ||
| 77 | ;; possibly using hooks, you would have added it to all text buffers | ||
| 78 | ;; -- here, it appears only in hypertext buffers, where it makes | ||
| 79 | ;; sense. Second, it is possible to build even further, and make | ||
| 80 | ;; a derived mode from a derived mode. The commands | ||
| 81 | ;; | ||
| 82 | ;; (define-derived-mode html-mode hypertext-mode "HTML") | ||
| 83 | ;; [various key definitions] | ||
| 84 | ;; | ||
| 85 | ;; will add a new major mode for HTML with very little fuss. | ||
| 86 | ;; | ||
| 87 | ;; Note also the function `derived-mode-p' which can tell if the current | ||
| 88 | ;; mode derives from another. In a hypertext-mode, buffer, for example, | ||
| 89 | ;; (derived-mode-p 'text-mode) would return non-nil. This should always | ||
| 90 | ;; be used in place of (eq major-mode 'text-mode). | ||
| 91 | |||
| 92 | ;;; Code: | ||
| 93 | |||
| 94 | (eval-when-compile (require 'cl)) | ||
| 95 | |||
| 96 | ;;; PRIVATE: defsubst must be defined before they are first used | ||
| 97 | |||
| 98 | (defsubst derived-mode-hook-name (mode) | ||
| 99 | "Construct the mode hook name based on mode name MODE." | ||
| 100 | (intern (concat (symbol-name mode) "-hook"))) | ||
| 101 | |||
| 102 | (defsubst derived-mode-map-name (mode) | ||
| 103 | "Construct a map name based on a MODE name." | ||
| 104 | (intern (concat (symbol-name mode) "-map"))) | ||
| 105 | |||
| 106 | (defsubst derived-mode-syntax-table-name (mode) | ||
| 107 | "Construct a syntax-table name based on a MODE name." | ||
| 108 | (intern (concat (symbol-name mode) "-syntax-table"))) | ||
| 109 | |||
| 110 | (defsubst derived-mode-abbrev-table-name (mode) | ||
| 111 | "Construct an abbrev-table name based on a MODE name." | ||
| 112 | (intern (concat (symbol-name mode) "-abbrev-table"))) | ||
| 113 | |||
| 114 | ;; PUBLIC: define a new major mode which inherits from an existing one. | ||
| 115 | |||
| 116 | ;;;###autoload | ||
| 117 | (defmacro define-derived-mode (child parent name &optional docstring &rest body) | ||
| 118 | "Create a new mode as a variant of an existing mode. | ||
| 119 | |||
| 120 | The arguments to this command are as follow: | ||
| 121 | |||
| 122 | CHILD: the name of the command for the derived mode. | ||
| 123 | PARENT: the name of the command for the parent mode (e.g. `text-mode') | ||
| 124 | or nil if there is no parent. | ||
| 125 | NAME: a string which will appear in the status line (e.g. \"Hypertext\") | ||
| 126 | DOCSTRING: an optional documentation string--if you do not supply one, | ||
| 127 | the function will attempt to invent something useful. | ||
| 128 | BODY: forms to execute just before running the | ||
| 129 | hooks for the new mode. Do not use `interactive' here. | ||
| 130 | |||
| 131 | BODY can start with a bunch of keyword arguments. The following keyword | ||
| 132 | arguments are currently understood: | ||
| 133 | :group GROUP | ||
| 134 | Declare the customization group that corresponds to this mode. | ||
| 135 | :syntax-table TABLE | ||
| 136 | Use TABLE instead of the default. | ||
| 137 | A nil value means to simply use the same syntax-table as the parent. | ||
| 138 | :abbrev-table TABLE | ||
| 139 | Use TABLE instead of the default. | ||
| 140 | A nil value means to simply use the same abbrev-table as the parent. | ||
| 141 | |||
| 142 | Here is how you could define LaTeX-Thesis mode as a variant of LaTeX mode: | ||
| 143 | |||
| 144 | (define-derived-mode LaTeX-thesis-mode LaTeX-mode \"LaTeX-Thesis\") | ||
| 145 | |||
| 146 | You could then make new key bindings for `LaTeX-thesis-mode-map' | ||
| 147 | without changing regular LaTeX mode. In this example, BODY is empty, | ||
| 148 | and DOCSTRING is generated by default. | ||
| 149 | |||
| 150 | On a more complicated level, the following command uses `sgml-mode' as | ||
| 151 | the parent, and then sets the variable `case-fold-search' to nil: | ||
| 152 | |||
| 153 | (define-derived-mode article-mode sgml-mode \"Article\" | ||
| 154 | \"Major mode for editing technical articles.\" | ||
| 155 | (setq case-fold-search nil)) | ||
| 156 | |||
| 157 | Note that if the documentation string had been left out, it would have | ||
| 158 | been generated automatically, with a reference to the keymap." | ||
| 159 | (declare (debug (&define name symbolp sexp [&optional stringp] | ||
| 160 | [&rest keywordp sexp] def-body))) | ||
| 161 | |||
| 162 | (when (and docstring (not (stringp docstring))) | ||
| 163 | ;; Some trickiness, since what appears to be the docstring may really be | ||
| 164 | ;; the first element of the body. | ||
| 165 | (push docstring body) | ||
| 166 | (setq docstring nil)) | ||
| 167 | |||
| 168 | (when (eq parent 'fundamental-mode) (setq parent nil)) | ||
| 169 | |||
| 170 | (let ((map (derived-mode-map-name child)) | ||
| 171 | (syntax (derived-mode-syntax-table-name child)) | ||
| 172 | (abbrev (derived-mode-abbrev-table-name child)) | ||
| 173 | (declare-abbrev t) | ||
| 174 | (declare-syntax t) | ||
| 175 | (hook (derived-mode-hook-name child)) | ||
| 176 | (group nil)) | ||
| 177 | |||
| 178 | ;; Process the keyword args. | ||
| 179 | (while (keywordp (car body)) | ||
| 180 | (case (pop body) | ||
| 181 | (:group (setq group (pop body))) | ||
| 182 | (:abbrev-table (setq abbrev (pop body)) (setq declare-abbrev nil)) | ||
| 183 | (:syntax-table (setq syntax (pop body)) (setq declare-syntax nil)) | ||
| 184 | (t (pop body)))) | ||
| 185 | |||
| 186 | (setq docstring (derived-mode-make-docstring | ||
| 187 | parent child docstring syntax abbrev)) | ||
| 188 | |||
| 189 | `(progn | ||
| 190 | (defvar ,map (make-sparse-keymap)) | ||
| 191 | ,(if declare-syntax | ||
| 192 | `(defvar ,syntax (make-syntax-table))) | ||
| 193 | ,(if declare-abbrev | ||
| 194 | `(defvar ,abbrev | ||
| 195 | (progn (define-abbrev-table ',abbrev nil) ,abbrev))) | ||
| 196 | (put ',child 'derived-mode-parent ',parent) | ||
| 197 | ,(if group `(put ',child 'custom-mode-group ,group)) | ||
| 198 | |||
| 199 | (defun ,child () | ||
| 200 | ,docstring | ||
| 201 | (interactive) | ||
| 202 | ; Run the parent. | ||
| 203 | (delay-mode-hooks | ||
| 204 | |||
| 205 | (,(or parent 'kill-all-local-variables)) | ||
| 206 | ; Identify the child mode. | ||
| 207 | (setq major-mode (quote ,child)) | ||
| 208 | (setq mode-name ,name) | ||
| 209 | ; Identify special modes. | ||
| 210 | ,(when parent | ||
| 211 | `(progn | ||
| 212 | (if (get (quote ,parent) 'mode-class) | ||
| 213 | (put (quote ,child) 'mode-class | ||
| 214 | (get (quote ,parent) 'mode-class))) | ||
| 215 | ; Set up maps and tables. | ||
| 216 | (unless (keymap-parent ,map) | ||
| 217 | (set-keymap-parent ,map (current-local-map))) | ||
| 218 | ,(when declare-syntax | ||
| 219 | `(let ((parent (char-table-parent ,syntax))) | ||
| 220 | (unless (and parent | ||
| 221 | (not (eq parent (standard-syntax-table)))) | ||
| 222 | (set-char-table-parent ,syntax (syntax-table))))))) | ||
| 223 | |||
| 224 | (use-local-map ,map) | ||
| 225 | ,(when syntax `(set-syntax-table ,syntax)) | ||
| 226 | ,(when abbrev `(setq local-abbrev-table ,abbrev)) | ||
| 227 | ; Splice in the body (if any). | ||
| 228 | ,@body | ||
| 229 | ) | ||
| 230 | ;; Run the hooks, if any. | ||
| 231 | ;; Make the generated code work in older Emacs versions | ||
| 232 | ;; that do not yet have run-mode-hooks. | ||
| 233 | (if (fboundp 'run-mode-hooks) | ||
| 234 | (run-mode-hooks ',hook) | ||
| 235 | (run-hooks ',hook)))))) | ||
| 236 | |||
| 237 | ;; PUBLIC: find the ultimate class of a derived mode. | ||
| 238 | |||
| 239 | (defun derived-mode-class (mode) | ||
| 240 | "Find the class of a major MODE. | ||
| 241 | A mode's class is the first ancestor which is NOT a derived mode. | ||
| 242 | Use the `derived-mode-parent' property of the symbol to trace backwards. | ||
| 243 | Since major-modes might all derive from `fundamental-mode', this function | ||
| 244 | is not very useful." | ||
| 245 | (while (get mode 'derived-mode-parent) | ||
| 246 | (setq mode (get mode 'derived-mode-parent))) | ||
| 247 | mode) | ||
| 248 | (make-obsolete 'derived-mode-class 'derived-mode-p "21.4") | ||
| 249 | |||
| 250 | |||
| 251 | ;;; PRIVATE | ||
| 252 | |||
| 253 | (defun derived-mode-make-docstring (parent child &optional | ||
| 254 | docstring syntax abbrev) | ||
| 255 | "Construct a docstring for a new mode if none is provided." | ||
| 256 | |||
| 257 | (let ((map (derived-mode-map-name child)) | ||
| 258 | (hook (derived-mode-hook-name child))) | ||
| 259 | |||
| 260 | (unless (stringp docstring) | ||
| 261 | ;; Use a default docstring. | ||
| 262 | (setq docstring | ||
| 263 | (if (null parent) | ||
| 264 | (format "Major-mode. | ||
| 265 | Uses keymap `%s', abbrev table `%s' and syntax-table `%s'." map abbrev syntax) | ||
| 266 | (format "Major mode derived from `%s' by `define-derived-mode'. | ||
| 267 | It inherits all of the parent's attributes, but has its own keymap, | ||
| 268 | abbrev table and syntax table: | ||
| 269 | |||
| 270 | `%s', `%s' and `%s' | ||
| 271 | |||
| 272 | which more-or-less shadow %s's corresponding tables." | ||
| 273 | parent map abbrev syntax parent)))) | ||
| 274 | |||
| 275 | (unless (string-match (regexp-quote (symbol-name hook)) docstring) | ||
| 276 | ;; Make sure the docstring mentions the mode's hook. | ||
| 277 | (setq docstring | ||
| 278 | (concat docstring | ||
| 279 | (if (null parent) | ||
| 280 | "\n\nThis mode " | ||
| 281 | (concat | ||
| 282 | "\n\nIn addition to any hooks its parent mode " | ||
| 283 | (if (string-match (regexp-quote (format "`%s'" parent)) | ||
| 284 | docstring) nil | ||
| 285 | (format "`%s' " parent)) | ||
| 286 | "might have run,\nthis mode ")) | ||
| 287 | (format "runs the hook `%s'" hook) | ||
| 288 | ", as the final step\nduring initialization."))) | ||
| 289 | |||
| 290 | (unless (string-match "\\\\[{[]" docstring) | ||
| 291 | ;; And don't forget to put the mode's keymap. | ||
| 292 | (setq docstring (concat docstring "\n\n\\{" (symbol-name map) "}"))) | ||
| 293 | |||
| 294 | docstring)) | ||
| 295 | |||
| 296 | |||
| 297 | ;;; OBSOLETE | ||
| 298 | ;; The functions below are only provided for backward compatibility with | ||
| 299 | ;; code byte-compiled with versions of derived.el prior to Emacs-21. | ||
| 300 | |||
| 301 | (defsubst derived-mode-setup-function-name (mode) | ||
| 302 | "Construct a setup-function name based on a MODE name." | ||
| 303 | (intern (concat (symbol-name mode) "-setup"))) | ||
| 304 | |||
| 305 | |||
| 306 | ;; Utility functions for defining a derived mode. | ||
| 307 | |||
| 308 | ;;;###autoload | ||
| 309 | (defun derived-mode-init-mode-variables (mode) | ||
| 310 | "Initialise variables for a new MODE. | ||
| 311 | Right now, if they don't already exist, set up a blank keymap, an | ||
| 312 | empty syntax table, and an empty abbrev table -- these will be merged | ||
| 313 | the first time the mode is used." | ||
| 314 | |||
| 315 | (if (boundp (derived-mode-map-name mode)) | ||
| 316 | t | ||
| 317 | (eval `(defvar ,(derived-mode-map-name mode) | ||
| 318 | (make-sparse-keymap) | ||
| 319 | ,(format "Keymap for %s." mode))) | ||
| 320 | (put (derived-mode-map-name mode) 'derived-mode-unmerged t)) | ||
| 321 | |||
| 322 | (if (boundp (derived-mode-syntax-table-name mode)) | ||
| 323 | t | ||
| 324 | (eval `(defvar ,(derived-mode-syntax-table-name mode) | ||
| 325 | ;; Make a syntax table which doesn't specify anything | ||
| 326 | ;; for any char. Valid data will be merged in by | ||
| 327 | ;; derived-mode-merge-syntax-tables. | ||
| 328 | (make-char-table 'syntax-table nil) | ||
| 329 | ,(format "Syntax table for %s." mode))) | ||
| 330 | (put (derived-mode-syntax-table-name mode) 'derived-mode-unmerged t)) | ||
| 331 | |||
| 332 | (if (boundp (derived-mode-abbrev-table-name mode)) | ||
| 333 | t | ||
| 334 | (eval `(defvar ,(derived-mode-abbrev-table-name mode) | ||
| 335 | (progn | ||
| 336 | (define-abbrev-table (derived-mode-abbrev-table-name mode) nil) | ||
| 337 | (make-abbrev-table)) | ||
| 338 | ,(format "Abbrev table for %s." mode))))) | ||
| 339 | |||
| 340 | ;; Utility functions for running a derived mode. | ||
| 341 | |||
| 342 | (defun derived-mode-set-keymap (mode) | ||
| 343 | "Set the keymap of the new MODE, maybe merging with the parent." | ||
| 344 | (let* ((map-name (derived-mode-map-name mode)) | ||
| 345 | (new-map (eval map-name)) | ||
| 346 | (old-map (current-local-map))) | ||
| 347 | (and old-map | ||
| 348 | (get map-name 'derived-mode-unmerged) | ||
| 349 | (derived-mode-merge-keymaps old-map new-map)) | ||
| 350 | (put map-name 'derived-mode-unmerged nil) | ||
| 351 | (use-local-map new-map))) | ||
| 352 | |||
| 353 | (defun derived-mode-set-syntax-table (mode) | ||
| 354 | "Set the syntax table of the new MODE, maybe merging with the parent." | ||
| 355 | (let* ((table-name (derived-mode-syntax-table-name mode)) | ||
| 356 | (old-table (syntax-table)) | ||
| 357 | (new-table (eval table-name))) | ||
| 358 | (if (get table-name 'derived-mode-unmerged) | ||
| 359 | (derived-mode-merge-syntax-tables old-table new-table)) | ||
| 360 | (put table-name 'derived-mode-unmerged nil) | ||
| 361 | (set-syntax-table new-table))) | ||
| 362 | |||
| 363 | (defun derived-mode-set-abbrev-table (mode) | ||
| 364 | "Set the abbrev table for MODE if it exists. | ||
| 365 | Always merge its parent into it, since the merge is non-destructive." | ||
| 366 | (let* ((table-name (derived-mode-abbrev-table-name mode)) | ||
| 367 | (old-table local-abbrev-table) | ||
| 368 | (new-table (eval table-name))) | ||
| 369 | (derived-mode-merge-abbrev-tables old-table new-table) | ||
| 370 | (setq local-abbrev-table new-table))) | ||
| 371 | |||
| 372 | ;;;(defun derived-mode-run-setup-function (mode) | ||
| 373 | ;;; "Run the setup function if it exists." | ||
| 374 | |||
| 375 | ;;; (let ((fname (derived-mode-setup-function-name mode))) | ||
| 376 | ;;; (if (fboundp fname) | ||
| 377 | ;;; (funcall fname)))) | ||
| 378 | |||
| 379 | (defun derived-mode-run-hooks (mode) | ||
| 380 | "Run the mode hook for MODE." | ||
| 381 | (let ((hooks-name (derived-mode-hook-name mode))) | ||
| 382 | (if (boundp hooks-name) | ||
| 383 | (run-hooks hooks-name)))) | ||
| 384 | |||
| 385 | ;; Functions to merge maps and tables. | ||
| 386 | |||
| 387 | (defun derived-mode-merge-keymaps (old new) | ||
| 388 | "Merge an OLD keymap into a NEW one. | ||
| 389 | The old keymap is set to be the last cdr of the new one, so that there will | ||
| 390 | be automatic inheritance." | ||
| 391 | ;; ?? Can this just use `set-keymap-parent'? | ||
| 392 | (let ((tail new)) | ||
| 393 | ;; Scan the NEW map for prefix keys. | ||
| 394 | (while (consp tail) | ||
| 395 | (and (consp (car tail)) | ||
| 396 | (let* ((key (vector (car (car tail)))) | ||
| 397 | (subnew (lookup-key new key)) | ||
| 398 | (subold (lookup-key old key))) | ||
| 399 | ;; If KEY is a prefix key in both OLD and NEW, merge them. | ||
| 400 | (and (keymapp subnew) (keymapp subold) | ||
| 401 | (derived-mode-merge-keymaps subold subnew)))) | ||
| 402 | (and (vectorp (car tail)) | ||
| 403 | ;; Search a vector of ASCII char bindings for prefix keys. | ||
| 404 | (let ((i (1- (length (car tail))))) | ||
| 405 | (while (>= i 0) | ||
| 406 | (let* ((key (vector i)) | ||
| 407 | (subnew (lookup-key new key)) | ||
| 408 | (subold (lookup-key old key))) | ||
| 409 | ;; If KEY is a prefix key in both OLD and NEW, merge them. | ||
| 410 | (and (keymapp subnew) (keymapp subold) | ||
| 411 | (derived-mode-merge-keymaps subold subnew))) | ||
| 412 | (setq i (1- i))))) | ||
| 413 | (setq tail (cdr tail)))) | ||
| 414 | (setcdr (nthcdr (1- (length new)) new) old)) | ||
| 415 | |||
| 416 | (defun derived-mode-merge-syntax-tables (old new) | ||
| 417 | "Merge an OLD syntax table into a NEW one. | ||
| 418 | Where the new table already has an entry, nothing is copied from the old one." | ||
| 419 | (set-char-table-parent new old)) | ||
| 420 | |||
| 421 | ;; Merge an old abbrev table into a new one. | ||
| 422 | ;; This function requires internal knowledge of how abbrev tables work, | ||
| 423 | ;; presuming that they are obarrays with the abbrev as the symbol, the expansion | ||
| 424 | ;; as the value of the symbol, and the hook as the function definition. | ||
| 425 | (defun derived-mode-merge-abbrev-tables (old new) | ||
| 426 | (if old | ||
| 427 | (mapatoms | ||
| 428 | (lambda (symbol) | ||
| 429 | (or (intern-soft (symbol-name symbol) new) | ||
| 430 | (define-abbrev new (symbol-name symbol) | ||
| 431 | (symbol-value symbol) (symbol-function symbol)))) | ||
| 432 | old))) | ||
| 433 | |||
| 434 | (provide 'derived) | ||
| 435 | |||
| 436 | ;;; derived.el ends here | ||
diff --git a/lisp/emacs-lisp/float-sup.el b/lisp/emacs-lisp/float-sup.el new file mode 100644 index 00000000000..4c45112e980 --- /dev/null +++ b/lisp/emacs-lisp/float-sup.el | |||
| @@ -0,0 +1,63 @@ | |||
| 1 | ;;; float-sup.el --- define some constants useful for floating point numbers. | ||
| 2 | |||
| 3 | ;; Copyright (C) 1985, 1986, 1987 Free Software Foundation, Inc. | ||
| 4 | |||
| 5 | ;; Maintainer: FSF | ||
| 6 | ;; Keywords: internal | ||
| 7 | |||
| 8 | ;; This file is part of GNU Emacs. | ||
| 9 | |||
| 10 | ;; GNU Emacs is free software; you can redistribute it and/or modify | ||
| 11 | ;; it under the terms of the GNU General Public License as published by | ||
| 12 | ;; the Free Software Foundation; either version 2, or (at your option) | ||
| 13 | ;; any later version. | ||
| 14 | |||
| 15 | ;; GNU Emacs is distributed in the hope that it will be useful, | ||
| 16 | ;; but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 17 | ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 18 | ;; GNU General Public License for more details. | ||
| 19 | |||
| 20 | ;; You should have received a copy of the GNU General Public License | ||
| 21 | ;; along with GNU Emacs; see the file COPYING. If not, write to the | ||
| 22 | ;; Free Software Foundation, Inc., 59 Temple Place - Suite 330, | ||
| 23 | ;; Boston, MA 02111-1307, USA. | ||
| 24 | |||
| 25 | ;;; Commentary: | ||
| 26 | |||
| 27 | ;;; Code: | ||
| 28 | |||
| 29 | ;; Provide a meaningful error message if we are running on | ||
| 30 | ;; bare (non-float) emacs. | ||
| 31 | |||
| 32 | (if (fboundp 'atan) | ||
| 33 | nil | ||
| 34 | (error "Floating point was disabled at compile time")) | ||
| 35 | |||
| 36 | ;; provide an easy hook to tell if we are running with floats or not. | ||
| 37 | ;; define pi and e via math-lib calls. (much less prone to killer typos.) | ||
| 38 | (defconst pi (* 4 (atan 1)) "The value of Pi (3.1415926...).") | ||
| 39 | ;; It's too inconvenient to make `e' a constant because it's used as | ||
| 40 | ;; a temporary variable all the time. | ||
| 41 | (defvar e (exp 1) "The value of e (2.7182818...).") | ||
| 42 | |||
| 43 | ;; Careful when editing this file ... typos here will be hard to spot. | ||
| 44 | ;; (defconst pi 3.14159265358979323846264338327 | ||
| 45 | ;; "The value of Pi (3.14159265358979323846264338327...)") | ||
| 46 | |||
| 47 | (defconst degrees-to-radians (/ pi 180.0) | ||
| 48 | "Degrees to radian conversion constant.") | ||
| 49 | (defconst radians-to-degrees (/ 180.0 pi) | ||
| 50 | "Radian to degree conversion constant.") | ||
| 51 | |||
| 52 | ;; these expand to a single multiply by a float when byte compiled | ||
| 53 | |||
| 54 | (defmacro degrees-to-radians (x) | ||
| 55 | "Convert ARG from degrees to radians." | ||
| 56 | (list '* (/ pi 180.0) x)) | ||
| 57 | (defmacro radians-to-degrees (x) | ||
| 58 | "Convert ARG from radians to degrees." | ||
| 59 | (list '* (/ 180.0 pi) x)) | ||
| 60 | |||
| 61 | (provide 'lisp-float-type) | ||
| 62 | |||
| 63 | ;;; float-sup.el ends here | ||
diff --git a/lisp/emacs-lisp/map-ynp.el b/lisp/emacs-lisp/map-ynp.el new file mode 100644 index 00000000000..2fa97f163d7 --- /dev/null +++ b/lisp/emacs-lisp/map-ynp.el | |||
| @@ -0,0 +1,264 @@ | |||
| 1 | ;;; map-ynp.el --- general-purpose boolean question-asker | ||
| 2 | |||
| 3 | ;; Copyright (C) 1991, 1992, 1993, 1994, 1995, 2000 Free Software Foundation, Inc. | ||
| 4 | |||
| 5 | ;; Author: Roland McGrath <roland@gnu.org> | ||
| 6 | ;; Maintainer: FSF | ||
| 7 | ;; Keywords: lisp, extensions | ||
| 8 | |||
| 9 | ;; This file is part of GNU Emacs. | ||
| 10 | |||
| 11 | ;; GNU Emacs is free software; you can redistribute it and/or modify | ||
| 12 | ;; it under the terms of the GNU General Public License as published by | ||
| 13 | ;; the Free Software Foundation; either version 2, or (at your option) | ||
| 14 | ;; any later version. | ||
| 15 | |||
| 16 | ;; GNU Emacs is distributed in the hope that it will be useful, | ||
| 17 | ;; but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 18 | ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 19 | ;; GNU General Public License for more details. | ||
| 20 | |||
| 21 | ;; You should have received a copy of the GNU General Public License | ||
| 22 | ;; along with GNU Emacs; see the file COPYING. If not, write to the | ||
| 23 | ;; Free Software Foundation, Inc., 59 Temple Place - Suite 330, | ||
| 24 | ;; Boston, MA 02111-1307, USA. | ||
| 25 | |||
| 26 | ;;; Commentary: | ||
| 27 | |||
| 28 | ;; map-y-or-n-p is a general-purpose question-asking function. | ||
| 29 | ;; It asks a series of y/n questions (a la y-or-n-p), and decides to | ||
| 30 | ;; apply an action to each element of a list based on the answer. | ||
| 31 | ;; The nice thing is that you also get some other possible answers | ||
| 32 | ;; to use, reminiscent of query-replace: ! to answer y to all remaining | ||
| 33 | ;; questions; ESC or q to answer n to all remaining questions; . to answer | ||
| 34 | ;; y once and then n for the remainder; and you can get help with C-h. | ||
| 35 | |||
| 36 | ;;; Code: | ||
| 37 | |||
| 38 | (defun map-y-or-n-p (prompter actor list &optional help action-alist | ||
| 39 | no-cursor-in-echo-area) | ||
| 40 | "Ask a series of boolean questions. | ||
| 41 | Takes args PROMPTER ACTOR LIST, and optional args HELP and ACTION-ALIST. | ||
| 42 | |||
| 43 | LIST is a list of objects, or a function of no arguments to return the next | ||
| 44 | object or nil. | ||
| 45 | |||
| 46 | If PROMPTER is a string, the prompt is \(format PROMPTER OBJECT\). If not | ||
| 47 | a string, PROMPTER is a function of one arg (an object from LIST), which | ||
| 48 | returns a string to be used as the prompt for that object. If the return | ||
| 49 | value is not a string, it may be nil to ignore the object or non-nil to act | ||
| 50 | on the object without asking the user. | ||
| 51 | |||
| 52 | ACTOR is a function of one arg (an object from LIST), | ||
| 53 | which gets called with each object that the user answers `yes' for. | ||
| 54 | |||
| 55 | If HELP is given, it is a list (OBJECT OBJECTS ACTION), | ||
| 56 | where OBJECT is a string giving the singular noun for an elt of LIST; | ||
| 57 | OBJECTS is the plural noun for elts of LIST, and ACTION is a transitive | ||
| 58 | verb describing ACTOR. The default is \(\"object\" \"objects\" \"act on\"\). | ||
| 59 | |||
| 60 | At the prompts, the user may enter y, Y, or SPC to act on that object; | ||
| 61 | n, N, or DEL to skip that object; ! to act on all following objects; | ||
| 62 | ESC or q to exit (skip all following objects); . (period) to act on the | ||
| 63 | current object and then exit; or \\[help-command] to get help. | ||
| 64 | |||
| 65 | If ACTION-ALIST is given, it is an alist (KEY FUNCTION HELP) of extra keys | ||
| 66 | that will be accepted. KEY is a character; FUNCTION is a function of one | ||
| 67 | arg (an object from LIST); HELP is a string. When the user hits KEY, | ||
| 68 | FUNCTION is called. If it returns non-nil, the object is considered | ||
| 69 | \"acted upon\", and the next object from LIST is processed. If it returns | ||
| 70 | nil, the prompt is repeated for the same object. | ||
| 71 | |||
| 72 | Final optional argument NO-CURSOR-IN-ECHO-AREA non-nil says not to set | ||
| 73 | `cursor-in-echo-area' while prompting. | ||
| 74 | |||
| 75 | This function uses `query-replace-map' to define the standard responses, | ||
| 76 | but not all of the responses which `query-replace' understands | ||
| 77 | are meaningful here. | ||
| 78 | |||
| 79 | Returns the number of actions taken." | ||
| 80 | (let* ((actions 0) | ||
| 81 | user-keys mouse-event map prompt char elt tail def | ||
| 82 | ;; Non-nil means we should use mouse menus to ask. | ||
| 83 | use-menus | ||
| 84 | delayed-switch-frame | ||
| 85 | (next (if (or (and list (symbolp list)) | ||
| 86 | (subrp list) | ||
| 87 | (byte-code-function-p list) | ||
| 88 | (and (consp list) | ||
| 89 | (eq (car list) 'lambda))) | ||
| 90 | (function (lambda () | ||
| 91 | (setq elt (funcall list)))) | ||
| 92 | (function (lambda () | ||
| 93 | (if list | ||
| 94 | (progn | ||
| 95 | (setq elt (car list) | ||
| 96 | list (cdr list)) | ||
| 97 | t) | ||
| 98 | nil)))))) | ||
| 99 | (if (and (listp last-nonmenu-event) | ||
| 100 | use-dialog-box) | ||
| 101 | ;; Make a list describing a dialog box. | ||
| 102 | (let ((object (if help (capitalize (nth 0 help)))) | ||
| 103 | (objects (if help (capitalize (nth 1 help)))) | ||
| 104 | (action (if help (capitalize (nth 2 help))))) | ||
| 105 | (setq map `(("Yes" . act) ("No" . skip) ("Quit" . exit) | ||
| 106 | (,(if help (concat action " " object " And Quit") | ||
| 107 | "Do it and Quit") . act-and-exit) | ||
| 108 | (,(if help (concat action " All " objects) | ||
| 109 | "Do All") . automatic) | ||
| 110 | ,@(mapcar (lambda (elt) | ||
| 111 | (cons (capitalize (nth 2 elt)) | ||
| 112 | (vector (nth 1 elt)))) | ||
| 113 | action-alist)) | ||
| 114 | use-menus t | ||
| 115 | mouse-event last-nonmenu-event)) | ||
| 116 | (setq user-keys (if action-alist | ||
| 117 | (concat (mapconcat (function | ||
| 118 | (lambda (elt) | ||
| 119 | (key-description | ||
| 120 | (char-to-string (car elt))))) | ||
| 121 | action-alist ", ") | ||
| 122 | " ") | ||
| 123 | "") | ||
| 124 | ;; Make a map that defines each user key as a vector containing | ||
| 125 | ;; its definition. | ||
| 126 | map (cons 'keymap | ||
| 127 | (append (mapcar (lambda (elt) | ||
| 128 | (cons (car elt) (vector (nth 1 elt)))) | ||
| 129 | action-alist) | ||
| 130 | query-replace-map)))) | ||
| 131 | (unwind-protect | ||
| 132 | (progn | ||
| 133 | (if (stringp prompter) | ||
| 134 | (setq prompter `(lambda (object) | ||
| 135 | (format ,prompter object)))) | ||
| 136 | (while (funcall next) | ||
| 137 | (setq prompt (funcall prompter elt)) | ||
| 138 | (cond ((stringp prompt) | ||
| 139 | ;; Prompt the user about this object. | ||
| 140 | (setq quit-flag nil) | ||
| 141 | (if use-menus | ||
| 142 | (setq def (or (x-popup-dialog (or mouse-event use-menus) | ||
| 143 | (cons prompt map)) | ||
| 144 | 'quit)) | ||
| 145 | ;; Prompt in the echo area. | ||
| 146 | (let ((cursor-in-echo-area (not no-cursor-in-echo-area)) | ||
| 147 | (message-log-max nil)) | ||
| 148 | (message "%s(y, n, !, ., q, %sor %s) " | ||
| 149 | prompt user-keys | ||
| 150 | (key-description (vector help-char))) | ||
| 151 | (if minibuffer-auto-raise | ||
| 152 | (raise-frame (window-frame (minibuffer-window)))) | ||
| 153 | (while (progn | ||
| 154 | (setq char (read-event)) | ||
| 155 | ;; If we get -1, from end of keyboard | ||
| 156 | ;; macro, try again. | ||
| 157 | (equal char -1))) | ||
| 158 | ;; Show the answer to the question. | ||
| 159 | (message "%s(y, n, !, ., q, %sor %s) %s" | ||
| 160 | prompt user-keys | ||
| 161 | (key-description (vector help-char)) | ||
| 162 | (single-key-description char))) | ||
| 163 | (setq def (lookup-key map (vector char)))) | ||
| 164 | (cond ((eq def 'exit) | ||
| 165 | (setq next (function (lambda () nil)))) | ||
| 166 | ((eq def 'act) | ||
| 167 | ;; Act on the object. | ||
| 168 | (funcall actor elt) | ||
| 169 | (setq actions (1+ actions))) | ||
| 170 | ((eq def 'skip) | ||
| 171 | ;; Skip the object. | ||
| 172 | ) | ||
| 173 | ((eq def 'act-and-exit) | ||
| 174 | ;; Act on the object and then exit. | ||
| 175 | (funcall actor elt) | ||
| 176 | (setq actions (1+ actions) | ||
| 177 | next (function (lambda () nil)))) | ||
| 178 | ((eq def 'quit) | ||
| 179 | (setq quit-flag t) | ||
| 180 | (setq next `(lambda () | ||
| 181 | (setq next ',next) | ||
| 182 | ',elt))) | ||
| 183 | ((eq def 'automatic) | ||
| 184 | ;; Act on this and all following objects. | ||
| 185 | (if (funcall prompter elt) | ||
| 186 | (progn | ||
| 187 | (funcall actor elt) | ||
| 188 | (setq actions (1+ actions)))) | ||
| 189 | (while (funcall next) | ||
| 190 | (if (funcall prompter elt) | ||
| 191 | (progn | ||
| 192 | (funcall actor elt) | ||
| 193 | (setq actions (1+ actions)))))) | ||
| 194 | ((eq def 'help) | ||
| 195 | (with-output-to-temp-buffer "*Help*" | ||
| 196 | (princ | ||
| 197 | (let ((object (if help (nth 0 help) "object")) | ||
| 198 | (objects (if help (nth 1 help) "objects")) | ||
| 199 | (action (if help (nth 2 help) "act on"))) | ||
| 200 | (concat | ||
| 201 | (format "Type SPC or `y' to %s the current %s; | ||
| 202 | DEL or `n' to skip the current %s; | ||
| 203 | RET or `q' to exit (skip all remaining %s); | ||
| 204 | C-g to quit (cancel the operation); | ||
| 205 | ! to %s all remaining %s;\n" | ||
| 206 | action object object objects action | ||
| 207 | objects) | ||
| 208 | (mapconcat (function | ||
| 209 | (lambda (elt) | ||
| 210 | (format "%s to %s" | ||
| 211 | (single-key-description | ||
| 212 | (nth 0 elt)) | ||
| 213 | (nth 2 elt)))) | ||
| 214 | action-alist | ||
| 215 | ";\n") | ||
| 216 | (if action-alist ";\n") | ||
| 217 | (format "or . (period) to %s \ | ||
| 218 | the current %s and exit." | ||
| 219 | action object)))) | ||
| 220 | (save-excursion | ||
| 221 | (set-buffer standard-output) | ||
| 222 | (help-mode))) | ||
| 223 | |||
| 224 | (setq next `(lambda () | ||
| 225 | (setq next ',next) | ||
| 226 | ',elt))) | ||
| 227 | ((vectorp def) | ||
| 228 | ;; A user-defined key. | ||
| 229 | (if (funcall (aref def 0) elt) ;Call its function. | ||
| 230 | ;; The function has eaten this object. | ||
| 231 | (setq actions (1+ actions)) | ||
| 232 | ;; Regurgitated; try again. | ||
| 233 | (setq next `(lambda () | ||
| 234 | (setq next ',next) | ||
| 235 | ',elt)))) | ||
| 236 | ((and (consp char) | ||
| 237 | (eq (car char) 'switch-frame)) | ||
| 238 | ;; switch-frame event. Put it off until we're done. | ||
| 239 | (setq delayed-switch-frame char) | ||
| 240 | (setq next `(lambda () | ||
| 241 | (setq next ',next) | ||
| 242 | ',elt))) | ||
| 243 | (t | ||
| 244 | ;; Random char. | ||
| 245 | (message "Type %s for help." | ||
| 246 | (key-description (vector help-char))) | ||
| 247 | (beep) | ||
| 248 | (sit-for 1) | ||
| 249 | (setq next `(lambda () | ||
| 250 | (setq next ',next) | ||
| 251 | ',elt))))) | ||
| 252 | (prompt | ||
| 253 | (funcall actor elt) | ||
| 254 | (setq actions (1+ actions)))))) | ||
| 255 | (if delayed-switch-frame | ||
| 256 | (setq unread-command-events | ||
| 257 | (cons delayed-switch-frame unread-command-events)))) | ||
| 258 | ;; Clear the last prompt from the minibuffer. | ||
| 259 | (let ((message-log-max nil)) | ||
| 260 | (message "")) | ||
| 261 | ;; Return the number of actions that were taken. | ||
| 262 | actions)) | ||
| 263 | |||
| 264 | ;;; map-ynp.el ends here | ||
diff --git a/lisp/emacs-lisp/regi.el b/lisp/emacs-lisp/regi.el new file mode 100644 index 00000000000..c0cae5b5771 --- /dev/null +++ b/lisp/emacs-lisp/regi.el | |||
| @@ -0,0 +1,258 @@ | |||
| 1 | ;;; regi.el --- REGular expression Interpreting engine | ||
| 2 | |||
| 3 | ;; Copyright (C) 1993 Free Software Foundation, Inc. | ||
| 4 | |||
| 5 | ;; Author: 1993 Barry A. Warsaw, Century Computing, Inc. <bwarsaw@cen.com> | ||
| 6 | ;; Maintainer: bwarsaw@cen.com | ||
| 7 | ;; Created: 24-Feb-1993 | ||
| 8 | ;; Version: 1.8 | ||
| 9 | ;; Last Modified: 1993/06/01 21:33:00 | ||
| 10 | ;; Keywords: extensions, matching | ||
| 11 | |||
| 12 | ;; This file is part of GNU Emacs. | ||
| 13 | |||
| 14 | ;; GNU Emacs is free software; you can redistribute it and/or modify | ||
| 15 | ;; it under the terms of the GNU General Public License as published by | ||
| 16 | ;; the Free Software Foundation; either version 2, or (at your option) | ||
| 17 | ;; any later version. | ||
| 18 | |||
| 19 | ;; GNU Emacs is distributed in the hope that it will be useful, | ||
| 20 | ;; but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 21 | ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 22 | ;; GNU General Public License for more details. | ||
| 23 | |||
| 24 | ;; You should have received a copy of the GNU General Public License | ||
| 25 | ;; along with GNU Emacs; see the file COPYING. If not, write to the | ||
| 26 | ;; Free Software Foundation, Inc., 59 Temple Place - Suite 330, | ||
| 27 | ;; Boston, MA 02111-1307, USA. | ||
| 28 | |||
| 29 | ;;; Commentary: | ||
| 30 | |||
| 31 | ;;; Code: | ||
| 32 | |||
| 33 | |||
| 34 | (defun regi-pos (&optional position col-p) | ||
| 35 | "Return the character position at various buffer positions. | ||
| 36 | Optional POSITION can be one of the following symbols: | ||
| 37 | |||
| 38 | `bol' == beginning of line | ||
| 39 | `boi' == beginning of indentation | ||
| 40 | `eol' == end of line [default] | ||
| 41 | `bonl' == beginning of next line | ||
| 42 | `bopl' == beginning of previous line | ||
| 43 | |||
| 44 | Optional COL-P non-nil returns `current-column' instead of character position." | ||
| 45 | (save-excursion | ||
| 46 | (cond | ||
| 47 | ((eq position 'bol) (beginning-of-line)) | ||
| 48 | ((eq position 'boi) (back-to-indentation)) | ||
| 49 | ((eq position 'bonl) (forward-line 1)) | ||
| 50 | ((eq position 'bopl) (forward-line -1)) | ||
| 51 | (t (end-of-line))) | ||
| 52 | (if col-p (current-column) (point)))) | ||
| 53 | |||
| 54 | (defun regi-mapcar (predlist func &optional negate-p case-fold-search-p) | ||
| 55 | "Build a regi frame where each element of PREDLIST appears exactly once. | ||
| 56 | The frame contains elements where each member of PREDLIST is | ||
| 57 | associated with FUNC, and optionally NEGATE-P and CASE-FOLD-SEARCH-P." | ||
| 58 | (let (frame tail) | ||
| 59 | (if (or negate-p case-fold-search-p) | ||
| 60 | (setq tail (list negate-p))) | ||
| 61 | (if case-fold-search-p | ||
| 62 | (setq tail (append tail (list case-fold-search-p)))) | ||
| 63 | (while predlist | ||
| 64 | (let ((element (list (car predlist) func))) | ||
| 65 | (if tail | ||
| 66 | (setq element (append element tail))) | ||
| 67 | (setq frame (append frame (list element)) | ||
| 68 | predlist (cdr predlist)) | ||
| 69 | )) | ||
| 70 | frame)) | ||
| 71 | |||
| 72 | |||
| 73 | (defun regi-interpret (frame &optional start end) | ||
| 74 | "Interpret the regi frame FRAME. | ||
| 75 | If optional START and END are supplied, they indicate the region of | ||
| 76 | interest, and the buffer is narrowed to the beginning of the line | ||
| 77 | containing START, and beginning of the line after the line containing | ||
| 78 | END. Otherwise, point and mark are not set and processing continues | ||
| 79 | until your FUNC returns the `abort' symbol (see below). Beware! Not | ||
| 80 | supplying a START or END could put you in an infinite loop. | ||
| 81 | |||
| 82 | A regi frame is a list of entries of the form: | ||
| 83 | |||
| 84 | (PRED FUNC [NEGATE-P [CASE-FOLD-SEARCH]]) | ||
| 85 | |||
| 86 | PRED is a predicate against which each line in the region is tested, | ||
| 87 | and if a match occurs, FUNC is `eval'd. Point is then moved to the | ||
| 88 | beginning of the next line, the frame is reset and checking continues. | ||
| 89 | If a match doesn't occur, the next entry is checked against the | ||
| 90 | current line until all entries in the frame are checked. At this | ||
| 91 | point, if no match occurred, the frame is reset and point is moved to | ||
| 92 | the next line. Checking continues until every line in the region is | ||
| 93 | checked. Optional NEGATE-P inverts the result of PRED before FUNC is | ||
| 94 | called and `case-fold-search' is bound to the optional value of | ||
| 95 | CASE-FOLD-SEARCH for the PRED check. | ||
| 96 | |||
| 97 | PRED can be a string, variable, function or one of the following | ||
| 98 | symbols: t, nil, `begin', `end', and `every'. If PRED is a string, or | ||
| 99 | a variable or list that evaluates to a string, it is interpreted as a | ||
| 100 | regular expression and is matched against the current line (from the | ||
| 101 | beginning) using `looking-at'. If PRED does not evaluate to a string, | ||
| 102 | it is interpreted as a binary value (nil or non-nil). | ||
| 103 | |||
| 104 | PRED can also be one of the following symbols: | ||
| 105 | |||
| 106 | t -- always produces a true outcome | ||
| 107 | `begin' -- always executes before anything else | ||
| 108 | `end' -- always executes after everything else | ||
| 109 | `every' -- execute after frame is matched on a line | ||
| 110 | |||
| 111 | Note that NEGATE-P and CASE-FOLD-SEARCH are meaningless if PRED is one | ||
| 112 | of these special symbols. Only the first occurrence of each symbol in | ||
| 113 | a frame entry is used, the rest are ignored. | ||
| 114 | |||
| 115 | Your FUNC can return values which control regi processing. If a list | ||
| 116 | is returned from your function, it can contain any combination of the | ||
| 117 | following elements: | ||
| 118 | |||
| 119 | the symbol `continue' | ||
| 120 | Tells regi to continue processing frame-entries after a match, | ||
| 121 | instead of resetting to the first entry and advancing to the next | ||
| 122 | line, as is the default behavior. When returning this symbol, | ||
| 123 | you must take care not to enter an infinite loop. | ||
| 124 | |||
| 125 | the symbol `abort' | ||
| 126 | Tells regi to terminate processing this frame. any end | ||
| 127 | frame-entry is still processed. | ||
| 128 | |||
| 129 | the list `(frame . NEWFRAME)' | ||
| 130 | Tells regi to use NEWFRAME as its current frame. In other words, | ||
| 131 | your FUNC can modify the executing regi frame on the fly. | ||
| 132 | |||
| 133 | the list `(step . STEP)' | ||
| 134 | Tells regi to move STEP number of lines forward during normal | ||
| 135 | processing. By default, regi moves forward 1 line. STEP can be | ||
| 136 | negative, but be careful of infinite loops. | ||
| 137 | |||
| 138 | You should usually take care to explicitly return nil from your | ||
| 139 | function if no action is to take place. Your FUNC will always be | ||
| 140 | `eval'ed. The following variables will be temporarily bound to some | ||
| 141 | useful information: | ||
| 142 | |||
| 143 | `curline' | ||
| 144 | the current line in the buffer, as a string | ||
| 145 | |||
| 146 | `curframe' | ||
| 147 | the full, current frame being executed | ||
| 148 | |||
| 149 | `curentry' | ||
| 150 | the current frame entry being executed." | ||
| 151 | |||
| 152 | (save-excursion | ||
| 153 | (save-restriction | ||
| 154 | (let (begin-tag end-tag every-tag current-frame working-frame donep) | ||
| 155 | |||
| 156 | ;; set up the narrowed region | ||
| 157 | (and start | ||
| 158 | end | ||
| 159 | (let* ((tstart start) | ||
| 160 | (start (min start end)) | ||
| 161 | (end (max start end))) | ||
| 162 | (narrow-to-region | ||
| 163 | (progn (goto-char end) (regi-pos 'bonl)) | ||
| 164 | (progn (goto-char start) (regi-pos 'bol))))) | ||
| 165 | |||
| 166 | ;; lets find the special tags and remove them from the working | ||
| 167 | ;; frame. note that only the last special tag is used. | ||
| 168 | (mapcar | ||
| 169 | (function | ||
| 170 | (lambda (entry) | ||
| 171 | (let ((pred (car entry)) | ||
| 172 | (func (car (cdr entry)))) | ||
| 173 | (cond | ||
| 174 | ((eq pred 'begin) (setq begin-tag func)) | ||
| 175 | ((eq pred 'end) (setq end-tag func)) | ||
| 176 | ((eq pred 'every) (setq every-tag func)) | ||
| 177 | (t | ||
| 178 | (setq working-frame (append working-frame (list entry)))) | ||
| 179 | ) ; end-cond | ||
| 180 | ))) | ||
| 181 | frame) ; end-mapcar | ||
| 182 | |||
| 183 | ;; execute the begin entry | ||
| 184 | (eval begin-tag) | ||
| 185 | |||
| 186 | ;; now process the frame | ||
| 187 | (setq current-frame working-frame) | ||
| 188 | (while (not (or donep (eobp))) | ||
| 189 | (let* ((entry (car current-frame)) | ||
| 190 | (pred (nth 0 entry)) | ||
| 191 | (func (nth 1 entry)) | ||
| 192 | (negate-p (nth 2 entry)) | ||
| 193 | (case-fold-search (nth 3 entry)) | ||
| 194 | match-p) | ||
| 195 | (catch 'regi-throw-top | ||
| 196 | (cond | ||
| 197 | ;; we are finished processing the frame for this line | ||
| 198 | ((not current-frame) | ||
| 199 | (setq current-frame working-frame) ;reset frame | ||
| 200 | (forward-line 1) | ||
| 201 | (throw 'regi-throw-top t)) | ||
| 202 | ;; see if predicate evaluates to a string | ||
| 203 | ((stringp (setq match-p (eval pred))) | ||
| 204 | (setq match-p (looking-at match-p))) | ||
| 205 | ) ; end-cond | ||
| 206 | |||
| 207 | ;; now that we've done the initial matching, check for | ||
| 208 | ;; negation of match | ||
| 209 | (and negate-p | ||
| 210 | (setq match-p (not match-p))) | ||
| 211 | |||
| 212 | ;; if the line matched, package up the argument list and | ||
| 213 | ;; funcall the FUNC | ||
| 214 | (if match-p | ||
| 215 | (let* ((curline (buffer-substring | ||
| 216 | (regi-pos 'bol) | ||
| 217 | (regi-pos 'eol))) | ||
| 218 | (curframe current-frame) | ||
| 219 | (curentry entry) | ||
| 220 | (result (eval func)) | ||
| 221 | (step (or (cdr (assq 'step result)) 1)) | ||
| 222 | ) | ||
| 223 | ;; changing frame on the fly? | ||
| 224 | (if (assq 'frame result) | ||
| 225 | (setq working-frame (cdr (assq 'frame result)))) | ||
| 226 | |||
| 227 | ;; continue processing current frame? | ||
| 228 | (if (memq 'continue result) | ||
| 229 | (setq current-frame (cdr current-frame)) | ||
| 230 | (forward-line step) | ||
| 231 | (setq current-frame working-frame)) | ||
| 232 | |||
| 233 | ;; abort current frame? | ||
| 234 | (if (memq 'abort result) | ||
| 235 | (progn | ||
| 236 | (setq donep t) | ||
| 237 | (throw 'regi-throw-top t))) | ||
| 238 | ) ; end-let | ||
| 239 | |||
| 240 | ;; else if no match occurred, then process the next | ||
| 241 | ;; frame-entry on the current line | ||
| 242 | (setq current-frame (cdr current-frame)) | ||
| 243 | |||
| 244 | ) ; end-if match-p | ||
| 245 | ) ; end catch | ||
| 246 | ) ; end let | ||
| 247 | |||
| 248 | ;; after every cycle, evaluate every-tag | ||
| 249 | (eval every-tag) | ||
| 250 | ) ; end-while | ||
| 251 | |||
| 252 | ;; now process the end entry | ||
| 253 | (eval end-tag))))) | ||
| 254 | |||
| 255 | |||
| 256 | (provide 'regi) | ||
| 257 | |||
| 258 | ;;; regi.el ends here | ||
diff --git a/lisp/emacs-lisp/timer.el b/lisp/emacs-lisp/timer.el new file mode 100644 index 00000000000..b7db0d01dc1 --- /dev/null +++ b/lisp/emacs-lisp/timer.el | |||
| @@ -0,0 +1,479 @@ | |||
| 1 | ;;; timer.el --- run a function with args at some time in future | ||
| 2 | |||
| 3 | ;; Copyright (C) 1996 Free Software Foundation, Inc. | ||
| 4 | |||
| 5 | ;; Maintainer: FSF | ||
| 6 | |||
| 7 | ;; This file is part of GNU Emacs. | ||
| 8 | |||
| 9 | ;; GNU Emacs is free software; you can redistribute it and/or modify | ||
| 10 | ;; it under the terms of the GNU General Public License as published by | ||
| 11 | ;; the Free Software Foundation; either version 2, or (at your option) | ||
| 12 | ;; any later version. | ||
| 13 | |||
| 14 | ;; GNU Emacs is distributed in the hope that it will be useful, | ||
| 15 | ;; but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 16 | ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 17 | ;; GNU General Public License for more details. | ||
| 18 | |||
| 19 | ;; You should have received a copy of the GNU General Public License | ||
| 20 | ;; along with GNU Emacs; see the file COPYING. If not, write to the | ||
| 21 | ;; Free Software Foundation, Inc., 59 Temple Place - Suite 330, | ||
| 22 | ;; Boston, MA 02111-1307, USA. | ||
| 23 | |||
| 24 | ;;; Commentary: | ||
| 25 | |||
| 26 | ;; This package gives you the capability to run Emacs Lisp commands at | ||
| 27 | ;; specified times in the future, either as one-shots or periodically. | ||
| 28 | |||
| 29 | ;;; Code: | ||
| 30 | |||
| 31 | ;; Layout of a timer vector: | ||
| 32 | ;; [triggered-p high-seconds low-seconds usecs repeat-delay | ||
| 33 | ;; function args idle-delay] | ||
| 34 | |||
| 35 | (defun timer-create () | ||
| 36 | "Create a timer object." | ||
| 37 | (let ((timer (make-vector 8 nil))) | ||
| 38 | (aset timer 0 t) | ||
| 39 | timer)) | ||
| 40 | |||
| 41 | (defun timerp (object) | ||
| 42 | "Return t if OBJECT is a timer." | ||
| 43 | (and (vectorp object) (= (length object) 8))) | ||
| 44 | |||
| 45 | (defun timer-set-time (timer time &optional delta) | ||
| 46 | "Set the trigger time of TIMER to TIME. | ||
| 47 | TIME must be in the internal format returned by, e.g., `current-time'. | ||
| 48 | If optional third argument DELTA is a positive number, make the timer | ||
| 49 | fire repeatedly that many seconds apart." | ||
| 50 | (or (timerp timer) | ||
| 51 | (error "Invalid timer")) | ||
| 52 | (aset timer 1 (car time)) | ||
| 53 | (aset timer 2 (if (consp (cdr time)) (car (cdr time)) (cdr time))) | ||
| 54 | (aset timer 3 (or (and (consp (cdr time)) (consp (cdr (cdr time))) | ||
| 55 | (nth 2 time)) | ||
| 56 | 0)) | ||
| 57 | (aset timer 4 (and (numberp delta) (> delta 0) delta)) | ||
| 58 | timer) | ||
| 59 | |||
| 60 | (defun timer-set-idle-time (timer secs &optional repeat) | ||
| 61 | "Set the trigger idle time of TIMER to SECS. | ||
| 62 | If optional third argument REPEAT is non-nil, make the timer | ||
| 63 | fire each time Emacs is idle for that many seconds." | ||
| 64 | (or (timerp timer) | ||
| 65 | (error "Invalid timer")) | ||
| 66 | (aset timer 1 0) | ||
| 67 | (aset timer 2 0) | ||
| 68 | (aset timer 3 0) | ||
| 69 | (timer-inc-time timer secs) | ||
| 70 | (aset timer 4 repeat) | ||
| 71 | timer) | ||
| 72 | |||
| 73 | (defun timer-next-integral-multiple-of-time (time secs) | ||
| 74 | "Yield the next value after TIME that is an integral multiple of SECS. | ||
| 75 | More precisely, the next value, after TIME, that is an integral multiple | ||
| 76 | of SECS seconds since the epoch. SECS may be a fraction." | ||
| 77 | (let ((time-base (ash 1 16))) | ||
| 78 | (if (fboundp 'atan) | ||
| 79 | ;; Use floating point, taking care to not lose precision. | ||
| 80 | (let* ((float-time-base (float time-base)) | ||
| 81 | (million 1000000.0) | ||
| 82 | (time-usec (+ (* million | ||
| 83 | (+ (* float-time-base (nth 0 time)) | ||
| 84 | (nth 1 time))) | ||
| 85 | (nth 2 time))) | ||
| 86 | (secs-usec (* million secs)) | ||
| 87 | (mod-usec (mod time-usec secs-usec)) | ||
| 88 | (next-usec (+ (- time-usec mod-usec) secs-usec)) | ||
| 89 | (time-base-million (* float-time-base million))) | ||
| 90 | (list (floor next-usec time-base-million) | ||
| 91 | (floor (mod next-usec time-base-million) million) | ||
| 92 | (floor (mod next-usec million)))) | ||
| 93 | ;; Floating point is not supported. | ||
| 94 | ;; Use integer arithmetic, avoiding overflow if possible. | ||
| 95 | (let* ((mod-sec (mod (+ (* (mod time-base secs) | ||
| 96 | (mod (nth 0 time) secs)) | ||
| 97 | (nth 1 time)) | ||
| 98 | secs)) | ||
| 99 | (next-1-sec (+ (- (nth 1 time) mod-sec) secs))) | ||
| 100 | (list (+ (nth 0 time) (floor next-1-sec time-base)) | ||
| 101 | (mod next-1-sec time-base) | ||
| 102 | 0))))) | ||
| 103 | |||
| 104 | (defun timer-relative-time (time secs &optional usecs) | ||
| 105 | "Advance TIME by SECS seconds and optionally USECS microseconds. | ||
| 106 | SECS may be a fraction." | ||
| 107 | (let ((high (car time)) | ||
| 108 | (low (if (consp (cdr time)) (nth 1 time) (cdr time))) | ||
| 109 | (micro (if (numberp (car-safe (cdr-safe (cdr time)))) | ||
| 110 | (nth 2 time) | ||
| 111 | 0))) | ||
| 112 | ;; Add | ||
| 113 | (if usecs (setq micro (+ micro usecs))) | ||
| 114 | (if (floatp secs) | ||
| 115 | (setq micro (+ micro (floor (* 1000000 (- secs (floor secs))))))) | ||
| 116 | (setq low (+ low (floor secs))) | ||
| 117 | |||
| 118 | ;; Normalize | ||
| 119 | ;; `/' rounds towards zero while `mod' returns a positive number, | ||
| 120 | ;; so we can't rely on (= a (+ (* 100 (/ a 100)) (mod a 100))). | ||
| 121 | (setq low (+ low (/ micro 1000000) (if (< micro 0) -1 0))) | ||
| 122 | (setq micro (mod micro 1000000)) | ||
| 123 | (setq high (+ high (/ low 65536) (if (< low 0) -1 0))) | ||
| 124 | (setq low (logand low 65535)) | ||
| 125 | |||
| 126 | (list high low (and (/= micro 0) micro)))) | ||
| 127 | |||
| 128 | (defun timer-inc-time (timer secs &optional usecs) | ||
| 129 | "Increment the time set in TIMER by SECS seconds and USECS microseconds. | ||
| 130 | SECS may be a fraction. If USECS is omitted, that means it is zero." | ||
| 131 | (let ((time (timer-relative-time | ||
| 132 | (list (aref timer 1) (aref timer 2) (aref timer 3)) | ||
| 133 | secs | ||
| 134 | usecs))) | ||
| 135 | (aset timer 1 (nth 0 time)) | ||
| 136 | (aset timer 2 (nth 1 time)) | ||
| 137 | (aset timer 3 (or (nth 2 time) 0)))) | ||
| 138 | |||
| 139 | (defun timer-set-time-with-usecs (timer time usecs &optional delta) | ||
| 140 | "Set the trigger time of TIMER to TIME plus USECS. | ||
| 141 | TIME must be in the internal format returned by, e.g., `current-time'. | ||
| 142 | The microsecond count from TIME is ignored, and USECS is used instead. | ||
| 143 | If optional fourth argument DELTA is a positive number, make the timer | ||
| 144 | fire repeatedly that many seconds apart." | ||
| 145 | (or (timerp timer) | ||
| 146 | (error "Invalid timer")) | ||
| 147 | (aset timer 1 (nth 0 time)) | ||
| 148 | (aset timer 2 (nth 1 time)) | ||
| 149 | (aset timer 3 usecs) | ||
| 150 | (aset timer 4 (and (numberp delta) (> delta 0) delta)) | ||
| 151 | timer) | ||
| 152 | (make-obsolete 'timer-set-time-with-usecs | ||
| 153 | "use `timer-set-time' and `timer-inc-time' instead." | ||
| 154 | "21.4") | ||
| 155 | |||
| 156 | (defun timer-set-function (timer function &optional args) | ||
| 157 | "Make TIMER call FUNCTION with optional ARGS when triggering." | ||
| 158 | (or (timerp timer) | ||
| 159 | (error "Invalid timer")) | ||
| 160 | (aset timer 5 function) | ||
| 161 | (aset timer 6 args) | ||
| 162 | timer) | ||
| 163 | |||
| 164 | (defun timer-activate (timer) | ||
| 165 | "Put TIMER on the list of active timers." | ||
| 166 | (if (and (timerp timer) | ||
| 167 | (integerp (aref timer 1)) | ||
| 168 | (integerp (aref timer 2)) | ||
| 169 | (integerp (aref timer 3)) | ||
| 170 | (aref timer 5)) | ||
| 171 | (let ((timers timer-list) | ||
| 172 | last) | ||
| 173 | ;; Skip all timers to trigger before the new one. | ||
| 174 | (while (and timers | ||
| 175 | (or (> (aref timer 1) (aref (car timers) 1)) | ||
| 176 | (and (= (aref timer 1) (aref (car timers) 1)) | ||
| 177 | (> (aref timer 2) (aref (car timers) 2))) | ||
| 178 | (and (= (aref timer 1) (aref (car timers) 1)) | ||
| 179 | (= (aref timer 2) (aref (car timers) 2)) | ||
| 180 | (> (aref timer 3) (aref (car timers) 3))))) | ||
| 181 | (setq last timers | ||
| 182 | timers (cdr timers))) | ||
| 183 | ;; Insert new timer after last which possibly means in front of queue. | ||
| 184 | (if last | ||
| 185 | (setcdr last (cons timer timers)) | ||
| 186 | (setq timer-list (cons timer timers))) | ||
| 187 | (aset timer 0 nil) | ||
| 188 | (aset timer 7 nil) | ||
| 189 | nil) | ||
| 190 | (error "Invalid or uninitialized timer"))) | ||
| 191 | |||
| 192 | (defun timer-activate-when-idle (timer &optional dont-wait) | ||
| 193 | "Arrange to activate TIMER whenever Emacs is next idle. | ||
| 194 | If optional argument DONT-WAIT is non-nil, then enable the | ||
| 195 | timer to activate immediately, or at the right time, if Emacs | ||
| 196 | is already idle." | ||
| 197 | (if (and (timerp timer) | ||
| 198 | (integerp (aref timer 1)) | ||
| 199 | (integerp (aref timer 2)) | ||
| 200 | (integerp (aref timer 3)) | ||
| 201 | (aref timer 5)) | ||
| 202 | (let ((timers timer-idle-list) | ||
| 203 | last) | ||
| 204 | ;; Skip all timers to trigger before the new one. | ||
| 205 | (while (and timers | ||
| 206 | (or (> (aref timer 1) (aref (car timers) 1)) | ||
| 207 | (and (= (aref timer 1) (aref (car timers) 1)) | ||
| 208 | (> (aref timer 2) (aref (car timers) 2))) | ||
| 209 | (and (= (aref timer 1) (aref (car timers) 1)) | ||
| 210 | (= (aref timer 2) (aref (car timers) 2)) | ||
| 211 | (> (aref timer 3) (aref (car timers) 3))))) | ||
| 212 | (setq last timers | ||
| 213 | timers (cdr timers))) | ||
| 214 | ;; Insert new timer after last which possibly means in front of queue. | ||
| 215 | (if last | ||
| 216 | (setcdr last (cons timer timers)) | ||
| 217 | (setq timer-idle-list (cons timer timers))) | ||
| 218 | (aset timer 0 (not dont-wait)) | ||
| 219 | (aset timer 7 t) | ||
| 220 | nil) | ||
| 221 | (error "Invalid or uninitialized timer"))) | ||
| 222 | |||
| 223 | ;;;###autoload | ||
| 224 | (defalias 'disable-timeout 'cancel-timer) | ||
| 225 | ;;;###autoload | ||
| 226 | (defun cancel-timer (timer) | ||
| 227 | "Remove TIMER from the list of active timers." | ||
| 228 | (or (timerp timer) | ||
| 229 | (error "Invalid timer")) | ||
| 230 | (setq timer-list (delq timer timer-list)) | ||
| 231 | (setq timer-idle-list (delq timer timer-idle-list)) | ||
| 232 | nil) | ||
| 233 | |||
| 234 | ;;;###autoload | ||
| 235 | (defun cancel-function-timers (function) | ||
| 236 | "Cancel all timers scheduled by `run-at-time' which would run FUNCTION." | ||
| 237 | (interactive "aCancel timers of function: ") | ||
| 238 | (let ((tail timer-list)) | ||
| 239 | (while tail | ||
| 240 | (if (eq (aref (car tail) 5) function) | ||
| 241 | (setq timer-list (delq (car tail) timer-list))) | ||
| 242 | (setq tail (cdr tail)))) | ||
| 243 | (let ((tail timer-idle-list)) | ||
| 244 | (while tail | ||
| 245 | (if (eq (aref (car tail) 5) function) | ||
| 246 | (setq timer-idle-list (delq (car tail) timer-idle-list))) | ||
| 247 | (setq tail (cdr tail))))) | ||
| 248 | |||
| 249 | ;; Record the last few events, for debugging. | ||
| 250 | (defvar timer-event-last-2 nil) | ||
| 251 | (defvar timer-event-last-1 nil) | ||
| 252 | (defvar timer-event-last nil) | ||
| 253 | |||
| 254 | (defvar timer-max-repeats 10 | ||
| 255 | "*Maximum number of times to repeat a timer, if real time jumps.") | ||
| 256 | |||
| 257 | (defun timer-until (timer time) | ||
| 258 | "Calculate number of seconds from when TIMER will run, until TIME. | ||
| 259 | TIMER is a timer, and stands for the time when its next repeat is scheduled. | ||
| 260 | TIME is a time-list." | ||
| 261 | (let ((high (- (car time) (aref timer 1))) | ||
| 262 | (low (- (nth 1 time) (aref timer 2)))) | ||
| 263 | (+ low (* high 65536)))) | ||
| 264 | |||
| 265 | (defun timer-event-handler (timer) | ||
| 266 | "Call the handler for the timer TIMER. | ||
| 267 | This function is called, by name, directly by the C code." | ||
| 268 | (setq timer-event-last-2 timer-event-last-1) | ||
| 269 | (setq timer-event-last-1 timer-event-last) | ||
| 270 | (setq timer-event-last timer) | ||
| 271 | (let ((inhibit-quit t)) | ||
| 272 | (if (timerp timer) | ||
| 273 | (progn | ||
| 274 | ;; Delete from queue. | ||
| 275 | (cancel-timer timer) | ||
| 276 | ;; Re-schedule if requested. | ||
| 277 | (if (aref timer 4) | ||
| 278 | (if (aref timer 7) | ||
| 279 | (timer-activate-when-idle timer) | ||
| 280 | (timer-inc-time timer (aref timer 4) 0) | ||
| 281 | ;; If real time has jumped forward, | ||
| 282 | ;; perhaps because Emacs was suspended for a long time, | ||
| 283 | ;; limit how many times things get repeated. | ||
| 284 | (if (and (numberp timer-max-repeats) | ||
| 285 | (< 0 (timer-until timer (current-time)))) | ||
| 286 | (let ((repeats (/ (timer-until timer (current-time)) | ||
| 287 | (aref timer 4)))) | ||
| 288 | (if (> repeats timer-max-repeats) | ||
| 289 | (timer-inc-time timer (* (aref timer 4) repeats))))) | ||
| 290 | (timer-activate timer))) | ||
| 291 | ;; Run handler. | ||
| 292 | ;; We do this after rescheduling so that the handler function | ||
| 293 | ;; can cancel its own timer successfully with cancel-timer. | ||
| 294 | (condition-case nil | ||
| 295 | (apply (aref timer 5) (aref timer 6)) | ||
| 296 | (error nil))) | ||
| 297 | (error "Bogus timer event")))) | ||
| 298 | |||
| 299 | ;; This function is incompatible with the one in levents.el. | ||
| 300 | (defun timeout-event-p (event) | ||
| 301 | "Non-nil if EVENT is a timeout event." | ||
| 302 | (and (listp event) (eq (car event) 'timer-event))) | ||
| 303 | |||
| 304 | ;;;###autoload | ||
| 305 | (defun run-at-time (time repeat function &rest args) | ||
| 306 | "Perform an action at time TIME. | ||
| 307 | Repeat the action every REPEAT seconds, if REPEAT is non-nil. | ||
| 308 | TIME should be a string like \"11:23pm\", nil meaning now, a number of seconds | ||
| 309 | from now, a value from `current-time', or t (with non-nil REPEAT) | ||
| 310 | meaning the next integral multiple of REPEAT. | ||
| 311 | REPEAT may be an integer or floating point number. | ||
| 312 | The action is to call FUNCTION with arguments ARGS. | ||
| 313 | |||
| 314 | This function returns a timer object which you can use in `cancel-timer'." | ||
| 315 | (interactive "sRun at time: \nNRepeat interval: \naFunction: ") | ||
| 316 | |||
| 317 | (or (null repeat) | ||
| 318 | (and (numberp repeat) (< 0 repeat)) | ||
| 319 | (error "Invalid repetition interval")) | ||
| 320 | |||
| 321 | ;; Special case: nil means "now" and is useful when repeating. | ||
| 322 | (if (null time) | ||
| 323 | (setq time (current-time))) | ||
| 324 | |||
| 325 | ;; Special case: t means the next integral multiple of REPEAT. | ||
| 326 | (if (and (eq time t) repeat) | ||
| 327 | (setq time (timer-next-integral-multiple-of-time (current-time) repeat))) | ||
| 328 | |||
| 329 | ;; Handle numbers as relative times in seconds. | ||
| 330 | (if (numberp time) | ||
| 331 | (setq time (timer-relative-time (current-time) time))) | ||
| 332 | |||
| 333 | ;; Handle relative times like "2 hours and 35 minutes" | ||
| 334 | (if (stringp time) | ||
| 335 | (let ((secs (timer-duration time))) | ||
| 336 | (if secs | ||
| 337 | (setq time (timer-relative-time (current-time) secs))))) | ||
| 338 | |||
| 339 | ;; Handle "11:23pm" and the like. Interpret it as meaning today | ||
| 340 | ;; which admittedly is rather stupid if we have passed that time | ||
| 341 | ;; already. (Though only Emacs hackers hack Emacs at that time.) | ||
| 342 | (if (stringp time) | ||
| 343 | (progn | ||
| 344 | (require 'diary-lib) | ||
| 345 | (let ((hhmm (diary-entry-time time)) | ||
| 346 | (now (decode-time))) | ||
| 347 | (if (>= hhmm 0) | ||
| 348 | (setq time | ||
| 349 | (encode-time 0 (% hhmm 100) (/ hhmm 100) (nth 3 now) | ||
| 350 | (nth 4 now) (nth 5 now) (nth 8 now))))))) | ||
| 351 | |||
| 352 | (or (consp time) | ||
| 353 | (error "Invalid time format")) | ||
| 354 | |||
| 355 | (let ((timer (timer-create))) | ||
| 356 | (timer-set-time timer time repeat) | ||
| 357 | (timer-set-function timer function args) | ||
| 358 | (timer-activate timer) | ||
| 359 | timer)) | ||
| 360 | |||
| 361 | ;;;###autoload | ||
| 362 | (defun run-with-timer (secs repeat function &rest args) | ||
| 363 | "Perform an action after a delay of SECS seconds. | ||
| 364 | Repeat the action every REPEAT seconds, if REPEAT is non-nil. | ||
| 365 | SECS and REPEAT may be integers or floating point numbers. | ||
| 366 | The action is to call FUNCTION with arguments ARGS. | ||
| 367 | |||
| 368 | This function returns a timer object which you can use in `cancel-timer'." | ||
| 369 | (interactive "sRun after delay (seconds): \nNRepeat interval: \naFunction: ") | ||
| 370 | (apply 'run-at-time secs repeat function args)) | ||
| 371 | |||
| 372 | ;;;###autoload | ||
| 373 | (defun add-timeout (secs function object &optional repeat) | ||
| 374 | "Add a timer to run SECS seconds from now, to call FUNCTION on OBJECT. | ||
| 375 | If REPEAT is non-nil, repeat the timer every REPEAT seconds. | ||
| 376 | This function is for compatibility; see also `run-with-timer'." | ||
| 377 | (run-with-timer secs repeat function object)) | ||
| 378 | |||
| 379 | ;;;###autoload | ||
| 380 | (defun run-with-idle-timer (secs repeat function &rest args) | ||
| 381 | "Perform an action the next time Emacs is idle for SECS seconds. | ||
| 382 | The action is to call FUNCTION with arguments ARGS. | ||
| 383 | SECS may be an integer or a floating point number. | ||
| 384 | |||
| 385 | If REPEAT is non-nil, do the action each time Emacs has been idle for | ||
| 386 | exactly SECS seconds (that is, only once for each time Emacs becomes idle). | ||
| 387 | |||
| 388 | This function returns a timer object which you can use in `cancel-timer'." | ||
| 389 | (interactive | ||
| 390 | (list (read-from-minibuffer "Run after idle (seconds): " nil nil t) | ||
| 391 | (y-or-n-p "Repeat each time Emacs is idle? ") | ||
| 392 | (intern (completing-read "Function: " obarray 'fboundp t)))) | ||
| 393 | (let ((timer (timer-create))) | ||
| 394 | (timer-set-function timer function args) | ||
| 395 | (timer-set-idle-time timer secs repeat) | ||
| 396 | (timer-activate-when-idle timer) | ||
| 397 | timer)) | ||
| 398 | |||
| 399 | (defun with-timeout-handler (tag) | ||
| 400 | (throw tag 'timeout)) | ||
| 401 | |||
| 402 | ;;;###autoload (put 'with-timeout 'lisp-indent-function 1) | ||
| 403 | |||
| 404 | ;;;###autoload | ||
| 405 | (defmacro with-timeout (list &rest body) | ||
| 406 | "Run BODY, but if it doesn't finish in SECONDS seconds, give up. | ||
| 407 | If we give up, we run the TIMEOUT-FORMS and return the value of the last one. | ||
| 408 | The call should look like: | ||
| 409 | (with-timeout (SECONDS TIMEOUT-FORMS...) BODY...) | ||
| 410 | The timeout is checked whenever Emacs waits for some kind of external | ||
| 411 | event \(such as keyboard input, input from subprocesses, or a certain time); | ||
| 412 | if the program loops without waiting in any way, the timeout will not | ||
| 413 | be detected." | ||
| 414 | (let ((seconds (car list)) | ||
| 415 | (timeout-forms (cdr list))) | ||
| 416 | `(let ((with-timeout-tag (cons nil nil)) | ||
| 417 | with-timeout-value with-timeout-timer) | ||
| 418 | (if (catch with-timeout-tag | ||
| 419 | (progn | ||
| 420 | (setq with-timeout-timer | ||
| 421 | (run-with-timer ,seconds nil | ||
| 422 | 'with-timeout-handler | ||
| 423 | with-timeout-tag)) | ||
| 424 | (setq with-timeout-value (progn . ,body)) | ||
| 425 | nil)) | ||
| 426 | (progn . ,timeout-forms) | ||
| 427 | (cancel-timer with-timeout-timer) | ||
| 428 | with-timeout-value)))) | ||
| 429 | |||
| 430 | (defun y-or-n-p-with-timeout (prompt seconds default-value) | ||
| 431 | "Like (y-or-n-p PROMPT), with a timeout. | ||
| 432 | If the user does not answer after SECONDS seconds, return DEFAULT-VALUE." | ||
| 433 | (with-timeout (seconds default-value) | ||
| 434 | (y-or-n-p prompt))) | ||
| 435 | |||
| 436 | (defvar timer-duration-words | ||
| 437 | (list (cons "microsec" 0.000001) | ||
| 438 | (cons "microsecond" 0.000001) | ||
| 439 | (cons "millisec" 0.001) | ||
| 440 | (cons "millisecond" 0.001) | ||
| 441 | (cons "sec" 1) | ||
| 442 | (cons "second" 1) | ||
| 443 | (cons "min" 60) | ||
| 444 | (cons "minute" 60) | ||
| 445 | (cons "hour" (* 60 60)) | ||
| 446 | (cons "day" (* 24 60 60)) | ||
| 447 | (cons "week" (* 7 24 60 60)) | ||
| 448 | (cons "fortnight" (* 14 24 60 60)) | ||
| 449 | (cons "month" (* 30 24 60 60)) ; Approximation | ||
| 450 | (cons "year" (* 365.25 24 60 60)) ; Approximation | ||
| 451 | ) | ||
| 452 | "Alist mapping temporal words to durations in seconds") | ||
| 453 | |||
| 454 | (defun timer-duration (string) | ||
| 455 | "Return number of seconds specified by STRING, or nil if parsing fails." | ||
| 456 | (let ((secs 0) | ||
| 457 | (start 0) | ||
| 458 | (case-fold-search t)) | ||
| 459 | (while (string-match | ||
| 460 | "[ \t]*\\([0-9.]+\\)?[ \t]*\\([a-z]+[a-rt-z]\\)s?[ \t]*" | ||
| 461 | string start) | ||
| 462 | (let ((count (if (match-beginning 1) | ||
| 463 | (string-to-number (match-string 1 string)) | ||
| 464 | 1)) | ||
| 465 | (itemsize (cdr (assoc (match-string 2 string) | ||
| 466 | timer-duration-words)))) | ||
| 467 | (if itemsize | ||
| 468 | (setq start (match-end 0) | ||
| 469 | secs (+ secs (* count itemsize))) | ||
| 470 | (setq secs nil | ||
| 471 | start (length string))))) | ||
| 472 | (if (= start (length string)) | ||
| 473 | secs | ||
| 474 | (if (string-match "\\`[0-9.]+\\'" string) | ||
| 475 | (string-to-number string))))) | ||
| 476 | |||
| 477 | (provide 'timer) | ||
| 478 | |||
| 479 | ;;; timer.el ends here | ||
diff --git a/lisp/emacs-lisp/warnings.el b/lisp/emacs-lisp/warnings.el new file mode 100644 index 00000000000..4d0354236a8 --- /dev/null +++ b/lisp/emacs-lisp/warnings.el | |||
| @@ -0,0 +1,311 @@ | |||
| 1 | ;;; warnings.el --- log and display warnings | ||
| 2 | |||
| 3 | ;; Copyright (C) 2002 Free Software Foundation, Inc. | ||
| 4 | |||
| 5 | ;; Maintainer: FSF | ||
| 6 | ;; Keywords: internal | ||
| 7 | |||
| 8 | ;; This file is part of GNU Emacs. | ||
| 9 | |||
| 10 | ;; GNU Emacs is free software; you can redistribute it and/or modify | ||
| 11 | ;; it under the terms of the GNU General Public License as published by | ||
| 12 | ;; the Free Software Foundation; either version 2, or (at your option) | ||
| 13 | ;; any later version. | ||
| 14 | |||
| 15 | ;; GNU Emacs is distributed in the hope that it will be useful, | ||
| 16 | ;; but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 17 | ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 18 | ;; GNU General Public License for more details. | ||
| 19 | |||
| 20 | ;; You should have received a copy of the GNU General Public License | ||
| 21 | ;; along with GNU Emacs; see the file COPYING. If not, write to the | ||
| 22 | ;; Free Software Foundation, Inc., 59 Temple Place - Suite 330, | ||
| 23 | ;; Boston, MA 02111-1307, USA. | ||
| 24 | |||
| 25 | ;;; Commentary: | ||
| 26 | |||
| 27 | ;; This file implements the entry points `warn', `lwarn' | ||
| 28 | ;; and `display-warnings'. | ||
| 29 | |||
| 30 | ;;; Code: | ||
| 31 | |||
| 32 | (defgroup warnings nil | ||
| 33 | "Log and display warnings." | ||
| 34 | :version "21.4" | ||
| 35 | :group 'lisp) | ||
| 36 | |||
| 37 | (defvar warning-levels | ||
| 38 | '((:emergency "Emergency%s: " ding) | ||
| 39 | (:error "Error%s: ") | ||
| 40 | (:warning "Warning%s: ") | ||
| 41 | (:debug "Debug%s: ")) | ||
| 42 | "List of severity level definitions for `display-warning'. | ||
| 43 | Each element looks like (LEVEL STRING FUNCTION) and | ||
| 44 | defines LEVEL as a severity level. STRING specifies the | ||
| 45 | description of this level. STRING should use `%s' to | ||
| 46 | specify where to put the warning group information, | ||
| 47 | or it can omit the `%s' so as not to include that information. | ||
| 48 | |||
| 49 | The optional FUNCTION, if non-nil, is a function to call | ||
| 50 | with no arguments, to get the user's attention. | ||
| 51 | |||
| 52 | The standard levels are :emergency, :error, :warning and :debug. | ||
| 53 | See `display-warning' for documentation of their meanings. | ||
| 54 | Level :debug is ignored by default (see `warning-minimum-level').") | ||
| 55 | (put 'warning-levels 'risky-local-variable t) | ||
| 56 | |||
| 57 | ;; These are for compatibility with XEmacs. | ||
| 58 | ;; I don't think there is any chance of designing meaningful criteria | ||
| 59 | ;; to distinguish so many levels. | ||
| 60 | (defvar warning-level-aliases | ||
| 61 | '((emergency . :emergency) | ||
| 62 | (error . :error) | ||
| 63 | (warning . :warning) | ||
| 64 | (notice . :warning) | ||
| 65 | (info . :warning) | ||
| 66 | (critical . :emergency) | ||
| 67 | (alarm . :emergency)) | ||
| 68 | "Alist of aliases for severity levels for `display-warning'. | ||
| 69 | Each element looks like (ALIAS . LEVEL) and defines | ||
| 70 | ALIAS as equivalent to LEVEL. LEVEL must be defined in `warning-levels'; | ||
| 71 | it may not itself be an alias.") | ||
| 72 | |||
| 73 | (defcustom warning-minimum-level :warning | ||
| 74 | "Minimum severity level for displaying the warning buffer. | ||
| 75 | If a warning's severity level is lower than this, | ||
| 76 | the warning is logged in the warnings buffer, but the buffer | ||
| 77 | is not immediately displayed. See also `warning-minimum-log-level'." | ||
| 78 | :group 'warnings | ||
| 79 | :type '(choice (const :emergency) (const :error) (const :warning)) | ||
| 80 | :version "21.4") | ||
| 81 | (defvaralias 'display-warning-minimum-level 'warning-minimum-level) | ||
| 82 | |||
| 83 | (defcustom warning-minimum-log-level :warning | ||
| 84 | "Minimum severity level for logging a warning. | ||
| 85 | If a warning severity level is lower than this, | ||
| 86 | the warning is completely ignored." | ||
| 87 | :group 'warnings | ||
| 88 | :type '(choice (const :emergency) (const :error) (const :warning)) | ||
| 89 | :version "21.4") | ||
| 90 | (defvaralias 'log-warning-minimum-level 'warning-minimum-log-level) | ||
| 91 | |||
| 92 | (defcustom warning-suppress-log-types nil | ||
| 93 | "List of warning types that should not be logged. | ||
| 94 | If any element of this list matches the GROUP argument to `display-warning', | ||
| 95 | the warning is completely ignored. | ||
| 96 | The element must match the first elements of GROUP. | ||
| 97 | Thus, (foo bar) as an element matches (foo bar) | ||
| 98 | or (foo bar ANYTHING...) as GROUP. | ||
| 99 | If GROUP is a symbol FOO, that is equivalent to the list (FOO), | ||
| 100 | so only the element (FOO) will match it." | ||
| 101 | :group 'warnings | ||
| 102 | :type '(repeat (repeat symbol)) | ||
| 103 | :version "21.4") | ||
| 104 | |||
| 105 | (defcustom warning-suppress-types nil | ||
| 106 | "Custom groups for warnings not to display immediately. | ||
| 107 | If any element of this list matches the GROUP argument to `display-warning', | ||
| 108 | the warning is logged nonetheless, but the warnings buffer is | ||
| 109 | not immediately displayed. | ||
| 110 | The element must match an initial segment of the list GROUP. | ||
| 111 | Thus, (foo bar) as an element matches (foo bar) | ||
| 112 | or (foo bar ANYTHING...) as GROUP. | ||
| 113 | If GROUP is a symbol FOO, that is equivalent to the list (FOO), | ||
| 114 | so only the element (FOO) will match it. | ||
| 115 | See also `warning-suppress-log-types'." | ||
| 116 | :group 'warnings | ||
| 117 | :type '(repeat (repeat symbol)) | ||
| 118 | :version "21.4") | ||
| 119 | |||
| 120 | ;;; The autoload cookie is so that programs can bind this variable | ||
| 121 | ;;; safely, testing the existing value, before they call one of the | ||
| 122 | ;;; warnings functions. | ||
| 123 | ;;;###autoload | ||
| 124 | (defvar warning-prefix-function nil | ||
| 125 | "Function to generate warning prefixes. | ||
| 126 | This function, if non-nil, is called with two arguments, | ||
| 127 | the severity level and its entry in `warning-levels', | ||
| 128 | and should return the entry that should actually be used. | ||
| 129 | The warnings buffer is current when this function is called | ||
| 130 | and the function can insert text in it. This text becomes | ||
| 131 | the beginning of the warning.") | ||
| 132 | |||
| 133 | ;;; The autoload cookie is so that programs can bind this variable | ||
| 134 | ;;; safely, testing the existing value, before they call one of the | ||
| 135 | ;;; warnings functions. | ||
| 136 | ;;;###autoload | ||
| 137 | (defvar warning-series nil | ||
| 138 | "Non-nil means treat multiple `display-warning' calls as a series. | ||
| 139 | A marker indicates a position in the warnings buffer | ||
| 140 | which is the start of the current series; it means that | ||
| 141 | additional warnings in the same buffer should not move point. | ||
| 142 | t means the next warning begins a series (and stores a marker here). | ||
| 143 | A symbol with a function definition is like t, except | ||
| 144 | also call that function before the next warning.") | ||
| 145 | (put 'warning-series 'risky-local-variable t) | ||
| 146 | |||
| 147 | ;;; The autoload cookie is so that programs can bind this variable | ||
| 148 | ;;; safely, testing the existing value, before they call one of the | ||
| 149 | ;;; warnings functions. | ||
| 150 | ;;;###autoload | ||
| 151 | (defvar warning-fill-prefix nil | ||
| 152 | "Non-nil means fill each warning text using this string as `fill-prefix'.") | ||
| 153 | |||
| 154 | ;;; The autoload cookie is so that programs can bind this variable | ||
| 155 | ;;; safely, testing the existing value, before they call one of the | ||
| 156 | ;;; warnings functions. | ||
| 157 | ;;;###autoload | ||
| 158 | (defvar warning-group-format " (%s)" | ||
| 159 | "Format for displaying the warning group in the warning message. | ||
| 160 | The result of formatting the group this way gets included in the | ||
| 161 | message under the control of the string in `warning-levels'.") | ||
| 162 | |||
| 163 | (defun warning-numeric-level (level) | ||
| 164 | "Return a numeric measure of the warning severity level LEVEL." | ||
| 165 | (let* ((elt (assq level warning-levels)) | ||
| 166 | (link (memq elt warning-levels))) | ||
| 167 | (length link))) | ||
| 168 | |||
| 169 | (defun warning-suppress-p (group suppress-list) | ||
| 170 | "Non-nil if a warning with group GROUP should be suppressed. | ||
| 171 | SUPPRESS-LIST is the list of kinds of warnings to suppress." | ||
| 172 | (let (some-match) | ||
| 173 | (dolist (elt suppress-list) | ||
| 174 | (if (symbolp group) | ||
| 175 | ;; If GROUP is a symbol, the ELT must be (GROUP). | ||
| 176 | (if (and (consp elt) | ||
| 177 | (eq (car elt) group) | ||
| 178 | (null (cdr elt))) | ||
| 179 | (setq some-match t)) | ||
| 180 | ;; If GROUP is a list, ELT must match it or some initial segment of it. | ||
| 181 | (let ((tem1 group) | ||
| 182 | (tem2 elt) | ||
| 183 | (match t)) | ||
| 184 | ;; Check elements of ELT until we run out of them. | ||
| 185 | (while tem2 | ||
| 186 | (if (not (equal (car tem1) (car tem2))) | ||
| 187 | (setq match nil)) | ||
| 188 | (setq tem1 (cdr tem1) | ||
| 189 | tem2 (cdr tem2))) | ||
| 190 | ;; If ELT is an initial segment of GROUP, MATCH is t now. | ||
| 191 | ;; So set SOME-MATCH. | ||
| 192 | (if match | ||
| 193 | (setq some-match t))))) | ||
| 194 | ;; If some element of SUPPRESS-LIST matched, | ||
| 195 | ;; we return t. | ||
| 196 | some-match)) | ||
| 197 | |||
| 198 | ;;;###autoload | ||
| 199 | (defun display-warning (group message &optional level buffer-name) | ||
| 200 | "Display a warning message, MESSAGE. | ||
| 201 | GROUP should be a custom group name (a symbol), | ||
| 202 | or else a list of symbols whose first element is a custom group name. | ||
| 203 | \(The rest of the symbols represent subcategories, for warning purposes | ||
| 204 | only, and you can use whatever symbols you like.) | ||
| 205 | |||
| 206 | LEVEL should be either :warning, :error, or :emergency. | ||
| 207 | :emergency -- a problem that will seriously impair Emacs operation soon | ||
| 208 | if you do not attend to it promptly. | ||
| 209 | :error -- data or circumstances that are inherently wrong. | ||
| 210 | :warning -- data or circumstances that are not inherently wrong, | ||
| 211 | but raise suspicion of a possible problem. | ||
| 212 | :debug -- info for debugging only. | ||
| 213 | |||
| 214 | BUFFER-NAME, if specified, is the name of the buffer for logging the | ||
| 215 | warning. By default, it is `*Warnings*'. | ||
| 216 | |||
| 217 | See the `warnings' custom group for user customization features. | ||
| 218 | |||
| 219 | See also `warning-series', `warning-prefix-function' and | ||
| 220 | `warning-fill-prefix' for additional programming features." | ||
| 221 | (unless level | ||
| 222 | (setq level :warning)) | ||
| 223 | (if (assq level warning-level-aliases) | ||
| 224 | (setq level (cdr (assq level warning-level-aliases)))) | ||
| 225 | (or (< (warning-numeric-level level) | ||
| 226 | (warning-numeric-level warning-minimum-log-level)) | ||
| 227 | (warning-suppress-p group warning-suppress-log-types) | ||
| 228 | (let* ((groupname (if (consp group) (car group) group)) | ||
| 229 | (buffer (get-buffer-create (or buffer-name "*Warnings*"))) | ||
| 230 | (level-info (assq level warning-levels)) | ||
| 231 | start end) | ||
| 232 | (with-current-buffer buffer | ||
| 233 | (goto-char (point-max)) | ||
| 234 | (when (and warning-series (symbolp warning-series)) | ||
| 235 | (setq warning-series | ||
| 236 | (prog1 (point-marker) | ||
| 237 | (unless (eq warning-series t) | ||
| 238 | (funcall warning-series))))) | ||
| 239 | (unless (bolp) | ||
| 240 | (newline)) | ||
| 241 | (setq start (point)) | ||
| 242 | (if warning-prefix-function | ||
| 243 | (setq level-info (funcall warning-prefix-function | ||
| 244 | level level-info))) | ||
| 245 | (insert (format (nth 1 level-info) | ||
| 246 | (format warning-group-format groupname)) | ||
| 247 | message) | ||
| 248 | (newline) | ||
| 249 | (when (and warning-fill-prefix (not (string-match "\n" message))) | ||
| 250 | (let ((fill-prefix warning-fill-prefix) | ||
| 251 | (fill-column 78)) | ||
| 252 | (fill-region start (point)))) | ||
| 253 | (setq end (point)) | ||
| 254 | (when (and (markerp warning-series) | ||
| 255 | (eq (marker-buffer warning-series) buffer)) | ||
| 256 | (goto-char warning-series))) | ||
| 257 | (if (nth 2 level-info) | ||
| 258 | (funcall (nth 2 level-info))) | ||
| 259 | (if noninteractive | ||
| 260 | ;; Noninteractively, take the text we inserted | ||
| 261 | ;; in the warnings buffer and print it. | ||
| 262 | ;; Do this unconditionally, since there is no way | ||
| 263 | ;; to view logged messages unless we output them. | ||
| 264 | (with-current-buffer buffer | ||
| 265 | (save-excursion | ||
| 266 | ;; Don't include the final newline in the arg | ||
| 267 | ;; to `message', because it adds a newline. | ||
| 268 | (goto-char end) | ||
| 269 | (if (bolp) | ||
| 270 | (forward-char -1)) | ||
| 271 | (message "%s" (buffer-substring start (point))))) | ||
| 272 | ;; Interactively, decide whether the warning merits | ||
| 273 | ;; immediate display. | ||
| 274 | (or (< (warning-numeric-level level) | ||
| 275 | (warning-numeric-level warning-minimum-level)) | ||
| 276 | (warning-suppress-p group warning-suppress-types) | ||
| 277 | (let ((window (display-buffer buffer))) | ||
| 278 | (when (and (markerp warning-series) | ||
| 279 | (eq (marker-buffer warning-series) buffer)) | ||
| 280 | (set-window-start window warning-series)) | ||
| 281 | (sit-for 0))))))) | ||
| 282 | |||
| 283 | ;;;###autoload | ||
| 284 | (defun lwarn (group level message &rest args) | ||
| 285 | "Display a warning message made from (format MESSAGE ARGS...). | ||
| 286 | Aside from generating the message with `format', | ||
| 287 | this is equivalent to `display-warning'. | ||
| 288 | |||
| 289 | GROUP should be a custom group name (a symbol). | ||
| 290 | or else a list of symbols whose first element is a custom group name. | ||
| 291 | \(The rest of the symbols represent subcategories and | ||
| 292 | can be whatever you like.) | ||
| 293 | |||
| 294 | LEVEL should be either :warning, :error, or :emergency. | ||
| 295 | :emergency -- a problem that will seriously impair Emacs operation soon | ||
| 296 | if you do not attend to it promptly. | ||
| 297 | :error -- invalid data or circumstances. | ||
| 298 | :warning -- suspicious data or circumstances." | ||
| 299 | (display-warning group (apply 'format message args) level)) | ||
| 300 | |||
| 301 | ;;;###autoload | ||
| 302 | (defun warn (message &rest args) | ||
| 303 | "Display a warning message made from (format MESSAGE ARGS...). | ||
| 304 | Aside from generating the message with `format', | ||
| 305 | this is equivalent to `display-warning', using | ||
| 306 | `emacs' as the group and `:warning' as the level." | ||
| 307 | (display-warning 'emacs (apply 'format message args))) | ||
| 308 | |||
| 309 | (provide 'warnings) | ||
| 310 | |||
| 311 | ;;; warnings.el ends here | ||
diff --git a/lisp/progmodes/which-func.el b/lisp/progmodes/which-func.el new file mode 100644 index 00000000000..4b1dfca6f5b --- /dev/null +++ b/lisp/progmodes/which-func.el | |||
| @@ -0,0 +1,256 @@ | |||
| 1 | ;;; which-func.el --- print current function in mode line | ||
| 2 | |||
| 3 | ;; Copyright (C) 1994, 1997, 1998, 2001, 2003 Free Software Foundation, Inc. | ||
| 4 | |||
| 5 | ;; Author: Alex Rezinsky <alexr@msil.sps.mot.com> | ||
| 6 | ;; (doesn't seem to be responsive any more) | ||
| 7 | ;; Keywords: mode-line, imenu, tools | ||
| 8 | |||
| 9 | ;; This file is part of GNU Emacs. | ||
| 10 | |||
| 11 | ;; GNU Emacs is free software; you can redistribute it and/or modify | ||
| 12 | ;; it under the terms of the GNU General Public License as published by | ||
| 13 | ;; the Free Software Foundation; either version 2, or (at your option) | ||
| 14 | ;; any later version. | ||
| 15 | |||
| 16 | ;; GNU Emacs is distributed in the hope that it will be useful, | ||
| 17 | ;; but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 18 | ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 19 | ;; GNU General Public License for more details. | ||
| 20 | |||
| 21 | ;; You should have received a copy of the GNU General Public License | ||
| 22 | ;; along with GNU Emacs; see the file COPYING. If not, write to the | ||
| 23 | ;; Free Software Foundation, Inc., 59 Temple Place - Suite 330, | ||
| 24 | ;; Boston, MA 02111-1307, USA. | ||
| 25 | |||
| 26 | ;;; Commentary: | ||
| 27 | |||
| 28 | ;; This package prints name of function where your current point is | ||
| 29 | ;; located in mode line. It assumes that you work with imenu package | ||
| 30 | ;; and imenu--index-alist is up to date. | ||
| 31 | |||
| 32 | ;; KNOWN BUGS | ||
| 33 | ;; ---------- | ||
| 34 | ;; Really this package shows not "function where the current point is | ||
| 35 | ;; located now", but "nearest function which defined above the current | ||
| 36 | ;; point". So if your current point is located after end of function | ||
| 37 | ;; FOO but before begin of function BAR, FOO will be displayed in mode | ||
| 38 | ;; line. | ||
| 39 | ;; - if two windows display the same buffer, both windows | ||
| 40 | ;; show the same `which-func' information. | ||
| 41 | |||
| 42 | ;; TODO LIST | ||
| 43 | ;; --------- | ||
| 44 | ;; 1. Dependence on imenu package should be removed. Separate | ||
| 45 | ;; function determination mechanism should be used to determine the end | ||
| 46 | ;; of a function as well as the beginning of a function. | ||
| 47 | ;; 2. This package should be realized with the help of overlay | ||
| 48 | ;; properties instead of imenu--index-alist variable. | ||
| 49 | |||
| 50 | ;;; History: | ||
| 51 | |||
| 52 | ;; THANKS TO | ||
| 53 | ;; --------- | ||
| 54 | ;; Per Abrahamsen <abraham@iesd.auc.dk> | ||
| 55 | ;; Some ideas (inserting in mode-line, using of post-command hook | ||
| 56 | ;; and toggling this mode) have been borrowed from his package | ||
| 57 | ;; column.el | ||
| 58 | ;; Peter Eisenhauer <pipe@fzi.de> | ||
| 59 | ;; Bug fixing in case nested indexes. | ||
| 60 | ;; Terry Tateyama <ttt@ursa0.cs.utah.edu> | ||
| 61 | ;; Suggestion to use find-file-hook for first imenu | ||
| 62 | ;; index building. | ||
| 63 | |||
| 64 | ;;; Code: | ||
| 65 | |||
| 66 | ;; Variables for customization | ||
| 67 | ;; --------------------------- | ||
| 68 | ;; | ||
| 69 | (defvar which-func-unknown "???" | ||
| 70 | "String to display in the mode line when current function is unknown.") | ||
| 71 | |||
| 72 | (defgroup which-func nil | ||
| 73 | "Mode to display the current function name in the modeline." | ||
| 74 | :group 'tools | ||
| 75 | :version "20.3") | ||
| 76 | |||
| 77 | (defcustom which-func-modes | ||
| 78 | '(emacs-lisp-mode c-mode c++-mode perl-mode cperl-mode makefile-mode | ||
| 79 | sh-mode fortran-mode f90-mode) | ||
| 80 | "List of major modes for which Which Function mode should be used. | ||
| 81 | For other modes it is disabled. If this is equal to t, | ||
| 82 | then Which Function mode is enabled in any major mode that supports it." | ||
| 83 | :group 'which-func | ||
| 84 | :type '(choice (const :tag "All modes" t) | ||
| 85 | (repeat (symbol :tag "Major mode")))) | ||
| 86 | |||
| 87 | (defcustom which-func-non-auto-modes nil | ||
| 88 | "List of major modes where Which Function mode is inactive till Imenu is used. | ||
| 89 | This means that Which Function mode won't really do anything | ||
| 90 | until you use Imenu, in these modes. Note that files | ||
| 91 | larger than `which-func-maxout' behave in this way too; | ||
| 92 | Which Function mode doesn't do anything until you use Imenu." | ||
| 93 | :group 'which-func | ||
| 94 | :type '(repeat (symbol :tag "Major mode"))) | ||
| 95 | |||
| 96 | (defcustom which-func-maxout 500000 | ||
| 97 | "Don't automatically compute the Imenu menu if buffer is this big or bigger. | ||
| 98 | Zero means compute the Imenu menu regardless of size." | ||
| 99 | :group 'which-func | ||
| 100 | :type 'integer) | ||
| 101 | |||
| 102 | (defcustom which-func-format '("[" which-func-current "]") | ||
| 103 | "Format for displaying the function in the mode line." | ||
| 104 | :group 'which-func | ||
| 105 | :type 'sexp) | ||
| 106 | ;;;###autoload (put 'which-func-format 'risky-local-variable t) | ||
| 107 | |||
| 108 | (defvar which-func-cleanup-function nil | ||
| 109 | "Function to transform a string before displaying it in the mode line. | ||
| 110 | The function is called with one argument, the string to display. | ||
| 111 | Its return value is displayed in the modeline. | ||
| 112 | If nil, no function is called. The default value is nil. | ||
| 113 | |||
| 114 | This feature can be useful if Imenu is set up to make more | ||
| 115 | detailed entries (e.g., containing the argument list of a function), | ||
| 116 | and you want to simplify them for the mode line | ||
| 117 | \(e.g., removing the parameter list to just have the function name.)") | ||
| 118 | |||
| 119 | ;;; Code, nothing to customize below here | ||
| 120 | ;;; ------------------------------------- | ||
| 121 | ;;; | ||
| 122 | (require 'imenu) | ||
| 123 | |||
| 124 | (defvar which-func-table (make-hash-table :test 'eq :weakness 'key)) | ||
| 125 | |||
| 126 | (defconst which-func-current | ||
| 127 | '(:eval (gethash (selected-window) which-func-table which-func-unknown))) | ||
| 128 | ;;;###autoload (put 'which-func-current 'risky-local-variable t) | ||
| 129 | |||
| 130 | (defvar which-func-mode nil | ||
| 131 | "Non-nil means display current function name in mode line. | ||
| 132 | This makes a difference only if `which-function-mode' is non-nil.") | ||
| 133 | (make-variable-buffer-local 'which-func-mode) | ||
| 134 | ;;(put 'which-func-mode 'permanent-local t) | ||
| 135 | |||
| 136 | (add-hook 'find-file-hook 'which-func-ff-hook t) | ||
| 137 | |||
| 138 | (defun which-func-ff-hook () | ||
| 139 | "File find hook for Which Function mode. | ||
| 140 | It creates the Imenu index for the buffer, if necessary." | ||
| 141 | (setq which-func-mode | ||
| 142 | (and which-function-mode | ||
| 143 | (or (eq which-func-modes t) | ||
| 144 | (member major-mode which-func-modes)))) | ||
| 145 | |||
| 146 | (condition-case nil | ||
| 147 | (if (and which-func-mode | ||
| 148 | (not (member major-mode which-func-non-auto-modes)) | ||
| 149 | (or (null which-func-maxout) | ||
| 150 | (< buffer-saved-size which-func-maxout) | ||
| 151 | (= which-func-maxout 0))) | ||
| 152 | (setq imenu--index-alist | ||
| 153 | (save-excursion (funcall imenu-create-index-function)))) | ||
| 154 | (error | ||
| 155 | (setq which-func-mode nil)))) | ||
| 156 | |||
| 157 | (defun which-func-update () | ||
| 158 | ;; "Update the Which-Function mode display for all windows." | ||
| 159 | ;; (walk-windows 'which-func-update-1 nil 'visible)) | ||
| 160 | (which-func-update-1 (selected-window))) | ||
| 161 | |||
| 162 | (defun which-func-update-1 (window) | ||
| 163 | "Update the Which-Function mode display for window WINDOW." | ||
| 164 | (with-selected-window window | ||
| 165 | (when which-func-mode | ||
| 166 | (condition-case info | ||
| 167 | (let ((current (which-function))) | ||
| 168 | (unless (equal current (gethash window which-func-table)) | ||
| 169 | (puthash window current which-func-table) | ||
| 170 | (force-mode-line-update))) | ||
| 171 | (error | ||
| 172 | (which-func-mode -1) | ||
| 173 | (error "Error in which-func-update: %s" info)))))) | ||
| 174 | |||
| 175 | ;;;###autoload | ||
| 176 | (defalias 'which-func-mode 'which-function-mode) | ||
| 177 | |||
| 178 | (defvar which-func-update-timer nil) | ||
| 179 | |||
| 180 | ;; This is the name people would normally expect. | ||
| 181 | ;;;###autoload | ||
| 182 | (define-minor-mode which-function-mode | ||
| 183 | "Toggle Which Function mode, globally. | ||
| 184 | When Which Function mode is enabled, the current function name is | ||
| 185 | continuously displayed in the mode line, in certain major modes. | ||
| 186 | |||
| 187 | With prefix ARG, turn Which Function mode on iff arg is positive, | ||
| 188 | and off otherwise." | ||
| 189 | :global t :group 'which-func | ||
| 190 | (if which-function-mode | ||
| 191 | ;;Turn it on | ||
| 192 | (progn | ||
| 193 | (setq which-func-update-timer | ||
| 194 | (run-with-idle-timer idle-update-delay t 'which-func-update)) | ||
| 195 | (dolist (buf (buffer-list)) | ||
| 196 | (with-current-buffer buf | ||
| 197 | (setq which-func-mode | ||
| 198 | (or (eq which-func-modes t) | ||
| 199 | (member major-mode which-func-modes)))))) | ||
| 200 | ;; Turn it off | ||
| 201 | (cancel-timer which-func-update-timer) | ||
| 202 | (setq which-func-update-timer nil) | ||
| 203 | (dolist (buf (buffer-list)) | ||
| 204 | (with-current-buffer buf (setq which-func-mode nil))))) | ||
| 205 | |||
| 206 | (defvar which-function-imenu-failed nil | ||
| 207 | "Locally t in a buffer if `imenu--make-index-alist' found nothing there.") | ||
| 208 | |||
| 209 | (defun which-function () | ||
| 210 | "Return current function name based on point. | ||
| 211 | Uses `imenu--index-alist' or `add-log-current-defun-function'. | ||
| 212 | If no function name is found, return nil." | ||
| 213 | (let (name) | ||
| 214 | ;; If Imenu is loaded, try to make an index alist with it. | ||
| 215 | (when (and (boundp 'imenu--index-alist) (null imenu--index-alist) | ||
| 216 | (null which-function-imenu-failed)) | ||
| 217 | (imenu--make-index-alist) | ||
| 218 | (unless imenu--index-alist | ||
| 219 | (make-local-variable 'which-function-imenu-failed) | ||
| 220 | (setq which-function-imenu-failed t))) | ||
| 221 | ;; If we have an index alist, use it. | ||
| 222 | (when (and (boundp 'imenu--index-alist) imenu--index-alist) | ||
| 223 | (let ((alist imenu--index-alist) | ||
| 224 | (minoffset (point-max)) | ||
| 225 | offset elem pair mark) | ||
| 226 | (while alist | ||
| 227 | (setq elem (car-safe alist) | ||
| 228 | alist (cdr-safe alist)) | ||
| 229 | ;; Elements of alist are either ("name" . marker), or | ||
| 230 | ;; ("submenu" ("name" . marker) ... ). | ||
| 231 | (unless (listp (cdr elem)) | ||
| 232 | (setq elem (list elem))) | ||
| 233 | (while elem | ||
| 234 | (setq pair (car elem) | ||
| 235 | elem (cdr elem)) | ||
| 236 | (and (consp pair) | ||
| 237 | (number-or-marker-p (setq mark (cdr pair))) | ||
| 238 | (if (>= (setq offset (- (point) mark)) 0) | ||
| 239 | (if (< offset minoffset) ; find the closest item | ||
| 240 | (setq minoffset offset | ||
| 241 | name (car pair))) | ||
| 242 | ;; Entries in order, so can skip all those after point. | ||
| 243 | (setq elem nil))))))) | ||
| 244 | ;; Try using add-log support. | ||
| 245 | (when (and (null name) (boundp 'add-log-current-defun-function) | ||
| 246 | add-log-current-defun-function) | ||
| 247 | (setq name (funcall add-log-current-defun-function))) | ||
| 248 | ;; Filter the name if requested. | ||
| 249 | (when name | ||
| 250 | (if which-func-cleanup-function | ||
| 251 | (funcall which-func-cleanup-function name) | ||
| 252 | name)))) | ||
| 253 | |||
| 254 | (provide 'which-func) | ||
| 255 | |||
| 256 | ;;; which-func.el ends here | ||
diff --git a/lisp/textmodes/enriched.el b/lisp/textmodes/enriched.el new file mode 100644 index 00000000000..e74cb6b8ba7 --- /dev/null +++ b/lisp/textmodes/enriched.el | |||
| @@ -0,0 +1,474 @@ | |||
| 1 | ;;; enriched.el --- read and save files in text/enriched format | ||
| 2 | |||
| 3 | ;; Copyright (c) 1994, 1995, 1996, 2002 Free Software Foundation, Inc. | ||
| 4 | |||
| 5 | ;; Author: Boris Goldowsky <boris@gnu.org> | ||
| 6 | ;; Keywords: wp, faces | ||
| 7 | |||
| 8 | ;; This file is part of GNU Emacs. | ||
| 9 | |||
| 10 | ;; GNU Emacs is free software; you can redistribute it and/or modify | ||
| 11 | ;; it under the terms of the GNU General Public License as published by | ||
| 12 | ;; the Free Software Foundation; either version 2, or (at your option) | ||
| 13 | ;; any later version. | ||
| 14 | |||
| 15 | ;; GNU Emacs is distributed in the hope that it will be useful, | ||
| 16 | ;; but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 17 | ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 18 | ;; GNU General Public License for more details. | ||
| 19 | |||
| 20 | ;; You should have received a copy of the GNU General Public License | ||
| 21 | ;; along with GNU Emacs; see the file COPYING. If not, write to the | ||
| 22 | ;; Free Software Foundation, Inc., 59 Temple Place - Suite 330, | ||
| 23 | ;; Boston, MA 02111-1307, USA. | ||
| 24 | |||
| 25 | ;;; Commentary: | ||
| 26 | |||
| 27 | ;; This file implements reading, editing, and saving files with | ||
| 28 | ;; text-properties such as faces, levels of indentation, and true line | ||
| 29 | ;; breaks distinguished from newlines just used to fit text into the window. | ||
| 30 | |||
| 31 | ;; The file format used is the MIME text/enriched format, which is a | ||
| 32 | ;; standard format defined in internet RFC 1563. All standard annotations | ||
| 33 | ;; are supported except for <smaller> and <bigger>, which are currently not | ||
| 34 | ;; possible to display. | ||
| 35 | |||
| 36 | ;; A separate file, enriched.doc, contains further documentation and other | ||
| 37 | ;; important information about this code. It also serves as an example | ||
| 38 | ;; file in text/enriched format. It should be in the etc directory of your | ||
| 39 | ;; emacs distribution. | ||
| 40 | |||
| 41 | ;;; Code: | ||
| 42 | |||
| 43 | (provide 'enriched) | ||
| 44 | |||
| 45 | ;;; | ||
| 46 | ;;; Variables controlling the display | ||
| 47 | ;;; | ||
| 48 | |||
| 49 | (defgroup enriched nil | ||
| 50 | "Read and save files in text/enriched format" | ||
| 51 | :group 'wp) | ||
| 52 | |||
| 53 | (defcustom enriched-verbose t | ||
| 54 | "*If non-nil, give status messages when reading and writing files." | ||
| 55 | :type 'boolean | ||
| 56 | :group 'enriched) | ||
| 57 | |||
| 58 | ;;; | ||
| 59 | ;;; Set up faces & display table | ||
| 60 | ;;; | ||
| 61 | |||
| 62 | ;; Emacs doesn't have a "fixed" face by default, since all faces currently | ||
| 63 | ;; have to be fixed-width. So we just pick one that looks different from the | ||
| 64 | ;; default. | ||
| 65 | (defface fixed | ||
| 66 | '((t (:weight bold))) | ||
| 67 | "Face used for text that must be shown in fixed width. | ||
| 68 | Currently, emacs can only display fixed-width fonts, but this may change. | ||
| 69 | This face is used for text specifically marked as fixed-width, for example | ||
| 70 | in text/enriched files." | ||
| 71 | :group 'enriched) | ||
| 72 | |||
| 73 | (defface excerpt | ||
| 74 | '((t (:slant italic))) | ||
| 75 | "Face used for text that is an excerpt from another document. | ||
| 76 | This is used in Enriched mode for text explicitly marked as an excerpt." | ||
| 77 | :group 'enriched) | ||
| 78 | |||
| 79 | (defconst enriched-display-table (or (copy-sequence standard-display-table) | ||
| 80 | (make-display-table))) | ||
| 81 | (aset enriched-display-table ?\f (make-vector (1- (frame-width)) ?-)) | ||
| 82 | |||
| 83 | (defconst enriched-par-props '(left-margin right-margin justification) | ||
| 84 | "Text-properties that usually apply to whole paragraphs. | ||
| 85 | These are set front-sticky everywhere except at hard newlines.") | ||
| 86 | |||
| 87 | ;;; | ||
| 88 | ;;; Variables controlling the file format | ||
| 89 | ;;; (bidirectional) | ||
| 90 | |||
| 91 | (defconst enriched-initial-annotation | ||
| 92 | (lambda () | ||
| 93 | (format "Content-Type: text/enriched\nText-Width: %d\n\n" | ||
| 94 | fill-column)) | ||
| 95 | "What to insert at the start of a text/enriched file. | ||
| 96 | If this is a string, it is inserted. If it is a list, it should be a lambda | ||
| 97 | expression, which is evaluated to get the string to insert.") | ||
| 98 | |||
| 99 | (defconst enriched-annotation-format "<%s%s>" | ||
| 100 | "General format of enriched-text annotations.") | ||
| 101 | |||
| 102 | (defconst enriched-annotation-regexp "<\\(/\\)?\\([-A-Za-z0-9]+\\)>" | ||
| 103 | "Regular expression matching enriched-text annotations.") | ||
| 104 | |||
| 105 | (defconst enriched-translations | ||
| 106 | '((face (bold-italic "bold" "italic") | ||
| 107 | (bold "bold") | ||
| 108 | (italic "italic") | ||
| 109 | (underline "underline") | ||
| 110 | (fixed "fixed") | ||
| 111 | (excerpt "excerpt") | ||
| 112 | (default ) | ||
| 113 | (nil enriched-encode-other-face)) | ||
| 114 | (left-margin (4 "indent")) | ||
| 115 | (right-margin (4 "indentright")) | ||
| 116 | (justification (none "nofill") | ||
| 117 | (right "flushright") | ||
| 118 | (left "flushleft") | ||
| 119 | (full "flushboth") | ||
| 120 | (center "center")) | ||
| 121 | (PARAMETER (t "param")) ; Argument of preceding annotation | ||
| 122 | ;; The following are not part of the standard: | ||
| 123 | (FUNCTION (enriched-decode-foreground "x-color") | ||
| 124 | (enriched-decode-background "x-bg-color") | ||
| 125 | (enriched-decode-display-prop "x-display")) | ||
| 126 | (read-only (t "x-read-only")) | ||
| 127 | (display (nil enriched-handle-display-prop)) | ||
| 128 | (unknown (nil format-annotate-value)) | ||
| 129 | ; (font-size (2 "bigger") ; unimplemented | ||
| 130 | ; (-2 "smaller")) | ||
| 131 | ) | ||
| 132 | "List of definitions of text/enriched annotations. | ||
| 133 | See `format-annotate-region' and `format-deannotate-region' for the definition | ||
| 134 | of this structure.") | ||
| 135 | |||
| 136 | (defconst enriched-ignore | ||
| 137 | '(front-sticky rear-nonsticky hard) | ||
| 138 | "Properties that are OK to ignore when saving text/enriched files. | ||
| 139 | Any property that is neither on this list nor dealt with by | ||
| 140 | `enriched-translations' will generate a warning.") | ||
| 141 | |||
| 142 | ;;; Internal variables | ||
| 143 | |||
| 144 | |||
| 145 | (defcustom enriched-mode-hook nil | ||
| 146 | "Hook run after entering/leaving Enriched mode. | ||
| 147 | If you set variables in this hook, you should arrange for them to be restored | ||
| 148 | to their old values if you leave Enriched mode. One way to do this is to add | ||
| 149 | them and their old values to `enriched-old-bindings'." | ||
| 150 | :type 'hook | ||
| 151 | :group 'enriched) | ||
| 152 | |||
| 153 | (defvar enriched-old-bindings nil | ||
| 154 | "Store old variable values that we change when entering mode. | ||
| 155 | The value is a list of \(VAR VALUE VAR VALUE...).") | ||
| 156 | (make-variable-buffer-local 'enriched-old-bindings) | ||
| 157 | |||
| 158 | ;;; | ||
| 159 | ;;; Define the mode | ||
| 160 | ;;; | ||
| 161 | |||
| 162 | (put 'enriched-mode 'permanent-local t) | ||
| 163 | ;;;###autoload | ||
| 164 | (define-minor-mode enriched-mode | ||
| 165 | "Minor mode for editing text/enriched files. | ||
| 166 | These are files with embedded formatting information in the MIME standard | ||
| 167 | text/enriched format. | ||
| 168 | Turning the mode on runs `enriched-mode-hook'. | ||
| 169 | |||
| 170 | More information about Enriched mode is available in the file | ||
| 171 | etc/enriched.doc in the Emacs distribution directory. | ||
| 172 | |||
| 173 | Commands: | ||
| 174 | |||
| 175 | \\{enriched-mode-map}" | ||
| 176 | nil " Enriched" nil | ||
| 177 | (cond ((null enriched-mode) | ||
| 178 | ;; Turn mode off | ||
| 179 | (setq buffer-file-format (delq 'text/enriched buffer-file-format)) | ||
| 180 | ;; restore old variable values | ||
| 181 | (while enriched-old-bindings | ||
| 182 | (set (pop enriched-old-bindings) (pop enriched-old-bindings)))) | ||
| 183 | |||
| 184 | ((memq 'text/enriched buffer-file-format) | ||
| 185 | ;; Mode already on; do nothing. | ||
| 186 | nil) | ||
| 187 | |||
| 188 | (t ; Turn mode on | ||
| 189 | (push 'text/enriched buffer-file-format) | ||
| 190 | ;; Save old variable values before we change them. | ||
| 191 | ;; These will be restored if we exit Enriched mode. | ||
| 192 | (setq enriched-old-bindings | ||
| 193 | (list 'buffer-display-table buffer-display-table | ||
| 194 | 'indent-line-function indent-line-function | ||
| 195 | 'default-text-properties default-text-properties)) | ||
| 196 | (make-local-variable 'indent-line-function) | ||
| 197 | (make-local-variable 'default-text-properties) | ||
| 198 | (setq indent-line-function 'indent-to-left-margin ;WHY?? -sm | ||
| 199 | buffer-display-table enriched-display-table) | ||
| 200 | (use-hard-newlines 1 nil) | ||
| 201 | (let ((sticky (plist-get default-text-properties 'front-sticky)) | ||
| 202 | (p enriched-par-props)) | ||
| 203 | (dolist (x p) | ||
| 204 | (add-to-list 'sticky x)) | ||
| 205 | (if sticky | ||
| 206 | (setq default-text-properties | ||
| 207 | (plist-put default-text-properties | ||
| 208 | 'front-sticky sticky))))))) | ||
| 209 | |||
| 210 | ;;; | ||
| 211 | ;;; Keybindings | ||
| 212 | ;;; | ||
| 213 | |||
| 214 | (defvar enriched-mode-map nil | ||
| 215 | "Keymap for Enriched mode.") | ||
| 216 | |||
| 217 | (if (null enriched-mode-map) | ||
| 218 | (fset 'enriched-mode-map (setq enriched-mode-map (make-sparse-keymap)))) | ||
| 219 | |||
| 220 | (if (not (assq 'enriched-mode minor-mode-map-alist)) | ||
| 221 | (setq minor-mode-map-alist | ||
| 222 | (cons (cons 'enriched-mode enriched-mode-map) | ||
| 223 | minor-mode-map-alist))) | ||
| 224 | |||
| 225 | (define-key enriched-mode-map "\C-a" 'beginning-of-line-text) | ||
| 226 | (define-key enriched-mode-map "\C-m" 'reindent-then-newline-and-indent) | ||
| 227 | (define-key enriched-mode-map "\C-j" 'reindent-then-newline-and-indent) | ||
| 228 | (define-key enriched-mode-map "\M-j" 'facemenu-justification-menu) | ||
| 229 | (define-key enriched-mode-map "\M-S" 'set-justification-center) | ||
| 230 | (define-key enriched-mode-map "\C-x\t" 'increase-left-margin) | ||
| 231 | (define-key enriched-mode-map "\C-c\C-l" 'set-left-margin) | ||
| 232 | (define-key enriched-mode-map "\C-c\C-r" 'set-right-margin) | ||
| 233 | |||
| 234 | ;;; | ||
| 235 | ;;; Some functions dealing with text-properties, especially indentation | ||
| 236 | ;;; | ||
| 237 | |||
| 238 | (defun enriched-map-property-regions (prop func &optional from to) | ||
| 239 | "Apply a function to regions of the buffer based on a text property. | ||
| 240 | For each contiguous region of the buffer for which the value of PROPERTY is | ||
| 241 | eq, the FUNCTION will be called. Optional arguments FROM and TO specify the | ||
| 242 | region over which to scan. | ||
| 243 | |||
| 244 | The specified function receives three arguments: the VALUE of the property in | ||
| 245 | the region, and the START and END of each region." | ||
| 246 | (save-excursion | ||
| 247 | (save-restriction | ||
| 248 | (if to (narrow-to-region (point-min) to)) | ||
| 249 | (goto-char (or from (point-min))) | ||
| 250 | (let ((begin (point)) | ||
| 251 | end | ||
| 252 | (marker (make-marker)) | ||
| 253 | (val (get-text-property (point) prop))) | ||
| 254 | (while (setq end (text-property-not-all begin (point-max) prop val)) | ||
| 255 | (move-marker marker end) | ||
| 256 | (funcall func val begin (marker-position marker)) | ||
| 257 | (setq begin (marker-position marker) | ||
| 258 | val (get-text-property marker prop))) | ||
| 259 | (if (< begin (point-max)) | ||
| 260 | (funcall func val begin (point-max))))))) | ||
| 261 | |||
| 262 | (put 'enriched-map-property-regions 'lisp-indent-hook 1) | ||
| 263 | |||
| 264 | (defun enriched-insert-indentation (&optional from to) | ||
| 265 | "Indent and justify each line in the region." | ||
| 266 | (save-excursion | ||
| 267 | (save-restriction | ||
| 268 | (if to (narrow-to-region (point-min) to)) | ||
| 269 | (goto-char (or from (point-min))) | ||
| 270 | (if (not (bolp)) (forward-line 1)) | ||
| 271 | (while (not (eobp)) | ||
| 272 | (if (eolp) | ||
| 273 | nil ; skip blank lines | ||
| 274 | (indent-to (current-left-margin)) | ||
| 275 | (justify-current-line t nil t)) | ||
| 276 | (forward-line 1))))) | ||
| 277 | |||
| 278 | ;;; | ||
| 279 | ;;; Encoding Files | ||
| 280 | ;;; | ||
| 281 | |||
| 282 | ;;;###autoload | ||
| 283 | (defun enriched-encode (from to orig-buf) | ||
| 284 | (if enriched-verbose (message "Enriched: encoding document...")) | ||
| 285 | (save-restriction | ||
| 286 | (narrow-to-region from to) | ||
| 287 | (delete-to-left-margin) | ||
| 288 | (unjustify-region) | ||
| 289 | (goto-char from) | ||
| 290 | (format-replace-strings '(("<" . "<<"))) | ||
| 291 | (format-insert-annotations | ||
| 292 | (format-annotate-region from (point-max) enriched-translations | ||
| 293 | 'enriched-make-annotation enriched-ignore)) | ||
| 294 | (goto-char from) | ||
| 295 | (insert (if (stringp enriched-initial-annotation) | ||
| 296 | enriched-initial-annotation | ||
| 297 | (save-excursion | ||
| 298 | ;; Eval this in the buffer we are annotating. This | ||
| 299 | ;; fixes a bug which was saving incorrect File-Width | ||
| 300 | ;; information, since we were looking at local | ||
| 301 | ;; variables in the wrong buffer. | ||
| 302 | (if orig-buf (set-buffer orig-buf)) | ||
| 303 | (funcall enriched-initial-annotation)))) | ||
| 304 | (enriched-map-property-regions 'hard | ||
| 305 | (lambda (v b e) | ||
| 306 | (if (and v (= ?\n (char-after b))) | ||
| 307 | (progn (goto-char b) (insert "\n")))) | ||
| 308 | (point) nil) | ||
| 309 | (if enriched-verbose (message nil)) | ||
| 310 | ;; Return new end. | ||
| 311 | (point-max))) | ||
| 312 | |||
| 313 | (defun enriched-make-annotation (internal-ann positive) | ||
| 314 | "Format an annotation INTERNAL-ANN. | ||
| 315 | INTERNAL-ANN may be a string, for a flag, or a list of the form (PARAM VALUE). | ||
| 316 | If POSITIVE is non-nil, this is the opening annotation; | ||
| 317 | if nil, the matching close." | ||
| 318 | (cond ((stringp internal-ann) | ||
| 319 | (format enriched-annotation-format (if positive "" "/") internal-ann)) | ||
| 320 | ;; Otherwise it is an annotation with parameters, represented as a list | ||
| 321 | (positive | ||
| 322 | (let ((item (car internal-ann)) | ||
| 323 | (params (cdr internal-ann))) | ||
| 324 | (concat (format enriched-annotation-format "" item) | ||
| 325 | (mapconcat (lambda (i) (concat "<param>" i "</param>")) | ||
| 326 | params "")))) | ||
| 327 | (t (format enriched-annotation-format "/" (car internal-ann))))) | ||
| 328 | |||
| 329 | (defun enriched-encode-other-face (old new) | ||
| 330 | "Generate annotations for random face change. | ||
| 331 | One annotation each for foreground color, background color, italic, etc." | ||
| 332 | (cons (and old (enriched-face-ans old)) | ||
| 333 | (and new (enriched-face-ans new)))) | ||
| 334 | |||
| 335 | (defun enriched-face-ans (face) | ||
| 336 | "Return annotations specifying FACE. | ||
| 337 | FACE may be a list of faces instead of a single face; | ||
| 338 | it can also be anything allowed as an element of a list | ||
| 339 | which can be the value of the `face' text property." | ||
| 340 | (cond ((and (consp face) (eq (car face) 'foreground-color)) | ||
| 341 | (list (list "x-color" (cdr face)))) | ||
| 342 | ((and (consp face) (eq (car face) 'background-color)) | ||
| 343 | (list (list "x-bg-color" (cdr face)))) | ||
| 344 | ((and (listp face) (eq (car face) :foreground)) | ||
| 345 | (list (list "x-color" (cadr face)))) | ||
| 346 | ((and (listp face) (eq (car face) :background)) | ||
| 347 | (list (list "x-bg-color" (cadr face)))) | ||
| 348 | ((listp face) | ||
| 349 | (apply 'append (mapcar 'enriched-face-ans face))) | ||
| 350 | ((let* ((fg (face-attribute face :foreground)) | ||
| 351 | (bg (face-attribute face :background)) | ||
| 352 | (props (face-font face t)) | ||
| 353 | (ans (cdr (format-annotate-single-property-change | ||
| 354 | 'face nil props enriched-translations)))) | ||
| 355 | (unless (eq fg 'unspecified) | ||
| 356 | (setq ans (cons (list "x-color" fg) ans))) | ||
| 357 | (unless (eq bg 'unspecified) | ||
| 358 | (setq ans (cons (list "x-bg-color" bg) ans))) | ||
| 359 | ans)))) | ||
| 360 | |||
| 361 | ;;; | ||
| 362 | ;;; Decoding files | ||
| 363 | ;;; | ||
| 364 | |||
| 365 | ;;;###autoload | ||
| 366 | (defun enriched-decode (from to) | ||
| 367 | (if enriched-verbose (message "Enriched: decoding document...")) | ||
| 368 | (use-hard-newlines 1 'never) | ||
| 369 | (save-excursion | ||
| 370 | (save-restriction | ||
| 371 | (narrow-to-region from to) | ||
| 372 | (goto-char from) | ||
| 373 | |||
| 374 | ;; Deal with header | ||
| 375 | (let ((file-width (enriched-get-file-width))) | ||
| 376 | (enriched-remove-header) | ||
| 377 | |||
| 378 | ;; Deal with newlines | ||
| 379 | (while (search-forward-regexp "\n\n+" nil t) | ||
| 380 | (if (current-justification) | ||
| 381 | (delete-char -1)) | ||
| 382 | (set-hard-newline-properties (match-beginning 0) (point))) | ||
| 383 | |||
| 384 | ;; Translate annotations | ||
| 385 | (format-deannotate-region from (point-max) enriched-translations | ||
| 386 | 'enriched-next-annotation) | ||
| 387 | |||
| 388 | ;; Indent or fill the buffer | ||
| 389 | (cond (file-width ; File was filled to this width | ||
| 390 | (setq fill-column file-width) | ||
| 391 | (if enriched-verbose (message "Indenting...")) | ||
| 392 | (enriched-insert-indentation)) | ||
| 393 | (t ; File was not filled. | ||
| 394 | (if enriched-verbose (message "Filling paragraphs...")) | ||
| 395 | (fill-region (point-min) (point-max)))) | ||
| 396 | (if enriched-verbose (message nil))) | ||
| 397 | (point-max)))) | ||
| 398 | |||
| 399 | (defun enriched-next-annotation () | ||
| 400 | "Find and return next text/enriched annotation. | ||
| 401 | Any \"<<\" strings encountered are converted to \"<\". | ||
| 402 | Return value is \(begin end name positive-p), or nil if none was found." | ||
| 403 | (while (and (search-forward "<" nil 1) | ||
| 404 | (progn (goto-char (match-beginning 0)) | ||
| 405 | (not (looking-at enriched-annotation-regexp)))) | ||
| 406 | (forward-char 1) | ||
| 407 | (if (= ?< (char-after (point))) | ||
| 408 | (delete-char 1) | ||
| 409 | ;; A single < that does not start an annotation is an error, | ||
| 410 | ;; which we note and then ignore. | ||
| 411 | (message "Warning: malformed annotation in file at %s" | ||
| 412 | (1- (point))))) | ||
| 413 | (if (not (eobp)) | ||
| 414 | (let* ((beg (match-beginning 0)) | ||
| 415 | (end (match-end 0)) | ||
| 416 | (name (downcase (buffer-substring | ||
| 417 | (match-beginning 2) (match-end 2)))) | ||
| 418 | (pos (not (match-beginning 1)))) | ||
| 419 | (list beg end name pos)))) | ||
| 420 | |||
| 421 | (defun enriched-get-file-width () | ||
| 422 | "Look for file width information on this line." | ||
| 423 | (save-excursion | ||
| 424 | (if (search-forward "Text-Width: " (+ (point) 1000) t) | ||
| 425 | (read (current-buffer))))) | ||
| 426 | |||
| 427 | (defun enriched-remove-header () | ||
| 428 | "Remove file-format header at point." | ||
| 429 | (while (looking-at "^[-A-Za-z]+: .*\n") | ||
| 430 | (delete-region (point) (match-end 0))) | ||
| 431 | (if (looking-at "^\n") | ||
| 432 | (delete-char 1))) | ||
| 433 | |||
| 434 | (defun enriched-decode-foreground (from to &optional color) | ||
| 435 | (if color | ||
| 436 | (list from to 'face (list ':foreground color)) | ||
| 437 | (message "Warning: no color specified for <x-color>") | ||
| 438 | nil)) | ||
| 439 | |||
| 440 | (defun enriched-decode-background (from to &optional color) | ||
| 441 | (if color | ||
| 442 | (list from to 'face (list ':background color)) | ||
| 443 | (message "Warning: no color specified for <x-bg-color>") | ||
| 444 | nil)) | ||
| 445 | |||
| 446 | ;;; Handling the `display' property. | ||
| 447 | |||
| 448 | |||
| 449 | (defun enriched-handle-display-prop (old new) | ||
| 450 | "Return a list of annotations for a change in the `display' property. | ||
| 451 | OLD is the old value of the property, NEW is the new value. Value | ||
| 452 | is a list `(CLOSE OPEN)', where CLOSE is a list of annotations to | ||
| 453 | close and OPEN a list of annotations to open. Each of these lists | ||
| 454 | has the form `(ANNOTATION PARAM ...)'." | ||
| 455 | (let ((annotation "x-display") | ||
| 456 | (param (prin1-to-string (or old new)))) | ||
| 457 | (if (null old) | ||
| 458 | (cons nil (list (list annotation param))) | ||
| 459 | (cons (list (list annotation param)) nil)))) | ||
| 460 | |||
| 461 | (defun enriched-decode-display-prop (start end &optional param) | ||
| 462 | "Decode a `display' property for text between START and END. | ||
| 463 | PARAM is a `<param>' found for the property. | ||
| 464 | Value is a list `(START END SYMBOL VALUE)' with START and END denoting | ||
| 465 | the range of text to assign text property SYMBOL with value VALUE " | ||
| 466 | (let ((prop (when (stringp param) | ||
| 467 | (condition-case () | ||
| 468 | (car (read-from-string param)) | ||
| 469 | (error nil))))) | ||
| 470 | (unless prop | ||
| 471 | (message "Warning: invalid <x-display> parameter %s" param)) | ||
| 472 | (list start end 'display prop))) | ||
| 473 | |||
| 474 | ;;; enriched.el ends here | ||