The value of this variable may be buffer-local.
The buffer about to be killed is current when this hook is run.")
-;; called by Frecord_buffer()
-(defvar record-buffer-hook nil
- "Function or functions to be called when a buffer is recorded.
-The value of this variable may be buffer-local.
-The buffer being recorded is passed as an argument to the hook.")
-
;; in C in FSFmacs
(defvar kill-emacs-hook nil
"Function or functions to be called when `kill-emacs' is called,
(setplist new (copy-list (symbol-plist symbol))))
new))
+(defun set-symbol-value-in-buffer (sym val buffer)
+ "Set the value of SYM to VAL in BUFFER. Useful with buffer-local variables.
+If SYM has a buffer-local value in BUFFER, or will have one if set, this
+function allows you to set the local value.
+
+NOTE: At some point, this will be moved into C and will be very fast."
+ (with-current-buffer buffer
+ (set sym val)))
+
;;;; String functions.
;; XEmacs
"Replace all matches in STR for REGEXP with NEWTEXT string,
and returns the new string.
Optional LITERAL non-nil means do a literal replacement.
-Otherwise treat \\ in NEWTEXT string as special:
- \\& means substitute original matched text,
- \\N means substitute match for \(...\) number N,
- \\\\ means insert one \\."
+Otherwise treat `\\' in NEWTEXT as special:
+ `\\&' in NEWTEXT means substitute original matched text.
+ `\\N' means substitute what matched the Nth `\\(...\\)'.
+ If Nth parens didn't match, substitute nothing.
+ `\\\\' means insert one `\\'.
+ `\\u' means upcase the next character.
+ `\\l' means downcase the next character.
+ `\\U' means begin upcasing all following characters.
+ `\\L' means begin downcasing all following characters.
+ `\\E' means terminate the effect of any `\\U' or `\\L'."
(check-argument-type 'stringp str)
(check-argument-type 'stringp newtext)
- (let ((rtn-str "")
- (start 0)
- (special)
- match prev-start)
- (while (setq match (string-match regexp str start))
- (setq prev-start start
- start (match-end 0)
- rtn-str
- (concat
- rtn-str
- (substring str prev-start match)
- (cond (literal newtext)
- (t (mapconcat
- (lambda (c)
- (if special
- (progn
- (setq special nil)
- (cond ((eq c ?\\) "\\")
- ((eq c ?&)
- (substring str
- (match-beginning 0)
- (match-end 0)))
- ((and (>= c ?0) (<= c ?9))
- (if (> c (+ ?0 (length
- (match-data))))
- ;; Invalid match num
- (error "Invalid match num: %c" c)
- (setq c (- c ?0))
- (substring str
- (match-beginning c)
- (match-end c))))
- (t (char-to-string c))))
- (if (eq c ?\\) (progn (setq special t) nil)
- (char-to-string c))))
- newtext ""))))))
- (concat rtn-str (substring str start))))
+ (if (> (length str) 50)
+ (with-temp-buffer
+ (insert str)
+ (goto-char 1)
+ (while (re-search-forward regexp nil t)
+ (replace-match newtext t literal))
+ (buffer-string))
+ (let ((start 0) newstr)
+ (while (string-match regexp str start)
+ (setq newstr (replace-match newtext t literal str)
+ start (+ (match-end 0) (- (length newstr) (length str)))
+ str newstr))
+ str)))
(defun split-string (string &optional pattern)
"Return a list of substrings of STRING which are separated by PATTERN.
(set-buffer ,buffer)
,@body))
-(defmacro with-temp-file (file &rest forms)
- "Create a new buffer, evaluate FORMS there, and write the buffer to FILE.
+(defmacro with-temp-file (filename &rest forms)
+ "Create a new buffer, evaluate FORMS there, and write the buffer to FILENAME.
The value of the last form in FORMS is returned, like `progn'.
See also `with-temp-buffer'."
(let ((temp-file (make-symbol "temp-file"))
(temp-buffer (make-symbol "temp-buffer")))
- `(let ((,temp-file ,file)
+ `(let ((,temp-file ,filename)
(,temp-buffer
(get-buffer-create (generate-new-buffer-name " *temp file*"))))
(unwind-protect
;; getf, remf in cl*.el.
-(defmacro putf (plist prop val)
- "Add property PROP to plist PLIST with value VAL.
-Analogous to (setq PLIST (plist-put PLIST PROP VAL))."
- `(setq ,plist (plist-put ,plist ,prop ,val)))
+(defmacro putf (plist property value)
+ "Add property PROPERTY to plist PLIST with value VALUE.
+Analogous to (setq PLIST (plist-put PLIST PROPERTY VALUE))."
+ `(setq ,plist (plist-put ,plist ,property ,value)))
-(defmacro laxputf (lax-plist prop val)
- "Add property PROP to lax plist LAX-PLIST with value VAL.
-Analogous to (setq LAX-PLIST (lax-plist-put LAX-PLIST PROP VAL))."
- `(setq ,lax-plist (lax-plist-put ,lax-plist ,prop ,val)))
+(defmacro laxputf (lax-plist property value)
+ "Add property PROPERTY to lax plist LAX-PLIST with value VALUE.
+Analogous to (setq LAX-PLIST (lax-plist-put LAX-PLIST PROPERTY VALUE))."
+ `(setq ,lax-plist (lax-plist-put ,lax-plist ,property ,value)))
-(defmacro laxremf (lax-plist prop)
- "Remove property PROP from lax plist LAX-PLIST.
-Analogous to (setq LAX-PLIST (lax-plist-remprop LAX-PLIST PROP))."
- `(setq ,lax-plist (lax-plist-remprop ,lax-plist ,prop)))
+(defmacro laxremf (lax-plist property)
+ "Remove property PROPERTY from lax plist LAX-PLIST.
+Analogous to (setq LAX-PLIST (lax-plist-remprop LAX-PLIST PROPERTY))."
+ `(setq ,lax-plist (lax-plist-remprop ,lax-plist ,property)))
\f
;;; Error functions
-(defun error (&rest args)
- "Signal an error, making error message by passing all args to `format'.
-This error is not continuable: you cannot continue execution after the
-error using the debugger `r' command. See also `cerror'."
- (while t
- (apply 'cerror args)))
+(defun error (datum &rest args)
+ "Signal a non-continuable error.
+DATUM should normally be an error symbol, i.e. a symbol defined using
+`define-error'. ARGS will be made into a list, and DATUM and ARGS passed
+as the two arguments to `signal', the most basic error handling function.
-(defun cerror (&rest args)
+This error is not continuable: you cannot continue execution after the
+error using the debugger `r' command. See also `cerror'.
+
+The correct semantics of ARGS varies from error to error, but for most
+errors that need to be generated in Lisp code, the first argument
+should be a string describing the *context* of the error (i.e. the
+exact operation being performed and what went wrong), and the remaining
+arguments or \"frobs\" (most often, there is one) specify the
+offending object(s) and/or provide additional details such as the exact
+error when a file error occurred, e.g.:
+
+-- the buffer in which an editing error occurred.
+-- an invalid value that was encountered. (In such cases, the string
+ should describe the purpose or \"semantics\" of the value [e.g. if the
+ value is an argument to a function, the name of the argument; if the value
+ is the value corresponding to a keyword, the name of the keyword; if the
+ value is supposed to be a list length, say this and say what the purpose
+ of the list is; etc.] as well as specifying why the value is invalid, if
+ that's not self-evident.)
+-- the file in which an error occurred. (In such cases, there should be a
+ second frob, probably a string, specifying the exact error that occurred.
+ This does not occur in the string that precedes the first frob, because
+ that frob describes the exact operation that was happening.
+
+For historical compatibility, DATUM can also be a string. In this case,
+DATUM and ARGS are passed together as the arguments to `format', and then
+an error is signalled using the error symbol `error' and formatted string.
+Although this usage of `error' is very common, it is deprecated because it
+totally defeats the purpose of having structured errors. There is now
+a rich set of defined errors you can use:
+
+error
+ syntax-error
+ invalid-read-syntax
+ list-formation-error
+ malformed-list
+ malformed-property-list
+ circular-list
+ circular-property-list
+
+ invalid-argument
+ wrong-type-argument
+ args-out-of-range
+ wrong-number-of-arguments
+ invalid-function
+ no-catch
+
+ invalid-state
+ void-function
+ cyclic-function-indirection
+ void-variable
+ cyclic-variable-indirection
+
+ invalid-operation
+ invalid-change
+ setting-constant
+ editing-error
+ beginning-of-buffer
+ end-of-buffer
+ buffer-read-only
+ io-error
+ end-of-file
+ arith-error
+ range-error
+ domain-error
+ singularity-error
+ overflow-error
+ underflow-error
+
+The five most common errors you will probably use or base your new
+errors off of are `syntax-error', `invalid-argument', `invalid-state',
+`invalid-operation', and `invalid-change'. Note the semantic differences:
+
+-- `syntax-error' is for errors in complex structures: parsed strings, lists,
+ and the like.
+-- `invalid-argument' is for errors in a simple value. Typically, the entire
+ value, not just one part of it, is wrong.
+-- `invalid-state' means that some settings have been changed in such a way
+ that their current state is unallowable. More and more, code is being
+ written more carefully, and catches the error when the settings are being
+ changed, rather than afterwards. This leads us to the next error:
+-- `invalid-change' means that an attempt is being made to change some settings
+ into an invalid state. `invalid-change' is a type of `invalid-operation'.
+-- `invalid-operation' refers to all cases where code is trying to do something
+ that's disallowed. This includes file errors, buffer errors (e.g. running
+ off the end of a buffer), `invalid-change' as just mentioned, and
+ arithmetic errors.
+
+See also `cerror', `signal', and `signal-error'."
+ (while t (apply
+ 'cerror datum args)))
+
+(defun cerror (datum &rest args)
"Like `error' but signals a continuable error."
- (signal 'error (list (apply 'format args))))
+ (cond ((stringp datum)
+ (signal 'error (list (apply 'format datum args))))
+ ((defined-error-p datum)
+ (signal datum args))
+ (t
+ (error 'invalid-argument "datum not string or error symbol" datum))))
(defmacro check-argument-type (predicate argument)
"Check that ARGUMENT satisfies PREDICATE.
-If not, signal a continuable `wrong-type-argument' error until the
-returned value satisfies PREDICATE, and assign the returned value
-to ARGUMENT."
- `(if (not (,(eval predicate) ,argument))
- (setq ,argument
- (wrong-type-argument ,predicate ,argument))))
+This is a macro, and ARGUMENT is not evaluated. If ARGUMENT is an lvalue,
+this function signals a continuable `wrong-type-argument' error until the
+returned value satisfies PREDICATE, and assigns the returned value
+to ARGUMENT. Otherwise, this function signals a non-continuable
+`wrong-type-argument' error if the returned value does not satisfy PREDICATE."
+ (if (symbolp argument)
+ `(if (not (,(eval predicate) ,argument))
+ (setq ,argument
+ (wrong-type-argument ,predicate ,argument)))
+ `(if (not (,(eval predicate) ,argument))
+ (signal-error 'wrong-type-argument (list ,predicate ,argument)))))
(defun signal-error (error-symbol data)
"Signal a non-continuable error. Args are ERROR-SYMBOL, and associated DATA.
(or conds (signal-error 'error (list "Not an error symbol" error-sym)))
(put error-sym 'error-conditions (cons error-sym conds))))
+(defun defined-error-p (sym)
+ "Returns non-nil if SYM names a currently-defined error."
+ (and (symbolp sym) (not (null (get sym 'error-conditions)))))
+
;;;; Miscellanea.
;; This is now in C.
-;(defun buffer-substring-no-properties (beg end)
-; "Return the text from BEG to END, without text properties, as a string."
-; (let ((string (buffer-substring beg end)))
+;(defun buffer-substring-no-properties (start end)
+; "Return the text from START to END, without text properties, as a string."
+; (let ((string (buffer-substring start end)))
; (set-text-properties 0 (length string) nil string)
; string))
(t
(error "Non-funcallable object: %s" function))))
+(defun function-allows-args (function n)
+ "Return whether FUNCTION can be called with N arguments."
+ (and (<= (function-min-args function) n)
+ (or (null (function-max-args function))
+ (<= n (function-max-args function)))))
+
;; This function used to be an alias to `buffer-substring', except
;; that FSF Emacs 20.4 added a BUFFER argument in an incompatible way.
;; The new FSF's semantics makes more sense, but we try to support