Mercurial > hg > xemacs-beta
annotate lisp/subr.el @ 5473:ac37a5f7e5be
Merge with trunk.
author | Mats Lidell <matsl@xemacs.org> |
---|---|
date | Thu, 17 Mar 2011 23:42:59 +0100 |
parents | a9094f28f9a9 f00192e1cd49 |
children | 1e544fd7be12 |
rev | line source |
---|---|
428 | 1 ;;; subr.el --- basic lisp subroutines for XEmacs |
2 | |
2525 | 3 ;; Copyright (C) 1985, 86, 92, 94, 95, 99, 2000, 2001, 2002, 2003 |
4 ;; Free Software Foundation, Inc. | |
428 | 5 ;; Copyright (C) 1995 Tinker Systems and INS Engineering Corp. |
6 ;; Copyright (C) 1995 Sun Microsystems. | |
1333 | 7 ;; Copyright (C) 2000, 2001, 2002, 2003 Ben Wing. |
428 | 8 |
9 ;; Maintainer: XEmacs Development Team | |
2525 | 10 ;; Keywords: extensions, dumped, internal |
428 | 11 |
12 ;; This file is part of XEmacs. | |
13 | |
5402
308d34e9f07d
Changed bulk of GPLv2 or later files identified by script
Mats Lidell <matsl@xemacs.org>
parents:
5220
diff
changeset
|
14 ;; XEmacs is free software: you can redistribute it and/or modify it |
308d34e9f07d
Changed bulk of GPLv2 or later files identified by script
Mats Lidell <matsl@xemacs.org>
parents:
5220
diff
changeset
|
15 ;; under the terms of the GNU General Public License as published by the |
308d34e9f07d
Changed bulk of GPLv2 or later files identified by script
Mats Lidell <matsl@xemacs.org>
parents:
5220
diff
changeset
|
16 ;; Free Software Foundation, either version 3 of the License, or (at your |
308d34e9f07d
Changed bulk of GPLv2 or later files identified by script
Mats Lidell <matsl@xemacs.org>
parents:
5220
diff
changeset
|
17 ;; option) any later version. |
428 | 18 |
5402
308d34e9f07d
Changed bulk of GPLv2 or later files identified by script
Mats Lidell <matsl@xemacs.org>
parents:
5220
diff
changeset
|
19 ;; XEmacs is distributed in the hope that it will be useful, but WITHOUT |
308d34e9f07d
Changed bulk of GPLv2 or later files identified by script
Mats Lidell <matsl@xemacs.org>
parents:
5220
diff
changeset
|
20 ;; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
308d34e9f07d
Changed bulk of GPLv2 or later files identified by script
Mats Lidell <matsl@xemacs.org>
parents:
5220
diff
changeset
|
21 ;; FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License |
308d34e9f07d
Changed bulk of GPLv2 or later files identified by script
Mats Lidell <matsl@xemacs.org>
parents:
5220
diff
changeset
|
22 ;; for more details. |
428 | 23 |
24 ;; You should have received a copy of the GNU General Public License | |
5402
308d34e9f07d
Changed bulk of GPLv2 or later files identified by script
Mats Lidell <matsl@xemacs.org>
parents:
5220
diff
changeset
|
25 ;; along with XEmacs. If not, see <http://www.gnu.org/licenses/>. |
428 | 26 |
1333 | 27 ;;; Synched up with: FSF 19.34. Some things synched up with later versions. |
428 | 28 |
29 ;;; Commentary: | |
30 | |
31 ;; This file is dumped with XEmacs. | |
32 | |
33 ;; There's not a whole lot in common now with the FSF version, | |
34 ;; be wary when applying differences. I've left in a number of lines | |
35 ;; of commentary just to give diff(1) something to synch itself with to | |
36 ;; provide useful context diffs. -sb | |
37 | |
1333 | 38 ;; BEGIN SYNCHED WITH FSF 21.2 |
39 | |
5284
d27c1ee1943b
Make the order of preloaded-file-list more sane.
Aidan Kehoe <kehoea@parhasard.net>
parents:
5281
diff
changeset
|
40 ;; XEmacs; no need for custom-declare-variable-list, preloaded-file-list is |
d27c1ee1943b
Make the order of preloaded-file-list more sane.
Aidan Kehoe <kehoea@parhasard.net>
parents:
5281
diff
changeset
|
41 ;; ordered to make it unnecessary. |
428 | 42 |
2525 | 43 (defun macro-declaration-function (macro decl) |
44 "Process a declaration found in a macro definition. | |
45 This is set as the value of the variable `macro-declaration-function'. | |
46 MACRO is the name of the macro being defined. | |
47 DECL is a list `(declare ...)' containing the declarations. | |
48 The return value of this function is not used." | |
49 (dolist (d (cdr decl)) | |
50 (cond ((and (consp d) (eq (car d) 'indent)) | |
51 (put macro 'lisp-indent-function (cadr d))) | |
52 ((and (consp d) (eq (car d) 'debug)) | |
53 (put macro 'edebug-form-spec (cadr d))) | |
54 (t | |
55 (message "Unknown declaration %s" d))))) | |
56 | |
57 (setq macro-declaration-function 'macro-declaration-function) | |
5281
aa20a889ff14
Remove a couple of redundant functions, backquote.el
Aidan Kehoe <kehoea@parhasard.net>
parents:
5220
diff
changeset
|
58 |
aa20a889ff14
Remove a couple of redundant functions, backquote.el
Aidan Kehoe <kehoea@parhasard.net>
parents:
5220
diff
changeset
|
59 ;; XEmacs; this is here because we use it in backquote.el, so it needs to be |
aa20a889ff14
Remove a couple of redundant functions, backquote.el
Aidan Kehoe <kehoea@parhasard.net>
parents:
5220
diff
changeset
|
60 ;; available the first time a `(...) form is expanded. |
aa20a889ff14
Remove a couple of redundant functions, backquote.el
Aidan Kehoe <kehoea@parhasard.net>
parents:
5220
diff
changeset
|
61 (defun list* (first &rest rest) ; See compiler macro in cl-macs.el |
aa20a889ff14
Remove a couple of redundant functions, backquote.el
Aidan Kehoe <kehoea@parhasard.net>
parents:
5220
diff
changeset
|
62 "Return a new list with specified args as elements, cons'd to last arg. |
aa20a889ff14
Remove a couple of redundant functions, backquote.el
Aidan Kehoe <kehoea@parhasard.net>
parents:
5220
diff
changeset
|
63 Thus, `(list* A B C D)' is equivalent to `(nconc (list A B C) D)', or to |
aa20a889ff14
Remove a couple of redundant functions, backquote.el
Aidan Kehoe <kehoea@parhasard.net>
parents:
5220
diff
changeset
|
64 `(cons A (cons B (cons C D)))'." |
aa20a889ff14
Remove a couple of redundant functions, backquote.el
Aidan Kehoe <kehoea@parhasard.net>
parents:
5220
diff
changeset
|
65 (cond ((not rest) first) |
aa20a889ff14
Remove a couple of redundant functions, backquote.el
Aidan Kehoe <kehoea@parhasard.net>
parents:
5220
diff
changeset
|
66 ((not (cdr rest)) (cons first (car rest))) |
aa20a889ff14
Remove a couple of redundant functions, backquote.el
Aidan Kehoe <kehoea@parhasard.net>
parents:
5220
diff
changeset
|
67 (t (let* ((n (length rest)) |
aa20a889ff14
Remove a couple of redundant functions, backquote.el
Aidan Kehoe <kehoea@parhasard.net>
parents:
5220
diff
changeset
|
68 (copy (copy-sequence rest)) |
aa20a889ff14
Remove a couple of redundant functions, backquote.el
Aidan Kehoe <kehoea@parhasard.net>
parents:
5220
diff
changeset
|
69 (last (nthcdr (- n 2) copy))) |
aa20a889ff14
Remove a couple of redundant functions, backquote.el
Aidan Kehoe <kehoea@parhasard.net>
parents:
5220
diff
changeset
|
70 (setcdr last (car (cdr last))) |
aa20a889ff14
Remove a couple of redundant functions, backquote.el
Aidan Kehoe <kehoea@parhasard.net>
parents:
5220
diff
changeset
|
71 (cons first copy))))) |
428 | 72 |
73 ;;;; Lisp language features. | |
74 | |
75 (defmacro lambda (&rest cdr) | |
76 "Return a lambda expression. | |
77 A call of the form (lambda ARGS DOCSTRING INTERACTIVE BODY) is | |
78 self-quoting; the result of evaluating the lambda expression is the | |
79 expression itself. The lambda expression may then be treated as a | |
80 function, i.e., stored as the function value of a symbol, passed to | |
81 funcall or mapcar, etc. | |
82 | |
83 ARGS should take the same form as an argument list for a `defun'. | |
3842 | 84 Optional DOCSTRING is a documentation string. |
85 If present, it should describe how to call the function. Docstrings are | |
86 rarely useful unless the lambda will be named, eg, using `fset'. | |
87 Optional INTERACTIVE should be a call to the function `interactive'. | |
88 BODY should be a list of lisp expressions. | |
89 | |
90 The byte-compiler treats lambda expressions specially. If the lambda | |
91 expression is syntactically a function to be called, it will be compiled | |
92 unless protected by `quote'. Conversely, quoting a lambda expression with | |
93 `function' hints to the byte-compiler that it should compile the expression. | |
94 \(The byte-compiler may or may not actually compile it; for example it will | |
95 never compile lambdas nested in a data structure: `'(#'(lambda (x) x))'). | |
96 | |
97 The byte-compiler will warn about common problems such as the form | |
98 `(fset 'f '(lambda (x) x))' (the lambda cannot be byte-compiled; probably | |
99 the programmer intended `#'', although leaving the lambda unquoted will | |
100 normally suffice), but in general is it the programmer's responsibility to | |
101 quote lambda expressions appropriately." | |
428 | 102 `(function (lambda ,@cdr))) |
103 | |
1333 | 104 ;; FSF 21.2 has various basic macros here. We don't because they're either |
105 ;; in cl*.el (which we dump and hence is always available) or built-in. | |
106 | |
107 ;; More powerful versions in cl.el. | |
108 ;(defmacro push (newelt listname) | |
109 ;(defmacro pop (listname) | |
110 | |
111 ;; Built-in. | |
112 ;(defmacro when (cond &rest body) | |
113 ;(defmacro unless (cond &rest body) | |
114 | |
115 ;; More powerful versions in cl-macs.el. | |
116 ;(defmacro dolist (spec &rest body) | |
117 ;(defmacro dotimes (spec &rest body) | |
118 | |
119 ;; In cl.el. Ours are defun, but cl arranges for them to be inlined anyway. | |
120 ;(defsubst caar (x) | |
121 ;(defsubst cadr (x) | |
122 ;(defsubst cdar (x) | |
123 ;(defsubst cddr (x) | |
124 | |
125 ;; Built-in. Our `last' is more powerful in that it handles circularity. | |
126 ;(defun last (x &optional n) | |
127 ;(defun butlast (x &optional n) | |
128 ;(defun nbutlast (x &optional n) | |
129 | |
130 ;; In cl-seq.el. | |
131 ;(defun remove (elt seq) | |
132 ;(defun remq (elt list) | |
133 | |
428 | 134 (defmacro defun-when-void (&rest args) |
135 "Define a function, just like `defun', unless it's already defined. | |
136 Used for compatibility among different emacs variants." | |
137 `(if (fboundp ',(car args)) | |
138 nil | |
139 (defun ,@args))) | |
140 | |
141 (defmacro define-function-when-void (&rest args) | |
142 "Define a function, just like `define-function', unless it's already defined. | |
143 Used for compatibility among different emacs variants." | |
144 `(if (fboundp ,(car args)) | |
145 nil | |
146 (define-function ,@args))) | |
147 | |
148 | |
5338
8608eadee6ba
Move #'delq, #'delete to Lisp, adding support for sequences.
Aidan Kehoe <kehoea@parhasard.net>
parents:
5327
diff
changeset
|
149 (defun delete (item sequence) |
8608eadee6ba
Move #'delq, #'delete to Lisp, adding support for sequences.
Aidan Kehoe <kehoea@parhasard.net>
parents:
5327
diff
changeset
|
150 "Delete by side effect any occurrences of ITEM as a member of SEQUENCE. |
8608eadee6ba
Move #'delq, #'delete to Lisp, adding support for sequences.
Aidan Kehoe <kehoea@parhasard.net>
parents:
5327
diff
changeset
|
151 |
8608eadee6ba
Move #'delq, #'delete to Lisp, adding support for sequences.
Aidan Kehoe <kehoea@parhasard.net>
parents:
5327
diff
changeset
|
152 The modified SEQUENCE is returned. Comparison is done with `equal'. |
8608eadee6ba
Move #'delq, #'delete to Lisp, adding support for sequences.
Aidan Kehoe <kehoea@parhasard.net>
parents:
5327
diff
changeset
|
153 |
8608eadee6ba
Move #'delq, #'delete to Lisp, adding support for sequences.
Aidan Kehoe <kehoea@parhasard.net>
parents:
5327
diff
changeset
|
154 If the first member of a list SEQUENCE is ITEM, there is no way to remove it |
8608eadee6ba
Move #'delq, #'delete to Lisp, adding support for sequences.
Aidan Kehoe <kehoea@parhasard.net>
parents:
5327
diff
changeset
|
155 by side effect; therefore, write `(setq foo (delete element foo))' to be |
8608eadee6ba
Move #'delq, #'delete to Lisp, adding support for sequences.
Aidan Kehoe <kehoea@parhasard.net>
parents:
5327
diff
changeset
|
156 sure of changing the value of `foo'. Also see: `remove'." |
8608eadee6ba
Move #'delq, #'delete to Lisp, adding support for sequences.
Aidan Kehoe <kehoea@parhasard.net>
parents:
5327
diff
changeset
|
157 (delete* item sequence :test #'equal)) |
8608eadee6ba
Move #'delq, #'delete to Lisp, adding support for sequences.
Aidan Kehoe <kehoea@parhasard.net>
parents:
5327
diff
changeset
|
158 |
8608eadee6ba
Move #'delq, #'delete to Lisp, adding support for sequences.
Aidan Kehoe <kehoea@parhasard.net>
parents:
5327
diff
changeset
|
159 (defun delq (item sequence) |
8608eadee6ba
Move #'delq, #'delete to Lisp, adding support for sequences.
Aidan Kehoe <kehoea@parhasard.net>
parents:
5327
diff
changeset
|
160 "Delete by side effect any occurrences of ITEM as a member of SEQUENCE. |
8608eadee6ba
Move #'delq, #'delete to Lisp, adding support for sequences.
Aidan Kehoe <kehoea@parhasard.net>
parents:
5327
diff
changeset
|
161 |
8608eadee6ba
Move #'delq, #'delete to Lisp, adding support for sequences.
Aidan Kehoe <kehoea@parhasard.net>
parents:
5327
diff
changeset
|
162 The modified SEQUENCE is returned. Comparison is done with `eq'. If |
8608eadee6ba
Move #'delq, #'delete to Lisp, adding support for sequences.
Aidan Kehoe <kehoea@parhasard.net>
parents:
5327
diff
changeset
|
163 SEQUENCE is a list and its first member is ITEM, there is no way to remove |
8608eadee6ba
Move #'delq, #'delete to Lisp, adding support for sequences.
Aidan Kehoe <kehoea@parhasard.net>
parents:
5327
diff
changeset
|
164 it by side effect; therefore, write `(setq foo (delq element foo))' to be |
8608eadee6ba
Move #'delq, #'delete to Lisp, adding support for sequences.
Aidan Kehoe <kehoea@parhasard.net>
parents:
5327
diff
changeset
|
165 sure of changing the value of `foo'." |
8608eadee6ba
Move #'delq, #'delete to Lisp, adding support for sequences.
Aidan Kehoe <kehoea@parhasard.net>
parents:
5327
diff
changeset
|
166 (delete* item sequence :test #'eq)) |
8608eadee6ba
Move #'delq, #'delete to Lisp, adding support for sequences.
Aidan Kehoe <kehoea@parhasard.net>
parents:
5327
diff
changeset
|
167 |
8608eadee6ba
Move #'delq, #'delete to Lisp, adding support for sequences.
Aidan Kehoe <kehoea@parhasard.net>
parents:
5327
diff
changeset
|
168 (defun remove (item sequence) |
8608eadee6ba
Move #'delq, #'delete to Lisp, adding support for sequences.
Aidan Kehoe <kehoea@parhasard.net>
parents:
5327
diff
changeset
|
169 "Remove all occurrences of ITEM in SEQUENCE, testing with `equal'. |
8608eadee6ba
Move #'delq, #'delete to Lisp, adding support for sequences.
Aidan Kehoe <kehoea@parhasard.net>
parents:
5327
diff
changeset
|
170 |
8608eadee6ba
Move #'delq, #'delete to Lisp, adding support for sequences.
Aidan Kehoe <kehoea@parhasard.net>
parents:
5327
diff
changeset
|
171 This is a non-destructive function; it makes a copy of SEQUENCE if necessary |
8608eadee6ba
Move #'delq, #'delete to Lisp, adding support for sequences.
Aidan Kehoe <kehoea@parhasard.net>
parents:
5327
diff
changeset
|
172 to avoid corrupting the original SEQUENCE. |
8608eadee6ba
Move #'delq, #'delete to Lisp, adding support for sequences.
Aidan Kehoe <kehoea@parhasard.net>
parents:
5327
diff
changeset
|
173 Also see: `remove*', `delete', `delete*'" |
8608eadee6ba
Move #'delq, #'delete to Lisp, adding support for sequences.
Aidan Kehoe <kehoea@parhasard.net>
parents:
5327
diff
changeset
|
174 (remove* item sequence :test #'equal)) |
8608eadee6ba
Move #'delq, #'delete to Lisp, adding support for sequences.
Aidan Kehoe <kehoea@parhasard.net>
parents:
5327
diff
changeset
|
175 |
8608eadee6ba
Move #'delq, #'delete to Lisp, adding support for sequences.
Aidan Kehoe <kehoea@parhasard.net>
parents:
5327
diff
changeset
|
176 (defun remq (item sequence) |
8608eadee6ba
Move #'delq, #'delete to Lisp, adding support for sequences.
Aidan Kehoe <kehoea@parhasard.net>
parents:
5327
diff
changeset
|
177 "Remove all occurrences of ITEM in SEQUENCE, comparing with `eq'. |
8608eadee6ba
Move #'delq, #'delete to Lisp, adding support for sequences.
Aidan Kehoe <kehoea@parhasard.net>
parents:
5327
diff
changeset
|
178 |
8608eadee6ba
Move #'delq, #'delete to Lisp, adding support for sequences.
Aidan Kehoe <kehoea@parhasard.net>
parents:
5327
diff
changeset
|
179 This is a non-destructive function; it makes a copy of SEQUENCE to avoid |
8608eadee6ba
Move #'delq, #'delete to Lisp, adding support for sequences.
Aidan Kehoe <kehoea@parhasard.net>
parents:
5327
diff
changeset
|
180 corrupting the original SEQUENCE. See also the more general `remove*'." |
8608eadee6ba
Move #'delq, #'delete to Lisp, adding support for sequences.
Aidan Kehoe <kehoea@parhasard.net>
parents:
5327
diff
changeset
|
181 (remove* item sequence :test #'eq)) |
8608eadee6ba
Move #'delq, #'delete to Lisp, adding support for sequences.
Aidan Kehoe <kehoea@parhasard.net>
parents:
5327
diff
changeset
|
182 |
1333 | 183 (defun assoc-default (key alist &optional test default) |
184 "Find object KEY in a pseudo-alist ALIST. | |
185 ALIST is a list of conses or objects. Each element (or the element's car, | |
186 if it is a cons) is compared with KEY by evaluating (TEST (car elt) KEY). | |
187 If that is non-nil, the element matches; | |
188 then `assoc-default' returns the element's cdr, if it is a cons, | |
189 or DEFAULT if the element is not a cons. | |
190 | |
191 If no element matches, the value is nil. | |
192 If TEST is omitted or nil, `equal' is used." | |
193 (let (found (tail alist) value) | |
194 (while (and tail (not found)) | |
195 (let ((elt (car tail))) | |
196 (when (funcall (or test 'equal) (if (consp elt) (car elt) elt) key) | |
197 (setq found t value (if (consp elt) (cdr elt) default)))) | |
198 (setq tail (cdr tail))) | |
199 value)) | |
200 | |
201 (defun assoc-ignore-case (key alist) | |
202 "Like `assoc', but ignores differences in case and text representation. | |
203 KEY must be a string. Upper-case and lower-case letters are treated as equal." | |
204 (let (element) | |
205 (while (and alist (not element)) | |
206 (if (eq t (compare-strings key 0 nil (car (car alist)) 0 nil t)) | |
207 (setq element (car alist))) | |
208 (setq alist (cdr alist))) | |
209 element)) | |
210 | |
211 (defun assoc-ignore-representation (key alist) | |
212 "Like `assoc', but ignores differences in text representation. | |
213 KEY must be a string." | |
214 (let (element) | |
215 (while (and alist (not element)) | |
216 (if (eq t (compare-strings key 0 nil (car (car alist)) 0 nil)) | |
217 (setq element (car alist))) | |
218 (setq alist (cdr alist))) | |
219 element)) | |
220 | |
221 (defun member-ignore-case (elt list) | |
222 "Like `member', but ignores differences in case and text representation. | |
223 ELT must be a string. Upper-case and lower-case letters are treated as equal." | |
224 (while (and list (not (eq t (compare-strings elt 0 nil (car list) 0 nil t)))) | |
225 (setq list (cdr list))) | |
226 list) | |
227 | |
228 | |
428 | 229 ;;;; Keymap support. |
230 ;; XEmacs: removed to keymap.el | |
231 | |
232 ;;;; The global keymap tree. | |
233 | |
234 ;;; global-map, esc-map, and ctl-x-map have their values set up in | |
235 ;;; keymap.c; we just give them docstrings here. | |
236 | |
237 ;;;; Event manipulation functions. | |
238 | |
239 ;; XEmacs: This stuff is done in C Code. | |
240 | |
1333 | 241 ;;;; Obsolescent names for functions generally appear elsewhere, in |
242 ;;;; obsolete.el or in the files they are related do. Many very old | |
243 ;;;; obsolete stuff has been removed entirely (e.g. anything with `dot' in | |
244 ;;;; place of `point'). | |
245 | |
246 ; alternate names (not obsolete) | |
247 (if (not (fboundp 'mod)) (define-function 'mod '%)) | |
248 (define-function 'move-marker 'set-marker) | |
249 (define-function 'beep 'ding) ; preserve lingual purity | |
250 (define-function 'indent-to-column 'indent-to) | |
251 (define-function 'backward-delete-char 'delete-backward-char) | |
252 (define-function 'search-forward-regexp (symbol-function 're-search-forward)) | |
253 (define-function 'search-backward-regexp (symbol-function 're-search-backward)) | |
254 (define-function 'remove-directory 'delete-directory) | |
255 (define-function 'set-match-data 'store-match-data) | |
256 (define-function 'send-string-to-terminal 'external-debugging-output) | |
4905
755ae5b97edb
Change "special form" to "special operator" in our sources.
Aidan Kehoe <kehoea@parhasard.net>
parents:
4817
diff
changeset
|
257 (define-function 'special-form-p 'special-operator-p) |
428 | 258 |
5089
99f8ebc082d9
Make #'substring an alias of #'subseq; give the latter the byte code.
Aidan Kehoe <kehoea@parhasard.net>
parents:
5004
diff
changeset
|
259 ;; XEmacs; this is in Lisp, its bytecode now taken by subseq. |
99f8ebc082d9
Make #'substring an alias of #'subseq; give the latter the byte code.
Aidan Kehoe <kehoea@parhasard.net>
parents:
5004
diff
changeset
|
260 (define-function 'substring 'subseq) |
5327
d1b17a33450b
Move the heavy lifting from cl-seq.el to C.
Aidan Kehoe <kehoea@parhasard.net>
parents:
5321
diff
changeset
|
261 |
d1b17a33450b
Move the heavy lifting from cl-seq.el to C.
Aidan Kehoe <kehoea@parhasard.net>
parents:
5321
diff
changeset
|
262 (define-function 'sort 'sort*) |
d1b17a33450b
Move the heavy lifting from cl-seq.el to C.
Aidan Kehoe <kehoea@parhasard.net>
parents:
5321
diff
changeset
|
263 (define-function 'fillarray 'fill) |
5089
99f8ebc082d9
Make #'substring an alias of #'subseq; give the latter the byte code.
Aidan Kehoe <kehoea@parhasard.net>
parents:
5004
diff
changeset
|
264 |
428 | 265 ;; XEmacs: |
266 (defun local-variable-if-set-p (sym buffer) | |
267 "Return t if SYM would be local to BUFFER after it is set. | |
268 A nil value for BUFFER is *not* the same as (current-buffer), but | |
269 can be used to determine whether `make-variable-buffer-local' has been | |
270 called on SYM." | |
271 (local-variable-p sym buffer t)) | |
272 | |
273 | |
274 ;;;; Hook manipulation functions. | |
275 | |
276 ;; (defconst run-hooks 'run-hooks ...) | |
277 | |
278 (defun make-local-hook (hook) | |
279 "Make the hook HOOK local to the current buffer. | |
1333 | 280 The return value is HOOK. |
281 | |
282 You never need to call this function now that `add-hook' does it for you | |
283 if its LOCAL argument is non-nil. | |
284 | |
428 | 285 When a hook is local, its local and global values |
286 work in concert: running the hook actually runs all the hook | |
287 functions listed in *either* the local value *or* the global value | |
288 of the hook variable. | |
289 | |
290 This function works by making `t' a member of the buffer-local value, | |
291 which acts as a flag to run the hook functions in the default value as | |
292 well. This works for all normal hooks, but does not work for most | |
293 non-normal hooks yet. We will be changing the callers of non-normal | |
294 hooks so that they can handle localness; this has to be done one by | |
295 one. | |
296 | |
297 This function does nothing if HOOK is already local in the current | |
298 buffer. | |
299 | |
1333 | 300 Do not use `make-local-variable' to make a hook variable buffer-local." |
428 | 301 (if (local-variable-p hook (current-buffer)) ; XEmacs |
302 nil | |
303 (or (boundp hook) (set hook nil)) | |
304 (make-local-variable hook) | |
1333 | 305 (set hook (list t))) |
306 hook) | |
428 | 307 |
308 (defun add-hook (hook function &optional append local) | |
309 "Add to the value of HOOK the function FUNCTION. | |
310 FUNCTION is not added if already present. | |
311 FUNCTION is added (if necessary) at the beginning of the hook list | |
312 unless the optional argument APPEND is non-nil, in which case | |
313 FUNCTION is added at the end. | |
314 | |
315 The optional fourth argument, LOCAL, if non-nil, says to modify | |
316 the hook's buffer-local value rather than its default value. | |
1333 | 317 This makes the hook buffer-local if needed. |
428 | 318 To make a hook variable buffer-local, always use |
319 `make-local-hook', not `make-local-variable'. | |
320 | |
321 HOOK should be a symbol, and FUNCTION may be any valid function. If | |
322 HOOK is void, it is first set to nil. If HOOK's value is a single | |
442 | 323 function, it is changed to a list of functions. |
324 | |
325 You can remove this hook yourself using `remove-hook'. | |
326 | |
1333 | 327 See also `add-one-shot-hook'." |
428 | 328 (or (boundp hook) (set hook nil)) |
329 (or (default-boundp hook) (set-default hook nil)) | |
1333 | 330 (if local (unless (local-variable-if-set-p hook (current-buffer)) ; XEmacs |
331 (make-local-hook hook)) | |
332 ;; Detect the case where make-local-variable was used on a hook | |
333 ;; and do what we used to do. | |
334 (unless (and (consp (symbol-value hook)) (memq t (symbol-value hook))) | |
335 (setq local t))) | |
336 (let ((hook-value (if local (symbol-value hook) (default-value hook)))) | |
337 ;; If the hook value is a single function, turn it into a list. | |
338 (when (or (not (listp hook-value)) (eq (car hook-value) 'lambda)) | |
339 (setq hook-value (list hook-value))) | |
340 ;; Do the actual addition if necessary | |
341 (unless (member function hook-value) | |
342 (setq hook-value | |
343 (if append | |
344 (append hook-value (list function)) | |
345 (cons function hook-value)))) | |
346 ;; Set the actual variable | |
347 (if local (set hook hook-value) (set-default hook hook-value)))) | |
428 | 348 |
349 (defun remove-hook (hook function &optional local) | |
350 "Remove from the value of HOOK the function FUNCTION. | |
351 HOOK should be a symbol, and FUNCTION may be any valid function. If | |
352 FUNCTION isn't the value of HOOK, or, if FUNCTION doesn't appear in the | |
353 list of hooks to run in HOOK, then nothing is done. See `add-hook'. | |
354 | |
355 The optional third argument, LOCAL, if non-nil, says to modify | |
356 the hook's buffer-local value rather than its default value. | |
1333 | 357 This makes the hook buffer-local if needed. |
428 | 358 To make a hook variable buffer-local, always use |
359 `make-local-hook', not `make-local-variable'." | |
1333 | 360 (or (boundp hook) (set hook nil)) |
361 (or (default-boundp hook) (set-default hook nil)) | |
362 (if local (unless (local-variable-if-set-p hook (current-buffer)) ; XEmacs | |
363 (make-local-hook hook)) | |
364 ;; Detect the case where make-local-variable was used on a hook | |
365 ;; and do what we used to do. | |
366 (unless (and (consp (symbol-value hook)) (memq t (symbol-value hook))) | |
367 (setq local t))) | |
368 (let ((hook-value (if local (symbol-value hook) (default-value hook)))) | |
369 ;; Remove the function, for both the list and the non-list cases. | |
370 ;; XEmacs: add hook-test, for handling one-shot hooks. | |
371 (flet ((hook-test | |
372 (fn hel) | |
373 (or (equal fn hel) | |
374 (and (symbolp hel) | |
375 (equal fn | |
376 (get hel 'one-shot-hook-fun)))))) | |
377 (if (or (not (listp hook-value)) (eq (car hook-value) 'lambda)) | |
378 (if (equal hook-value function) (setq hook-value nil)) | |
379 (setq hook-value (delete* function (copy-sequence hook-value) | |
380 :test 'hook-test))) | |
381 ;; If the function is on the global hook, we need to shadow it locally | |
382 ;;(when (and local (member* function (default-value hook) | |
383 ;; :test 'hook-test) | |
384 ;; (not (member* (cons 'not function) hook-value | |
385 ;; :test 'hook-test))) | |
386 ;; (push (cons 'not function) hook-value)) | |
387 ;; Set the actual variable | |
388 (if local (set hook hook-value) (set-default hook hook-value))))) | |
442 | 389 |
390 ;; XEmacs addition | |
391 ;; #### we need a coherent scheme for indicating compatibility info, | |
392 ;; so that it can be programmatically retrieved. | |
393 (defun add-local-hook (hook function &optional append) | |
394 "Add to the local value of HOOK the function FUNCTION. | |
1333 | 395 You don't need this any more. It's equivalent to specifying the LOCAL |
396 argument to `add-hook'." | |
442 | 397 (add-hook hook function append t)) |
398 | |
399 ;; XEmacs addition | |
400 (defun remove-local-hook (hook function) | |
401 "Remove from the local value of HOOK the function FUNCTION. | |
1333 | 402 You don't need this any more. It's equivalent to specifying the LOCAL |
403 argument to `remove-hook'." | |
404 (remove-hook hook function t)) | |
442 | 405 |
406 (defun add-one-shot-hook (hook function &optional append local) | |
407 "Add to the value of HOOK the one-shot function FUNCTION. | |
408 FUNCTION will automatically be removed from the hook the first time | |
409 after it runs (whether to completion or to an error). | |
410 FUNCTION is not added if already present. | |
411 FUNCTION is added (if necessary) at the beginning of the hook list | |
412 unless the optional argument APPEND is non-nil, in which case | |
413 FUNCTION is added at the end. | |
414 | |
415 HOOK should be a symbol, and FUNCTION may be any valid function. If | |
416 HOOK is void, it is first set to nil. If HOOK's value is a single | |
417 function, it is changed to a list of functions. | |
418 | |
419 You can remove this hook yourself using `remove-hook'. | |
420 | |
1333 | 421 See also `add-hook'." |
442 | 422 (let ((sym (gensym))) |
423 (fset sym `(lambda (&rest args) | |
424 (unwind-protect | |
425 (apply ',function args) | |
426 (remove-hook ',hook ',sym ',local)))) | |
427 (put sym 'one-shot-hook-fun function) | |
428 (add-hook hook sym append local))) | |
429 | |
430 (defun add-local-one-shot-hook (hook function &optional append) | |
431 "Add to the local value of HOOK the one-shot function FUNCTION. | |
1333 | 432 You don't need this any more. It's equivalent to specifying the LOCAL |
433 argument to `add-one-shot-hook'." | |
442 | 434 (add-one-shot-hook hook function append t)) |
428 | 435 |
4461
42fad34efb3f
Support COMPARE-FN in add-to-list; thank you Brian Palmer.
Aidan Kehoe <kehoea@parhasard.net>
parents:
4369
diff
changeset
|
436 (defun add-to-list (list-var element &optional append compare-fn) |
428 | 437 "Add to the value of LIST-VAR the element ELEMENT if it isn't there yet. |
4461
42fad34efb3f
Support COMPARE-FN in add-to-list; thank you Brian Palmer.
Aidan Kehoe <kehoea@parhasard.net>
parents:
4369
diff
changeset
|
438 The test for presence of ELEMENT is done with COMPARE-FN; if |
42fad34efb3f
Support COMPARE-FN in add-to-list; thank you Brian Palmer.
Aidan Kehoe <kehoea@parhasard.net>
parents:
4369
diff
changeset
|
439 COMPARE-FN is nil, then it defaults to `equal'. If ELEMENT is added, |
42fad34efb3f
Support COMPARE-FN in add-to-list; thank you Brian Palmer.
Aidan Kehoe <kehoea@parhasard.net>
parents:
4369
diff
changeset
|
440 it is added at the beginning of the list, unless the optional argument |
42fad34efb3f
Support COMPARE-FN in add-to-list; thank you Brian Palmer.
Aidan Kehoe <kehoea@parhasard.net>
parents:
4369
diff
changeset
|
441 APPEND is non-nil, in which case ELEMENT is added at the end. |
878 | 442 |
428 | 443 If you want to use `add-to-list' on a variable that is not defined |
444 until a certain package is loaded, you should put the call to `add-to-list' | |
445 into a hook function that will be run only after loading the package. | |
446 `eval-after-load' provides one way to do this. In some cases | |
447 other hooks, such as major mode hooks, can do the job." | |
4463 | 448 (if (member* element (symbol-value list-var) :test (or compare-fn #'equal)) |
878 | 449 (symbol-value list-var) |
450 (set list-var | |
451 (if append | |
452 (append (symbol-value list-var) (list element)) | |
453 (cons element (symbol-value list-var)))))) | |
428 | 454 |
1333 | 455 ;; END SYNCHED WITH FSF 21.2 |
456 | |
428 | 457 ;; XEmacs additions |
458 ;; called by Fkill_buffer() | |
459 (defvar kill-buffer-hook nil | |
460 "Function or functions to be called when a buffer is killed. | |
461 The value of this variable may be buffer-local. | |
462 The buffer about to be killed is current when this hook is run.") | |
463 | |
464 ;; in C in FSFmacs | |
465 (defvar kill-emacs-hook nil | |
466 "Function or functions to be called when `kill-emacs' is called, | |
467 just before emacs is actually killed.") | |
468 | |
469 ;; not obsolete. | |
470 ;; #### These are a bad idea, because the CL RPLACA and RPLACD | |
471 ;; return the cons cell, not the new CAR/CDR. -hniksic | |
472 ;; The proper definition would be: | |
473 ;; (defun rplaca (conscell newcar) | |
474 ;; (setcar conscell newcar) | |
475 ;; conscell) | |
476 ;; ...and analogously for RPLACD. | |
477 (define-function 'rplaca 'setcar) | |
478 (define-function 'rplacd 'setcdr) | |
479 | |
480 (defun copy-symbol (symbol &optional copy-properties) | |
481 "Return a new uninterned symbol with the same name as SYMBOL. | |
482 If COPY-PROPERTIES is non-nil, the new symbol will have a copy of | |
483 SYMBOL's value, function, and property lists." | |
484 (let ((new (make-symbol (symbol-name symbol)))) | |
485 (when copy-properties | |
486 ;; This will not copy SYMBOL's chain of forwarding objects, but | |
487 ;; I think that's OK. Callers should not expect such magic to | |
488 ;; keep working in the copy in the first place. | |
489 (and (boundp symbol) | |
490 (set new (symbol-value symbol))) | |
491 (and (fboundp symbol) | |
492 (fset new (symbol-function symbol))) | |
493 (setplist new (copy-list (symbol-plist symbol)))) | |
494 new)) | |
495 | |
442 | 496 (defun set-symbol-value-in-buffer (sym val buffer) |
497 "Set the value of SYM to VAL in BUFFER. Useful with buffer-local variables. | |
498 If SYM has a buffer-local value in BUFFER, or will have one if set, this | |
499 function allows you to set the local value. | |
500 | |
501 NOTE: At some point, this will be moved into C and will be very fast." | |
502 (with-current-buffer buffer | |
503 (set sym val))) | |
444 | 504 |
1333 | 505 |
506 ;; BEGIN SYNCHED WITH FSF 21.2 | |
507 | |
508 ;; #### #### #### AAaargh! Must be in C, because it is used insanely | |
509 ;; early in the bootstrap process. | |
510 ;(defun split-path (path) | |
511 ; "Explode a search path into a list of strings. | |
512 ;The path components are separated with the characters specified | |
513 ;with `path-separator'." | |
514 ; (while (or (not stringp path-separator) | |
515 ; (/= (length path-separator) 1)) | |
516 ; (setq path-separator (signal 'error (list "\ | |
517 ;`path-separator' should be set to a single-character string" | |
518 ; path-separator)))) | |
519 ; (split-string-by-char path (aref separator 0))) | |
520 | |
521 (defmacro with-current-buffer (buffer &rest body) | |
522 "Temporarily make BUFFER the current buffer and execute the forms in BODY. | |
523 The value returned is the value of the last form in BODY. | |
524 See also `with-temp-buffer'." | |
525 `(save-current-buffer | |
526 (set-buffer ,buffer) | |
527 ,@body)) | |
528 | |
529 (defmacro with-temp-file (filename &rest forms) | |
530 "Create a new buffer, evaluate FORMS there, and write the buffer to FILENAME. | |
531 The value of the last form in FORMS is returned, like `progn'. | |
532 See also `with-temp-buffer'." | |
533 (let ((temp-file (make-symbol "temp-file")) | |
534 (temp-buffer (make-symbol "temp-buffer"))) | |
535 `(let ((,temp-file ,filename) | |
536 (,temp-buffer | |
537 (get-buffer-create (generate-new-buffer-name " *temp file*")))) | |
538 (unwind-protect | |
539 (prog1 | |
540 (with-current-buffer ,temp-buffer | |
541 ,@forms) | |
542 (with-current-buffer ,temp-buffer | |
543 (widen) | |
544 (write-region (point-min) (point-max) ,temp-file nil 0))) | |
545 (and (buffer-name ,temp-buffer) | |
546 (kill-buffer ,temp-buffer)))))) | |
547 | |
548 ;; FSF compatibility | |
549 (defmacro with-temp-message (message &rest body) | |
550 "Display MESSAGE temporarily while BODY is evaluated. | |
551 The original message is restored to the echo area after BODY has finished. | |
552 The value returned is the value of the last form in BODY. | |
553 If MESSAGE is nil, the echo area and message log buffer are unchanged. | |
554 Use a MESSAGE of \"\" to temporarily clear the echo area. | |
428 | 555 |
1333 | 556 Note that this function exists for FSF compatibility purposes. A better way |
557 under XEmacs is to give the message a particular label (see `display-message'); | |
558 then, the old message is automatically restored when you clear your message | |
559 with `clear-message'." | |
560 ;; FSF additional doc string from 21.2: | |
561 ;; MESSAGE is written to the message log buffer if `message-log-max' is non-nil. | |
562 (let ((current-message (make-symbol "current-message")) | |
563 (temp-message (make-symbol "with-temp-message"))) | |
564 `(let ((,temp-message ,message) | |
565 (,current-message)) | |
566 (unwind-protect | |
567 (progn | |
568 (when ,temp-message | |
569 (setq ,current-message (current-message)) | |
570 (message "%s" ,temp-message)) | |
571 ,@body) | |
572 (and ,temp-message ,current-message | |
573 (message "%s" ,current-message)))))) | |
574 | |
575 (defmacro with-temp-buffer (&rest forms) | |
576 "Create a temporary buffer, and evaluate FORMS there like `progn'. | |
577 See also `with-temp-file' and `with-output-to-string'." | |
578 (let ((temp-buffer (make-symbol "temp-buffer"))) | |
579 `(let ((,temp-buffer | |
580 (get-buffer-create (generate-new-buffer-name " *temp*")))) | |
581 (unwind-protect | |
582 (with-current-buffer ,temp-buffer | |
583 ,@forms) | |
584 (and (buffer-name ,temp-buffer) | |
585 (kill-buffer ,temp-buffer)))))) | |
586 | |
587 (defmacro with-output-to-string (&rest body) | |
588 "Execute BODY, return the text it sent to `standard-output', as a string." | |
589 `(let ((standard-output | |
590 (get-buffer-create (generate-new-buffer-name " *string-output*")))) | |
591 (let ((standard-output standard-output)) | |
592 ,@body) | |
593 (with-current-buffer standard-output | |
594 (prog1 | |
595 (buffer-string) | |
596 (kill-buffer nil))))) | |
597 | |
2135 | 598 (defmacro with-local-quit (&rest body) |
599 "Execute BODY with `inhibit-quit' temporarily bound to nil." | |
600 `(condition-case nil | |
601 (let ((inhibit-quit nil)) | |
602 ,@body) | |
603 (quit (setq quit-flag t)))) | |
604 | |
605 ;; FSF 21.3. | |
1333 | 606 |
607 ; (defmacro combine-after-change-calls (&rest body) | |
608 ; "Execute BODY, but don't call the after-change functions till the end. | |
609 ; If BODY makes changes in the buffer, they are recorded | |
610 ; and the functions on `after-change-functions' are called several times | |
611 ; when BODY is finished. | |
612 ; The return value is the value of the last form in BODY. | |
613 | |
614 ; If `before-change-functions' is non-nil, then calls to the after-change | |
615 ; functions can't be deferred, so in that case this macro has no effect. | |
616 | |
617 ; Do not alter `after-change-functions' or `before-change-functions' | |
618 ; in BODY." | |
2135 | 619 ; (declare (indent 0) (debug t)) |
1333 | 620 ; `(unwind-protect |
621 ; (let ((combine-after-change-calls t)) | |
622 ; . ,body) | |
623 ; (combine-after-change-execute))) | |
801 | 624 |
4369
ef9eb714f0e4
Add ascii-case-table, #'with-case-table; make iso8859-1.el more comprehensible.
Aidan Kehoe <kehoea@parhasard.net>
parents:
4329
diff
changeset
|
625 (defmacro with-case-table (table &rest body) |
ef9eb714f0e4
Add ascii-case-table, #'with-case-table; make iso8859-1.el more comprehensible.
Aidan Kehoe <kehoea@parhasard.net>
parents:
4329
diff
changeset
|
626 "Execute the forms in BODY with TABLE as the current case table. |
ef9eb714f0e4
Add ascii-case-table, #'with-case-table; make iso8859-1.el more comprehensible.
Aidan Kehoe <kehoea@parhasard.net>
parents:
4329
diff
changeset
|
627 The value returned is the value of the last form in BODY." |
ef9eb714f0e4
Add ascii-case-table, #'with-case-table; make iso8859-1.el more comprehensible.
Aidan Kehoe <kehoea@parhasard.net>
parents:
4329
diff
changeset
|
628 (declare (indent 1) (debug t)) |
ef9eb714f0e4
Add ascii-case-table, #'with-case-table; make iso8859-1.el more comprehensible.
Aidan Kehoe <kehoea@parhasard.net>
parents:
4329
diff
changeset
|
629 (let ((old-case-table (make-symbol "table")) |
ef9eb714f0e4
Add ascii-case-table, #'with-case-table; make iso8859-1.el more comprehensible.
Aidan Kehoe <kehoea@parhasard.net>
parents:
4329
diff
changeset
|
630 (old-buffer (make-symbol "buffer"))) |
ef9eb714f0e4
Add ascii-case-table, #'with-case-table; make iso8859-1.el more comprehensible.
Aidan Kehoe <kehoea@parhasard.net>
parents:
4329
diff
changeset
|
631 `(let ((,old-case-table (current-case-table)) |
ef9eb714f0e4
Add ascii-case-table, #'with-case-table; make iso8859-1.el more comprehensible.
Aidan Kehoe <kehoea@parhasard.net>
parents:
4329
diff
changeset
|
632 (,old-buffer (current-buffer))) |
ef9eb714f0e4
Add ascii-case-table, #'with-case-table; make iso8859-1.el more comprehensible.
Aidan Kehoe <kehoea@parhasard.net>
parents:
4329
diff
changeset
|
633 (unwind-protect |
ef9eb714f0e4
Add ascii-case-table, #'with-case-table; make iso8859-1.el more comprehensible.
Aidan Kehoe <kehoea@parhasard.net>
parents:
4329
diff
changeset
|
634 (progn (set-case-table ,table) |
ef9eb714f0e4
Add ascii-case-table, #'with-case-table; make iso8859-1.el more comprehensible.
Aidan Kehoe <kehoea@parhasard.net>
parents:
4329
diff
changeset
|
635 ,@body) |
ef9eb714f0e4
Add ascii-case-table, #'with-case-table; make iso8859-1.el more comprehensible.
Aidan Kehoe <kehoea@parhasard.net>
parents:
4329
diff
changeset
|
636 (with-current-buffer ,old-buffer |
ef9eb714f0e4
Add ascii-case-table, #'with-case-table; make iso8859-1.el more comprehensible.
Aidan Kehoe <kehoea@parhasard.net>
parents:
4329
diff
changeset
|
637 (set-case-table ,old-case-table)))))) |
2135 | 638 |
639 (defvar delay-mode-hooks nil | |
640 "If non-nil, `run-mode-hooks' should delay running the hooks.") | |
641 (defvar delayed-mode-hooks nil | |
642 "List of delayed mode hooks waiting to be run.") | |
643 (make-variable-buffer-local 'delayed-mode-hooks) | |
644 (put 'delay-mode-hooks 'permanent-local t) | |
645 | |
646 (defun run-mode-hooks (&rest hooks) | |
647 "Run mode hooks `delayed-mode-hooks' and HOOKS, or delay HOOKS. | |
648 Execution is delayed if `delay-mode-hooks' is non-nil. | |
649 Major mode functions should use this." | |
650 (if delay-mode-hooks | |
651 ;; Delaying case. | |
652 (dolist (hook hooks) | |
653 (push hook delayed-mode-hooks)) | |
654 ;; Normal case, just run the hook as before plus any delayed hooks. | |
655 (setq hooks (nconc (nreverse delayed-mode-hooks) hooks)) | |
656 (setq delayed-mode-hooks nil) | |
657 (apply 'run-hooks hooks))) | |
658 | |
659 (defmacro delay-mode-hooks (&rest body) | |
660 "Execute BODY, but delay any `run-mode-hooks'. | |
661 Only affects hooks run in the current buffer." | |
662 `(progn | |
663 (make-local-variable 'delay-mode-hooks) | |
664 (let ((delay-mode-hooks t)) | |
665 ,@body))) | |
666 | |
1333 | 667 (defmacro with-syntax-table (table &rest body) |
668 "Evaluate BODY with syntax table of current buffer set to a copy of TABLE. | |
669 The syntax table of the current buffer is saved, BODY is evaluated, and the | |
670 saved table is restored, even in case of an abnormal exit. | |
671 Value is what BODY returns." | |
672 (let ((old-table (make-symbol "table")) | |
673 (old-buffer (make-symbol "buffer"))) | |
674 `(let ((,old-table (syntax-table)) | |
675 (,old-buffer (current-buffer))) | |
676 (unwind-protect | |
677 (progn | |
678 (set-syntax-table (copy-syntax-table ,table)) | |
679 ,@body) | |
680 (save-current-buffer | |
681 (set-buffer ,old-buffer) | |
682 (set-syntax-table ,old-table)))))) | |
683 | |
684 (put 'with-syntax-table 'lisp-indent-function 1) | |
685 (put 'with-syntax-table 'edebug-form-spec '(form body)) | |
686 | |
687 | |
688 ;; Moved from mule-coding.el. | |
689 (defmacro with-string-as-buffer-contents (str &rest body) | |
690 "With the contents of the current buffer being STR, run BODY. | |
4516
e96f3aca4d63
Document initial position of point in `with-string-as-buffer-contents'.
Stephen J. Turnbull <stephen@xemacs.org>
parents:
4504
diff
changeset
|
691 Point starts positioned to end of buffer. |
1333 | 692 Returns the new contents of the buffer, as modified by BODY. |
693 The original current buffer is restored afterwards." | |
694 `(with-temp-buffer | |
695 (insert ,str) | |
696 ,@body | |
697 (buffer-string))) | |
698 | |
699 | |
700 (defmacro save-match-data (&rest body) | |
701 "Execute BODY forms, restoring the global value of the match data." | |
702 (let ((original (make-symbol "match-data"))) | |
703 (list 'let (list (list original '(match-data))) | |
704 (list 'unwind-protect | |
705 (cons 'progn body) | |
706 (list 'store-match-data original))))) | |
707 | |
708 | |
709 (defun match-string (num &optional string) | |
710 "Return string of text matched by last search. | |
711 NUM specifies which parenthesized expression in the last regexp. | |
712 Value is nil if NUMth pair didn't match, or there were less than NUM pairs. | |
713 Zero means the entire text matched by the whole regexp or whole string. | |
714 STRING should be given if the last search was by `string-match' on STRING." | |
715 (if (match-beginning num) | |
716 (if string | |
717 (substring string (match-beginning num) (match-end num)) | |
718 (buffer-substring (match-beginning num) (match-end num))))) | |
801 | 719 |
1333 | 720 (defun match-string-no-properties (num &optional string) |
721 "Return string of text matched by last search, without text properties. | |
722 NUM specifies which parenthesized expression in the last regexp. | |
723 Value is nil if NUMth pair didn't match, or there were less than NUM pairs. | |
724 Zero means the entire text matched by the whole regexp or whole string. | |
725 STRING should be given if the last search was by `string-match' on STRING." | |
726 (if (match-beginning num) | |
727 (if string | |
728 (let ((result | |
729 (substring string (match-beginning num) (match-end num)))) | |
730 (set-text-properties 0 (length result) nil result) | |
731 result) | |
732 (buffer-substring-no-properties (match-beginning num) | |
733 (match-end num))))) | |
734 | |
1425 | 735 (defconst split-string-default-separators "[ \f\t\n\r\v]+" |
736 "The default value of separators for `split-string'. | |
737 | |
738 A regexp matching strings of whitespace. May be locale-dependent | |
739 \(as yet unimplemented). Should not match non-breaking spaces. | |
740 | |
741 Warning: binding this to a different value and using it as default is | |
742 likely to have undesired semantics.") | |
743 | |
744 ;; specification for `split-string' agreed with rms 2003-04-23 | |
745 ;; xemacs design <87vfx5vor0.fsf@tleepslib.sk.tsukuba.ac.jp> | |
746 | |
1495 | 747 ;; The specification says that if both SEPARATORS and OMIT-NULLS are |
748 ;; defaulted, OMIT-NULLS should be treated as t. Simplifying the logical | |
749 ;; expression leads to the equivalent implementation that if SEPARATORS | |
750 ;; is defaulted, OMIT-NULLS is treated as t. | |
751 | |
1425 | 752 (defun split-string (string &optional separators omit-nulls) |
753 "Splits STRING into substrings bounded by matches for SEPARATORS. | |
754 | |
755 The beginning and end of STRING, and each match for SEPARATORS, are | |
756 splitting points. The substrings matching SEPARATORS are removed, and | |
757 the substrings between the splitting points are collected as a list, | |
1333 | 758 which is returned. |
1425 | 759 |
2138 | 760 If SEPARATORS is non-`nil', it should be a regular expression matching text |
761 which separates, but is not part of, the substrings. If `nil' it defaults to | |
1495 | 762 `split-string-default-separators', normally \"[ \\f\\t\\n\\r\\v]+\", and |
2138 | 763 OMIT-NULLS is forced to `t'. |
1333 | 764 |
2138 | 765 If OMIT-NULLS is `t', zero-length substrings are omitted from the list \(so |
1425 | 766 that for the default value of SEPARATORS leading and trailing whitespace |
2138 | 767 are effectively trimmed). If `nil', all zero-length substrings are retained, |
1425 | 768 which correctly parses CSV format, for example. |
769 | |
1495 | 770 Note that the effect of `(split-string STRING)' is the same as |
771 `(split-string STRING split-string-default-separators t)'). In the rare | |
772 case that you wish to retain zero-length substrings when splitting on | |
773 whitespace, use `(split-string STRING split-string-default-separators nil)'. | |
1333 | 774 |
2138 | 775 Modifies the match data when successful; use `save-match-data' if necessary." |
1425 | 776 |
1495 | 777 (let ((keep-nulls (not (if separators omit-nulls t))) |
1425 | 778 (rexp (or separators split-string-default-separators)) |
1333 | 779 (start 0) |
780 notfirst | |
781 (list nil)) | |
782 (while (and (string-match rexp string | |
783 (if (and notfirst | |
784 (= start (match-beginning 0)) | |
785 (< start (length string))) | |
786 (1+ start) start)) | |
1425 | 787 (< start (length string))) |
1333 | 788 (setq notfirst t) |
1425 | 789 (if (or keep-nulls (< start (match-beginning 0))) |
1333 | 790 (setq list |
791 (cons (substring string start (match-beginning 0)) | |
792 list))) | |
793 (setq start (match-end 0))) | |
1425 | 794 (if (or keep-nulls (< start (length string))) |
1333 | 795 (setq list |
796 (cons (substring string start) | |
797 list))) | |
798 (nreverse list))) | |
799 | |
800 (defun subst-char-in-string (fromchar tochar string &optional inplace) | |
801 "Replace FROMCHAR with TOCHAR in STRING each time it occurs. | |
802 Unless optional argument INPLACE is non-nil, return a new string." | |
5321
57a64ab2ae45
Implement some basic Lisp functions in terms of Common Lisp builtins.
Aidan Kehoe <kehoea@parhasard.net>
parents:
5284
diff
changeset
|
803 (funcall (if inplace #'nsubstitute #'substitute) tochar fromchar |
57a64ab2ae45
Implement some basic Lisp functions in terms of Common Lisp builtins.
Aidan Kehoe <kehoea@parhasard.net>
parents:
5284
diff
changeset
|
804 (the string string) :test #'eq)) |
1333 | 805 |
806 ;; XEmacs addition: | |
428 | 807 (defun replace-in-string (str regexp newtext &optional literal) |
808 "Replace all matches in STR for REGEXP with NEWTEXT string, | |
809 and returns the new string. | |
810 Optional LITERAL non-nil means do a literal replacement. | |
442 | 811 Otherwise treat `\\' in NEWTEXT as special: |
812 `\\&' in NEWTEXT means substitute original matched text. | |
813 `\\N' means substitute what matched the Nth `\\(...\\)'. | |
814 If Nth parens didn't match, substitute nothing. | |
815 `\\\\' means insert one `\\'. | |
816 `\\u' means upcase the next character. | |
817 `\\l' means downcase the next character. | |
818 `\\U' means begin upcasing all following characters. | |
819 `\\L' means begin downcasing all following characters. | |
820 `\\E' means terminate the effect of any `\\U' or `\\L'." | |
428 | 821 (check-argument-type 'stringp str) |
822 (check-argument-type 'stringp newtext) | |
442 | 823 (if (> (length str) 50) |
924 | 824 (let ((cfs case-fold-search)) |
825 (with-temp-buffer | |
826 (setq case-fold-search cfs) | |
827 (insert str) | |
828 (goto-char 1) | |
442 | 829 (while (re-search-forward regexp nil t) |
830 (replace-match newtext t literal)) | |
924 | 831 (buffer-string))) |
832 (let ((start 0) newstr) | |
833 (while (string-match regexp str start) | |
834 (setq newstr (replace-match newtext t literal str) | |
835 start (+ (match-end 0) (- (length newstr) (length str))) | |
836 str newstr)) | |
837 str))) | |
428 | 838 |
1333 | 839 (defun replace-regexp-in-string (regexp rep string &optional |
840 fixedcase literal subexp start) | |
841 "Replace all matches for REGEXP with REP in STRING. | |
842 | |
843 Return a new string containing the replacements. | |
844 | |
4199 | 845 Optional arguments FIXEDCASE and LITERAL are like the arguments with |
846 the same names of function `replace-match'. If START is non-nil, | |
847 start replacements at that index in STRING. | |
848 | |
849 For compatibility with old XEmacs code and with recent GNU Emacs, the | |
850 interpretation of SUBEXP is somewhat complicated. If SUBEXP is a | |
851 buffer, it is interpreted as the buffer which provides syntax tables | |
852 and case tables for the match and replacement. If it is not a buffer, | |
853 the current buffer is used. If SUBEXP is an integer, it is the index | |
854 of the subexpression of REGEXP which is to be replaced. | |
428 | 855 |
1333 | 856 REP is either a string used as the NEWTEXT arg of `replace-match' or a |
857 function. If it is a function it is applied to each match to generate | |
858 the replacement passed to `replace-match'; the match-data at this | |
4199 | 859 point are such that `(match-string SUBEXP STRING)' is the function's |
860 argument if SUBEXP is an integer \(otherwise the whole match is passed | |
861 and replaced). | |
428 | 862 |
1333 | 863 To replace only the first match (if any), make REGEXP match up to \\' |
864 and replace a sub-expression, e.g. | |
865 (replace-regexp-in-string \"\\(foo\\).*\\'\" \"bar\" \" foo foo\" nil nil 1) | |
866 => \" bar foo\" | |
4199 | 867 |
868 Signals `invalid-argument' if SUBEXP is not an integer, buffer, or nil; | |
869 or is an integer, but the indicated subexpression was not matched. | |
870 Signals `invalid-argument' if STRING is nil but the last text matched was a string, | |
871 or if STRING is a string but the last text matched was a buffer." | |
428 | 872 |
1333 | 873 ;; To avoid excessive consing from multiple matches in long strings, |
874 ;; don't just call `replace-match' continually. Walk down the | |
875 ;; string looking for matches of REGEXP and building up a (reversed) | |
876 ;; list MATCHES. This comprises segments of STRING which weren't | |
877 ;; matched interspersed with replacements for segments that were. | |
878 ;; [For a `large' number of replacments it's more efficient to | |
879 ;; operate in a temporary buffer; we can't tell from the function's | |
880 ;; args whether to choose the buffer-based implementation, though it | |
881 ;; might be reasonable to do so for long enough STRING.] | |
882 (let ((l (length string)) | |
883 (start (or start 0)) | |
4199 | 884 (expndx (if (integerp subexp) subexp 0)) |
1333 | 885 matches str mb me) |
886 (save-match-data | |
887 (while (and (< start l) (string-match regexp string start)) | |
888 (setq mb (match-beginning 0) | |
889 me (match-end 0)) | |
890 ;; If we matched the empty string, make sure we advance by one char | |
891 (when (= me mb) (setq me (min l (1+ mb)))) | |
892 ;; Generate a replacement for the matched substring. | |
893 ;; Operate only on the substring to minimize string consing. | |
894 ;; Set up match data for the substring for replacement; | |
895 ;; presumably this is likely to be faster than munging the | |
896 ;; match data directly in Lisp. | |
897 (string-match regexp (setq str (substring string mb me))) | |
898 (setq matches | |
899 (cons (replace-match (if (stringp rep) | |
900 rep | |
4199 | 901 (funcall rep (match-string expndx str))) |
902 ;; no, this subexp shouldn't be expndx | |
1333 | 903 fixedcase literal str subexp) |
904 (cons (substring string start mb) ; unmatched prefix | |
905 matches))) | |
906 (setq start me)) | |
907 ;; Reconstruct a string from the pieces. | |
908 (setq matches (cons (substring string start l) matches)) ; leftover | |
909 (apply #'concat (nreverse matches))))) | |
428 | 910 |
1333 | 911 ;; END SYNCHED WITH FSF 21.2 |
912 | |
913 | |
1899 | 914 ;; BEGIN SYNCHED WITH FSF 21.3 |
915 | |
916 (defun add-to-invisibility-spec (arg) | |
917 "Add elements to `buffer-invisibility-spec'. | |
918 See documentation for `buffer-invisibility-spec' for the kind of elements | |
919 that can be added." | |
920 (if (eq buffer-invisibility-spec t) | |
921 (setq buffer-invisibility-spec (list t))) | |
922 (setq buffer-invisibility-spec | |
923 (cons arg buffer-invisibility-spec))) | |
924 | |
925 (defun remove-from-invisibility-spec (arg) | |
926 "Remove elements from `buffer-invisibility-spec'." | |
927 (if (consp buffer-invisibility-spec) | |
928 (setq buffer-invisibility-spec (delete arg buffer-invisibility-spec)))) | |
929 | |
930 ;; END SYNCHED WITH FSF 21.3 | |
931 | |
932 | |
1333 | 933 ;;; Basic string functions |
883 | 934 |
1333 | 935 ;; XEmacs |
936 (defun string-equal-ignore-case (str1 str2) | |
937 "Return t if two strings have identical contents, ignoring case differences. | |
938 Case is not significant. Text properties and extents are ignored. | |
939 Symbols are also allowed; their print names are used instead. | |
428 | 940 |
1333 | 941 See also `equalp'." |
942 (if (symbolp str1) | |
943 (setq str1 (symbol-name str1))) | |
944 (if (symbolp str2) | |
945 (setq str2 (symbol-name str2))) | |
946 (eq t (compare-strings str1 nil nil str2 nil nil t))) | |
428 | 947 |
948 (defun insert-face (string face) | |
949 "Insert STRING and highlight with FACE. Return the extent created." | |
950 (let ((p (point)) ext) | |
951 (insert string) | |
952 (setq ext (make-extent p (point))) | |
953 (set-extent-face ext face) | |
954 ext)) | |
955 | |
956 ;; not obsolete. | |
957 (define-function 'string= 'string-equal) | |
958 (define-function 'string< 'string-lessp) | |
959 (define-function 'int-to-string 'number-to-string) | |
960 (define-function 'string-to-int 'string-to-number) | |
961 | |
962 ;; These two names are a bit awkward, as they conflict with the normal | |
963 ;; foo-to-bar naming scheme, but CLtL2 has them, so they stay. | |
964 (define-function 'char-int 'char-to-int) | |
965 (define-function 'int-char 'int-to-char) | |
966 | |
4329
d9eb5ea14f65
Provide %b in #'format; use it for converting between ints and bit vectors.
Aidan Kehoe <kehoea@parhasard.net>
parents:
4267
diff
changeset
|
967 ;; XEmacs addition. |
d9eb5ea14f65
Provide %b in #'format; use it for converting between ints and bit vectors.
Aidan Kehoe <kehoea@parhasard.net>
parents:
4267
diff
changeset
|
968 (defun integer-to-bit-vector (integer &optional minlength) |
d9eb5ea14f65
Provide %b in #'format; use it for converting between ints and bit vectors.
Aidan Kehoe <kehoea@parhasard.net>
parents:
4267
diff
changeset
|
969 "Return INTEGER converted to a bit vector. |
d9eb5ea14f65
Provide %b in #'format; use it for converting between ints and bit vectors.
Aidan Kehoe <kehoea@parhasard.net>
parents:
4267
diff
changeset
|
970 Optional argument MINLENGTH gives a minimum length for the returned vector. |
d9eb5ea14f65
Provide %b in #'format; use it for converting between ints and bit vectors.
Aidan Kehoe <kehoea@parhasard.net>
parents:
4267
diff
changeset
|
971 If MINLENGTH is not given, zero high-order bits will be ignored." |
d9eb5ea14f65
Provide %b in #'format; use it for converting between ints and bit vectors.
Aidan Kehoe <kehoea@parhasard.net>
parents:
4267
diff
changeset
|
972 (check-argument-type #'integerp integer) |
d9eb5ea14f65
Provide %b in #'format; use it for converting between ints and bit vectors.
Aidan Kehoe <kehoea@parhasard.net>
parents:
4267
diff
changeset
|
973 (setq minlength (or minlength 0)) |
d9eb5ea14f65
Provide %b in #'format; use it for converting between ints and bit vectors.
Aidan Kehoe <kehoea@parhasard.net>
parents:
4267
diff
changeset
|
974 (check-nonnegative-number minlength) |
d9eb5ea14f65
Provide %b in #'format; use it for converting between ints and bit vectors.
Aidan Kehoe <kehoea@parhasard.net>
parents:
4267
diff
changeset
|
975 (read (format (format "#*%%0%db" minlength) integer))) |
d9eb5ea14f65
Provide %b in #'format; use it for converting between ints and bit vectors.
Aidan Kehoe <kehoea@parhasard.net>
parents:
4267
diff
changeset
|
976 |
d9eb5ea14f65
Provide %b in #'format; use it for converting between ints and bit vectors.
Aidan Kehoe <kehoea@parhasard.net>
parents:
4267
diff
changeset
|
977 ;; XEmacs addition. |
d9eb5ea14f65
Provide %b in #'format; use it for converting between ints and bit vectors.
Aidan Kehoe <kehoea@parhasard.net>
parents:
4267
diff
changeset
|
978 (defun bit-vector-to-integer (bit-vector) |
d9eb5ea14f65
Provide %b in #'format; use it for converting between ints and bit vectors.
Aidan Kehoe <kehoea@parhasard.net>
parents:
4267
diff
changeset
|
979 "Return BIT-VECTOR converted to an integer. |
d9eb5ea14f65
Provide %b in #'format; use it for converting between ints and bit vectors.
Aidan Kehoe <kehoea@parhasard.net>
parents:
4267
diff
changeset
|
980 If bignum support is available, BIT-VECTOR's length is unlimited. |
d9eb5ea14f65
Provide %b in #'format; use it for converting between ints and bit vectors.
Aidan Kehoe <kehoea@parhasard.net>
parents:
4267
diff
changeset
|
981 Otherwise the limit is the number of value bits in an Lisp integer. " |
d9eb5ea14f65
Provide %b in #'format; use it for converting between ints and bit vectors.
Aidan Kehoe <kehoea@parhasard.net>
parents:
4267
diff
changeset
|
982 (check-argument-type #'bit-vector-p bit-vector) |
d9eb5ea14f65
Provide %b in #'format; use it for converting between ints and bit vectors.
Aidan Kehoe <kehoea@parhasard.net>
parents:
4267
diff
changeset
|
983 (setq bit-vector (prin1-to-string bit-vector)) |
d9eb5ea14f65
Provide %b in #'format; use it for converting between ints and bit vectors.
Aidan Kehoe <kehoea@parhasard.net>
parents:
4267
diff
changeset
|
984 (aset bit-vector 1 ?b) |
d9eb5ea14f65
Provide %b in #'format; use it for converting between ints and bit vectors.
Aidan Kehoe <kehoea@parhasard.net>
parents:
4267
diff
changeset
|
985 (read bit-vector)) |
d9eb5ea14f65
Provide %b in #'format; use it for converting between ints and bit vectors.
Aidan Kehoe <kehoea@parhasard.net>
parents:
4267
diff
changeset
|
986 |
771 | 987 (defun string-width (string) |
988 "Return number of columns STRING occupies when displayed. | |
989 With international (Mule) support, uses the charset-columns attribute of | |
990 the characters in STRING, which may not accurately represent the actual | |
991 display width when using a window system. With no international support, | |
992 simply returns the length of the string." | |
5321
57a64ab2ae45
Implement some basic Lisp functions in terms of Common Lisp builtins.
Aidan Kehoe <kehoea@parhasard.net>
parents:
5284
diff
changeset
|
993 (reduce #'+ (the string string) :initial-value 0 :key #'char-width)) |
771 | 994 |
777 | 995 (defun char-width (character) |
996 "Return number of columns a CHARACTER occupies when displayed." | |
5321
57a64ab2ae45
Implement some basic Lisp functions in terms of Common Lisp builtins.
Aidan Kehoe <kehoea@parhasard.net>
parents:
5284
diff
changeset
|
997 (charset-width (char-charset character))) |
777 | 998 |
999 ;; The following several functions are useful in GNU Emacs 20 because | |
1000 ;; of the multibyte "characters" the internal representation of which | |
1001 ;; leaks into Lisp. In XEmacs/Mule they are trivial and unnecessary. | |
1002 ;; We provide them for compatibility reasons solely. | |
1003 | |
1004 (defun string-to-sequence (string type) | |
1005 "Convert STRING to a sequence of TYPE which contains characters in STRING. | |
1006 TYPE should be `list' or `vector'." | |
1007 (ecase type | |
1008 (list | |
4267 | 1009 (append string nil)) |
777 | 1010 (vector |
4267 | 1011 (vconcat string)))) |
777 | 1012 |
1013 (defun string-to-list (string) | |
1014 "Return a list of characters in STRING." | |
4267 | 1015 (append string nil)) |
777 | 1016 |
1017 (defun string-to-vector (string) | |
1018 "Return a vector of characters in STRING." | |
4267 | 1019 (vconcat string)) |
777 | 1020 |
1021 (defun store-substring (string idx obj) | |
1022 "Embed OBJ (string or character) at index IDX of STRING." | |
5321
57a64ab2ae45
Implement some basic Lisp functions in terms of Common Lisp builtins.
Aidan Kehoe <kehoea@parhasard.net>
parents:
5284
diff
changeset
|
1023 (if (stringp obj) |
57a64ab2ae45
Implement some basic Lisp functions in terms of Common Lisp builtins.
Aidan Kehoe <kehoea@parhasard.net>
parents:
5284
diff
changeset
|
1024 (replace (the string string) obj :start1 idx) |
57a64ab2ae45
Implement some basic Lisp functions in terms of Common Lisp builtins.
Aidan Kehoe <kehoea@parhasard.net>
parents:
5284
diff
changeset
|
1025 (prog1 string (aset string idx obj)))) |
777 | 1026 |
851 | 1027 ;; From FSF 21.1; ELLIPSES is XEmacs addition. |
1028 | |
1029 (defun truncate-string-to-width (str end-column &optional start-column padding | |
1333 | 1030 ellipses) |
777 | 1031 "Truncate string STR to end at column END-COLUMN. |
814 | 1032 The optional 3rd arg START-COLUMN, if non-nil, specifies |
777 | 1033 the starting column; that means to return the characters occupying |
1034 columns START-COLUMN ... END-COLUMN of STR. | |
1035 | |
814 | 1036 The optional 4th arg PADDING, if non-nil, specifies a padding character |
777 | 1037 to add at the end of the result if STR doesn't reach column END-COLUMN, |
1038 or if END-COLUMN comes in the middle of a character in STR. | |
1039 PADDING is also added at the beginning of the result | |
1040 if column START-COLUMN appears in the middle of a character in STR. | |
1041 | |
1042 If PADDING is nil, no padding is added in these cases, so | |
851 | 1043 the resulting string may be narrower than END-COLUMN. |
1044 | |
1045 BUG: Currently assumes that the padding character is of width one. You | |
1046 will get weird results if not. | |
1047 | |
1048 If ELLIPSES is non-nil, add ellipses (specified by ELLIPSES if a string, | |
1049 else `...') if STR extends past END-COLUMN. The ellipses will be added in | |
1050 such a way that the total string occupies no more than END-COLUMN columns | |
1051 -- i.e. if the string goes past END-COLUMN, it will be truncated somewhere | |
1052 short of END-COLUMN so that, with the ellipses added (and padding, if the | |
1053 proper place to truncate the string would be in the middle of a character), | |
1054 the string occupies exactly END-COLUMN columns." | |
777 | 1055 (or start-column |
1056 (setq start-column 0)) | |
814 | 1057 (let ((len (length str)) |
1058 (idx 0) | |
1059 (column 0) | |
1060 (head-padding "") (tail-padding "") | |
1061 ch last-column last-idx from-idx) | |
851 | 1062 |
1063 ;; find the index of START-COLUMN; bail out if end of string reached. | |
814 | 1064 (condition-case nil |
1065 (while (< column start-column) | |
1066 (setq ch (aref str idx) | |
1067 column (+ column (char-width ch)) | |
1068 idx (1+ idx))) | |
1069 (args-out-of-range (setq idx len))) | |
1070 (if (< column start-column) | |
851 | 1071 ;; if string ends before START-COLUMN, return either a blank string |
1072 ;; or a string entirely padded. | |
1073 (if padding (make-string (- end-column start-column) padding) "") | |
814 | 1074 (if (and padding (> column start-column)) |
1075 (setq head-padding (make-string (- column start-column) padding))) | |
1076 (setq from-idx idx) | |
851 | 1077 ;; If END-COLUMN is before START-COLUMN, then bail out. |
814 | 1078 (if (< end-column column) |
851 | 1079 (setq idx from-idx ellipses "") |
1080 | |
1081 ;; handle ELLIPSES | |
1082 (cond ((null ellipses) (setq ellipses "")) | |
1083 ((if (<= (string-width str) end-column) | |
1084 ;; string fits, no ellipses | |
1085 (setq ellipses ""))) | |
1086 (t | |
1087 ;; else, insert default value and ... | |
1088 (or (stringp ellipses) (setq ellipses "...")) | |
1089 ;; ... take away the width of the ellipses from the | |
1090 ;; destination. do all computations with new, shorter | |
1091 ;; width. the padding computed will get us exactly up to | |
1092 ;; the shorted width, which is right -- it just gets added | |
1093 ;; to the right of the ellipses. | |
924 | 1094 (setq end-column (- end-column (string-width ellipses))))) |
851 | 1095 |
1096 ;; find the index of END-COLUMN; bail out if end of string reached. | |
814 | 1097 (condition-case nil |
1098 (while (< column end-column) | |
1099 (setq last-column column | |
1100 last-idx idx | |
1101 ch (aref str idx) | |
1102 column (+ column (char-width ch)) | |
1103 idx (1+ idx))) | |
1104 (args-out-of-range (setq idx len))) | |
851 | 1105 ;; if we went too far (stopped in middle of character), back up. |
814 | 1106 (if (> column end-column) |
1107 (setq column last-column idx last-idx)) | |
851 | 1108 ;; compute remaining padding |
814 | 1109 (if (and padding (< column end-column)) |
1110 (setq tail-padding (make-string (- end-column column) padding)))) | |
851 | 1111 ;; get substring ... |
814 | 1112 (setq str (substring str from-idx idx)) |
851 | 1113 ;; and construct result |
814 | 1114 (if padding |
851 | 1115 (concat head-padding str tail-padding ellipses) |
1116 (concat str ellipses))))) | |
801 | 1117 |
428 | 1118 |
1119 ;; alist/plist functions | |
1120 (defun plist-to-alist (plist) | |
1121 "Convert property list PLIST into the equivalent association-list form. | |
1122 The alist is returned. This converts from | |
1123 | |
1124 \(a 1 b 2 c 3) | |
1125 | |
1126 into | |
1127 | |
1128 \((a . 1) (b . 2) (c . 3)) | |
1129 | |
1130 The original plist is not modified. See also `destructive-plist-to-alist'." | |
1131 (let (alist) | |
1132 (while plist | |
1133 (setq alist (cons (cons (car plist) (cadr plist)) alist)) | |
1134 (setq plist (cddr plist))) | |
1135 (nreverse alist))) | |
1136 | |
4806
fd36a980d701
Use uninterned symbols in various information-hiding contexts.
Aidan Kehoe <kehoea@parhasard.net>
parents:
4575
diff
changeset
|
1137 ((macro |
fd36a980d701
Use uninterned symbols in various information-hiding contexts.
Aidan Kehoe <kehoea@parhasard.net>
parents:
4575
diff
changeset
|
1138 . (lambda (map-plist-definition) |
fd36a980d701
Use uninterned symbols in various information-hiding contexts.
Aidan Kehoe <kehoea@parhasard.net>
parents:
4575
diff
changeset
|
1139 "Replace the variable names in MAP-PLIST-DEFINITION with uninterned |
fd36a980d701
Use uninterned symbols in various information-hiding contexts.
Aidan Kehoe <kehoea@parhasard.net>
parents:
4575
diff
changeset
|
1140 symbols, avoiding the risk of interference with variables in other functions |
fd36a980d701
Use uninterned symbols in various information-hiding contexts.
Aidan Kehoe <kehoea@parhasard.net>
parents:
4575
diff
changeset
|
1141 introduced by dynamic scope." |
5327
d1b17a33450b
Move the heavy lifting from cl-seq.el to C.
Aidan Kehoe <kehoea@parhasard.net>
parents:
5321
diff
changeset
|
1142 (nsublis '((mp-function . #:function) |
d1b17a33450b
Move the heavy lifting from cl-seq.el to C.
Aidan Kehoe <kehoea@parhasard.net>
parents:
5321
diff
changeset
|
1143 (plist . #:plist) |
d1b17a33450b
Move the heavy lifting from cl-seq.el to C.
Aidan Kehoe <kehoea@parhasard.net>
parents:
5321
diff
changeset
|
1144 (result . #:result)) |
d1b17a33450b
Move the heavy lifting from cl-seq.el to C.
Aidan Kehoe <kehoea@parhasard.net>
parents:
5321
diff
changeset
|
1145 ;; Need to specify #'eq as the test, otherwise we have a |
d1b17a33450b
Move the heavy lifting from cl-seq.el to C.
Aidan Kehoe <kehoea@parhasard.net>
parents:
5321
diff
changeset
|
1146 ;; bootstrap issue, since #'eql is in cl.el, loaded after |
d1b17a33450b
Move the heavy lifting from cl-seq.el to C.
Aidan Kehoe <kehoea@parhasard.net>
parents:
5321
diff
changeset
|
1147 ;; this file. |
d1b17a33450b
Move the heavy lifting from cl-seq.el to C.
Aidan Kehoe <kehoea@parhasard.net>
parents:
5321
diff
changeset
|
1148 map-plist-definition :test #'eq))) |
4806
fd36a980d701
Use uninterned symbols in various information-hiding contexts.
Aidan Kehoe <kehoea@parhasard.net>
parents:
4575
diff
changeset
|
1149 (defun map-plist (mp-function plist) |
fd36a980d701
Use uninterned symbols in various information-hiding contexts.
Aidan Kehoe <kehoea@parhasard.net>
parents:
4575
diff
changeset
|
1150 "Map FUNCTION (a function of two args) over each key/value pair in PLIST. |
783 | 1151 Return a list of the results." |
4806
fd36a980d701
Use uninterned symbols in various information-hiding contexts.
Aidan Kehoe <kehoea@parhasard.net>
parents:
4575
diff
changeset
|
1152 (let (result) |
fd36a980d701
Use uninterned symbols in various information-hiding contexts.
Aidan Kehoe <kehoea@parhasard.net>
parents:
4575
diff
changeset
|
1153 (while plist |
fd36a980d701
Use uninterned symbols in various information-hiding contexts.
Aidan Kehoe <kehoea@parhasard.net>
parents:
4575
diff
changeset
|
1154 (push (funcall mp-function (car plist) (cadr plist)) result) |
fd36a980d701
Use uninterned symbols in various information-hiding contexts.
Aidan Kehoe <kehoea@parhasard.net>
parents:
4575
diff
changeset
|
1155 (setq plist (cddr plist))) |
fd36a980d701
Use uninterned symbols in various information-hiding contexts.
Aidan Kehoe <kehoea@parhasard.net>
parents:
4575
diff
changeset
|
1156 (nreverse result)))) |
783 | 1157 |
428 | 1158 (defun destructive-plist-to-alist (plist) |
1159 "Convert property list PLIST into the equivalent association-list form. | |
1160 The alist is returned. This converts from | |
1161 | |
1162 \(a 1 b 2 c 3) | |
1163 | |
1164 into | |
1165 | |
1166 \((a . 1) (b . 2) (c . 3)) | |
1167 | |
1168 The original plist is destroyed in the process of constructing the alist. | |
1169 See also `plist-to-alist'." | |
1170 (let ((head plist) | |
1171 next) | |
1172 (while plist | |
1173 ;; remember the next plist pair. | |
1174 (setq next (cddr plist)) | |
1175 ;; make the cons holding the property value into the alist element. | |
1176 (setcdr (cdr plist) (cadr plist)) | |
1177 (setcar (cdr plist) (car plist)) | |
1178 ;; reattach into alist form. | |
1179 (setcar plist (cdr plist)) | |
1180 (setcdr plist next) | |
1181 (setq plist next)) | |
1182 head)) | |
1183 | |
1184 (defun alist-to-plist (alist) | |
1185 "Convert association list ALIST into the equivalent property-list form. | |
1186 The plist is returned. This converts from | |
1187 | |
1188 \((a . 1) (b . 2) (c . 3)) | |
1189 | |
1190 into | |
1191 | |
1192 \(a 1 b 2 c 3) | |
1193 | |
1194 The original alist is not modified. See also `destructive-alist-to-plist'." | |
1195 (let (plist) | |
1196 (while alist | |
1197 (let ((el (car alist))) | |
1198 (setq plist (cons (cdr el) (cons (car el) plist)))) | |
1199 (setq alist (cdr alist))) | |
1200 (nreverse plist))) | |
1201 | |
1202 ;; getf, remf in cl*.el. | |
1203 | |
444 | 1204 (defmacro putf (plist property value) |
1205 "Add property PROPERTY to plist PLIST with value VALUE. | |
1206 Analogous to (setq PLIST (plist-put PLIST PROPERTY VALUE))." | |
1207 `(setq ,plist (plist-put ,plist ,property ,value))) | |
428 | 1208 |
444 | 1209 (defmacro laxputf (lax-plist property value) |
1210 "Add property PROPERTY to lax plist LAX-PLIST with value VALUE. | |
1211 Analogous to (setq LAX-PLIST (lax-plist-put LAX-PLIST PROPERTY VALUE))." | |
1212 `(setq ,lax-plist (lax-plist-put ,lax-plist ,property ,value))) | |
428 | 1213 |
444 | 1214 (defmacro laxremf (lax-plist property) |
1215 "Remove property PROPERTY from lax plist LAX-PLIST. | |
1216 Analogous to (setq LAX-PLIST (lax-plist-remprop LAX-PLIST PROPERTY))." | |
1217 `(setq ,lax-plist (lax-plist-remprop ,lax-plist ,property))) | |
428 | 1218 |
1219 ;;; Error functions | |
1220 | |
442 | 1221 (defun error (datum &rest args) |
1222 "Signal a non-continuable error. | |
1223 DATUM should normally be an error symbol, i.e. a symbol defined using | |
1224 `define-error'. ARGS will be made into a list, and DATUM and ARGS passed | |
1225 as the two arguments to `signal', the most basic error handling function. | |
1226 | |
428 | 1227 This error is not continuable: you cannot continue execution after the |
442 | 1228 error using the debugger `r' command. See also `cerror'. |
1229 | |
1230 The correct semantics of ARGS varies from error to error, but for most | |
1231 errors that need to be generated in Lisp code, the first argument | |
1232 should be a string describing the *context* of the error (i.e. the | |
1233 exact operation being performed and what went wrong), and the remaining | |
1234 arguments or \"frobs\" (most often, there is one) specify the | |
1235 offending object(s) and/or provide additional details such as the exact | |
1236 error when a file error occurred, e.g.: | |
1237 | |
1238 -- the buffer in which an editing error occurred. | |
1239 -- an invalid value that was encountered. (In such cases, the string | |
1240 should describe the purpose or \"semantics\" of the value [e.g. if the | |
1241 value is an argument to a function, the name of the argument; if the value | |
1242 is the value corresponding to a keyword, the name of the keyword; if the | |
1243 value is supposed to be a list length, say this and say what the purpose | |
1244 of the list is; etc.] as well as specifying why the value is invalid, if | |
1245 that's not self-evident.) | |
1246 -- the file in which an error occurred. (In such cases, there should be a | |
1247 second frob, probably a string, specifying the exact error that occurred. | |
1248 This does not occur in the string that precedes the first frob, because | |
1249 that frob describes the exact operation that was happening. | |
1250 | |
1251 For historical compatibility, DATUM can also be a string. In this case, | |
1252 DATUM and ARGS are passed together as the arguments to `format', and then | |
1253 an error is signalled using the error symbol `error' and formatted string. | |
1254 Although this usage of `error' is very common, it is deprecated because it | |
1255 totally defeats the purpose of having structured errors. There is now | |
1256 a rich set of defined errors you can use: | |
1257 | |
563 | 1258 quit |
1259 | |
442 | 1260 error |
1261 invalid-argument | |
563 | 1262 syntax-error |
1263 invalid-read-syntax | |
1264 invalid-regexp | |
1265 structure-formation-error | |
1266 list-formation-error | |
1267 malformed-list | |
1268 malformed-property-list | |
1269 circular-list | |
1270 circular-property-list | |
1271 invalid-function | |
1272 no-catch | |
1273 undefined-keystroke-sequence | |
1274 invalid-constant | |
442 | 1275 wrong-type-argument |
1276 args-out-of-range | |
1277 wrong-number-of-arguments | |
428 | 1278 |
442 | 1279 invalid-state |
1280 void-function | |
1281 cyclic-function-indirection | |
1282 void-variable | |
1283 cyclic-variable-indirection | |
509 | 1284 invalid-byte-code |
563 | 1285 stack-overflow |
1286 out-of-memory | |
1287 invalid-key-binding | |
1288 internal-error | |
442 | 1289 |
1290 invalid-operation | |
1291 invalid-change | |
1292 setting-constant | |
563 | 1293 protected-field |
442 | 1294 editing-error |
1295 beginning-of-buffer | |
1296 end-of-buffer | |
1297 buffer-read-only | |
1298 io-error | |
509 | 1299 file-error |
1300 file-already-exists | |
1301 file-locked | |
1302 file-supersession | |
563 | 1303 end-of-file |
1304 process-error | |
1305 network-error | |
509 | 1306 tooltalk-error |
563 | 1307 gui-error |
1308 dialog-box-error | |
1309 sound-error | |
1310 conversion-error | |
1311 text-conversion-error | |
1312 image-conversion-error | |
1313 base64-conversion-error | |
1314 selection-conversion-error | |
442 | 1315 arith-error |
1316 range-error | |
1317 domain-error | |
1318 singularity-error | |
1319 overflow-error | |
1320 underflow-error | |
509 | 1321 search-failed |
563 | 1322 printing-unreadable-object |
1323 unimplemented | |
509 | 1324 |
563 | 1325 Note the semantic differences between some of the more common errors: |
442 | 1326 |
563 | 1327 -- `invalid-argument' is for all cases where a bad value is encountered. |
1328 -- `invalid-constant' is for arguments where only a specific set of values | |
1329 is allowed. | |
1330 -- `syntax-error' is when complex structures (parsed strings, lists, | |
1331 and the like) are badly formed. If the problem is just a single bad | |
1332 value inside the structure, you should probably be using something else, | |
1333 e.g. `invalid-constant', `wrong-type-argument', or `invalid-argument'. | |
442 | 1334 -- `invalid-state' means that some settings have been changed in such a way |
1335 that their current state is unallowable. More and more, code is being | |
1336 written more carefully, and catches the error when the settings are being | |
1337 changed, rather than afterwards. This leads us to the next error: | |
1338 -- `invalid-change' means that an attempt is being made to change some settings | |
1339 into an invalid state. `invalid-change' is a type of `invalid-operation'. | |
1340 -- `invalid-operation' refers to all cases where code is trying to do something | |
563 | 1341 that's disallowed, or when an error occurred during an operation. (These |
1342 two concepts are merged because there's no clear distinction between them.) | |
1343 -- `io-error' refers to errors involving interaction with any external | |
1344 components (files, other programs, the operating system, etc). | |
442 | 1345 |
1346 See also `cerror', `signal', and `signal-error'." | |
1347 (while t (apply | |
1348 'cerror datum args))) | |
1349 | |
1350 (defun cerror (datum &rest args) | |
428 | 1351 "Like `error' but signals a continuable error." |
442 | 1352 (cond ((stringp datum) |
1353 (signal 'error (list (apply 'format datum args)))) | |
1354 ((defined-error-p datum) | |
1355 (signal datum args)) | |
1356 (t | |
1357 (error 'invalid-argument "datum not string or error symbol" datum)))) | |
428 | 1358 |
1359 (defmacro check-argument-type (predicate argument) | |
1360 "Check that ARGUMENT satisfies PREDICATE. | |
442 | 1361 This is a macro, and ARGUMENT is not evaluated. If ARGUMENT is an lvalue, |
1362 this function signals a continuable `wrong-type-argument' error until the | |
1363 returned value satisfies PREDICATE, and assigns the returned value | |
1364 to ARGUMENT. Otherwise, this function signals a non-continuable | |
1365 `wrong-type-argument' error if the returned value does not satisfy PREDICATE." | |
1366 (if (symbolp argument) | |
1367 `(if (not (,(eval predicate) ,argument)) | |
1368 (setq ,argument | |
1369 (wrong-type-argument ,predicate ,argument))) | |
1370 `(if (not (,(eval predicate) ,argument)) | |
1371 (signal-error 'wrong-type-argument (list ,predicate ,argument))))) | |
428 | 1372 |
872 | 1373 (defun args-out-of-range (value min max) |
1374 "Signal an error until the correct in-range value is given by the user. | |
1375 This function loops, signalling a continuable `args-out-of-range' error | |
1376 with VALUE, MIN and MAX as the data associated with the error and then | |
1377 checking the returned value to make sure it's not outside the given | |
1378 boundaries \(nil for either means no boundary on that side). At that | |
1379 point, the gotten value is returned." | |
1380 (loop | |
1381 for newval = (signal 'args-out-of-range (list value min max)) | |
1382 do (setq value newval) | |
1383 finally return value | |
1384 while (not (argument-in-range-p value min max)))) | |
1385 | |
1386 (defun argument-in-range-p (argument min max) | |
1387 "Return true if ARGUMENT is within the range of [MIN, MAX]. | |
1388 This includes boundaries. nil for either value means no limit on that side." | |
1389 (and (or (not min) (<= min argument)) | |
1390 (or (not max) (<= argument max)))) | |
1391 | |
1392 (defmacro check-argument-range (argument min max) | |
1393 "Check that ARGUMENT is within the range [MIN, MAX]. | |
1394 This is a macro, and ARGUMENT is not evaluated. If ARGUMENT is an lvalue, | |
1395 this function signals a continuable `args-out-of-range' error until the | |
1396 returned value is within range, and assigns the returned value | |
1397 to ARGUMENT. Otherwise, this function signals a non-continuable | |
1398 `args-out-of-range' error if the returned value is out of range." | |
1399 (if (symbolp argument) | |
1400 `(if (not (argument-in-range-p ,argument ,min ,max)) | |
924 | 1401 (setq ,argument |
1402 (args-out-of-range ,argument ,min ,max))) | |
872 | 1403 (let ((newsym (gensym))) |
1404 `(let ((,newsym ,argument)) | |
924 | 1405 (if (not (argument-in-range-p ,newsym ,min ,max)) |
4103 | 1406 (signal-error 'args-out-of-range (list ,newsym ,min ,max))))))) |
872 | 1407 |
428 | 1408 (defun signal-error (error-symbol data) |
1409 "Signal a non-continuable error. Args are ERROR-SYMBOL, and associated DATA. | |
1410 An error symbol is a symbol defined using `define-error'. | |
1411 DATA should be a list. Its elements are printed as part of the error message. | |
1412 If the signal is handled, DATA is made available to the handler. | |
1413 See also `signal', and the functions to handle errors: `condition-case' | |
1414 and `call-with-condition-handler'." | |
1415 (while t | |
1416 (signal error-symbol data))) | |
1417 | |
1418 (defun define-error (error-sym doc-string &optional inherits-from) | |
1419 "Define a new error, denoted by ERROR-SYM. | |
1420 DOC-STRING is an informative message explaining the error, and will be | |
1421 printed out when an unhandled error occurs. | |
1422 ERROR-SYM is a sub-error of INHERITS-FROM (which defaults to `error'). | |
1423 | |
1424 \[`define-error' internally works by putting on ERROR-SYM an `error-message' | |
1425 property whose value is DOC-STRING, and an `error-conditions' property | |
1426 that is a list of ERROR-SYM followed by each of its super-errors, up | |
1427 to and including `error'. You will sometimes see code that sets this up | |
1428 directly rather than calling `define-error', but you should *not* do this | |
1429 yourself.]" | |
1430 (check-argument-type 'symbolp error-sym) | |
1431 (check-argument-type 'stringp doc-string) | |
1432 (put error-sym 'error-message doc-string) | |
1433 (or inherits-from (setq inherits-from 'error)) | |
1434 (let ((conds (get inherits-from 'error-conditions))) | |
1435 (or conds (signal-error 'error (list "Not an error symbol" error-sym))) | |
1436 (put error-sym 'error-conditions (cons error-sym conds)))) | |
1437 | |
442 | 1438 (defun defined-error-p (sym) |
1439 "Returns non-nil if SYM names a currently-defined error." | |
1440 (and (symbolp sym) (not (null (get sym 'error-conditions))))) | |
1441 | |
793 | 1442 (defun backtrace-in-condition-handler-eliminating-handler (handler-arg-name) |
1443 "Return a backtrace inside of a condition handler, eliminating the handler. | |
1444 This is for use in the condition handler inside of call-with-condition-handler, | |
1445 when written like this: | |
1446 | |
1447 \(call-with-condition-handler | |
1448 #'(lambda (__some_weird_arg__) | |
1449 do the handling ...) | |
1450 #'(lambda () | |
1451 do the stuff that might cause an error)) | |
1452 | |
1453 Pass in the name (a symbol) of the argument used in the lambda function | |
1454 that specifies the handler, and make sure the argument name is unique, and | |
1455 this function generates a backtrace and strips off the part above where the | |
1456 error occurred (i.e. the handler itself)." | |
1457 (let* ((bt (with-output-to-string (backtrace nil t))) | |
1458 (bt (save-match-data | |
1459 ;; Try to eliminate the part of the backtrace | |
1460 ;; above where the error occurred. | |
1461 (if (string-match | |
1462 (concat "bind (\\(?:.* \\)?" (symbol-name handler-arg-name) | |
1463 "\\(?:.* \\)?)[ \t\n]*\\(?:(lambda \\|#<compiled-function \\)(" | |
1464 (symbol-name handler-arg-name) | |
1465 ").*\n\\(\\(?:.\\|\n\\)*\\)$") | |
1466 bt) (match-string 1 bt) bt)))) | |
1467 bt)) | |
1468 | |
1469 (put 'with-trapping-errors 'lisp-indent-function 0) | |
1470 (defmacro with-trapping-errors (&rest keys-body) | |
1471 "Trap errors in BODY, outputting a warning and a backtrace. | |
1472 Usage looks like | |
1473 | |
1474 \(with-trapping-errors | |
1475 [:operation OPERATION] | |
1476 [:error-form ERROR-FORM] | |
1477 [:no-backtrace NO-BACKTRACE] | |
1478 [:class CLASS] | |
1479 [:level LEVEL] | |
1480 [:resignal RESIGNAL] | |
1481 BODY) | |
1482 | |
1483 Return value without error is whatever BODY returns. With error, return | |
1484 result of ERROR-FORM (which will be evaluated only when the error actually | |
1485 occurs), which defaults to nil. OPERATION is given in the warning message. | |
1486 CLASS and LEVEL are the warning class and level (default to class | |
1487 `general', level `warning'). If NO-BACKTRACE is given, no backtrace is | |
1488 displayed. If RESIGNAL is given, the error is resignaled after the warning | |
1489 is displayed and the ERROR-FORM is executed." | |
1490 (let ((operation "unknown") | |
1491 (error-form nil) | |
1492 (no-backtrace nil) | |
1493 (class ''general) | |
1494 (level ''warning) | |
4806
fd36a980d701
Use uninterned symbols in various information-hiding contexts.
Aidan Kehoe <kehoea@parhasard.net>
parents:
4575
diff
changeset
|
1495 (resignal nil) |
fd36a980d701
Use uninterned symbols in various information-hiding contexts.
Aidan Kehoe <kehoea@parhasard.net>
parents:
4575
diff
changeset
|
1496 (cte-cc-var '#:cte-cc-var) |
fd36a980d701
Use uninterned symbols in various information-hiding contexts.
Aidan Kehoe <kehoea@parhasard.net>
parents:
4575
diff
changeset
|
1497 (call-trapping-errors-arg '#:call-trapping-errors-Ldc9FC5Hr)) |
793 | 1498 (let* ((keys '(operation error-form no-backtrace class level resignal)) |
1499 (keys-with-colon | |
1500 (mapcar #'(lambda (sym) | |
1501 (intern (concat ":" (symbol-name sym)))) keys))) | |
1502 (while (memq (car keys-body) keys-with-colon) | |
1503 (let* ((key-with-colon (pop keys-body)) | |
1504 (key (intern (substring (symbol-name key-with-colon) 1)))) | |
1505 (set key (pop keys-body))))) | |
4806
fd36a980d701
Use uninterned symbols in various information-hiding contexts.
Aidan Kehoe <kehoea@parhasard.net>
parents:
4575
diff
changeset
|
1506 `(condition-case ,(if resignal cte-cc-var nil) |
793 | 1507 (call-with-condition-handler |
4806
fd36a980d701
Use uninterned symbols in various information-hiding contexts.
Aidan Kehoe <kehoea@parhasard.net>
parents:
4575
diff
changeset
|
1508 #'(lambda (,call-trapping-errors-arg) |
793 | 1509 (let ((errstr (error-message-string |
4806
fd36a980d701
Use uninterned symbols in various information-hiding contexts.
Aidan Kehoe <kehoea@parhasard.net>
parents:
4575
diff
changeset
|
1510 ,call-trapping-errors-arg))) |
793 | 1511 ,(if no-backtrace |
1512 `(lwarn ,class ,level | |
1513 (if (warning-level-< | |
1514 ,level | |
1515 display-warning-minimum-level) | |
1516 "Error in %s: %s" | |
1517 "Error in %s:\n%s\n") | |
1518 ,operation errstr) | |
1519 `(lwarn ,class ,level | |
1520 "Error in %s: %s\n\nBacktrace follows:\n\n%s" | |
1521 ,operation errstr | |
1522 (backtrace-in-condition-handler-eliminating-handler | |
4806
fd36a980d701
Use uninterned symbols in various information-hiding contexts.
Aidan Kehoe <kehoea@parhasard.net>
parents:
4575
diff
changeset
|
1523 ',call-trapping-errors-arg))))) |
793 | 1524 #'(lambda () |
1525 (progn ,@keys-body))) | |
1526 (error | |
1527 ,error-form | |
4817
0142cb4d1049
Fix a bug I introduced in #'with-trapping-errors.
Aidan Kehoe <kehoea@parhasard.net>
parents:
4806
diff
changeset
|
1528 ,@(if resignal `((signal (car ,cte-cc-var) (cdr ,cte-cc-var))))) |
793 | 1529 ))) |
1530 | |
428 | 1531 ;;;; Miscellanea. |
1532 | |
1533 ;; This is now in C. | |
444 | 1534 ;(defun buffer-substring-no-properties (start end) |
1535 ; "Return the text from START to END, without text properties, as a string." | |
1536 ; (let ((string (buffer-substring start end))) | |
428 | 1537 ; (set-text-properties 0 (length string) nil string) |
1538 ; string)) | |
1539 | |
1540 (defun get-buffer-window-list (&optional buffer minibuf frame) | |
1541 "Return windows currently displaying BUFFER, or nil if none. | |
1542 BUFFER defaults to the current buffer. | |
1543 See `walk-windows' for the meaning of MINIBUF and FRAME." | |
1544 (cond ((null buffer) | |
1545 (setq buffer (current-buffer))) | |
1546 ((not (bufferp buffer)) | |
1547 (setq buffer (get-buffer buffer)))) | |
1548 (let (windows) | |
1549 (walk-windows (lambda (window) | |
1550 (if (eq (window-buffer window) buffer) | |
1551 (push window windows))) | |
1552 minibuf frame) | |
1553 windows)) | |
1554 | |
1555 (defun ignore (&rest ignore) | |
1556 "Do nothing and return nil. | |
1557 This function accepts any number of arguments, but ignores them." | |
1558 (interactive) | |
1559 nil) | |
1560 | |
883 | 1561 ;; defined in lisp/bindings.el in GNU Emacs. |
1562 (defmacro bound-and-true-p (var) | |
1563 "Return the value of symbol VAR if it is bound, else nil." | |
1564 `(and (boundp (quote ,var)) ,var)) | |
1565 | |
1566 ;; `propertize' is a builtin in GNU Emacs 21. | |
1567 (defun propertize (string &rest properties) | |
1568 "Return a copy of STRING with text properties added. | |
1569 First argument is the string to copy. | |
1570 Remaining arguments form a sequence of PROPERTY VALUE pairs for text | |
1571 properties to add to the result." | |
1572 (let ((str (copy-sequence string))) | |
1573 (add-text-properties 0 (length str) | |
1574 properties | |
1575 str) | |
1576 str)) | |
1577 | |
1578 ;; `delete-and-extract-region' is a builtin in GNU Emacs 21. | |
1579 (defun delete-and-extract-region (start end) | |
1580 "Delete the text between START and END and return it." | |
1581 (let ((region (buffer-substring start end))) | |
1582 (delete-region start end) | |
1583 region)) | |
1584 | |
428 | 1585 (define-function 'eval-in-buffer 'with-current-buffer) |
1586 (make-obsolete 'eval-in-buffer 'with-current-buffer) | |
1587 | |
1588 ;;; `functionp' has been moved into C. | |
1589 | |
1590 ;;(defun functionp (object) | |
1591 ;; "Non-nil if OBJECT can be called as a function." | |
1592 ;; (or (and (symbolp object) (fboundp object)) | |
1593 ;; (subrp object) | |
1594 ;; (compiled-function-p object) | |
1595 ;; (eq (car-safe object) 'lambda))) | |
1596 | |
1597 (defun function-interactive (function) | |
1598 "Return the interactive specification of FUNCTION. | |
1599 FUNCTION can be any funcallable object. | |
1600 The specification will be returned as the list of the symbol `interactive' | |
1601 and the specs. | |
1602 If FUNCTION is not interactive, nil will be returned." | |
1603 (setq function (indirect-function function)) | |
1604 (cond ((compiled-function-p function) | |
1605 (compiled-function-interactive function)) | |
1606 ((subrp function) | |
1607 (subr-interactive function)) | |
1608 ((eq (car-safe function) 'lambda) | |
1609 (let ((spec (if (stringp (nth 2 function)) | |
1610 (nth 3 function) | |
1611 (nth 2 function)))) | |
1612 (and (eq (car-safe spec) 'interactive) | |
1613 spec))) | |
1614 (t | |
1615 (error "Non-funcallable object: %s" function)))) | |
1616 | |
442 | 1617 (defun function-allows-args (function n) |
1618 "Return whether FUNCTION can be called with N arguments." | |
1619 (and (<= (function-min-args function) n) | |
1620 (or (null (function-max-args function)) | |
1621 (<= n (function-max-args function))))) | |
1622 | |
428 | 1623 ;; This function used to be an alias to `buffer-substring', except |
1624 ;; that FSF Emacs 20.4 added a BUFFER argument in an incompatible way. | |
1625 ;; The new FSF's semantics makes more sense, but we try to support | |
1626 ;; both for backward compatibility. | |
1627 (defun buffer-string (&optional buffer old-end old-buffer) | |
1628 "Return the contents of the current buffer as a string. | |
1629 If narrowing is in effect, this function returns only the visible part | |
1630 of the buffer. | |
1631 | |
1632 If BUFFER is specified, the contents of that buffer are returned. | |
1633 | |
1634 The arguments OLD-END and OLD-BUFFER are supported for backward | |
1635 compatibility with pre-21.2 XEmacsen times when arguments to this | |
1636 function were (buffer-string &optional START END BUFFER)." | |
1637 (cond | |
1638 ((or (stringp buffer) (bufferp buffer)) | |
1639 ;; Most definitely the new way. | |
1640 (buffer-substring nil nil buffer)) | |
1641 ((or (stringp old-buffer) (bufferp old-buffer) | |
1642 (natnump buffer) (natnump old-end)) | |
1643 ;; Definitely the old way. | |
1644 (buffer-substring buffer old-end old-buffer)) | |
1645 (t | |
1646 ;; Probably the old way. | |
1647 (buffer-substring buffer old-end old-buffer)))) | |
1648 | |
1333 | 1649 ;; BEGIN SYNC WITH FSF 21.2 |
1650 | |
428 | 1651 ;; This was not present before. I think Jamie had some objections |
1652 ;; to this, so I'm leaving this undefined for now. --ben | |
1653 | |
1654 ;;; The objection is this: there is more than one way to load the same file. | |
1655 ;;; "foo", "foo.elc", "foo.el", and "/some/path/foo.elc" are all different | |
1656 ;;; ways to load the exact same code. `eval-after-load' is too stupid to | |
1657 ;;; deal with this sort of thing. If this sort of feature is desired, then | |
1658 ;;; it should work off of a hook on `provide'. Features are unique and | |
1659 ;;; the arguments to (load) are not. --Stig | |
1660 | |
1661 ;; We provide this for FSFmacs compatibility, at least until we devise | |
1662 ;; something better. | |
1663 | |
1664 ;;;; Specifying things to do after certain files are loaded. | |
1665 | |
1666 (defun eval-after-load (file form) | |
1667 "Arrange that, if FILE is ever loaded, FORM will be run at that time. | |
1668 This makes or adds to an entry on `after-load-alist'. | |
1669 If FILE is already loaded, evaluate FORM right now. | |
1670 It does nothing if FORM is already on the list for FILE. | |
1333 | 1671 FILE must match exactly. Normally FILE is the name of a library, |
1672 with no directory or extension specified, since that is how `load' | |
1673 is normally called." | |
1674 ;; Make sure `load-history' contains the files dumped with Emacs | |
1675 ;; for the case that FILE is one of the files dumped with Emacs. | |
1676 (if-fboundp 'load-symbol-file-load-history | |
1677 (load-symbol-file-load-history)) | |
428 | 1678 ;; Make sure there is an element for FILE. |
1679 (or (assoc file after-load-alist) | |
1680 (setq after-load-alist (cons (list file) after-load-alist))) | |
1681 ;; Add FORM to the element if it isn't there. | |
1682 (let ((elt (assoc file after-load-alist))) | |
1683 (or (member form (cdr elt)) | |
1684 (progn | |
1685 (nconc elt (list form)) | |
1686 ;; If the file has been loaded already, run FORM right away. | |
1687 (and (assoc file load-history) | |
1688 (eval form))))) | |
1689 form) | |
1690 (make-compatible 'eval-after-load "") | |
1691 | |
1692 (defun eval-next-after-load (file) | |
1693 "Read the following input sexp, and run it whenever FILE is loaded. | |
1694 This makes or adds to an entry on `after-load-alist'. | |
1695 FILE should be the name of a library, with no directory name." | |
1696 (eval-after-load file (read))) | |
1697 (make-compatible 'eval-next-after-load "") | |
1698 | |
1333 | 1699 ;; END SYNC WITH FSF 21.2 |
428 | 1700 |
3000 | 1701 ;; BEGIN SYNC WITH FSF 22.0.50.1 (CVS) |
1702 (defun delete-dups (list) | |
1703 "Destructively remove `equal' duplicates from LIST. | |
1704 Store the result in LIST and return it. LIST must be a proper list. | |
1705 Of several `equal' occurrences of an element in LIST, the first | |
1706 one is kept." | |
1707 (let ((tail list)) | |
1708 (while tail | |
1709 (setcdr tail (delete (car tail) (cdr tail))) | |
1710 (setq tail (cdr tail)))) | |
1711 list) | |
1712 | |
1713 ;; END SYNC WITH FSF 22.0.50.1 (CVS) | |
1714 | |
2525 | 1715 ;; (defun shell-quote-argument (argument) in process.el. |
1716 | |
1717 ;; (defun make-syntax-table (&optional oldtable) in syntax.el. | |
1718 | |
4575
eecd28508f4a
Add #'subr-arity, API taken from GNU, implementation our own.
Aidan Kehoe <kehoea@parhasard.net>
parents:
4516
diff
changeset
|
1719 ;; (defun syntax-after (pos) in syntax.el. |
2525 | 1720 |
1721 ;; global-set-key, local-set-key, global-unset-key, local-unset-key in | |
1722 ;; keymap.el. | |
1723 | |
1724 ;; frame-configuration-p is in frame.el. | |
1725 | |
1726 ;; functionp is built-in. | |
1727 | |
1728 ;; interactive-form in obsolete.el. | |
1729 | |
1730 ;; assq-del-all in obsolete.el. | |
1731 | |
4266 | 1732 ;; make-temp-file in files.el. |
2525 | 1733 |
1734 ;; add-minor-mode in modeline.el. | |
1735 | |
1736 ;; text-clone stuff #### doesn't exist; should go in text-props.el and | |
1737 ;; requires changes to extents.c (modification hooks). | |
1738 | |
1739 ;; play-sound is built-in. | |
1740 | |
1741 ;; define-mail-user-agent is in simple.el. | |
1742 | |
4501
c4fd85dd95bd
Add #'skip-chars-quote to subr.el
Aidan Kehoe <kehoea@parhasard.net>
parents:
4463
diff
changeset
|
1743 ;; XEmacs; added. |
c4fd85dd95bd
Add #'skip-chars-quote to subr.el
Aidan Kehoe <kehoea@parhasard.net>
parents:
4463
diff
changeset
|
1744 (defun skip-chars-quote (string) |
c4fd85dd95bd
Add #'skip-chars-quote to subr.el
Aidan Kehoe <kehoea@parhasard.net>
parents:
4463
diff
changeset
|
1745 "Return a string that means all characters in STRING will be skipped, |
c4fd85dd95bd
Add #'skip-chars-quote to subr.el
Aidan Kehoe <kehoea@parhasard.net>
parents:
4463
diff
changeset
|
1746 if passed to `skip-chars-forward' or `skip-chars-backward'. |
c4fd85dd95bd
Add #'skip-chars-quote to subr.el
Aidan Kehoe <kehoea@parhasard.net>
parents:
4463
diff
changeset
|
1747 |
c4fd85dd95bd
Add #'skip-chars-quote to subr.el
Aidan Kehoe <kehoea@parhasard.net>
parents:
4463
diff
changeset
|
1748 Ranges and carets are not treated specially. This implementation is |
c4fd85dd95bd
Add #'skip-chars-quote to subr.el
Aidan Kehoe <kehoea@parhasard.net>
parents:
4463
diff
changeset
|
1749 in Lisp; do not use it in performance-critical code." |
c4fd85dd95bd
Add #'skip-chars-quote to subr.el
Aidan Kehoe <kehoea@parhasard.net>
parents:
4463
diff
changeset
|
1750 (let ((list (delete-duplicates (string-to-list string) :test #'=))) |
5366
f00192e1cd49
Examining the result of #'length: `eql', not `=', it's better style & cheaper
Aidan Kehoe <kehoea@parhasard.net>
parents:
5338
diff
changeset
|
1751 (when (not (eql 1 (length list))) ;; No quoting needed in a string of |
f00192e1cd49
Examining the result of #'length: `eql', not `=', it's better style & cheaper
Aidan Kehoe <kehoea@parhasard.net>
parents:
5338
diff
changeset
|
1752 ;; length 1. |
f00192e1cd49
Examining the result of #'length: `eql', not `=', it's better style & cheaper
Aidan Kehoe <kehoea@parhasard.net>
parents:
5338
diff
changeset
|
1753 (when (eql ?^ (car list)) |
4504
b82fdf7305ee
Correct the implementation, add a few basic tests for #'skip-chars-quote.
Aidan Kehoe <kehoea@parhasard.net>
parents:
4501
diff
changeset
|
1754 (setq list (nconc (cdr list) '(?^)))) |
b82fdf7305ee
Correct the implementation, add a few basic tests for #'skip-chars-quote.
Aidan Kehoe <kehoea@parhasard.net>
parents:
4501
diff
changeset
|
1755 (when (memq ?\\ list) |
b82fdf7305ee
Correct the implementation, add a few basic tests for #'skip-chars-quote.
Aidan Kehoe <kehoea@parhasard.net>
parents:
4501
diff
changeset
|
1756 (setq list (delq ?\\ list) |
b82fdf7305ee
Correct the implementation, add a few basic tests for #'skip-chars-quote.
Aidan Kehoe <kehoea@parhasard.net>
parents:
4501
diff
changeset
|
1757 list (nconc (list ?\\ ?\\) list))) |
b82fdf7305ee
Correct the implementation, add a few basic tests for #'skip-chars-quote.
Aidan Kehoe <kehoea@parhasard.net>
parents:
4501
diff
changeset
|
1758 (when (memq ?- list) |
b82fdf7305ee
Correct the implementation, add a few basic tests for #'skip-chars-quote.
Aidan Kehoe <kehoea@parhasard.net>
parents:
4501
diff
changeset
|
1759 (setq list (delq ?- list) |
b82fdf7305ee
Correct the implementation, add a few basic tests for #'skip-chars-quote.
Aidan Kehoe <kehoea@parhasard.net>
parents:
4501
diff
changeset
|
1760 list (nconc list '(?\\ ?-))))) |
4501
c4fd85dd95bd
Add #'skip-chars-quote to subr.el
Aidan Kehoe <kehoea@parhasard.net>
parents:
4463
diff
changeset
|
1761 (apply #'string list))) |
c4fd85dd95bd
Add #'skip-chars-quote to subr.el
Aidan Kehoe <kehoea@parhasard.net>
parents:
4463
diff
changeset
|
1762 |
4575
eecd28508f4a
Add #'subr-arity, API taken from GNU, implementation our own.
Aidan Kehoe <kehoea@parhasard.net>
parents:
4516
diff
changeset
|
1763 ;; XEmacs addition to subr.el; docstring and API taken initially from GNU's |
eecd28508f4a
Add #'subr-arity, API taken from GNU, implementation our own.
Aidan Kehoe <kehoea@parhasard.net>
parents:
4516
diff
changeset
|
1764 ;; data.c, revision 1.275, GPLv2. |
eecd28508f4a
Add #'subr-arity, API taken from GNU, implementation our own.
Aidan Kehoe <kehoea@parhasard.net>
parents:
4516
diff
changeset
|
1765 (defun subr-arity (subr) |
eecd28508f4a
Add #'subr-arity, API taken from GNU, implementation our own.
Aidan Kehoe <kehoea@parhasard.net>
parents:
4516
diff
changeset
|
1766 "Return minimum and maximum number of args allowed for SUBR. |
eecd28508f4a
Add #'subr-arity, API taken from GNU, implementation our own.
Aidan Kehoe <kehoea@parhasard.net>
parents:
4516
diff
changeset
|
1767 SUBR must be a built-in function (not just a symbol that refers to one). |
eecd28508f4a
Add #'subr-arity, API taken from GNU, implementation our own.
Aidan Kehoe <kehoea@parhasard.net>
parents:
4516
diff
changeset
|
1768 The returned value is a pair (MIN . MAX). MIN is the minimum number |
eecd28508f4a
Add #'subr-arity, API taken from GNU, implementation our own.
Aidan Kehoe <kehoea@parhasard.net>
parents:
4516
diff
changeset
|
1769 of args. MAX is the maximum number or the symbol `many', for a |
4905
755ae5b97edb
Change "special form" to "special operator" in our sources.
Aidan Kehoe <kehoea@parhasard.net>
parents:
4817
diff
changeset
|
1770 function with `&rest' args, or `unevalled' for a special operator. |
4575
eecd28508f4a
Add #'subr-arity, API taken from GNU, implementation our own.
Aidan Kehoe <kehoea@parhasard.net>
parents:
4516
diff
changeset
|
1771 |
4905
755ae5b97edb
Change "special form" to "special operator" in our sources.
Aidan Kehoe <kehoea@parhasard.net>
parents:
4817
diff
changeset
|
1772 See also `special-operator-p', `subr-min-args', `subr-max-args', |
4575
eecd28508f4a
Add #'subr-arity, API taken from GNU, implementation our own.
Aidan Kehoe <kehoea@parhasard.net>
parents:
4516
diff
changeset
|
1773 `function-allows-args'. " |
eecd28508f4a
Add #'subr-arity, API taken from GNU, implementation our own.
Aidan Kehoe <kehoea@parhasard.net>
parents:
4516
diff
changeset
|
1774 (check-argument-type #'subrp subr) |
eecd28508f4a
Add #'subr-arity, API taken from GNU, implementation our own.
Aidan Kehoe <kehoea@parhasard.net>
parents:
4516
diff
changeset
|
1775 (cons (subr-min-args subr) |
eecd28508f4a
Add #'subr-arity, API taken from GNU, implementation our own.
Aidan Kehoe <kehoea@parhasard.net>
parents:
4516
diff
changeset
|
1776 (cond |
4905
755ae5b97edb
Change "special form" to "special operator" in our sources.
Aidan Kehoe <kehoea@parhasard.net>
parents:
4817
diff
changeset
|
1777 ((special-operator-p subr) |
4575
eecd28508f4a
Add #'subr-arity, API taken from GNU, implementation our own.
Aidan Kehoe <kehoea@parhasard.net>
parents:
4516
diff
changeset
|
1778 'unevalled) |
eecd28508f4a
Add #'subr-arity, API taken from GNU, implementation our own.
Aidan Kehoe <kehoea@parhasard.net>
parents:
4516
diff
changeset
|
1779 ((null (subr-max-args subr)) |
eecd28508f4a
Add #'subr-arity, API taken from GNU, implementation our own.
Aidan Kehoe <kehoea@parhasard.net>
parents:
4516
diff
changeset
|
1780 'many) |
eecd28508f4a
Add #'subr-arity, API taken from GNU, implementation our own.
Aidan Kehoe <kehoea@parhasard.net>
parents:
4516
diff
changeset
|
1781 (t (subr-max-args subr))))) |
eecd28508f4a
Add #'subr-arity, API taken from GNU, implementation our own.
Aidan Kehoe <kehoea@parhasard.net>
parents:
4516
diff
changeset
|
1782 |
5004
788c38f20376
Do not assume #'format-decode exists in fileio.c.
Aidan Kehoe <kehoea@parhasard.net>
parents:
4905
diff
changeset
|
1783 ;; XEmacs; move these here from C. Would be nice to drop them entirely, but |
788c38f20376
Do not assume #'format-decode exists in fileio.c.
Aidan Kehoe <kehoea@parhasard.net>
parents:
4905
diff
changeset
|
1784 ;; they're used reasonably often, since they've been around for a long time |
788c38f20376
Do not assume #'format-decode exists in fileio.c.
Aidan Kehoe <kehoea@parhasard.net>
parents:
4905
diff
changeset
|
1785 ;; and they're portable to GNU. |
788c38f20376
Do not assume #'format-decode exists in fileio.c.
Aidan Kehoe <kehoea@parhasard.net>
parents:
4905
diff
changeset
|
1786 |
5182
2e528066e2fc
Move #'sort*, #'fill, #'merge to C from cl-seq.el.
Aidan Kehoe <kehoea@parhasard.net>
parents:
5089
diff
changeset
|
1787 ;; No longer used in C, now list_merge() accepts a KEY argument. |
5004
788c38f20376
Do not assume #'format-decode exists in fileio.c.
Aidan Kehoe <kehoea@parhasard.net>
parents:
4905
diff
changeset
|
1788 (defun car-less-than-car (a b) |
788c38f20376
Do not assume #'format-decode exists in fileio.c.
Aidan Kehoe <kehoea@parhasard.net>
parents:
4905
diff
changeset
|
1789 "Return t if the car of A is numerically less than the car of B." |
788c38f20376
Do not assume #'format-decode exists in fileio.c.
Aidan Kehoe <kehoea@parhasard.net>
parents:
4905
diff
changeset
|
1790 (< (car a) (car b))) |
788c38f20376
Do not assume #'format-decode exists in fileio.c.
Aidan Kehoe <kehoea@parhasard.net>
parents:
4905
diff
changeset
|
1791 |
788c38f20376
Do not assume #'format-decode exists in fileio.c.
Aidan Kehoe <kehoea@parhasard.net>
parents:
4905
diff
changeset
|
1792 ;; Used in packages. |
788c38f20376
Do not assume #'format-decode exists in fileio.c.
Aidan Kehoe <kehoea@parhasard.net>
parents:
4905
diff
changeset
|
1793 (defun cdr-less-than-cdr (a b) |
788c38f20376
Do not assume #'format-decode exists in fileio.c.
Aidan Kehoe <kehoea@parhasard.net>
parents:
4905
diff
changeset
|
1794 "Return t if (cdr A) is numerically less than (cdr B)." |
788c38f20376
Do not assume #'format-decode exists in fileio.c.
Aidan Kehoe <kehoea@parhasard.net>
parents:
4905
diff
changeset
|
1795 (< (cdr a) (cdr b))) |
788c38f20376
Do not assume #'format-decode exists in fileio.c.
Aidan Kehoe <kehoea@parhasard.net>
parents:
4905
diff
changeset
|
1796 |
5220
2157ecaedc1d
Add `float-time', implemented in Lisp.
Aidan Kehoe <kehoea@parhasard.net>
parents:
5182
diff
changeset
|
1797 ;; XEmacs; this is in editfns.c in GNU. |
2157ecaedc1d
Add `float-time', implemented in Lisp.
Aidan Kehoe <kehoea@parhasard.net>
parents:
5182
diff
changeset
|
1798 (defun float-time (&optional specified-time) |
2157ecaedc1d
Add `float-time', implemented in Lisp.
Aidan Kehoe <kehoea@parhasard.net>
parents:
5182
diff
changeset
|
1799 "Convert time value SPECIFIED-TIME to a floating point number. |
2157ecaedc1d
Add `float-time', implemented in Lisp.
Aidan Kehoe <kehoea@parhasard.net>
parents:
5182
diff
changeset
|
1800 |
2157ecaedc1d
Add `float-time', implemented in Lisp.
Aidan Kehoe <kehoea@parhasard.net>
parents:
5182
diff
changeset
|
1801 See `current-time'. Since the result is a floating-point number, this may |
2157ecaedc1d
Add `float-time', implemented in Lisp.
Aidan Kehoe <kehoea@parhasard.net>
parents:
5182
diff
changeset
|
1802 not have the same accuracy as does the result of `current-time'. |
2157ecaedc1d
Add `float-time', implemented in Lisp.
Aidan Kehoe <kehoea@parhasard.net>
parents:
5182
diff
changeset
|
1803 |
2157ecaedc1d
Add `float-time', implemented in Lisp.
Aidan Kehoe <kehoea@parhasard.net>
parents:
5182
diff
changeset
|
1804 If not supplied, SPECIFIED-TIME defaults to the result of `current-time'." |
2157ecaedc1d
Add `float-time', implemented in Lisp.
Aidan Kehoe <kehoea@parhasard.net>
parents:
5182
diff
changeset
|
1805 (or specified-time (setq specified-time (current-time))) |
2157ecaedc1d
Add `float-time', implemented in Lisp.
Aidan Kehoe <kehoea@parhasard.net>
parents:
5182
diff
changeset
|
1806 (+ (* (pop specified-time) (+ #x10000 0.0)) |
2157ecaedc1d
Add `float-time', implemented in Lisp.
Aidan Kehoe <kehoea@parhasard.net>
parents:
5182
diff
changeset
|
1807 (if (consp specified-time) |
2157ecaedc1d
Add `float-time', implemented in Lisp.
Aidan Kehoe <kehoea@parhasard.net>
parents:
5182
diff
changeset
|
1808 (pop specified-time) |
2157ecaedc1d
Add `float-time', implemented in Lisp.
Aidan Kehoe <kehoea@parhasard.net>
parents:
5182
diff
changeset
|
1809 (prog1 |
2157ecaedc1d
Add `float-time', implemented in Lisp.
Aidan Kehoe <kehoea@parhasard.net>
parents:
5182
diff
changeset
|
1810 specified-time |
2157ecaedc1d
Add `float-time', implemented in Lisp.
Aidan Kehoe <kehoea@parhasard.net>
parents:
5182
diff
changeset
|
1811 (setq specified-time nil))) |
2157ecaedc1d
Add `float-time', implemented in Lisp.
Aidan Kehoe <kehoea@parhasard.net>
parents:
5182
diff
changeset
|
1812 (or (and specified-time |
2157ecaedc1d
Add `float-time', implemented in Lisp.
Aidan Kehoe <kehoea@parhasard.net>
parents:
5182
diff
changeset
|
1813 (/ (car specified-time) 1000000.0)) |
2157ecaedc1d
Add `float-time', implemented in Lisp.
Aidan Kehoe <kehoea@parhasard.net>
parents:
5182
diff
changeset
|
1814 0.0))) |
2157ecaedc1d
Add `float-time', implemented in Lisp.
Aidan Kehoe <kehoea@parhasard.net>
parents:
5182
diff
changeset
|
1815 |
428 | 1816 ;;; subr.el ends here |