1 ;;; eldoc-eval.el --- Enable eldoc support when minibuffer is in use.
3 ;; Copyright (C) 2011, 2012, 2013 Free Software Foundation, Inc.
5 ;; Author: Thierry Volpiatto <thierry.volpiatto@gmail.com>
8 ;; This file is part of GNU Emacs.
10 ;; GNU Emacs is free software: you can redistribute it and/or modify
11 ;; it under the terms of the GNU General Public License as published by
12 ;; the Free Software Foundation, either version 3 of the License, or
13 ;; (at your option) any later version.
15 ;; GNU Emacs is distributed in the hope that it will be useful,
16 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
17 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 ;; GNU General Public License for more details.
20 ;; You should have received a copy of the GNU General Public License
21 ;; along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>.
25 ;; This package enables eldoc support when minibuffer is in use.
27 ;; Eldoc info is shown by default in mode-line,
28 ;; but you can have eldoc info somewhere else by setting
29 ;; `eldoc-in-minibuffer-show-fn' to another function (e.g `tooltip-show').
31 ;; By default with this package `M-:' will use `pp-eval-expression'
32 ;; instead of `eval-expression'; you can change that by setting
33 ;; `eval-preferred-function'.
35 ;; It also provides a convenient macro to enable eldoc support
36 ;; in your own functions using minibuffer or in your defadvices,
37 ;; that is `with-eldoc-in-minibuffer'.
39 ;; Users of own minibuffer frame will have to set
40 ;; `eldoc-in-minibuffer-own-frame-p' to non-nil.
42 ;; You can turn off eldoc support in minibuffer any time
43 ;; by setting `eldoc-in-minibuffer' to nil.
48 ;; FIXME: This has no autoloads and (require 'eldoc-eval) will change Emacs's
49 ;; behavior, against usual conventions. The fix is to define
50 ;; eldoc-in-minibuffer as a (global) minor mode, then autoload it. So the
51 ;; default value will be nil, and the user can enable it with
52 ;; (eldoc-in-minibuffer 1) or by customizing eldoc-in-minibuffer, rather than
53 ;; by adding (require 'eldoc-eval) in her .emacs.
55 ;;; Minibuffer support.
56 ;; Enable displaying eldoc info in something else
57 ;; Than minibuffer when this one is in use.
59 (defcustom eldoc-in-minibuffer t
60 "Turn on eldoc in minibuffer."
64 (defcustom eldoc-in-minibuffer-show-fn 'eldoc-show-in-mode-line
65 "A function to display eldoc info.
66 Should take one arg: the string to display"
70 (defcustom eldoc-show-in-mode-line-delay 12
71 "The time we show eldoc when Emacs is idle."
75 (defcustom eval-preferred-function 'pp-eval-expression
76 "Preferred function to use with `M-:'."
80 (defcustom eldoc-in-minibuffer-own-frame-p nil
81 "Whether minibuffer has its own frame or not."
85 ;;; Compatibility with Emacs-24.4
86 ;; New implementation of eldoc in minibuffer that come
87 ;; with Emacs-24.4 show the eldoc info of current-buffer while
88 ;; minibuffer is in use, disable this and inline old Emacs behavior.
90 (when (boundp 'eldoc-message-function)
91 (setq eldoc-message-function 'message)
93 (defadvice eldoc-display-message-no-interference-p
94 (around eldoc-eval activate)
95 (if (not eldoc-in-minibuffer)
98 (not executing-kbd-macro)
99 (not (and (boundp 'edebug-active) edebug-active))
100 ;; Having this mode operate in an active minibuffer/echo area causes
101 ;; interference with what's going on there.
102 (not cursor-in-echo-area)
103 (not (eq (selected-window) (minibuffer-window)))))))
106 (defvar eldoc-active-minibuffers-list nil
107 "List of active minibuffers with eldoc enabled.")
108 (defvar eldoc-mode-line-rolling-flag nil)
110 (defun eldoc-store-minibuffer ()
111 "Store minibuffer buffer name in `eldoc-active-minibuffers-list'.
112 This function is called by each minibuffer started with eldoc support.
113 See `with-eldoc-in-minibuffer'."
114 (with-selected-window (minibuffer-window)
115 (push (current-buffer) eldoc-active-minibuffers-list)))
117 (defmacro with-eldoc-in-minibuffer (&rest body)
118 "Enable eldoc support for minibuffer input that runs in BODY."
119 (declare (indent 0) (debug t))
120 `(let ((timer (and eldoc-in-minibuffer
123 'repeat 'eldoc-mode-in-minibuffer))))
125 (minibuffer-with-setup-hook
126 ;; When minibuffer is activated in body,
128 'eldoc-store-minibuffer
130 (and timer (cancel-timer timer))
131 ;; Each time a minibuffer exits or aborts
132 ;; its buffer is removed from stack,
133 ;; assuming we can only exit the active minibuffer
135 (setq eldoc-active-minibuffers-list
136 (cdr eldoc-active-minibuffers-list)))))
138 (defun eldoc-current-buffer ()
139 "Return the current buffer prior to activating the minibuffer."
140 (with-selected-frame (last-nonminibuffer-frame)
142 (cond (eldoc-in-minibuffer-own-frame-p
144 ((fboundp 'window-in-direction)
146 'above (minibuffer-window)))
147 (t (minibuffer-selected-window))))))
149 (defun eldoc-show-in-mode-line (str)
150 "Display string STR in the mode-line next to minibuffer."
151 (let (mode-line-in-non-selected-windows)
152 (with-current-buffer (eldoc-current-buffer)
153 (make-local-variable 'mode-line-format)
154 (let ((mode-line-format (concat " " str)))
155 (eldoc-maybe-roll-message-in-mode-line mode-line-format))
156 (force-mode-line-update))))
158 (defun eldoc-maybe-roll-message-in-mode-line (str)
159 (let* ((max (window-width (get-buffer-window (eldoc-current-buffer))))
162 (if (and (> len max) eldoc-mode-line-rolling-flag)
164 (setq tmp-str (substring tmp-str 2)
165 mode-line-format (concat tmp-str " [<]" str))
166 (force-mode-line-update nil)
167 (when (< (length tmp-str) 2) (setq tmp-str str)))
168 (force-mode-line-update nil)
169 (sit-for eldoc-show-in-mode-line-delay))))
171 (defun eldoc-mode-line-toggle-rolling ()
173 (setq eldoc-mode-line-rolling-flag (not eldoc-mode-line-rolling-flag)))
174 (define-key minibuffer-local-map (kbd "<C-M-right>") 'eldoc-mode-line-toggle-rolling)
176 (defun eldoc-mode-in-minibuffer ()
177 "Show eldoc for current minibuffer input."
178 (let ((buf (window-buffer (active-minibuffer-window))))
179 ;; If this minibuffer have been started with
180 ;;`with-eldoc-in-minibuffer' give it eldoc support
181 ;; and update mode-line, otherwise do nothing.
183 (when (member buf eldoc-active-minibuffers-list)
184 (with-current-buffer buf
185 (let* ((sym (save-excursion
186 (unless (looking-back ")\\|\"")
188 (eldoc-current-symbol)))
189 (info-fn (eldoc-fnsym-in-current-sexp))
190 (doc (or (eldoc-get-var-docstring sym)
191 (eldoc-get-fnsym-args-string
192 (car info-fn) (cadr info-fn)))))
193 (when doc (funcall eldoc-in-minibuffer-show-fn doc)))))
195 (beginning-of-buffer nil)
196 (error (message "Eldoc in minibuffer error: %S" err)))))
198 (defun eval-expression-with-eldoc ()
199 "Eval expression with eldoc support in mode-line."
201 (with-eldoc-in-minibuffer
202 (call-interactively eval-preferred-function)))
206 ;; FIXME: Turn eldoc-in-minibuffer into a global minor mode, and place this
207 ;; binding in its keymap.
208 (global-set-key [remap eval-expression] 'eval-expression-with-eldoc)
211 (provide 'eldoc-eval)
212 ;;; eldoc-eval.el ends here