Mercurial > hg > xemacs-beta
comparison lisp/prim/subr.el @ 0:376386a54a3c r19-14
Import from CVS: tag r19-14
author | cvs |
---|---|
date | Mon, 13 Aug 2007 08:45:50 +0200 |
parents | |
children | ac2d302a0011 |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:376386a54a3c |
---|---|
1 ;;; subr.el --- basic lisp subroutines for XEmacs | |
2 | |
3 ;;; Copyright (C) 1985, 1986, 1992, 1994, 1995 Free Software Foundation, Inc. | |
4 ;;; Copyright (C) 1995 Tinker Systems and INS Engineering Corp. | |
5 ;;; Copyright (C) 1995 Sun Microsystems. | |
6 | |
7 ;; This file is part of XEmacs. | |
8 | |
9 ;; XEmacs is free software; you can redistribute it and/or modify it | |
10 ;; under the terms of the GNU General Public License as published by | |
11 ;; the Free Software Foundation; either version 2, or (at your option) | |
12 ;; any later version. | |
13 | |
14 ;; XEmacs is distributed in the hope that it will be useful, but | |
15 ;; WITHOUT ANY WARRANTY; without even the implied warranty of | |
16 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
17 ;; General Public License for more details. | |
18 | |
19 ;; You should have received a copy of the GNU General Public License | |
20 ;; along with XEmacs; see the file COPYING. If not, write to the Free | |
21 ;; Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. | |
22 | |
23 ;;; Synched up with: FSF 19.30. | |
24 | |
25 ;;; Code: | |
26 | |
27 | |
28 ;;;; Lisp language features. | |
29 | |
30 (defmacro lambda (&rest cdr) | |
31 "Return a lambda expression. | |
32 A call of the form (lambda ARGS DOCSTRING INTERACTIVE BODY) is | |
33 self-quoting; the result of evaluating the lambda expression is the | |
34 expression itself. The lambda expression may then be treated as a | |
35 function, i.e., stored as the function value of a symbol, passed to | |
36 funcall or mapcar, etc. | |
37 | |
38 ARGS should take the same form as an argument list for a `defun'. | |
39 DOCSTRING is an optional documentation string. | |
40 If present, it should describe how to call the function. | |
41 But documentation strings are usually not useful in nameless functions. | |
42 INTERACTIVE should be a call to the function `interactive', which see. | |
43 It may also be omitted. | |
44 BODY should be a list of lisp expressions." | |
45 ;; Note that this definition should not use backquotes; subr.el should not | |
46 ;; depend on backquote.el. | |
47 ;; #### - I don't see why. So long as backquote.el doesn't use anything | |
48 ;; from subr.el, there's no problem with using backquotes here. --Stig | |
49 (list 'function (cons 'lambda cdr))) | |
50 | |
51 (define-function 'not 'null) | |
52 (if (not (fboundp 'numberp)) | |
53 (define-function 'numberp 'integerp)) ; different when floats | |
54 | |
55 (defun local-variable-if-set-p (sym buffer) | |
56 "Return t if SYM would be local to BUFFER after it is set. | |
57 A nil value for BUFFER is *not* the same as (current-buffer), but | |
58 can be used to determine whether `make-variable-buffer-local' has been | |
59 called on SYM." | |
60 (local-variable-p sym buffer t)) | |
61 | |
62 | |
63 ;;;; Hook manipulation functions. | |
64 | |
65 (defun make-local-hook (hook) | |
66 "Make the hook HOOK local to the current buffer. | |
67 When a hook is local, its local and global values | |
68 work in concert: running the hook actually runs all the hook | |
69 functions listed in *either* the local value *or* the global value | |
70 of the hook variable. | |
71 | |
72 This function works by making `t' a member of the buffer-local value, | |
73 which acts as a flag to run the hook functions in the default value as | |
74 well. This works for all normal hooks, but does not work for most | |
75 non-normal hooks yet. We will be changing the callers of non-normal | |
76 hooks so that they can handle localness; this has to be done one by | |
77 one. | |
78 | |
79 This function does nothing if HOOK is already local in the current | |
80 buffer. | |
81 | |
82 Do not use `make-local-variable' to make a hook variable buffer-local." | |
83 (if (local-variable-p hook (current-buffer)) | |
84 nil | |
85 (or (boundp hook) (set hook nil)) | |
86 (make-local-variable hook) | |
87 (set hook (list t)))) | |
88 | |
89 (defun add-hook (hook function &optional append local) | |
90 "Add to the value of HOOK the function FUNCTION. | |
91 FUNCTION is not added if already present. | |
92 FUNCTION is added (if necessary) at the beginning of the hook list | |
93 unless the optional argument APPEND is non-nil, in which case | |
94 FUNCTION is added at the end. | |
95 | |
96 The optional fourth argument, LOCAL, if non-nil, says to modify | |
97 the hook's buffer-local value rather than its default value. | |
98 This makes no difference if the hook is not buffer-local. | |
99 To make a hook variable buffer-local, always use | |
100 `make-local-hook', not `make-local-variable'. | |
101 | |
102 HOOK should be a symbol, and FUNCTION may be any valid function. If | |
103 HOOK is void, it is first set to nil. If HOOK's value is a single | |
104 function, it is changed to a list of functions." | |
105 ;(interactive "SAdd to hook-var (symbol): \naAdd which function to %s? ") | |
106 (or (boundp hook) (set hook nil)) | |
107 (or (default-boundp hook) (set-default hook nil)) | |
108 ;; If the hook value is a single function, turn it into a list. | |
109 (let ((old (symbol-value hook))) | |
110 (if (or (not (listp old)) (eq (car old) 'lambda)) | |
111 (set hook (list old)))) | |
112 (if (or local | |
113 ;; Detect the case where make-local-variable was used on a hook | |
114 ;; and do what we used to do. | |
115 (and (local-variable-if-set-p hook (current-buffer)) | |
116 (not (memq t (symbol-value hook))))) | |
117 ;; Alter the local value only. | |
118 (or (if (consp function) | |
119 (member function (symbol-value hook)) | |
120 (memq function (symbol-value hook))) | |
121 (set hook | |
122 (if append | |
123 (append (symbol-value hook) (list function)) | |
124 (cons function (symbol-value hook))))) | |
125 ;; Alter the global value (which is also the only value, | |
126 ;; if the hook doesn't have a local value). | |
127 (or (if (consp function) | |
128 (member function (default-value hook)) | |
129 (memq function (default-value hook))) | |
130 (set-default hook | |
131 (if append | |
132 (append (default-value hook) (list function)) | |
133 (cons function (default-value hook))))))) | |
134 | |
135 (defun remove-hook (hook function &optional local) | |
136 "Remove from the value of HOOK the function FUNCTION. | |
137 HOOK should be a symbol, and FUNCTION may be any valid function. If | |
138 FUNCTION isn't the value of HOOK, or, if FUNCTION doesn't appear in the | |
139 list of hooks to run in HOOK, then nothing is done. See `add-hook'. | |
140 | |
141 The optional third argument, LOCAL, if non-nil, says to modify | |
142 the hook's buffer-local value rather than its default value. | |
143 This makes no difference if the hook is not buffer-local. | |
144 To make a hook variable buffer-local, always use | |
145 `make-local-hook', not `make-local-variable'." | |
146 (if (or (not (boundp hook)) ;unbound symbol, or | |
147 (not (default-boundp 'hook)) | |
148 (null (symbol-value hook)) ;value is nil, or | |
149 (null function)) ;function is nil, then | |
150 nil ;Do nothing. | |
151 (if (or local | |
152 ;; Detect the case where make-local-variable was used on a hook | |
153 ;; and do what we used to do. | |
154 (and (local-variable-p hook (current-buffer)) | |
155 (not (memq t (symbol-value hook))))) | |
156 (let ((hook-value (symbol-value hook))) | |
157 (if (consp hook-value) | |
158 (if (member function hook-value) | |
159 (setq hook-value (delete function (copy-sequence hook-value)))) | |
160 (if (equal hook-value function) | |
161 (setq hook-value nil))) | |
162 (set hook hook-value)) | |
163 (let ((hook-value (default-value hook))) | |
164 (if (consp hook-value) | |
165 (if (member function hook-value) | |
166 (setq hook-value (delete function (copy-sequence hook-value)))) | |
167 (if (equal hook-value function) | |
168 (setq hook-value nil))) | |
169 (set-default hook hook-value))))) | |
170 | |
171 (defun add-to-list (list-var element) | |
172 "Add to the value of LIST-VAR the element ELEMENT if it isn't there yet. | |
173 If you want to use `add-to-list' on a variable that is not defined | |
174 until a certain package is loaded, you should put the call to `add-to-list' | |
175 into a hook function that will be run only after loading the package. | |
176 `eval-after-load' provides one way to do this. In some cases | |
177 other hooks, such as major mode hooks, can do the job." | |
178 (or (member element (symbol-value list-var)) | |
179 (set list-var (cons element (symbol-value list-var))))) | |
180 | |
181 ;; called by Fkill_buffer() | |
182 (defvar kill-buffer-hook nil | |
183 "Function or functions to be called when a buffer is killed. | |
184 The value of this variable may be buffer-local. | |
185 The buffer about to be killed is current when this hook is run.") | |
186 | |
187 ;; in C in FSFmacs | |
188 (defvar kill-emacs-hook nil | |
189 "Function or functions to be called when `kill-emacs' is called, | |
190 just before emacs is actually killed.") | |
191 | |
192 ;; not obsolete. | |
193 (define-function 'rplaca 'setcar) | |
194 (define-function 'rplacd 'setcdr) | |
195 | |
196 (defun mapvector (__function __seq) | |
197 "Apply FUNCTION to each element of SEQ, making a vector of the results. | |
198 The result is a vector of the same length as SEQ. | |
199 SEQ may be a list, a vector or a string." | |
200 (let* ((len (length __seq)) | |
201 (vec (make-vector len 'nil)) | |
202 (i 0)) | |
203 (while (< i len) | |
204 (aset vec i (funcall __function (cond ((listp __seq) | |
205 (nth i __seq)) | |
206 (t (aref __seq i))))) | |
207 (setq i (+ i 1))) | |
208 vec)) | |
209 | |
210 ;;;; String functions. | |
211 | |
212 (defun replace-in-string (str regexp newtext &optional literal) | |
213 "Replaces all matches in STR for REGEXP with NEWTEXT string. | |
214 Optional LITERAL non-nil means do a literal replacement. | |
215 Otherwise treat \\ in NEWTEXT string as special: | |
216 \\& means substitute original matched text, | |
217 \\N means substitute match for \(...\) number N, | |
218 \\\\ means insert one \\." | |
219 (if (not (stringp str)) | |
220 (error "(replace-in-string): First argument must be a string: %s" str)) | |
221 (if (stringp newtext) | |
222 nil | |
223 (error "(replace-in-string): 3rd arg must be a string: %s" | |
224 newtext)) | |
225 (let ((rtn-str "") | |
226 (start 0) | |
227 (special) | |
228 match prev-start) | |
229 (while (setq match (string-match regexp str start)) | |
230 (setq prev-start start | |
231 start (match-end 0) | |
232 rtn-str | |
233 (concat | |
234 rtn-str | |
235 (substring str prev-start match) | |
236 (cond (literal newtext) | |
237 (t (mapconcat | |
238 (function | |
239 (lambda (c) | |
240 (if special | |
241 (progn | |
242 (setq special nil) | |
243 (cond ((eq c ?\\) "\\") | |
244 ((eq c ?&) | |
245 (substring str | |
246 (match-beginning 0) | |
247 (match-end 0))) | |
248 ((and (>= c ?0) (<= c ?9)) | |
249 (if (> c (+ ?0 (length | |
250 (match-data)))) | |
251 ;; Invalid match num | |
252 (error "(replace-in-string) Invalid match num: %c" c) | |
253 (setq c (- c ?0)) | |
254 (substring str | |
255 (match-beginning c) | |
256 (match-end c)))) | |
257 (t (char-to-string c)))) | |
258 (if (eq c ?\\) (progn (setq special t) nil) | |
259 (char-to-string c))))) | |
260 newtext "")))))) | |
261 (concat rtn-str (substring str start)))) | |
262 | |
263 (defun split-string (string pattern) | |
264 "Return a list of substrings of STRING which are separated by PATTERN." | |
265 (let (parts (start 0)) | |
266 (while (string-match pattern string start) | |
267 (setq parts (cons (substring string start (match-beginning 0)) parts) | |
268 start (match-end 0))) | |
269 (nreverse (cons (substring string start) parts)) | |
270 )) | |
271 | |
272 (defmacro with-output-to-string (&rest forms) | |
273 "Collect output to `standard-output' while evaluating FORMS and return | |
274 it as a string." | |
275 ;; by "William G. Dubuque" <wgd@zurich.ai.mit.edu> w/ mods from Stig | |
276 (` (save-excursion | |
277 (set-buffer (get-buffer-create " *string-output*")) | |
278 (setq buffer-read-only nil) | |
279 (buffer-disable-undo (current-buffer)) | |
280 (erase-buffer) | |
281 (let ((standard-output (current-buffer))) | |
282 (,@ forms)) | |
283 (prog1 | |
284 (buffer-string) | |
285 (erase-buffer))))) | |
286 | |
287 (defun insert-face (string face) | |
288 "Insert STRING and highlight with FACE. Returns the extent created." | |
289 (let ((p (point)) ext) | |
290 (insert string) | |
291 (setq ext (make-extent p (point))) | |
292 (set-extent-face ext face) | |
293 ext)) | |
294 | |
295 ;; not obsolete. | |
296 (define-function 'string= 'string-equal) | |
297 (define-function 'string< 'string-lessp) | |
298 (define-function 'int-to-string 'number-to-string) | |
299 (define-function 'string-to-int 'string-to-number) | |
300 | |
301 ;; alist/plist functions | |
302 (defun plist-to-alist (plist) | |
303 "Convert property list PLIST into the equivalent association-list form. | |
304 The alist is returned. This converts from | |
305 | |
306 \(a 1 b 2 c 3) | |
307 | |
308 into | |
309 | |
310 \((a . 1) (b . 2) (c . 3)) | |
311 | |
312 The original plist is not modified. See also `destructive-plist-to-alist'." | |
313 (let (alist) | |
314 (while plist | |
315 (setq alist (cons (cons (car plist) (cadr plist)) alist)) | |
316 (setq plist (cddr plist))) | |
317 (nreverse alist))) | |
318 | |
319 (defun destructive-plist-to-alist (plist) | |
320 "Convert property list PLIST into the equivalent association-list form. | |
321 The alist is returned. This converts from | |
322 | |
323 \(a 1 b 2 c 3) | |
324 | |
325 into | |
326 | |
327 \((a . 1) (b . 2) (c . 3)) | |
328 | |
329 The original plist is destroyed in the process of constructing the alist. | |
330 See also `plist-to-alist'." | |
331 (let ((head plist) | |
332 next) | |
333 (while plist | |
334 ;; remember the next plist pair. | |
335 (setq next (cddr plist)) | |
336 ;; make the cons holding the property value into the alist element. | |
337 (setcdr (cdr plist) (cadr plist)) | |
338 (setcar (cdr plist) (car plist)) | |
339 ;; reattach into alist form. | |
340 (setcar plist (cdr plist)) | |
341 (setcdr plist next) | |
342 (setq plist next)) | |
343 head)) | |
344 | |
345 (defun alist-to-plist (alist) | |
346 "Convert association list ALIST into the equivalent property-list form. | |
347 The plist is returned. This converts from | |
348 | |
349 \((a . 1) (b . 2) (c . 3)) | |
350 | |
351 into | |
352 | |
353 \(a 1 b 2 c 3) | |
354 | |
355 The original alist is not modified. See also `destructive-alist-to-plist'." | |
356 (let (plist) | |
357 (while alist | |
358 (let ((el (car alist))) | |
359 (setq plist (cons (cdr el) (cons (car el) plist)))) | |
360 (setq alist (cdr alist))) | |
361 (nreverse plist))) | |
362 | |
363 ;; getf, remf in cl*.el. | |
364 | |
365 (defmacro putf (plist prop val) | |
366 "Add property PROP to plist PLIST with value VAL. | |
367 Analogous to (setq PLIST (plist-put PLIST PROP VAL))." | |
368 `(setq ,plist (plist-put ,plist ,prop ,val))) | |
369 | |
370 (defmacro laxputf (lax-plist prop val) | |
371 "Add property PROP to lax plist LAX-PLIST with value VAL. | |
372 Analogous to (setq LAX-PLIST (lax-plist-put LAX-PLIST PROP VAL))." | |
373 `(setq ,lax-plist (lax-plist-put ,lax-plist ,prop ,val))) | |
374 | |
375 (defmacro laxremf (lax-plist prop) | |
376 "Remove property PROP from lax plist LAX-PLIST. | |
377 Analogous to (setq LAX-PLIST (lax-plist-remprop LAX-PLIST PROP))." | |
378 `(setq ,lax-plist (lax-plist-remprop ,lax-plist ,prop))) | |
379 | |
380 ;;; Error functions | |
381 | |
382 (defun error (&rest args) | |
383 "Signal an error, making error message by passing all args to `format'. | |
384 This error is not continuable: you cannot continue execution after the | |
385 error using the debugger `r' command. See also `cerror'." | |
386 (while t | |
387 (apply 'cerror args))) | |
388 | |
389 (defun cerror (&rest args) | |
390 "Like `error' but signals a continuable error." | |
391 (signal 'error (list (apply 'format args)))) | |
392 | |
393 (defmacro check-argument-type (predicate argument) | |
394 "Check that ARGUMENT satisfies PREDICATE. | |
395 If not, signal a continuable `wrong-type-argument' error until the | |
396 returned value satifies PREDICATE, and assign the returned value | |
397 to ARGUMENT." | |
398 `(if (not (,(eval predicate) ,argument)) | |
399 (setq ,argument | |
400 (wrong-type-argument ,predicate ,argument)))) | |
401 | |
402 (defun signal-error (error-symbol data) | |
403 "Signal a non-continuable error. Args are ERROR-SYMBOL, and associated DATA. | |
404 An error symbol is a symbol defined using `define-error'. | |
405 DATA should be a list. Its elements are printed as part of the error message. | |
406 If the signal is handled, DATA is made available to the handler. | |
407 See also `signal', and the functions to handle errors: `condition-case' | |
408 and `call-with-condition-handler'." | |
409 (while t | |
410 (signal error-symbol data))) | |
411 | |
412 (defun define-error (error-sym doc-string &optional inherits-from) | |
413 "Define a new error, denoted by ERROR-SYM. | |
414 DOC-STRING is an informative message explaining the error, and will be | |
415 printed out when an unhandled error occurs. | |
416 ERROR-SYM is a sub-error of INHERITS-FROM (which defaults to `error'). | |
417 | |
418 \[`define-error' internally works by putting on ERROR-SYM an `error-message' | |
419 property whose value is DOC-STRING, and an `error-conditions' property | |
420 that is a list of ERROR-SYM followed by each of its super-errors, up | |
421 to and including `error'. You will sometimes see code that sets this up | |
422 directly rather than calling `define-error', but you should *not* do this | |
423 yourself.]" | |
424 (check-argument-type 'symbolp error-sym) | |
425 (check-argument-type 'stringp doc-string) | |
426 (put error-sym 'error-message doc-string) | |
427 (or inherits-from (setq inherits-from 'error)) | |
428 (let ((conds (get inherits-from 'error-conditions))) | |
429 (or conds (signal-error 'error (list "Not an error symbol" error-sym))) | |
430 (put error-sym 'error-conditions (cons error-sym conds)))) | |
431 | |
432 ;;;; Miscellanea. | |
433 | |
434 (defun buffer-substring-no-properties (beg end) | |
435 "Return the text from BEG to END, without text properties, as a string." | |
436 (let ((string (buffer-substring beg end))) | |
437 (set-text-properties 0 (length string) nil string) | |
438 string)) | |
439 | |
440 (defun ignore (&rest ignore) | |
441 "Do nothing and return nil. | |
442 This function accepts any number of arguments, but ignores them." | |
443 (interactive) | |
444 nil) | |
445 | |
446 (defmacro save-current-buffer (&rest forms) | |
447 "Restore the current buffer setting after executing FORMS. | |
448 Does not restore the values of point and mark. | |
449 See also: `save-excursion'." | |
450 ;; by Stig@hackvan.com | |
451 (` (let ((_cur_buf_ (current-buffer))) | |
452 (unwind-protect | |
453 (progn (,@ forms)) | |
454 (set-buffer _cur_buf_))))) | |
455 | |
456 (defmacro eval-in-buffer (buffer &rest forms) | |
457 "Evaluate FORMS in BUFFER. | |
458 See also: `save-current-buffer' and `save-excursion'." | |
459 ;; by Stig@hackvan.com | |
460 (` (save-current-buffer | |
461 (set-buffer (, buffer)) | |
462 (,@ forms)))) | |
463 | |
464 ;;; The real defn is in abbrev.el but some early callers | |
465 ;;; (eg lisp-mode-abbrev-table) want this before abbrev.el is loaded... | |
466 | |
467 (if (not (fboundp 'define-abbrev-table)) | |
468 (progn | |
469 (setq abbrev-table-name-list '()) | |
470 (fset 'define-abbrev-table (function (lambda (name defs) | |
471 ;; These are fixed-up when abbrev.el loads. | |
472 (setq abbrev-table-name-list | |
473 (cons (cons name defs) | |
474 abbrev-table-name-list))))))) | |
475 | |
476 (defun functionp (obj) | |
477 "Returns t if OBJ is a function, nil otherwise." | |
478 (cond | |
479 ((symbolp obj) (fboundp obj)) | |
480 ((subrp obj)) | |
481 ((compiled-function-p obj)) | |
482 ((consp obj) | |
483 (if (eq (car obj) 'lambda) (listp (car (cdr obj))))) | |
484 (t nil))) | |
485 | |
486 ;; This was not present before. I think Jamie had some objections | |
487 ;; to this, so I'm leaving this undefined for now. --ben | |
488 | |
489 ;;; The objection is this: there is more than one way to load the same file. | |
490 ;;; "foo", "foo.elc", "foo.el", and "/some/path/foo.elc" are all differrent | |
491 ;;; ways to load the exact same code. `eval-after-load' is too stupid to | |
492 ;;; deal with this sort of thing. If this sort of feature is desired, then | |
493 ;;; it should work off of a hook on `provide'. Features are unique and | |
494 ;;; the arguments to (load) are not. --Stig | |
495 | |
496 ;;;; Specifying things to do after certain files are loaded. | |
497 | |
498 ;(defun eval-after-load (file form) | |
499 ; "Arrange that, if FILE is ever loaded, FORM will be run at that time. | |
500 ;This makes or adds to an entry on `after-load-alist'. | |
501 ;If FILE is already loaded, evaluate FORM right now. | |
502 ;It does nothing if FORM is already on the list for FILE. | |
503 ;FILE should be the name of a library, with no directory name." | |
504 ; ;; Make sure there is an element for FILE. | |
505 ; (or (assoc file after-load-alist) | |
506 ; (setq after-load-alist (cons (list file) after-load-alist))) | |
507 ; ;; Add FORM to the element if it isn't there. | |
508 ; (let ((elt (assoc file after-load-alist))) | |
509 ; (or (member form (cdr elt)) | |
510 ; (progn | |
511 ; (nconc elt (list form)) | |
512 ; ;; If the file has been loaded already, run FORM right away. | |
513 ; (and (assoc file load-history) | |
514 ; (eval form))))) | |
515 ; form) | |
516 ; | |
517 ;(defun eval-next-after-load (file) | |
518 ; "Read the following input sexp, and run it whenever FILE is loaded. | |
519 ;This makes or adds to an entry on `after-load-alist'. | |
520 ;FILE should be the name of a library, with no directory name." | |
521 ; (eval-after-load file (read))) | |
522 | |
523 ; alternate names (not obsolete) | |
524 (if (not (fboundp 'mod)) (define-function 'mod '%)) | |
525 (define-function 'move-marker 'set-marker) | |
526 (define-function 'beep 'ding) ;preserve lingual purtity | |
527 (define-function 'indent-to-column 'indent-to) | |
528 (define-function 'backward-delete-char 'delete-backward-char) | |
529 (define-function 'search-forward-regexp (symbol-function 're-search-forward)) | |
530 (define-function 'search-backward-regexp (symbol-function 're-search-backward)) | |
531 (define-function 'remove-directory 'delete-directory) | |
532 (define-function 'set-match-data 'store-match-data) | |
533 (define-function 'send-string-to-terminal 'external-debugging-output) | |
534 (define-function 'buffer-string 'buffer-substring) |