comparison lisp/subr.el @ 412:697ef44129c6 r21-2-14

Import from CVS: tag r21-2-14
author cvs
date Mon, 13 Aug 2007 11:20:41 +0200
parents b8cc9ab3f761
children da8ed4261e83
comparison
equal deleted inserted replaced
411:12e008d41344 412:697ef44129c6
1 ;;; subr.el --- basic lisp subroutines for XEmacs 1 ;;; subr.el --- basic lisp subroutines for XEmacs
2 2
3 ;; Copyright (C) 1985, 1986, 1992, 1994-5, 1997 Free Software Foundation, Inc. 3 ;; Copyright (C) 1985, 1986, 1992, 1994-5, 1997 Free Software Foundation, Inc.
4 ;; Copyright (C) 1995 Tinker Systems and INS Engineering Corp. 4 ;; Copyright (C) 1995 Tinker Systems and INS Engineering Corp.
5 ;; Copyright (C) 1995 Sun Microsystems. 5 ;; Copyright (C) 1995 Sun Microsystems.
6 ;; Copyright (C) 2000 Ben Wing.
7 6
8 ;; Maintainer: XEmacs Development Team 7 ;; Maintainer: XEmacs Development Team
9 ;; Keywords: extensions, dumped 8 ;; Keywords: extensions, dumped
10 9
11 ;; This file is part of XEmacs. 10 ;; This file is part of XEmacs.
116 one. 115 one.
117 116
118 This function does nothing if HOOK is already local in the current 117 This function does nothing if HOOK is already local in the current
119 buffer. 118 buffer.
120 119
121 Do not use `make-local-variable' to make a hook variable buffer-local. 120 Do not use `make-local-variable' to make a hook variable buffer-local."
122
123 See also `add-local-hook' and `remove-local-hook'."
124 (if (local-variable-p hook (current-buffer)) ; XEmacs 121 (if (local-variable-p hook (current-buffer)) ; XEmacs
125 nil 122 nil
126 (or (boundp hook) (set hook nil)) 123 (or (boundp hook) (set hook nil))
127 (make-local-variable hook) 124 (make-local-variable hook)
128 (set hook (list t)))) 125 (set hook (list t))))
140 To make a hook variable buffer-local, always use 137 To make a hook variable buffer-local, always use
141 `make-local-hook', not `make-local-variable'. 138 `make-local-hook', not `make-local-variable'.
142 139
143 HOOK should be a symbol, and FUNCTION may be any valid function. If 140 HOOK should be a symbol, and FUNCTION may be any valid function. If
144 HOOK is void, it is first set to nil. If HOOK's value is a single 141 HOOK is void, it is first set to nil. If HOOK's value is a single
145 function, it is changed to a list of functions. 142 function, it is changed to a list of functions."
146
147 You can remove this hook yourself using `remove-hook'.
148
149 See also `add-local-hook' and `add-one-shot-hook'."
150 (or (boundp hook) (set hook nil)) 143 (or (boundp hook) (set hook nil))
151 (or (default-boundp hook) (set-default hook nil)) 144 (or (default-boundp hook) (set-default hook nil))
152 ;; If the hook value is a single function, turn it into a list. 145 ;; If the hook value is a single function, turn it into a list.
153 (let ((old (symbol-value hook))) 146 (let ((old (symbol-value hook)))
154 (if (or (not (listp old)) (eq (car old) 'lambda)) 147 (if (or (not (listp old)) (eq (car old) 'lambda))
190 (if (or (not (boundp hook)) ;unbound symbol, or 183 (if (or (not (boundp hook)) ;unbound symbol, or
191 (not (default-boundp 'hook)) 184 (not (default-boundp 'hook))
192 (null (symbol-value hook)) ;value is nil, or 185 (null (symbol-value hook)) ;value is nil, or
193 (null function)) ;function is nil, then 186 (null function)) ;function is nil, then
194 nil ;Do nothing. 187 nil ;Do nothing.
195 (flet ((hook-remove 188 (if (or local
196 (function hook-value) 189 ;; Detect the case where make-local-variable was used on a hook
197 (flet ((hook-test 190 ;; and do what we used to do.
198 (fn hel) 191 (and (local-variable-p hook (current-buffer))
199 (or (equal fn hel) 192 (not (memq t (symbol-value hook)))))
200 (and (symbolp hel) 193 (let ((hook-value (symbol-value hook)))
201 (equal fn 194 (if (and (consp hook-value) (not (functionp hook-value)))
202 (get hel 'one-shot-hook-fun)))))) 195 (if (member function hook-value)
203 (if (and (consp hook-value) 196 (setq hook-value (delete function (copy-sequence hook-value))))
204 (not (functionp hook-value))) 197 (if (equal hook-value function)
205 (if (member* function hook-value :test 'hook-test) 198 (setq hook-value nil)))
206 (setq hook-value 199 (set hook hook-value))
207 (delete* function (copy-sequence hook-value) 200 (let ((hook-value (default-value hook)))
208 :test 'hook-test))) 201 (if (and (consp hook-value) (not (functionp hook-value)))
209 (if (equal hook-value function) 202 (if (member function hook-value)
210 (setq hook-value nil))) 203 (setq hook-value (delete function (copy-sequence hook-value))))
211 hook-value))) 204 (if (equal hook-value function)
212 (if (or local 205 (setq hook-value nil)))
213 ;; Detect the case where make-local-variable was used on a hook 206 (set-default hook hook-value)))))
214 ;; and do what we used to do.
215 (and (local-variable-p hook (current-buffer))
216 (not (memq t (symbol-value hook)))))
217 (set hook (hook-remove function (symbol-value hook)))
218 (set-default hook (hook-remove function (default-value hook)))))))
219
220 ;; XEmacs addition
221 ;; #### we need a coherent scheme for indicating compatibility info,
222 ;; so that it can be programmatically retrieved.
223 (defun add-local-hook (hook function &optional append)
224 "Add to the local value of HOOK the function FUNCTION.
225 This modifies only the buffer-local value for the hook (which is
226 automatically make buffer-local, if necessary), not its default value.
227 FUNCTION is not added if already present.
228 FUNCTION is added (if necessary) at the beginning of the hook list
229 unless the optional argument APPEND is non-nil, in which case
230 FUNCTION is added at the end.
231
232 HOOK should be a symbol, and FUNCTION may be any valid function. If
233 HOOK is void, it is first set to nil. If HOOK's value is a single
234 function, it is changed to a list of functions.
235
236 You can remove this hook yourself using `remove-local-hook'.
237
238 See also `add-hook' and `make-local-hook'."
239 (make-local-hook hook)
240 (add-hook hook function append t))
241
242 ;; XEmacs addition
243 (defun remove-local-hook (hook function)
244 "Remove from the local value of HOOK the function FUNCTION.
245 This modifies only the buffer-local value for the hook, not its default
246 value. (Nothing happens if the hook is not buffer-local.)
247 HOOK should be a symbol, and FUNCTION may be any valid function. If
248 FUNCTION isn't the value of HOOK, or, if FUNCTION doesn't appear in the
249 list of hooks to run in HOOK, then nothing is done. See `add-hook'.
250
251 See also `add-local-hook' and `make-local-hook'."
252 (if (local-variable-p hook (current-buffer))
253 (remove-hook hook function t)))
254
255 (defun add-one-shot-hook (hook function &optional append local)
256 "Add to the value of HOOK the one-shot function FUNCTION.
257 FUNCTION will automatically be removed from the hook the first time
258 after it runs (whether to completion or to an error).
259 FUNCTION is not added if already present.
260 FUNCTION is added (if necessary) at the beginning of the hook list
261 unless the optional argument APPEND is non-nil, in which case
262 FUNCTION is added at the end.
263
264 HOOK should be a symbol, and FUNCTION may be any valid function. If
265 HOOK is void, it is first set to nil. If HOOK's value is a single
266 function, it is changed to a list of functions.
267
268 You can remove this hook yourself using `remove-hook'.
269
270 See also `add-hook', `add-local-hook', and `add-local-one-shot-hook'."
271 (let ((sym (gensym)))
272 (fset sym `(lambda (&rest args)
273 (unwind-protect
274 (apply ',function args)
275 (remove-hook ',hook ',sym ',local))))
276 (put sym 'one-shot-hook-fun function)
277 (add-hook hook sym append local)))
278
279 (defun add-local-one-shot-hook (hook function &optional append)
280 "Add to the local value of HOOK the one-shot function FUNCTION.
281 FUNCTION will automatically be removed from the hook the first time
282 after it runs (whether to completion or to an error).
283 FUNCTION is not added if already present.
284 FUNCTION is added (if necessary) at the beginning of the hook list
285 unless the optional argument APPEND is non-nil, in which case
286 FUNCTION is added at the end.
287
288 The optional fourth argument, LOCAL, if non-nil, says to modify
289 the hook's buffer-local value rather than its default value.
290 This makes no difference if the hook is not buffer-local.
291 To make a hook variable buffer-local, always use
292 `make-local-hook', not `make-local-variable'.
293
294 HOOK should be a symbol, and FUNCTION may be any valid function. If
295 HOOK is void, it is first set to nil. If HOOK's value is a single
296 function, it is changed to a list of functions.
297
298 You can remove this hook yourself using `remove-local-hook'.
299
300 See also `add-hook', `add-local-hook', and `add-local-one-shot-hook'."
301 (make-local-hook hook)
302 (add-one-shot-hook hook function append t))
303 207
304 (defun add-to-list (list-var element) 208 (defun add-to-list (list-var element)
305 "Add to the value of LIST-VAR the element ELEMENT if it isn't there yet. 209 "Add to the value of LIST-VAR the element ELEMENT if it isn't there yet.
306 The test for presence of ELEMENT is done with `equal'. 210 The test for presence of ELEMENT is done with `equal'.
307 If you want to use `add-to-list' on a variable that is not defined 211 If you want to use `add-to-list' on a variable that is not defined
332 ;; (setcar conscell newcar) 236 ;; (setcar conscell newcar)
333 ;; conscell) 237 ;; conscell)
334 ;; ...and analogously for RPLACD. 238 ;; ...and analogously for RPLACD.
335 (define-function 'rplaca 'setcar) 239 (define-function 'rplaca 'setcar)
336 (define-function 'rplacd 'setcdr) 240 (define-function 'rplacd 'setcdr)
337
338 (defun copy-symbol (symbol &optional copy-properties)
339 "Return a new uninterned symbol with the same name as SYMBOL.
340 If COPY-PROPERTIES is non-nil, the new symbol will have a copy of
341 SYMBOL's value, function, and property lists."
342 (let ((new (make-symbol (symbol-name symbol))))
343 (when copy-properties
344 ;; This will not copy SYMBOL's chain of forwarding objects, but
345 ;; I think that's OK. Callers should not expect such magic to
346 ;; keep working in the copy in the first place.
347 (and (boundp symbol)
348 (set new (symbol-value symbol)))
349 (and (fboundp symbol)
350 (fset new (symbol-function symbol)))
351 (setplist new (copy-list (symbol-plist symbol))))
352 new))
353 241
354 ;;;; String functions. 242 ;;;; String functions.
355 243
356 ;; XEmacs 244 ;; XEmacs
357 (defun replace-in-string (str regexp newtext &optional literal) 245 (defun replace-in-string (str regexp newtext &optional literal)
404 (defun split-string (string &optional pattern) 292 (defun split-string (string &optional pattern)
405 "Return a list of substrings of STRING which are separated by PATTERN. 293 "Return a list of substrings of STRING which are separated by PATTERN.
406 If PATTERN is omitted, it defaults to \"[ \\f\\t\\n\\r\\v]+\"." 294 If PATTERN is omitted, it defaults to \"[ \\f\\t\\n\\r\\v]+\"."
407 (or pattern 295 (or pattern
408 (setq pattern "[ \f\t\n\r\v]+")) 296 (setq pattern "[ \f\t\n\r\v]+"))
409 (let (parts (start 0) (len (length string))) 297 ;; The FSF version of this function takes care not to cons in case
410 (if (string-match pattern string) 298 ;; of infloop. Maybe we should synch?
411 (setq parts (cons (substring string 0 (match-beginning 0)) parts) 299 (let (parts (start 0))
412 start (match-end 0))) 300 (while (string-match pattern string start)
413 (while (and (< start len)
414 (string-match pattern string (if (> start (match-beginning 0))
415 start
416 (1+ start))))
417 (setq parts (cons (substring string start (match-beginning 0)) parts) 301 (setq parts (cons (substring string start (match-beginning 0)) parts)
418 start (match-end 0))) 302 start (match-end 0)))
419 (nreverse (cons (substring string start) parts)))) 303 (nreverse (cons (substring string start) parts))))
420 304
421 ;; #### #### #### AAaargh! Must be in C, because it is used insanely 305 ;; #### #### #### AAaargh! Must be in C, because it is used insanely
433 317
434 (defmacro with-output-to-string (&rest forms) 318 (defmacro with-output-to-string (&rest forms)
435 "Collect output to `standard-output' while evaluating FORMS and return 319 "Collect output to `standard-output' while evaluating FORMS and return
436 it as a string." 320 it as a string."
437 ;; by "William G. Dubuque" <wgd@zurich.ai.mit.edu> w/ mods from Stig 321 ;; by "William G. Dubuque" <wgd@zurich.ai.mit.edu> w/ mods from Stig
438 `(with-current-buffer (get-buffer-create 322 `(with-current-buffer (get-buffer-create " *string-output*")
439 (generate-new-buffer-name " *string-output*"))
440 (setq buffer-read-only nil) 323 (setq buffer-read-only nil)
441 (buffer-disable-undo (current-buffer)) 324 (buffer-disable-undo (current-buffer))
442 (erase-buffer) 325 (erase-buffer)
443 (let ((standard-output (current-buffer))) 326 (let ((standard-output (current-buffer)))
444 ,@forms) 327 ,@forms)
445 (prog1 328 (prog1
446 (buffer-string) 329 (buffer-string)
447 (erase-buffer)))) 330 (erase-buffer))))
448 331
449 (defmacro with-current-buffer (buffer &rest body) 332 (defmacro with-current-buffer (buffer &rest body)
450 "Temporarily make BUFFER the current buffer and execute the forms in BODY. 333 "Execute the forms in BODY with BUFFER as the current buffer.
451 The value returned is the value of the last form in BODY. 334 The value returned is the value of the last form in BODY.
452 See also `with-temp-buffer'." 335 See also `with-temp-buffer'."
453 `(save-current-buffer 336 `(save-current-buffer
454 (set-buffer ,buffer) 337 (set-buffer ,buffer)
455 ,@body)) 338 ,@body))
488 ;; Moved from mule-coding.el. 371 ;; Moved from mule-coding.el.
489 (defmacro with-string-as-buffer-contents (str &rest body) 372 (defmacro with-string-as-buffer-contents (str &rest body)
490 "With the contents of the current buffer being STR, run BODY. 373 "With the contents of the current buffer being STR, run BODY.
491 Returns the new contents of the buffer, as modified by BODY. 374 Returns the new contents of the buffer, as modified by BODY.
492 The original current buffer is restored afterwards." 375 The original current buffer is restored afterwards."
493 `(with-temp-buffer 376 `(let ((tempbuf (get-buffer-create " *string-as-buffer-contents*")))
494 (insert ,str) 377 (with-current-buffer tempbuf
495 ,@body 378 (unwind-protect
496 (buffer-string))) 379 (progn
380 (buffer-disable-undo (current-buffer))
381 (erase-buffer)
382 (insert ,str)
383 ,@body
384 (buffer-string))
385 (erase-buffer tempbuf)))))
497 386
498 (defun insert-face (string face) 387 (defun insert-face (string face)
499 "Insert STRING and highlight with FACE. Return the extent created." 388 "Insert STRING and highlight with FACE. Return the extent created."
500 (let ((p (point)) ext) 389 (let ((p (point)) ext)
501 (insert string) 390 (insert string)
673 (defun ignore (&rest ignore) 562 (defun ignore (&rest ignore)
674 "Do nothing and return nil. 563 "Do nothing and return nil.
675 This function accepts any number of arguments, but ignores them." 564 This function accepts any number of arguments, but ignores them."
676 (interactive) 565 (interactive)
677 nil) 566 nil)
567
568 (define-function 'mapc-internal 'mapc)
569 (make-obsolete 'mapc-internal 'mapc)
678 570
679 (define-function 'eval-in-buffer 'with-current-buffer) 571 (define-function 'eval-in-buffer 'with-current-buffer)
680 (make-obsolete 'eval-in-buffer 'with-current-buffer) 572 (make-obsolete 'eval-in-buffer 'with-current-buffer)
681 573
682 ;;; The real defn is in abbrev.el but some early callers 574 ;;; The real defn is in abbrev.el but some early callers
720 (and (eq (car-safe spec) 'interactive) 612 (and (eq (car-safe spec) 'interactive)
721 spec))) 613 spec)))
722 (t 614 (t
723 (error "Non-funcallable object: %s" function)))) 615 (error "Non-funcallable object: %s" function))))
724 616
725 (defun function-allows-args (function n)
726 "Return whether FUNCTION can be called with N arguments."
727 (and (<= (function-min-args function) n)
728 (or (null (function-max-args function))
729 (<= n (function-max-args function)))))
730
731 ;; This function used to be an alias to `buffer-substring', except 617 ;; This function used to be an alias to `buffer-substring', except
732 ;; that FSF Emacs 20.4 added a BUFFER argument in an incompatible way. 618 ;; that FSF Emacs 20.4 added a BUFFER argument in an incompatible way.
733 ;; The new FSF's semantics makes more sense, but we try to support 619 ;; The new FSF's semantics makes more sense, but we try to support
734 ;; both for backward compatibility. 620 ;; both for backward compatibility.
735 (defun buffer-string (&optional buffer old-end old-buffer) 621 (defun buffer-string (&optional buffer old-end old-buffer)
740 If BUFFER is specified, the contents of that buffer are returned. 626 If BUFFER is specified, the contents of that buffer are returned.
741 627
742 The arguments OLD-END and OLD-BUFFER are supported for backward 628 The arguments OLD-END and OLD-BUFFER are supported for backward
743 compatibility with pre-21.2 XEmacsen times when arguments to this 629 compatibility with pre-21.2 XEmacsen times when arguments to this
744 function were (buffer-string &optional START END BUFFER)." 630 function were (buffer-string &optional START END BUFFER)."
745 (cond 631 (if (or (null buffer)
746 ((or (stringp buffer) (bufferp buffer)) 632 (bufferp buffer)
747 ;; Most definitely the new way. 633 (stringp buffer))
748 (buffer-substring nil nil buffer)) 634 ;; The new way
749 ((or (stringp old-buffer) (bufferp old-buffer) 635 (buffer-substring nil nil buffer)
750 (natnump buffer) (natnump old-end)) 636 ;; The old way
751 ;; Definitely the old way. 637 (buffer-substring buffer old-end old-buffer)))
752 (buffer-substring buffer old-end old-buffer))
753 (t
754 ;; Probably the old way.
755 (buffer-substring buffer old-end old-buffer))))
756 638
757 ;; This was not present before. I think Jamie had some objections 639 ;; This was not present before. I think Jamie had some objections
758 ;; to this, so I'm leaving this undefined for now. --ben 640 ;; to this, so I'm leaving this undefined for now. --ben
759 641
760 ;;; The objection is this: there is more than one way to load the same file. 642 ;;; The objection is this: there is more than one way to load the same file.