;;; eldoc-eval.el --- Enable eldoc support when minibuffer is in use.
-;; Copyright (C) 2011 Free Software Foundation, Inc.
+;; Copyright (C) 2011, 2012, 2013 Free Software Foundation, Inc.
;; Author: Thierry Volpiatto <thierry.volpiatto@gmail.com>
;; Version: 0.1
;;; Commentary:
;;
-;; This package enable eldoc support when minibuffer is in use.
+;; This package enables eldoc support when minibuffer is in use.
;;
-;; Eldoc info are shown by default in mode-line.
+;; Eldoc info is shown by default in mode-line,
;; but you can have eldoc info somewhere else by setting
-;; `eldoc-in-minibuffer-show-fn' to an other function (e.g `tooltip-show').
+;; `eldoc-in-minibuffer-show-fn' to another function (e.g `tooltip-show').
;;
;; By default with this package `M-:' will use `pp-eval-expression'
-;; instead of `eval-expression'; You can change that in
-;; `eval-prefered-function'.
+;; instead of `eval-expression'; you can change that by setting
+;; `eldoc-eval-preferred-function'.
;;
-;; It provide also a convenient macro to enable eldoc support
+;; It also provides a convenient macro to enable eldoc support
;; in your own functions using minibuffer or in your defadvices,
;; that is `with-eldoc-in-minibuffer'.
;;
;; Users of own minibuffer frame will have to set
-;; `eldoc-in-minibuffer-own-frame-p' to non--nil.
+;; `eldoc-in-minibuffer-own-frame-p' to non-nil.
;;
-;; You can turn off at anytime eldoc support in minibuffer
-;; by setting `eldoc-in-minibuffer' to nil.
+;; You can turn On/Off eldoc support in minibuffer any time
+;; with `eldoc-in-minibuffer-mode'.
+;;
+;;; Install:
+;; Add to .emacs:
+;;
+;; (autoload 'eldoc-in-minibuffer-mode "eldoc-eval")
+;; (eldoc-in-minibuffer-mode 1)
+
;;; Code:
(require 'eldoc)
-
;;; Minibuffer support.
;; Enable displaying eldoc info in something else
;; Than minibuffer when this one is in use.
;;
-(defcustom eldoc-in-minibuffer t
- "Turn on eldoc in minibuffer."
- :group 'eldoc
- :type 'bolean)
+(defgroup eldoc-eval nil
+ "Show eldoc infos in mode line while minibuffer is in use."
+ :group 'eldoc)
(defcustom eldoc-in-minibuffer-show-fn 'eldoc-show-in-mode-line
"A function to display eldoc info.
Should take one arg: the string to display"
- :group 'eldoc
:type 'function)
(defcustom eldoc-show-in-mode-line-delay 12
"The time we show eldoc when Emacs is idle."
- :group 'eldoc
:type 'number)
-(defcustom eval-prefered-function 'pp-eval-expression
- "Prefered function to use with `M-:'."
- :group 'lisp
+(defcustom eldoc-eval-preferred-function 'pp-eval-expression
+ "Preferred function to use with `M-:'."
:type 'function)
(defcustom eldoc-in-minibuffer-own-frame-p nil
- "Whether minibuffer have own frame or not."
- :group 'lisp
+ "Whether minibuffer has its own frame or not."
:type 'boolean)
+;;; Compatibility with Emacs-24.4
+;; New implementation of eldoc in minibuffer that come
+;; with Emacs-24.4 show the eldoc info of current-buffer while
+;; minibuffer is in use, disable this and inline old Emacs behavior.
+;;
+(defconst eldoc-eval--old-message-function
+ (and (boundp 'eldoc-message-function) eldoc-message-function))
+
+(defadvice eldoc-display-message-no-interference-p
+ (after eldoc-eval activate)
+ (when eldoc-in-minibuffer-mode
+ (setq ad-return-value
+ (and ad-return-value
+ ;; Having this mode operate in an active minibuffer/echo area
+ ;; causes interference with what's going on there.
+ (not cursor-in-echo-area)
+ (not (eq (selected-window) (minibuffer-window)))))))
+
;; Internal.
(defvar eldoc-active-minibuffers-list nil
- "Store actives minibuffers with eldoc enabled.")
+ "List of active minibuffers with eldoc enabled.")
(defvar eldoc-mode-line-rolling-flag nil)
(defun eldoc-store-minibuffer ()
This function is called by each minibuffer started with eldoc support.
See `with-eldoc-in-minibuffer'."
(with-selected-window (minibuffer-window)
- (push (buffer-name) eldoc-active-minibuffers-list)))
+ (push (current-buffer) eldoc-active-minibuffers-list)))
(defmacro with-eldoc-in-minibuffer (&rest body)
- "Enable eldoc support for minibuffer input that run in BODY."
+ "Enable eldoc support for minibuffer input that runs in BODY."
(declare (indent 0) (debug t))
- `(let ((timer (and eldoc-in-minibuffer
+ `(let ((timer (and eldoc-in-minibuffer-mode
(run-with-idle-timer
eldoc-idle-delay
- 'repeat 'eldoc-mode-in-minibuffer))))
+ 'repeat #'eldoc-run-in-minibuffer))))
(unwind-protect
(minibuffer-with-setup-hook
- ;; When minibuffer is activated in body,
- ;; store it.
- 'eldoc-store-minibuffer
+ ;; When minibuffer is activated in body, store it.
+ #'eldoc-store-minibuffer
,@body)
(and timer (cancel-timer timer))
- ;; Each time a minibuffer exit or abort
- ;; his buffer is removed from stack,
+ ;; Each time a minibuffer exits or aborts
+ ;; its buffer is removed from stack,
;; assuming we can only exit the active minibuffer
;; on top of stack.
(setq eldoc-active-minibuffers-list
(cdr eldoc-active-minibuffers-list)))))
(defun eldoc-current-buffer ()
- "The `current-buffer' before activating minibuffer."
+ "Return the current buffer prior to activating the minibuffer."
(with-selected-frame (last-nonminibuffer-frame)
(window-buffer
(cond (eldoc-in-minibuffer-own-frame-p
(defun eldoc-mode-line-toggle-rolling ()
(interactive)
- (setq eldoc-mode-line-rolling-flag (not eldoc-mode-line-rolling-flag)))
-(define-key minibuffer-local-map (kbd "<C-M-right>") 'eldoc-mode-line-toggle-rolling)
-
-(defun eldoc-mode-in-minibuffer ()
- "Show eldoc for current minibuffer input."
- (let ((buf (with-selected-window (minibuffer-window)
- (buffer-name))))
+ (if (and eldoc-in-minibuffer-mode
+ (minibuffer-window-active-p (selected-window)))
+ (setq eldoc-mode-line-rolling-flag (not eldoc-mode-line-rolling-flag))
+ (error "No active minibuffer found")))
+
+(defvar eldoc-in-minibuffer-mode-map
+ (let ((map (make-sparse-keymap)))
+ ;; FIXME: Should we use [remap eval-expression] instead?
+ (define-key map (kbd "M-:") 'eldoc-eval-expression)
+ map))
+
+;;;###autoload
+(define-minor-mode eldoc-in-minibuffer-mode
+ "Show eldoc for current minibuffer input."
+ :global t
+ (if eldoc-in-minibuffer-mode
+ (progn
+ (add-hook 'minibuffer-exit-hook
+ (lambda ()
+ (setq eldoc-mode-line-rolling-flag nil)))
+ (and (boundp 'eldoc-message-function)
+ (setq eldoc-message-function 'message))
+ (define-key minibuffer-local-map (kbd "C-@")
+ 'eldoc-mode-line-toggle-rolling)
+ (setq eldoc-minor-mode-string " Eldoc-eval"))
+ (setq eldoc-minor-mode-string " Eldoc")
+ (and (boundp 'eldoc-message-function)
+ (setq eldoc-message-function eldoc-eval--old-message-function))
+ (define-key minibuffer-local-map (kbd "C-@") 'set-mark-command)))
+
+(defun eldoc-run-in-minibuffer ()
+ (let ((buf (window-buffer (active-minibuffer-window))))
;; If this minibuffer have been started with
;;`with-eldoc-in-minibuffer' give it eldoc support
;; and update mode-line, otherwise do nothing.
- (when (member buf eldoc-active-minibuffers-list)
- (let* ((str-all (with-current-buffer buf
- (minibuffer-completion-contents)))
- (sym (when str-all
- (with-temp-buffer
- (insert str-all)
- (goto-char (point-max))
+ (condition-case err
+ (when (member buf eldoc-active-minibuffers-list)
+ (with-current-buffer buf
+ (let* ((sym (save-excursion
(unless (looking-back ")\\|\"")
(forward-char -1))
- (eldoc-current-symbol))))
- (info-fn (eldoc-fnsym-in-current-sexp))
- (doc (or (eldoc-get-var-docstring sym)
- (eldoc-get-fnsym-args-string
- (car info-fn) (cadr info-fn)))))
- (when doc (funcall eldoc-in-minibuffer-show-fn doc))))))
-
-(defun eval-expression-with-eldoc ()
+ (eldoc-current-symbol)))
+ (info-fn (eldoc-fnsym-in-current-sexp))
+ (doc (or (eldoc-get-var-docstring sym)
+ (eldoc-get-fnsym-args-string
+ (car info-fn) (cadr info-fn)))))
+ (when doc (funcall eldoc-in-minibuffer-show-fn doc)))))
+ (scan-error nil)
+ (beginning-of-buffer nil)
+ (error (message "Eldoc in minibuffer error: %S" err)))))
+
+;;;###autoload
+(defun eldoc-eval-expression ()
"Eval expression with eldoc support in mode-line."
(interactive)
(with-eldoc-in-minibuffer
- (call-interactively eval-prefered-function)))
-
-;; Bind it to `M-:'.
-(global-set-key [remap eval-expression] 'eval-expression-with-eldoc)
+ (call-interactively eldoc-eval-preferred-function)))
(provide 'eldoc-eval)