diff options
author | Eli Zaretskii <[email protected]> | 2012-12-10 14:08:02 +0200 |
---|---|---|
committer | Eli Zaretskii <[email protected]> | 2012-12-10 14:08:02 +0200 |
commit | 3907e630a71d48e693062b350571990d7ba08bbb (patch) | |
tree | 2be1ecc0796e42c7a453a9fd5131eb5866f79876 /lisp/subr.el | |
parent | cf2d22b874ca2df0072e32ee641e8efffe4abd6d (diff) | |
parent | 81606b10501169a5671061b8461bbc32dcec8705 (diff) |
Merge from trunk + rename the event. Not tested yet.
Diffstat (limited to 'lisp/subr.el')
-rw-r--r-- | lisp/subr.el | 207 |
1 files changed, 187 insertions, 20 deletions
diff --git a/lisp/subr.el b/lisp/subr.el index 1a850b1eab..1e509036cd 100644 --- a/lisp/subr.el +++ b/lisp/subr.el @@ -1159,17 +1159,6 @@ 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)) -(defun w32notify-handle-event (event) - "Handle file system monitoring event. -If EVENT is a file-notification event, then its callback is called. -Otherwise, a `filewatch-error' is signaled." - (interactive "e") - - (if (and (eq (car event) 'file-notify) - (= (length event) 3)) - (funcall (nth 2 event) (nth 1 event)) - (signal 'filewatch-error (cons "Not a valid file-notify event" event)))) - ;;;; Obsolescent names for functions. @@ -1202,8 +1191,6 @@ is converted into a string by expressing it in decimal." (make-obsolete 'unfocus-frame "it does nothing." "22.1") (make-obsolete 'make-variable-frame-local "explicitly check for a frame-parameter instead." "22.2") -(make-obsolete 'interactive-p 'called-interactively-p "23.2") -(set-advertised-calling-convention 'called-interactively-p '(kind) "23.1") (set-advertised-calling-convention 'all-completions '(string collection &optional predicate) "23.1") (set-advertised-calling-convention 'unintern '(name obarray) "23.3") @@ -2635,13 +2622,14 @@ When the hook runs, the temporary buffer is current. This hook is normally set up with a function to put the buffer in Help mode.") -;; Avoid compiler warnings about this variable, -;; which has a special meaning on certain system types. -(defvar buffer-file-type nil +(defvar-local buffer-file-type nil "Non-nil if the visited file is a binary file. -This variable is meaningful on MS-DOG and Windows NT. +This variable is meaningful on MS-DOG and MS-Windows. On those systems, it is automatically local in every buffer. -On other systems, this variable is normally always nil.") +On other systems, this variable is normally always nil. + +WARNING: This variable is obsolete and will disappear Real Soon Now. +Don't use it!") ;; The `assert' macro from the cl package signals ;; `cl-assertion-failed' at runtime so always define it. @@ -3200,6 +3188,7 @@ in which case `save-window-excursion' cannot help." ;; Return nil. nil) +;; Doc is very similar to with-temp-buffer-window. (defmacro with-output-to-temp-buffer (bufname &rest body) "Bind `standard-output' to buffer BUFNAME, eval BODY, then show that buffer. @@ -3225,7 +3214,9 @@ with the buffer BUFNAME temporarily current. It runs the hook `temp-buffer-show-hook' after displaying buffer BUFNAME, with that buffer temporarily current, and the window that was used to display it temporarily selected. But it doesn't run `temp-buffer-show-hook' -if it uses `temp-buffer-show-function'." +if it uses `temp-buffer-show-function'. + +See the related form `with-temp-buffer-window'." (declare (debug t)) (let ((old-dir (make-symbol "old-dir")) (buf (make-symbol "buf"))) @@ -3856,7 +3847,7 @@ This is used on the `modification-hooks' property of text clones." (if (not (re-search-forward (overlay-get ol1 'text-clone-syntax) cend t)) ;; Mark the overlay for deletion. - (overlay-put ol1 'text-clones nil) + (setq end cbeg) (when (< (match-end 0) cend) ;; Shrink the clone at its end. (setq end (min end (match-end 0))) @@ -3971,6 +3962,152 @@ The properties used on SYMBOL are `composefunc', `sendfunc', (put symbol 'abortfunc (or abortfunc 'kill-buffer)) (put symbol 'hookvar (or hookvar 'mail-send-hook))) +(defvar called-interactively-p-functions nil + "Special hook called to skip special frames in `called-interactively-p'. +The functions are called with 3 arguments: (I FRAME1 FRAME2), +where FRAME1 is a \"current frame\", FRAME2 is the next frame, +I is the index of the frame after FRAME2. It should return nil +if those frames don't seem special and otherwise, it should return +the number of frames to skip (minus 1).") + +(defmacro internal--called-interactively-p--get-frame (n) + ;; `sym' will hold a global variable, which will be used kind of like C's + ;; "static" variables. + (let ((sym (make-symbol "base-index"))) + `(progn + (defvar ,sym + (let ((i 1)) + (while (not (eq (nth 1 (backtrace-frame i)) + 'called-interactively-p)) + (setq i (1+ i))) + i)) + ;; (unless (eq (nth 1 (backtrace-frame ,sym)) 'called-interactively-p) + ;; (error "called-interactively-p: %s is out-of-sync!" ,sym)) + (backtrace-frame (+ ,sym ,n))))) + +(defun called-interactively-p (&optional kind) + "Return t if the containing function was called by `call-interactively'. +If KIND is `interactive', then only return t if the call was made +interactively by the user, i.e. not in `noninteractive' mode nor +when `executing-kbd-macro'. +If KIND is `any', on the other hand, it will return t for any kind of +interactive call, including being called as the binding of a key or +from a keyboard macro, even in `noninteractive' mode. + +This function is very brittle, it may fail to return the intended result when +the code is debugged, advised, or instrumented in some form. Some macros and +special forms (such as `condition-case') may also sometimes wrap their bodies +in a `lambda', so any call to `called-interactively-p' from those bodies will +indicate whether that lambda (rather than the surrounding function) was called +interactively. + +Instead of using this function, it is cleaner and more reliable to give your +function an extra optional argument whose `interactive' spec specifies +non-nil unconditionally (\"p\" is a good way to do this), or via +\(not (or executing-kbd-macro noninteractive)). + +The only known proper use of `interactive' for KIND is in deciding +whether to display a helpful message, or how to display it. If you're +thinking of using it for any other purpose, it is quite likely that +you're making a mistake. Think: what do you want to do when the +command is called from a keyboard macro?" + (declare (advertised-calling-convention (kind) "23.1")) + (when (not (and (eq kind 'interactive) + (or executing-kbd-macro noninteractive))) + (let* ((i 1) ;; 0 is the called-interactively-p frame. + frame nextframe + (get-next-frame + (lambda () + (setq frame nextframe) + (setq nextframe (internal--called-interactively-p--get-frame i)) + ;; (message "Frame %d = %S" i nextframe) + (setq i (1+ i))))) + (funcall get-next-frame) ;; Get the first frame. + (while + ;; FIXME: The edebug and advice handling should be made modular and + ;; provided directly by edebug.el and nadvice.el. + (progn + ;; frame =(backtrace-frame i-2) + ;; nextframe=(backtrace-frame i-1) + (funcall get-next-frame) + ;; `pcase' would be a fairly good fit here, but it sometimes moves + ;; branches within local functions, which then messes up the + ;; `backtrace-frame' data we get, + (or + ;; Skip special forms (from non-compiled code). + (and frame (null (car frame))) + ;; Skip also `interactive-p' (because we don't want to know if + ;; interactive-p was called interactively but if it's caller was) + ;; and `byte-code' (idem; this appears in subexpressions of things + ;; like condition-case, which are wrapped in a separate bytecode + ;; chunk). + ;; FIXME: For lexical-binding code, this is much worse, + ;; because the frames look like "byte-code -> funcall -> #[...]", + ;; which is not a reliable signature. + (memq (nth 1 frame) '(interactive-p 'byte-code)) + ;; Skip package-specific stack-frames. + (let ((skip (run-hook-with-args-until-success + 'called-interactively-p-functions + i frame nextframe))) + (pcase skip + (`nil nil) + (`0 t) + (_ (setq i (+ i skip -1)) (funcall get-next-frame))))))) + ;; Now `frame' should be "the function from which we were called". + (pcase (cons frame nextframe) + ;; No subr calls `interactive-p', so we can rule that out. + (`((,_ ,(pred (lambda (f) (subrp (indirect-function f)))) . ,_) . ,_) nil) + ;; Somehow, I sometimes got `command-execute' rather than + ;; `call-interactively' on my stacktrace !? + ;;(`(,_ . (t command-execute . ,_)) t) + (`(,_ . (t call-interactively . ,_)) t))))) + +(defun interactive-p () + "Return t if the containing function was run directly by user input. +This means that the function was called with `call-interactively' +\(which includes being called as the binding of a key) +and input is currently coming from the keyboard (not a keyboard macro), +and Emacs is not running in batch mode (`noninteractive' is nil). + +The only known proper use of `interactive-p' is in deciding whether to +display a helpful message, or how to display it. If you're thinking +of using it for any other purpose, it is quite likely that you're +making a mistake. Think: what do you want to do when the command is +called from a keyboard macro or in batch mode? + +To test whether your function was called with `call-interactively', +either (i) add an extra optional argument and give it an `interactive' +spec that specifies non-nil unconditionally (such as \"p\"); or (ii) +use `called-interactively-p'." + (declare (obsolete called-interactively-p "23.2")) + (called-interactively-p 'interactive)) + +(defun function-arity (f &optional num) + "Return the (MIN . MAX) arity of F. +If the maximum arity is infinite, MAX is `many'. +F can be a function or a macro. +If NUM is non-nil, return non-nil iff F can be called with NUM args." + (if (symbolp f) (setq f (indirect-function f))) + (if (eq (car-safe f) 'macro) (setq f (cdr f))) + (let ((res + (if (subrp f) + (let ((x (subr-arity f))) + (if (eq (cdr x) 'unevalled) (cons (car x) 'many))) + (let* ((args (if (consp f) (cadr f) (aref f 0))) + (max (length args)) + (opt (memq '&optional args)) + (rest (memq '&rest args)) + (min (- max (length opt)))) + (if opt + (cons min (if rest 'many (1- max))) + (if rest + (cons (- max (length rest)) 'many) + (cons min max))))))) + (if (not num) + res + (and (>= num (car res)) + (or (eq 'many (cdr res)) (<= num (cdr res))))))) + (defun set-temporary-overlay-map (map &optional keep-pred) "Set MAP as a temporary keymap taking precedence over most other keymaps. Note that this does NOT take precedence over the \"overriding\" maps @@ -4186,6 +4323,36 @@ convenience wrapper around `make-progress-reporter' and friends. nil ,@(cdr (cdr spec))))) +;;;; Support for watching filesystem events. + +(defun inotify-event-p (event) + "Check if EVENT is an inotify event." + (and (listp event) + (>= (length event) 3) + (eq (car event) 'file-inotify))) + +;;;###autoload +(defun inotify-handle-event (event) + "Handle inotify file system monitoring event. +If EVENT is an inotify filewatch event, call its callback. +Otherwise, signal a `filewatch-error'." + (interactive "e") + (unless (inotify-event-p event) + (signal 'filewatch-error (cons "Not a valid inotify event" event))) + (funcall (nth 2 event) (nth 1 event))) + +(defun w32notify-handle-event (event) + "Handle MS-Windows file system monitoring event. +If EVENT is an MS-Windows filewatch event, call its callback. +Otherwise, signal a `filewatch-error'." + (interactive "e") + (if (and (eq (car event) 'file-w32notify) + (= (length event) 3)) + (funcall (nth 2 event) (nth 1 event)) + (signal 'filewatch-error + (cons "Not a valid MS-Windows file-notify event" event)))) + + ;;;; Comparing version strings. (defconst version-separator "." |