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)