From f95e9344c9a9e0f5d28df1a9e8ac0ebed3c512fb Mon Sep 17 00:00:00 2001 From: Stefan Monnier Date: Fri, 4 May 2012 21:47:04 -0400 Subject: [PATCH] New function set-temporary-overlay-map and macros (defvar|setq)-local. * lisp/subr.el (setq-local, defvar-local): New macros. (kbd): Redefine as an alias. (with-selected-window): Leave unrelated frames alone. (set-temporary-overlay-map): New function. --- etc/NEWS | 5 ++++ lisp/ChangeLog | 7 +++++ lisp/subr.el | 72 ++++++++++++++++++++++++++++++++++++++------------ 3 files changed, 67 insertions(+), 17 deletions(-) diff --git a/etc/NEWS b/etc/NEWS index ca9b018a2f7..c47fd166215 100644 --- a/etc/NEWS +++ b/etc/NEWS @@ -199,7 +199,12 @@ still be supported for Emacs 24.x. * Lisp changes in Emacs 24.2 +** New function `set-temporary-overlay-map'. + +** New macros `setq-local' and `defvar-local'. + ** New error type and new function `user-error'. Doesn't trigger the debugger. + ** Completion *** New function `completion-table-with-quoting' to handle completion diff --git a/lisp/ChangeLog b/lisp/ChangeLog index 5c38eb86fa7..276cd7fca6f 100644 --- a/lisp/ChangeLog +++ b/lisp/ChangeLog @@ -1,3 +1,10 @@ +2012-05-05 Stefan Monnier + + * subr.el (setq-local, defvar-local): New macros. + (kbd): Redefine as an alias. + (with-selected-window): Leave unrelated frames alone. + (set-temporary-overlay-map): New function. + 2012-05-04 Stefan Monnier * subr.el (user-error): New function. diff --git a/lisp/subr.el b/lisp/subr.el index 8cfb1eeea16..5d28b96cd7e 100644 --- a/lisp/subr.el +++ b/lisp/subr.el @@ -116,6 +116,19 @@ BODY should be a list of Lisp expressions. ;; depend on backquote.el. (list 'function (cons 'lambda cdr))) +(defmacro setq-local (var val) + "Set variable VAR to value VAL in current buffer." + ;; Can't use backquote here, it's too early in the bootstrap. + (list 'set (list 'make-local-variable (list 'quote var)) val)) + +(defmacro defvar-local (var val &optional docstring) + "Define VAR as a buffer-local variable with default value VAL. +Like `defvar' but additionally marks the variable as being automatically +buffer-local wherever it is set." + ;; Can't use backquote here, it's too early in the bootstrap. + (list 'progn (list 'defvar var val docstring) + (list 'make-variable-buffer-local (list 'quote var)))) + (defun apply-partially (fun &rest args) "Return a function that is a partial application of FUN to ARGS. ARGS is a list of the first N arguments to pass to FUN. @@ -506,11 +519,8 @@ side-effects, and the argument LIST is not modified." ;;;; Keymap support. -(defmacro kbd (keys) - "Convert KEYS to the internal Emacs key representation. -KEYS should be a string constant in the format used for -saving keyboard macros (see `edmacro-mode')." - (read-kbd-macro keys)) +(defalias 'kbd 'read-kbd-macro) +(put 'kbd 'pure t) (defun undefined () "Beep to tell the user this binding is undefined." @@ -2986,21 +2996,26 @@ potentially make a different buffer current. It does not alter the buffer list ordering." (declare (indent 1) (debug t)) ;; Most of this code is a copy of save-selected-window. - `(let ((save-selected-window-window (selected-window)) - ;; It is necessary to save all of these, because calling - ;; select-window changes frame-selected-window for whatever - ;; frame that window is in. - (save-selected-window-alist - (mapcar (lambda (frame) (list frame (frame-selected-window frame))) - (frame-list)))) + `(let* ((save-selected-window-destination ,window) + (save-selected-window-window (selected-window)) + ;; Selecting a window on another frame changes not only the + ;; selected-window but also the frame-selected-window of the + ;; destination frame. So we need to save&restore it. + (save-selected-window-other-frame + (unless (eq (selected-frame) + (window-frame save-selected-window-destination)) + (frame-selected-window + (window-frame save-selected-window-destination))))) (save-current-buffer (unwind-protect - (progn (select-window ,window 'norecord) + (progn (select-window save-selected-window-destination 'norecord) ,@body) - (dolist (elt save-selected-window-alist) - (and (frame-live-p (car elt)) - (window-live-p (cadr elt)) - (set-frame-selected-window (car elt) (cadr elt) 'norecord))) + ;; First reset frame-selected-window. + (if (window-live-p save-selected-window-other-frame) + ;; We don't use set-frame-selected-window because it does not + ;; pass the `norecord' argument to Fselect_window. + (select-window save-selected-window-other-frame 'norecord)) + ;; Then reset the actual selected-window. (when (window-live-p save-selected-window-window) (select-window save-selected-window-window 'norecord)))))) @@ -3808,6 +3823,29 @@ The properties used on SYMBOL are `composefunc', `sendfunc', (put symbol 'abortfunc (or abortfunc 'kill-buffer)) (put symbol 'hookvar (or hookvar 'mail-send-hook))) +(defun set-temporary-overlay-map (map &optional keep-pred) + (let* ((clearfunsym (make-symbol "clear-temporary-overlay-map")) + (overlaysym (make-symbol "t")) + (alist (list (cons overlaysym map))) + (clearfun + ;; FIXME: Use lexical-binding. + `(lambda () + (unless ,(cond ((null keep-pred) nil) + ((eq t keep-pred) + `(eq this-command + (lookup-key ',map + (this-command-keys-vector)))) + (t `(funcall ',keep-pred))) + (remove-hook 'pre-command-hook ',clearfunsym) + (setq emulation-mode-map-alists + (delq ',alist emulation-mode-map-alists)))))) + (set overlaysym overlaysym) + (fset clearfunsym clearfun) + (add-hook 'pre-command-hook clearfunsym) + ;; FIXME: That's the keymaps with highest precedence, except for + ;; the `keymap' text-property ;-( + (push alist emulation-mode-map-alists))) + ;;;; Progress reporters. ;; Progress reporter has the following structure: -- 2.39.2