comparison lisp/subr.el @ 442:abe6d1db359e r21-2-36

Import from CVS: tag r21-2-36
author cvs
date Mon, 13 Aug 2007 11:35:02 +0200
parents 3ecd8885ac67
children 576fb035e263
comparison
equal deleted inserted replaced
441:72a7cfa4a488 442:abe6d1db359e
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.
6 7
7 ;; Maintainer: XEmacs Development Team 8 ;; Maintainer: XEmacs Development Team
8 ;; Keywords: extensions, dumped 9 ;; Keywords: extensions, dumped
9 10
10 ;; This file is part of XEmacs. 11 ;; This file is part of XEmacs.
115 one. 116 one.
116 117
117 This function does nothing if HOOK is already local in the current 118 This function does nothing if HOOK is already local in the current
118 buffer. 119 buffer.
119 120
120 Do not use `make-local-variable' to make a hook variable buffer-local." 121 Do not use `make-local-variable' to make a hook variable buffer-local.
122
123 See also `add-local-hook' and `remove-local-hook'."
121 (if (local-variable-p hook (current-buffer)) ; XEmacs 124 (if (local-variable-p hook (current-buffer)) ; XEmacs
122 nil 125 nil
123 (or (boundp hook) (set hook nil)) 126 (or (boundp hook) (set hook nil))
124 (make-local-variable hook) 127 (make-local-variable hook)
125 (set hook (list t)))) 128 (set hook (list t))))
137 To make a hook variable buffer-local, always use 140 To make a hook variable buffer-local, always use
138 `make-local-hook', not `make-local-variable'. 141 `make-local-hook', not `make-local-variable'.
139 142
140 HOOK should be a symbol, and FUNCTION may be any valid function. If 143 HOOK should be a symbol, and FUNCTION may be any valid function. If
141 HOOK is void, it is first set to nil. If HOOK's value is a single 144 HOOK is void, it is first set to nil. If HOOK's value is a single
142 function, it is changed to a list of functions." 145 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'."
143 (or (boundp hook) (set hook nil)) 150 (or (boundp hook) (set hook nil))
144 (or (default-boundp hook) (set-default hook nil)) 151 (or (default-boundp hook) (set-default hook nil))
145 ;; If the hook value is a single function, turn it into a list. 152 ;; If the hook value is a single function, turn it into a list.
146 (let ((old (symbol-value hook))) 153 (let ((old (symbol-value hook)))
147 (if (or (not (listp old)) (eq (car old) 'lambda)) 154 (if (or (not (listp old)) (eq (car old) 'lambda))
183 (if (or (not (boundp hook)) ;unbound symbol, or 190 (if (or (not (boundp hook)) ;unbound symbol, or
184 (not (default-boundp 'hook)) 191 (not (default-boundp 'hook))
185 (null (symbol-value hook)) ;value is nil, or 192 (null (symbol-value hook)) ;value is nil, or
186 (null function)) ;function is nil, then 193 (null function)) ;function is nil, then
187 nil ;Do nothing. 194 nil ;Do nothing.
188 (if (or local 195 (flet ((hook-remove
189 ;; Detect the case where make-local-variable was used on a hook 196 (function hook-value)
190 ;; and do what we used to do. 197 (flet ((hook-test
191 (and (local-variable-p hook (current-buffer)) 198 (fn hel)
192 (not (memq t (symbol-value hook))))) 199 (or (equal fn hel)
193 (let ((hook-value (symbol-value hook))) 200 (and (symbolp hel)
194 (if (and (consp hook-value) (not (functionp hook-value))) 201 (equal fn
195 (if (member function hook-value) 202 (get hel 'one-shot-hook-fun))))))
196 (setq hook-value (delete function (copy-sequence hook-value)))) 203 (if (and (consp hook-value)
197 (if (equal hook-value function) 204 (not (functionp hook-value)))
198 (setq hook-value nil))) 205 (if (member* function hook-value :test 'hook-test)
199 (set hook hook-value)) 206 (setq hook-value
200 (let ((hook-value (default-value hook))) 207 (delete* function (copy-sequence hook-value)
201 (if (and (consp hook-value) (not (functionp hook-value))) 208 :test 'hook-test)))
202 (if (member function hook-value) 209 (if (equal hook-value function)
203 (setq hook-value (delete function (copy-sequence hook-value)))) 210 (setq hook-value nil)))
204 (if (equal hook-value function) 211 hook-value)))
205 (setq hook-value nil))) 212 (if (or local
206 (set-default hook hook-value))))) 213 ;; Detect the case where make-local-variable was used on a hook
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))
207 303
208 (defun add-to-list (list-var element) 304 (defun add-to-list (list-var element)
209 "Add to the value of LIST-VAR the element ELEMENT if it isn't there yet. 305 "Add to the value of LIST-VAR the element ELEMENT if it isn't there yet.
210 The test for presence of ELEMENT is done with `equal'. 306 The test for presence of ELEMENT is done with `equal'.
211 If you want to use `add-to-list' on a variable that is not defined 307 If you want to use `add-to-list' on a variable that is not defined
220 ;; called by Fkill_buffer() 316 ;; called by Fkill_buffer()
221 (defvar kill-buffer-hook nil 317 (defvar kill-buffer-hook nil
222 "Function or functions to be called when a buffer is killed. 318 "Function or functions to be called when a buffer is killed.
223 The value of this variable may be buffer-local. 319 The value of this variable may be buffer-local.
224 The buffer about to be killed is current when this hook is run.") 320 The buffer about to be killed is current when this hook is run.")
225
226 ;; called by Frecord_buffer()
227 (defvar record-buffer-hook nil
228 "Function or functions to be called when a buffer is recorded.
229 The value of this variable may be buffer-local.
230 The buffer being recorded is passed as an argument to the hook.")
231 321
232 ;; in C in FSFmacs 322 ;; in C in FSFmacs
233 (defvar kill-emacs-hook nil 323 (defvar kill-emacs-hook nil
234 "Function or functions to be called when `kill-emacs' is called, 324 "Function or functions to be called when `kill-emacs' is called,
235 just before emacs is actually killed.") 325 just before emacs is actually killed.")
259 (and (fboundp symbol) 349 (and (fboundp symbol)
260 (fset new (symbol-function symbol))) 350 (fset new (symbol-function symbol)))
261 (setplist new (copy-list (symbol-plist symbol)))) 351 (setplist new (copy-list (symbol-plist symbol))))
262 new)) 352 new))
263 353
354 (defun set-symbol-value-in-buffer (sym val buffer)
355 "Set the value of SYM to VAL in BUFFER. Useful with buffer-local variables.
356 If SYM has a buffer-local value in BUFFER, or will have one if set, this
357 function allows you to set the local value.
358
359 NOTE: At some point, this will be moved into C and will be very fast."
360 (with-current-buffer buffer
361 (set sym val)))
362
264 ;;;; String functions. 363 ;;;; String functions.
265 364
266 ;; XEmacs 365 ;; XEmacs
267 (defun replace-in-string (str regexp newtext &optional literal) 366 (defun replace-in-string (str regexp newtext &optional literal)
268 "Replace all matches in STR for REGEXP with NEWTEXT string, 367 "Replace all matches in STR for REGEXP with NEWTEXT string,
269 and returns the new string. 368 and returns the new string.
270 Optional LITERAL non-nil means do a literal replacement. 369 Optional LITERAL non-nil means do a literal replacement.
271 Otherwise treat \\ in NEWTEXT string as special: 370 Otherwise treat `\\' in NEWTEXT as special:
272 \\& means substitute original matched text, 371 `\\&' in NEWTEXT means substitute original matched text.
273 \\N means substitute match for \(...\) number N, 372 `\\N' means substitute what matched the Nth `\\(...\\)'.
274 \\\\ means insert one \\." 373 If Nth parens didn't match, substitute nothing.
374 `\\\\' means insert one `\\'.
375 `\\u' means upcase the next character.
376 `\\l' means downcase the next character.
377 `\\U' means begin upcasing all following characters.
378 `\\L' means begin downcasing all following characters.
379 `\\E' means terminate the effect of any `\\U' or `\\L'."
275 (check-argument-type 'stringp str) 380 (check-argument-type 'stringp str)
276 (check-argument-type 'stringp newtext) 381 (check-argument-type 'stringp newtext)
277 (let ((rtn-str "") 382 (if (> (length str) 50)
278 (start 0) 383 (with-temp-buffer
279 (special) 384 (insert str)
280 match prev-start) 385 (goto-char 1)
281 (while (setq match (string-match regexp str start)) 386 (while (re-search-forward regexp nil t)
282 (setq prev-start start 387 (replace-match newtext t literal))
283 start (match-end 0) 388 (buffer-string))
284 rtn-str 389 (let ((start 0) newstr)
285 (concat 390 (while (string-match regexp str start)
286 rtn-str 391 (setq newstr (replace-match newtext t literal str)
287 (substring str prev-start match) 392 start (+ (match-end 0) (- (length newstr) (length str)))
288 (cond (literal newtext) 393 str newstr))
289 (t (mapconcat 394 str)))
290 (lambda (c)
291 (if special
292 (progn
293 (setq special nil)
294 (cond ((eq c ?\\) "\\")
295 ((eq c ?&)
296 (substring str
297 (match-beginning 0)
298 (match-end 0)))
299 ((and (>= c ?0) (<= c ?9))
300 (if (> c (+ ?0 (length
301 (match-data))))
302 ;; Invalid match num
303 (error "Invalid match num: %c" c)
304 (setq c (- c ?0))
305 (substring str
306 (match-beginning c)
307 (match-end c))))
308 (t (char-to-string c))))
309 (if (eq c ?\\) (progn (setq special t) nil)
310 (char-to-string c))))
311 newtext ""))))))
312 (concat rtn-str (substring str start))))
313 395
314 (defun split-string (string &optional pattern) 396 (defun split-string (string &optional pattern)
315 "Return a list of substrings of STRING which are separated by PATTERN. 397 "Return a list of substrings of STRING which are separated by PATTERN.
316 If PATTERN is omitted, it defaults to \"[ \\f\\t\\n\\r\\v]+\"." 398 If PATTERN is omitted, it defaults to \"[ \\f\\t\\n\\r\\v]+\"."
317 (or pattern 399 (or pattern
343 425
344 (defmacro with-output-to-string (&rest forms) 426 (defmacro with-output-to-string (&rest forms)
345 "Collect output to `standard-output' while evaluating FORMS and return 427 "Collect output to `standard-output' while evaluating FORMS and return
346 it as a string." 428 it as a string."
347 ;; by "William G. Dubuque" <wgd@zurich.ai.mit.edu> w/ mods from Stig 429 ;; by "William G. Dubuque" <wgd@zurich.ai.mit.edu> w/ mods from Stig
348 `(with-current-buffer (get-buffer-create " *string-output*") 430 `(with-current-buffer (get-buffer-create
431 (generate-new-buffer-name " *string-output*"))
349 (setq buffer-read-only nil) 432 (setq buffer-read-only nil)
350 (buffer-disable-undo (current-buffer)) 433 (buffer-disable-undo (current-buffer))
351 (erase-buffer) 434 (erase-buffer)
352 (let ((standard-output (current-buffer))) 435 (let ((standard-output (current-buffer)))
353 ,@forms) 436 ,@forms)
397 ;; Moved from mule-coding.el. 480 ;; Moved from mule-coding.el.
398 (defmacro with-string-as-buffer-contents (str &rest body) 481 (defmacro with-string-as-buffer-contents (str &rest body)
399 "With the contents of the current buffer being STR, run BODY. 482 "With the contents of the current buffer being STR, run BODY.
400 Returns the new contents of the buffer, as modified by BODY. 483 Returns the new contents of the buffer, as modified by BODY.
401 The original current buffer is restored afterwards." 484 The original current buffer is restored afterwards."
402 `(let ((tempbuf (get-buffer-create " *string-as-buffer-contents*"))) 485 `(with-temp-buffer
403 (with-current-buffer tempbuf 486 (insert ,str)
404 (unwind-protect 487 ,@body
405 (progn 488 (buffer-string)))
406 (buffer-disable-undo (current-buffer))
407 (erase-buffer)
408 (insert ,str)
409 ,@body
410 (buffer-string))
411 (erase-buffer tempbuf)))))
412 489
413 (defun insert-face (string face) 490 (defun insert-face (string face)
414 "Insert STRING and highlight with FACE. Return the extent created." 491 "Insert STRING and highlight with FACE. Return the extent created."
415 (let ((p (point)) ext) 492 (let ((p (point)) ext)
416 (insert string) 493 (insert string)
509 Analogous to (setq LAX-PLIST (lax-plist-remprop LAX-PLIST PROP))." 586 Analogous to (setq LAX-PLIST (lax-plist-remprop LAX-PLIST PROP))."
510 `(setq ,lax-plist (lax-plist-remprop ,lax-plist ,prop))) 587 `(setq ,lax-plist (lax-plist-remprop ,lax-plist ,prop)))
511 588
512 ;;; Error functions 589 ;;; Error functions
513 590
514 (defun error (&rest args) 591 (defun error (datum &rest args)
515 "Signal an error, making error message by passing all args to `format'. 592 "Signal a non-continuable error.
593 DATUM should normally be an error symbol, i.e. a symbol defined using
594 `define-error'. ARGS will be made into a list, and DATUM and ARGS passed
595 as the two arguments to `signal', the most basic error handling function.
596
516 This error is not continuable: you cannot continue execution after the 597 This error is not continuable: you cannot continue execution after the
517 error using the debugger `r' command. See also `cerror'." 598 error using the debugger `r' command. See also `cerror'.
518 (while t 599
519 (apply 'cerror args))) 600 The correct semantics of ARGS varies from error to error, but for most
520 601 errors that need to be generated in Lisp code, the first argument
521 (defun cerror (&rest args) 602 should be a string describing the *context* of the error (i.e. the
603 exact operation being performed and what went wrong), and the remaining
604 arguments or \"frobs\" (most often, there is one) specify the
605 offending object(s) and/or provide additional details such as the exact
606 error when a file error occurred, e.g.:
607
608 -- the buffer in which an editing error occurred.
609 -- an invalid value that was encountered. (In such cases, the string
610 should describe the purpose or \"semantics\" of the value [e.g. if the
611 value is an argument to a function, the name of the argument; if the value
612 is the value corresponding to a keyword, the name of the keyword; if the
613 value is supposed to be a list length, say this and say what the purpose
614 of the list is; etc.] as well as specifying why the value is invalid, if
615 that's not self-evident.)
616 -- the file in which an error occurred. (In such cases, there should be a
617 second frob, probably a string, specifying the exact error that occurred.
618 This does not occur in the string that precedes the first frob, because
619 that frob describes the exact operation that was happening.
620
621 For historical compatibility, DATUM can also be a string. In this case,
622 DATUM and ARGS are passed together as the arguments to `format', and then
623 an error is signalled using the error symbol `error' and formatted string.
624 Although this usage of `error' is very common, it is deprecated because it
625 totally defeats the purpose of having structured errors. There is now
626 a rich set of defined errors you can use:
627
628 error
629 syntax-error
630 invalid-read-syntax
631 list-formation-error
632 malformed-list
633 malformed-property-list
634 circular-list
635 circular-property-list
636
637 invalid-argument
638 wrong-type-argument
639 args-out-of-range
640 wrong-number-of-arguments
641 invalid-function
642 no-catch
643
644 invalid-state
645 void-function
646 cyclic-function-indirection
647 void-variable
648 cyclic-variable-indirection
649
650 invalid-operation
651 invalid-change
652 setting-constant
653 editing-error
654 beginning-of-buffer
655 end-of-buffer
656 buffer-read-only
657 io-error
658 end-of-file
659 arith-error
660 range-error
661 domain-error
662 singularity-error
663 overflow-error
664 underflow-error
665
666 The five most common errors you will probably use or base your new
667 errors off of are `syntax-error', `invalid-argument', `invalid-state',
668 `invalid-operation', and `invalid-change'. Note the semantic differences:
669
670 -- `syntax-error' is for errors in complex structures: parsed strings, lists,
671 and the like.
672 -- `invalid-argument' is for errors in a simple value. Typically, the entire
673 value, not just one part of it, is wrong.
674 -- `invalid-state' means that some settings have been changed in such a way
675 that their current state is unallowable. More and more, code is being
676 written more carefully, and catches the error when the settings are being
677 changed, rather than afterwards. This leads us to the next error:
678 -- `invalid-change' means that an attempt is being made to change some settings
679 into an invalid state. `invalid-change' is a type of `invalid-operation'.
680 -- `invalid-operation' refers to all cases where code is trying to do something
681 that's disallowed. This includes file errors, buffer errors (e.g. running
682 off the end of a buffer), `invalid-change' as just mentioned, and
683 arithmetic errors.
684
685 See also `cerror', `signal', and `signal-error'."
686 (while t (apply
687 'cerror datum args)))
688
689 (defun cerror (datum &rest args)
522 "Like `error' but signals a continuable error." 690 "Like `error' but signals a continuable error."
523 (signal 'error (list (apply 'format args)))) 691 (cond ((stringp datum)
692 (signal 'error (list (apply 'format datum args))))
693 ((defined-error-p datum)
694 (signal datum args))
695 (t
696 (error 'invalid-argument "datum not string or error symbol" datum))))
524 697
525 (defmacro check-argument-type (predicate argument) 698 (defmacro check-argument-type (predicate argument)
526 "Check that ARGUMENT satisfies PREDICATE. 699 "Check that ARGUMENT satisfies PREDICATE.
527 If not, signal a continuable `wrong-type-argument' error until the 700 This is a macro, and ARGUMENT is not evaluated. If ARGUMENT is an lvalue,
528 returned value satisfies PREDICATE, and assign the returned value 701 this function signals a continuable `wrong-type-argument' error until the
529 to ARGUMENT." 702 returned value satisfies PREDICATE, and assigns the returned value
530 `(if (not (,(eval predicate) ,argument)) 703 to ARGUMENT. Otherwise, this function signals a non-continuable
531 (setq ,argument 704 `wrong-type-argument' error if the returned value does not satisfy PREDICATE."
532 (wrong-type-argument ,predicate ,argument)))) 705 (if (symbolp argument)
706 `(if (not (,(eval predicate) ,argument))
707 (setq ,argument
708 (wrong-type-argument ,predicate ,argument)))
709 `(if (not (,(eval predicate) ,argument))
710 (signal-error 'wrong-type-argument (list ,predicate ,argument)))))
533 711
534 (defun signal-error (error-symbol data) 712 (defun signal-error (error-symbol data)
535 "Signal a non-continuable error. Args are ERROR-SYMBOL, and associated DATA. 713 "Signal a non-continuable error. Args are ERROR-SYMBOL, and associated DATA.
536 An error symbol is a symbol defined using `define-error'. 714 An error symbol is a symbol defined using `define-error'.
537 DATA should be a list. Its elements are printed as part of the error message. 715 DATA should be a list. Its elements are printed as part of the error message.
558 (put error-sym 'error-message doc-string) 736 (put error-sym 'error-message doc-string)
559 (or inherits-from (setq inherits-from 'error)) 737 (or inherits-from (setq inherits-from 'error))
560 (let ((conds (get inherits-from 'error-conditions))) 738 (let ((conds (get inherits-from 'error-conditions)))
561 (or conds (signal-error 'error (list "Not an error symbol" error-sym))) 739 (or conds (signal-error 'error (list "Not an error symbol" error-sym)))
562 (put error-sym 'error-conditions (cons error-sym conds)))) 740 (put error-sym 'error-conditions (cons error-sym conds))))
741
742 (defun defined-error-p (sym)
743 "Returns non-nil if SYM names a currently-defined error."
744 (and (symbolp sym) (not (null (get sym 'error-conditions)))))
563 745
564 ;;;; Miscellanea. 746 ;;;; Miscellanea.
565 747
566 ;; This is now in C. 748 ;; This is now in C.
567 ;(defun buffer-substring-no-properties (beg end) 749 ;(defun buffer-substring-no-properties (beg end)
635 (and (eq (car-safe spec) 'interactive) 817 (and (eq (car-safe spec) 'interactive)
636 spec))) 818 spec)))
637 (t 819 (t
638 (error "Non-funcallable object: %s" function)))) 820 (error "Non-funcallable object: %s" function))))
639 821
822 (defun function-allows-args (function n)
823 "Return whether FUNCTION can be called with N arguments."
824 (and (<= (function-min-args function) n)
825 (or (null (function-max-args function))
826 (<= n (function-max-args function)))))
827
640 ;; This function used to be an alias to `buffer-substring', except 828 ;; This function used to be an alias to `buffer-substring', except
641 ;; that FSF Emacs 20.4 added a BUFFER argument in an incompatible way. 829 ;; that FSF Emacs 20.4 added a BUFFER argument in an incompatible way.
642 ;; The new FSF's semantics makes more sense, but we try to support 830 ;; The new FSF's semantics makes more sense, but we try to support
643 ;; both for backward compatibility. 831 ;; both for backward compatibility.
644 (defun buffer-string (&optional buffer old-end old-buffer) 832 (defun buffer-string (&optional buffer old-end old-buffer)