diff options
Diffstat (limited to 'lisp/subr.el')
-rw-r--r-- | lisp/subr.el | 156 |
1 files changed, 110 insertions, 46 deletions
diff --git a/lisp/subr.el b/lisp/subr.el index 2b3231b879b..23e4dcfa7ed 100644 --- a/lisp/subr.el +++ b/lisp/subr.el @@ -193,9 +193,9 @@ except that PLACE is evaluated only once (after NEWELT)." (list 'setq place (list 'cons newelt place)) (require 'macroexp) - (macroexp-let2 macroexp-copyable-p v newelt + (macroexp-let2 macroexp-copyable-p x newelt (gv-letplace (getter setter) place - (funcall setter `(cons ,v ,getter)))))) + (funcall setter `(cons ,x ,getter)))))) (defmacro pop (place) "Return the first element of PLACE's value, and remove it from the list. @@ -257,10 +257,9 @@ Then evaluate RESULT to get return value, default nil. ;; use dolist. ;; FIXME: This cost disappears in byte-compiled lexical-binding files. (let ((temp '--dolist-tail--)) - ;; This is not a reliable test, but it does not matter because both - ;; semantics are acceptable, tho one is slightly faster with dynamic - ;; scoping and the other is slightly faster (and has cleaner semantics) - ;; with lexical scoping. + ;; This test does not matter much because both semantics are acceptable, + ;; but one is slightly faster with dynamic scoping and the other is + ;; slightly faster (and has cleaner semantics) with lexical scoping. (if lexical-binding `(let ((,temp ,(nth 1 spec))) (while ,temp @@ -280,8 +279,11 @@ Then evaluate RESULT to get return value, default nil. (defmacro dotimes (spec &rest body) "Loop a certain number of times. Evaluate BODY with VAR bound to successive integers running from 0, -inclusive, to COUNT, exclusive. Then evaluate RESULT to get -the return value (nil if RESULT is omitted). Its use is deprecated. +inclusive, to COUNT, exclusive. + +Finally RESULT is evaluated to get the return value (nil if +RESULT is omitted). Using RESULT is deprecated, and may result +in compilation warnings about unused variables. \(fn (VAR COUNT [RESULT]) BODY...)" (declare (indent 1) (debug dolist)) @@ -292,9 +294,9 @@ the return value (nil if RESULT is omitted). Its use is deprecated. (let ((temp '--dotimes-limit--) (start 0) (end (nth 1 spec))) - ;; This is not a reliable test, but it does not matter because both - ;; semantics are acceptable, tho one is slightly faster with dynamic - ;; scoping and the other has cleaner semantics. + ;; This test does not matter much because both semantics are acceptable, + ;; but one is slightly faster with dynamic scoping and the other has + ;; cleaner semantics. (if lexical-binding (let ((counter '--dotimes-counter--)) `(let ((,temp ,end) @@ -767,7 +769,6 @@ If that is non-nil, the element matches; then `assoc-default' If no element matches, the value is nil. If TEST is omitted or nil, `equal' is used." - (declare (side-effect-free t)) (let (found (tail alist) value) (while (and tail (not found)) (let ((elt (car tail))) @@ -884,6 +885,10 @@ side-effects, and the argument LIST is not modified." ;;;; Keymap support. +;; Declare before first use of `save-match-data', +;; where it is used internally. +(defvar save-match-data-internal) + (defun kbd (keys) "Convert KEYS to the internal Emacs key representation. KEYS should be a string in the format returned by commands such @@ -894,8 +899,9 @@ This is the same format used for saving keyboard macros (see For an approximate inverse of this, see `key-description'." ;; Don't use a defalias, since the `pure' property is true only for ;; the calling convention of `kbd'. - (read-kbd-macro keys)) -(put 'kbd 'pure t) + (declare (pure t)) + ;; A pure function is expected to preserve the match data. + (save-match-data (read-kbd-macro keys))) (defun undefined () "Beep to tell the user this binding is undefined." @@ -1558,7 +1564,6 @@ be a list of the form returned by `event-start' and `event-end'." ;;;; Obsolescent names for functions. -(make-obsolete 'forward-point "use (+ (point) N) instead." "23.1") (make-obsolete 'buffer-has-markers-at nil "24.3") (make-obsolete 'invocation-directory "use the variable of the same name." @@ -1604,8 +1609,6 @@ be a list of the form returned by `event-start' and `event-end'." (make-obsolete 'set-window-redisplay-end-trigger nil "23.1") (make-obsolete 'run-window-configuration-change-hook nil "27.1") -(make-obsolete 'process-filter-multibyte-p nil "23.1") -(make-obsolete 'set-process-filter-multibyte nil "23.1") (make-obsolete-variable 'command-debug-status "expect it to be removed in a future version." "25.2") @@ -1621,6 +1624,9 @@ be a list of the form returned by `event-start' and `event-end'." (defvaralias 'messages-buffer-max-lines 'message-log-max) (define-obsolete-variable-alias 'inhibit-null-byte-detection 'inhibit-nul-byte-detection "27.1") +(make-obsolete-variable 'load-dangerous-libraries + "no longer used." "27.1") + ;;;; Alternate names for functions - these are not being phased out. @@ -1645,7 +1651,8 @@ be a list of the form returned by `event-start' and `event-end'." (defalias 'point-at-eol 'line-end-position) (defalias 'point-at-bol 'line-beginning-position) -(defalias 'user-original-login-name 'user-login-name) +(define-obsolete-function-alias 'user-original-login-name + 'user-login-name "28.1") ;;;; Hook manipulation functions. @@ -1774,6 +1781,21 @@ all symbols are bound before any of the VALUEFORMs are evalled." ,@(mapcar (lambda (binder) `(setq ,@binder)) binders) ,@body)) +(defmacro dlet (binders &rest body) + "Like `let*' but using dynamic scoping." + (declare (indent 1) (debug let)) + ;; (defvar FOO) only affects the current scope, but in order for + ;; this not to affect code after the `let*' we need to create a new scope, + ;; which is what the surrounding `let' is for. + ;; FIXME: (let () ...) currently doesn't actually create a new scope, + ;; which is why we use (let (_) ...). + `(let (_) + ,@(mapcar (lambda (binder) + `(defvar ,(if (consp binder) (car binder) binder))) + binders) + (let* ,binders ,@body))) + + (defmacro with-wrapper-hook (hook args &rest body) "Run BODY, using wrapper functions from HOOK with additional ARGS. HOOK is an abnormal hook. Each hook function in HOOK \"wraps\" @@ -1804,6 +1826,7 @@ FUN is then called once." (defmacro subr--with-wrapper-hook-no-warnings (hook args &rest body) "Like (with-wrapper-hook HOOK ARGS BODY), but without warnings." + (declare (debug (form sexp body))) ;; We need those two gensyms because CL's lexical scoping is not available ;; for function arguments :-( (let ((funs (make-symbol "funs")) @@ -2263,6 +2286,8 @@ Otherwise TYPE is assumed to be a symbol property." (not (eq 'require (car match))))))) (throw 'found file)))))) +(declare-function read-library-name "find-func" nil) + (defun locate-library (library &optional nosuffix path interactive-call) "Show the precise file name of Emacs library LIBRARY. LIBRARY should be a relative file name of the library, a string. @@ -2279,12 +2304,7 @@ is used instead of `load-path'. When called from a program, the file name is normally returned as a string. When run interactively, the argument INTERACTIVE-CALL is t, and the file name is displayed in the echo area." - (interactive (list (completing-read "Locate library: " - (apply-partially - 'locate-file-completion-table - load-path (get-load-suffixes))) - nil nil - t)) + (interactive (list (read-library-name) nil nil t)) (let ((file (locate-file library (or path load-path) (append (unless nosuffix (get-load-suffixes)) @@ -2327,13 +2347,19 @@ use `start-file-process'." (if program (list :command (cons program program-args)))))) -(defun process-lines (program &rest args) +(defun process-lines-handling-status (program status-handler &rest args) "Execute PROGRAM with ARGS, returning its output as a list of lines. -Signal an error if the program returns with a non-zero exit status." +If STATUS-HANDLER is non-NIL, it must be a function with one +argument, which will be called with the exit status of the +program before the output is collected. If STATUS-HANDLER is +NIL, an error is signalled if the program returns with a non-zero +exit status." (with-temp-buffer (let ((status (apply 'call-process program nil (current-buffer) nil args))) - (unless (eq status 0) - (error "%s exited with status %s" program status)) + (if status-handler + (funcall status-handler status) + (unless (eq status 0) + (error "%s exited with status %s" program status))) (goto-char (point-min)) (let (lines) (while (not (eobp)) @@ -2344,6 +2370,18 @@ Signal an error if the program returns with a non-zero exit status." (forward-line 1)) (nreverse lines))))) +(defun process-lines (program &rest args) + "Execute PROGRAM with ARGS, returning its output as a list of lines. +Signal an error if the program returns with a non-zero exit status. +Also see `process-lines-ignore-status'." + (apply #'process-lines-handling-status program nil args)) + +(defun process-lines-ignore-status (program &rest args) + "Execute PROGRAM with ARGS, returning its output as a list of lines. +The exit status of the program is ignored. +Also see `process-lines'." + (apply #'process-lines-handling-status program #'identity args)) + (defun process-live-p (process) "Return non-nil if PROCESS is alive. A process is considered alive if its status is `run', `open', @@ -2521,10 +2559,15 @@ by doing (clear-string STRING)." ;; And of course, don't keep the sensitive data around. (erase-buffer)))))))) -(defun read-number (prompt &optional default) +(defvar read-number-history nil + "The default history for the `read-number' function.") + +(defun read-number (prompt &optional default hist) "Read a numeric value in the minibuffer, prompting with PROMPT. DEFAULT specifies a default value to return if the user just types RET. The value of DEFAULT is inserted into PROMPT. +HIST specifies a history list variable. See `read-from-minibuffer' +for details of the HIST argument. This function is used by the `interactive' code letter `n'." (let ((n nil) (default1 (if (consp default) (car default) default))) @@ -2538,7 +2581,7 @@ This function is used by the `interactive' code letter `n'." (while (progn (let ((str (read-from-minibuffer - prompt nil nil nil nil + prompt nil nil nil (or hist 'read-number-history) (when default (if (consp default) (mapcar 'number-to-string (delq nil default)) @@ -3049,9 +3092,17 @@ If MESSAGE is nil, instructions to type EXIT-CHAR are displayed there." o1)) (defun remove-overlays (&optional beg end name val) - "Clear BEG and END of overlays whose property NAME has value VAL. -Overlays might be moved and/or split. -BEG and END default respectively to the beginning and end of buffer." + "Remove overlays between BEG and END that have property NAME with value VAL. +Overlays might be moved and/or split. If any targeted overlays +start before BEG, the overlays will be altered so that they end +at BEG. Likewise, if the targeted overlays end after END, they +will be altered so that they start at END. Overlays that start +at or after BEG and end before END will be removed completely. + +BEG and END default respectively to the beginning and end of the +buffer. +Values are compared with `eq'. +If either NAME or VAL are specified, both should be specified." ;; This speeds up the loops over overlays. (unless beg (setq beg (point-min))) (unless end (setq end (point-max))) @@ -3200,7 +3251,7 @@ See Info node `(elisp)Security Considerations'." ;; First, quote argument so that CommandLineToArgvW will ;; understand it. See - ;; http://msdn.microsoft.com/en-us/library/17w5ykft%28v=vs.85%29.aspx + ;; https://msdn.microsoft.com/en-us/library/17w5ykft%28v=vs.85%29.aspx ;; After we perform that level of quoting, escape shell ;; metacharacters so that cmd won't mangle our argument. If the ;; argument contains no double quote characters, we can just @@ -3967,7 +4018,7 @@ the function `undo--wrap-and-run-primitive-undo'." (let (;; (inhibit-modification-hooks t) (before-change-functions ;; Ugly Hack: if the body uses syntax-ppss/syntax-propertize - ;; (e.g. via a regexp-search or sexp-movement trigerring + ;; (e.g. via a regexp-search or sexp-movement triggering ;; on-the-fly syntax-propertize), make sure that this gets ;; properly refreshed after subsequent changes. (if (memq #'syntax-ppss-flush-cache before-change-functions) @@ -4009,7 +4060,7 @@ the function `undo--wrap-and-run-primitive-undo'." (defmacro combine-change-calls (beg end &rest body) "Evaluate BODY, running the change hooks just once. -BODY is a sequence of lisp forms to evaluate. BEG and END bound +BODY is a sequence of Lisp forms to evaluate. BEG and END bound the region the change hooks will be run for. Firstly, `before-change-functions' is invoked for the region @@ -4027,7 +4078,8 @@ change `before-change-functions' or `after-change-functions'. Additionally, the buffer modifications of BODY are recorded on the buffer's undo list as a single \(apply ...) entry containing -the function `undo--wrap-and-run-primitive-undo'. " +the function `undo--wrap-and-run-primitive-undo'." + (declare (debug t) (indent 2)) `(combine-change-calls-1 ,beg ,end (lambda () ,@body))) (defun undo--wrap-and-run-primitive-undo (beg end list) @@ -4080,8 +4132,6 @@ MODES is as for `set-default-file-modes'." ;;; Matching and match data. -(defvar save-match-data-internal) - ;; We use save-match-data-internal as the local variable because ;; that works ok in practice (people should not use that variable elsewhere). ;; We used to use an uninterned symbol; the compiler handles that properly @@ -4382,6 +4432,27 @@ Unless optional argument INPLACE is non-nil, return a new string." (aset newstr i tochar))) newstr)) +(defun string-replace (fromstring tostring instring) + "Replace FROMSTRING with TOSTRING in INSTRING each time it occurs." + (declare (pure t)) + (when (equal fromstring "") + (signal 'wrong-length-argument fromstring)) + (let ((start 0) + (result nil) + pos) + (while (setq pos (string-search fromstring instring start)) + (unless (= start pos) + (push (substring instring start pos) result)) + (push tostring result) + (setq start (+ pos (length fromstring)))) + (if (null result) + ;; No replacements were done, so just return the original string. + instring + ;; Get any remaining bit. + (unless (= start (length instring)) + (push (substring instring start) result)) + (apply #'concat (nreverse result))))) + (defun replace-regexp-in-string (regexp rep string &optional fixedcase literal subexp start) "Replace all matches for REGEXP with REP in STRING. @@ -4649,13 +4720,6 @@ This function is called directly from the C code." ;; Finally, run any other hook. (run-hook-with-args 'after-load-functions abs-file)) -(defun eval-next-after-load (file) - "Read the following input sexp, and run it whenever FILE is loaded. -This makes or adds to an entry on `after-load-alist'. -FILE should be the name of a library, with no directory name." - (declare (obsolete eval-after-load "23.2")) - (eval-after-load file (read))) - (defun display-delayed-warnings () "Display delayed warnings from `delayed-warnings-list'. |