diff options
| author | Stefan Monnier <monnier@iro.umontreal.ca> | 2011-02-01 12:09:25 -0500 |
|---|---|---|
| committer | Stefan Monnier <monnier@iro.umontreal.ca> | 2011-02-01 12:09:25 -0500 |
| commit | 8f1d2ef658f95549eb33fe5265f8f11c5129bece (patch) | |
| tree | b7cd852a1adb423384532cfe22c31547160b22bc /lisp/subr.el | |
| parent | 590130fb19e1f433965c421d98fedeb2d7c33310 (diff) | |
| parent | 1dc4075fa8809805aed5092e93e225e889725c94 (diff) | |
| download | emacs-8f1d2ef658f95549eb33fe5265f8f11c5129bece.tar.gz | |
Merge from trunk
Diffstat (limited to 'lisp/subr.el')
| -rw-r--r-- | lisp/subr.el | 263 |
1 files changed, 150 insertions, 113 deletions
diff --git a/lisp/subr.el b/lisp/subr.el index 99f632fb586..c72752eb8f2 100644 --- a/lisp/subr.el +++ b/lisp/subr.el @@ -1,7 +1,6 @@ ;;; subr.el --- basic lisp subroutines for Emacs -;; Copyright (C) 1985, 1986, 1992, 1994, 1995, 1999, 2000, 2001, 2002, 2003, -;; 2004, 2005, 2006, 2007, 2008, 2009, 2010 +;; Copyright (C) 1985-1986, 1992, 1994-1995, 1999-2011 ;; Free Software Foundation, Inc. ;; Maintainer: FSF @@ -60,7 +59,7 @@ function-definitions that `check-declare' does not recognize, e.g. `defstruct'. To specify a value for FILEONLY without passing an argument list, -set ARGLIST to `t'. This is necessary because `nil' means an +set ARGLIST to t. This is necessary because nil means an empty argument list, rather than an unspecified one. Note that for the purposes of `check-declare', this statement @@ -417,7 +416,7 @@ Unibyte strings are converted to multibyte for comparison." (assoc-string key alist nil)) (defun member-ignore-case (elt list) - "Like `member', but ignores differences in case and text representation. + "Like `member', but ignore differences in case and text representation. ELT must be a string. Upper-case and lower-case letters are treated as equal. Unibyte strings are converted to multibyte for comparison. Non-strings in LIST are ignored." @@ -489,6 +488,7 @@ saving keyboard macros (see `edmacro-mode')." (read-kbd-macro keys)) (defun undefined () + "Beep to tell the user this binding is undefined." (interactive) (ding)) @@ -858,24 +858,37 @@ in the current Emacs session, then this function may return nil." (defsubst event-start (event) "Return the starting position of EVENT. -If EVENT is a mouse or key press or a mouse click, this returns the location -of the event. -If EVENT is a drag, this returns the drag's starting position. -The return value is of the form +EVENT should be a click, drag, or key press event. +If it is a key press event, the return value has the form + (WINDOW POS (0 . 0) 0) +If it is a click or drag event, it has the form (WINDOW AREA-OR-POS (X . Y) TIMESTAMP OBJECT POS (COL . ROW) IMAGE (DX . DY) (WIDTH . HEIGHT)) -The `posn-' functions access elements of such lists." +The `posn-' functions access elements of such lists. +For more information, see Info node `(elisp)Click Events'. + +If EVENT is a mouse or key press or a mouse click, this is the +position of the event. If EVENT is a drag, this is the starting +position of the drag." (if (consp event) (nth 1 event) (list (selected-window) (point) '(0 . 0) 0))) (defsubst event-end (event) "Return the ending location of EVENT. EVENT should be a click, drag, or key press event. -If EVENT is a click event, this function is the same as `event-start'. -The return value is of the form +If EVENT is a key press event, the return value has the form + (WINDOW POS (0 . 0) 0) +If EVENT is a click event, this function is the same as +`event-start'. For click and drag events, the return value has +the form (WINDOW AREA-OR-POS (X . Y) TIMESTAMP OBJECT POS (COL . ROW) IMAGE (DX . DY) (WIDTH . HEIGHT)) -The `posn-' functions access elements of such lists." +The `posn-' functions access elements of such lists. +For more information, see Info node `(elisp)Click Events'. + +If EVENT is a mouse or key press or a mouse click, this is the +position of the event. If EVENT is a drag, this is the starting +position of the drag." (if (consp event) (nth (if (consp (nth 2 event)) 2 1) event) (list (selected-window) (point) '(0 . 0) 0))) @@ -921,8 +934,9 @@ Select the corresponding window as well." (defsubst posn-x-y (position) "Return the x and y coordinates in POSITION. -POSITION should be a list of the form returned by the `event-start' -and `event-end' functions." +The return value has the form (X . Y), where X and Y are given in +pixels. POSITION should be a list of the form returned by +`event-start' and `event-end'." (nth 2 position)) (declare-function scroll-bar-scale "scroll-bar" (num-denom whole)) @@ -961,7 +975,9 @@ and `event-end' functions." (setq spacing 0))) (cons (/ (car pair) (frame-char-width frame)) (- (/ (cdr pair) (+ (frame-char-height frame) spacing)) - (if (null header-line-format) 0 1)))))))) + (if (null (with-current-buffer (window-buffer window) + header-line-format)) + 0 1)))))))) (defun posn-actual-col-row (position) "Return the actual column and row in POSITION, measured in characters. @@ -1002,14 +1018,15 @@ and `event-end' functions." (defsubst posn-object-x-y (position) "Return the x and y coordinates relative to the object of POSITION. -POSITION should be a list of the form returned by the `event-start' -and `event-end' functions." +The return value has the form (DX . DY), where DX and DY are +given in pixels. POSITION should be a list of the form returned +by `event-start' and `event-end'." (nth 8 position)) (defsubst posn-object-width-height (position) "Return the pixel width and height of the object of POSITION. -POSITION should be a list of the form returned by the `event-start' -and `event-end' functions." +The return value has the form (WIDTH . HEIGHT). POSITION should +be a list of the form returned by `event-start' and `event-end'." (nth 9 position)) @@ -1361,9 +1378,8 @@ if it is empty or a duplicate." (defun run-mode-hooks (&rest hooks) "Run mode hooks `delayed-mode-hooks' and HOOKS, or delay HOOKS. -Execution is delayed if `delay-mode-hooks' is non-nil. -If `delay-mode-hooks' is nil, run `after-change-major-mode-hook' -after running the mode hooks. +Execution is delayed if the variable `delay-mode-hooks' is non-nil. +Otherwise, runs the mode hooks and then `after-change-major-mode-hook'. Major mode functions should use this instead of `run-hooks' when running their FOO-mode-hook." (if delay-mode-hooks @@ -1485,26 +1501,6 @@ If TOGGLE has a `:menu-tag', that is used for the menu item's label." ;;; Load history -;; (defvar symbol-file-load-history-loaded nil -;; "Non-nil means we have loaded the file `fns-VERSION.el' in `exec-directory'. -;; That file records the part of `load-history' for preloaded files, -;; which is cleared out before dumping to make Emacs smaller.") - -;; (defun load-symbol-file-load-history () -;; "Load the file `fns-VERSION.el' in `exec-directory' if not already done. -;; That file records the part of `load-history' for preloaded files, -;; which is cleared out before dumping to make Emacs smaller." -;; (unless symbol-file-load-history-loaded -;; (load (expand-file-name -;; ;; fns-XX.YY.ZZ.el does not work on DOS filesystem. -;; (if (eq system-type 'ms-dos) -;; "fns.el" -;; (format "fns-%s.el" emacs-version)) -;; exec-directory) -;; ;; The file name fns-%s.el already has a .el extension. -;; nil nil t) -;; (setq symbol-file-load-history-loaded t))) - (defun symbol-file (symbol &optional type) "Return the name of the file that defined SYMBOL. The value is normally an absolute file name. It can also be nil, @@ -1622,11 +1618,7 @@ extension for a compressed format \(e.g. \".gz\") on FILE will not affect this name matching. Alternatively, FILE can be a feature (i.e. a symbol), in which case FORM -is evaluated whenever that feature is `provide'd. Note that although -provide statements are usually at the end of files, this is not always -the case (e.g., sometimes they are at the start to avoid a recursive -load error). If your FORM should not be evaluated until the code in -FILE has been, do not use the symbol form for FILE in such cases. +is evaluated at the end of any file that `provide's this feature. Usually FILE is just a library name like \"font-lock\" or a feature name like 'font-lock. @@ -1635,11 +1627,27 @@ This function makes or adds to an entry on `after-load-alist'." ;; Add this FORM into after-load-alist (regardless of whether we'll be ;; evaluating it now). (let* ((regexp-or-feature - (if (stringp file) (setq file (purecopy (load-history-regexp file))) file)) + (if (stringp file) + (setq file (purecopy (load-history-regexp file))) + file)) (elt (assoc regexp-or-feature after-load-alist))) (unless elt (setq elt (list regexp-or-feature)) (push elt after-load-alist)) + (when (symbolp regexp-or-feature) + ;; For features, the after-load-alist elements get run when `provide' is + ;; called rather than at the end of the file. So add an indirection to + ;; make sure that `form' is really run "after-load" in case the provide + ;; call happens early. + (setq form + `(when load-file-name + (let ((fun (make-symbol "eval-after-load-helper"))) + (fset fun `(lambda (file) + (if (not (equal file ',load-file-name)) + nil + (remove-hook 'after-load-functions ',fun) + ,',form))) + (add-hook 'after-load-functions fun))))) ;; Add FORM to the element unless it's already there. (unless (member form (cdr elt)) (nconc elt (purecopy (list form)))) @@ -1895,7 +1903,7 @@ This function echoes `.' for each character that the user types. The user ends with RET, LFD, or ESC. DEL or C-h rubs out. C-y yanks the current kill. C-u kills line. C-g quits; if `inhibit-quit' was non-nil around this function, -then it returns nil if the user types C-g, but quit-flag remains set. +then it returns nil if the user types C-g, but `quit-flag' remains set. Once the caller uses the password, it can erase the password by doing (clear-string STRING)." @@ -1993,6 +2001,35 @@ The value of DEFAULT is inserted into PROMPT." t))) n)) +(defun read-char-choice (prompt chars &optional inhibit-keyboard-quit) + "Read and return one of CHARS, prompting for PROMPT. +Any input that is not one of CHARS is ignored. + +If optional argument INHIBIT-KEYBOARD-QUIT is non-nil, ignore +keyboard-quit events while waiting for a valid input." + (unless (consp chars) + (error "Called `read-char-choice' without valid char choices")) + (let ((cursor-in-echo-area t) + (executing-kbd-macro executing-kbd-macro) + char done) + (while (not done) + (unless (get-text-property 0 'face prompt) + (setq prompt (propertize prompt 'face 'minibuffer-prompt))) + (setq char (let ((inhibit-quit inhibit-keyboard-quit)) + (read-key prompt))) + (cond + ((not (numberp char))) + ((memq char chars) + (setq done t)) + ((and executing-kbd-macro (= char -1)) + ;; read-event returns -1 if we are in a kbd macro and + ;; there are no more events in the macro. Attempt to + ;; get an event interactively. + (setq executing-kbd-macro nil)))) + ;; Display the question with the answer. + (message "%s%s" prompt (char-to-string char)) + char)) + (defun sit-for (seconds &optional nodisp obsolete) "Perform redisplay, then wait for SECONDS seconds or until input is available. SECONDS may be a floating-point value. @@ -2034,6 +2071,56 @@ floating point support." (push read unread-command-events) nil)))))) (set-advertised-calling-convention 'sit-for '(seconds &optional nodisp) "22.1") + +(defun y-or-n-p (prompt) + "Ask user a \"y or n\" question. Return t if answer is \"y\". +PROMPT is the string to display to ask the question. It should +end in a space; `y-or-n-p' adds \"(y or n) \" to it. + +No confirmation of the answer is requested; a single character is enough. +Also accepts Space to mean yes, or Delete to mean no. \(Actually, it uses +the bindings in `query-replace-map'; see the documentation of that variable +for more information. In this case, the useful bindings are `act', `skip', +`recenter', and `quit'.\) + +Under a windowing system a dialog box will be used if `last-nonmenu-event' +is nil and `use-dialog-box' is non-nil." + ;; ¡Beware! when I tried to edebug this code, Emacs got into a weird state + ;; where all the keys were unbound (i.e. it somehow got triggered + ;; within read-key, apparently). I had to kill it. + (let ((answer 'recenter)) + (if (and (display-popup-menus-p) + (listp last-nonmenu-event) + use-dialog-box) + (setq answer + (x-popup-dialog t `(,prompt ("yes" . act) ("No" . skip)))) + (setq prompt (concat prompt + (if (eq ?\s (aref prompt (1- (length prompt)))) + "" " ") + "(y or n) ")) + (while + (let* ((key + (let ((cursor-in-echo-area t)) + (when minibuffer-auto-raise + (raise-frame (window-frame (minibuffer-window)))) + (read-key (propertize (if (eq answer 'recenter) + prompt + (concat "Please answer y or n. " + prompt)) + 'face 'minibuffer-prompt))))) + (setq answer (lookup-key query-replace-map (vector key) t)) + (cond + ((memq answer '(skip act)) nil) + ((eq answer 'recenter) (recenter) t) + ((memq answer '(exit-prefix quit)) (signal 'quit nil) t) + (t t))) + (ding) + (discard-input))) + (let ((ret (eq answer 'act))) + (unless noninteractive + (message "%s %s" prompt (if ret "y" "n"))) + ret))) + ;;; Atomic change groups. @@ -2293,11 +2380,16 @@ directory if it does not exist." ;; unless we're in batch mode or dumping Emacs (or noninteractive purify-flag - (file-accessible-directory-p (directory-file-name user-emacs-directory)) - (make-directory user-emacs-directory)) + (file-accessible-directory-p + (directory-file-name user-emacs-directory)) + (let ((umask (default-file-modes))) + (unwind-protect + (progn + (set-default-file-modes ?\700) + (make-directory user-emacs-directory)) + (set-default-file-modes umask)))) (abbreviate-file-name (expand-file-name new-name user-emacs-directory)))))) - ;;;; Misc. useful functions. @@ -2374,13 +2466,8 @@ Note: :data and :device are currently not supported on Windows." "''" ;; Quote everything except POSIX filename characters. ;; This should be safe enough even for really weird shells. - (let ((result "") (start 0) end) - (while (string-match "[^-0-9a-zA-Z_./]" argument start) - (setq end (match-beginning 0) - result (concat result (substring argument start end) - "\\" (substring argument end (1+ end))) - start (1+ end))) - (concat result (substring argument start)))))) + (replace-regexp-in-string "\n" "'\n'" + (replace-regexp-in-string "[^-0-9a-zA-Z_./\n]" "\\\\\\&" argument))))) (defun string-or-null-p (object) "Return t if OBJECT is a string or nil. @@ -2438,7 +2525,7 @@ Replaces `category' properties with their defined properties." (defvar yank-undo-function) (defun insert-for-yank (string) - "Calls `insert-for-yank-1' repetitively for each `yank-handler' segment. + "Call `insert-for-yank-1' repetitively for each `yank-handler' segment. See `insert-for-yank-1' for more details." (let (to) @@ -2464,7 +2551,7 @@ If PARAM is present and non-nil, it replaces STRING as the object `yank-rectangle', PARAM may be a list of strings to insert as a rectangle. If NOEXCLUDE is present and non-nil, the normal removal of the - yank-excluded-properties is not performed; instead FUNCTION is + `yank-excluded-properties' is not performed; instead FUNCTION is responsible for removing those properties. This may be necessary if FUNCTION adjusts point before or after inserting the object. If UNDO is present and non-nil, it is a function that will be called @@ -3122,7 +3209,7 @@ is non-nil, start replacements at that index in STRING. REP is either a string used as the NEWTEXT arg of `replace-match' or a function. If it is a function, it is called with the actual text of each match, and its value is used as the replacement text. When REP is called, -the match-data are the result of matching REGEXP against a substring +the match data are the result of matching REGEXP against a substring of STRING. To replace only the first match (if any), make REGEXP match up to \\' @@ -3328,56 +3415,6 @@ clone should be incorporated in the clone." (overlay-put ol2 'evaporate t) (overlay-put ol2 'text-clones dups))) -;;;; Misc functions moved over from the C side. - -(defun y-or-n-p (prompt) - "Ask user a \"y or n\" question. Return t if answer is \"y\". -The argument PROMPT is the string to display to ask the question. -It should end in a space; `y-or-n-p' adds `(y or n) ' to it. -No confirmation of the answer is requested; a single character is enough. -Also accepts Space to mean yes, or Delete to mean no. \(Actually, it uses -the bindings in `query-replace-map'; see the documentation of that variable -for more information. In this case, the useful bindings are `act', `skip', -`recenter', and `quit'.\) - -Under a windowing system a dialog box will be used if `last-nonmenu-event' -is nil and `use-dialog-box' is non-nil." - ;; ¡Beware! when I tried to edebug this code, Emacs got into a weird state - ;; where all the keys were unbound (i.e. it somehow got triggered - ;; within read-key, apparently). I had to kill it. - (let ((answer 'recenter)) - (if (and (display-popup-menus-p) - (listp last-nonmenu-event) - use-dialog-box) - (setq answer - (x-popup-dialog t `(,prompt ("yes" . act) ("No" . skip)))) - (setq prompt (concat prompt - (if (eq ?\s (aref prompt (1- (length prompt)))) - "" " ") - "(y or n) ")) - (while - (let* ((key - (let ((cursor-in-echo-area t)) - (when minibuffer-auto-raise - (raise-frame (window-frame (minibuffer-window)))) - (read-key (propertize (if (eq answer 'recenter) - prompt - (concat "Please answer y or n. " - prompt)) - 'face 'minibuffer-prompt))))) - (setq answer (lookup-key query-replace-map (vector key) t)) - (cond - ((memq answer '(skip act)) nil) - ((eq answer 'recenter) (recenter) t) - ((memq answer '(exit-prefix quit)) (signal 'quit nil) t) - (t t))) - (ding) - (discard-input))) - (let ((ret (eq answer 'act))) - (unless noninteractive - (message "%s %s" prompt (if ret "y" "n"))) - ret))) - ;;;; Mail user agents. ;; Here we include just enough for other packages to be able @@ -3824,9 +3861,9 @@ which is higher than \"1alpha\"." ;; The following statement ought to be in print.c, but `provide' can't ;; be used there. +;; http://lists.gnu.org/archive/html/emacs-devel/2009-08/msg00236.html (when (hash-table-p (car (read-from-string (prin1-to-string (make-hash-table))))) (provide 'hashtable-print-readable)) -;; arch-tag: f7e0e6e5-70aa-4897-ae72-7a3511ec40bc ;;; subr.el ends here |
