]> code.delx.au - gnu-emacs-elpa/blob - packages/eldoc-eval/eldoc-eval.el
Clean up copyright notices.
[gnu-emacs-elpa] / packages / eldoc-eval / eldoc-eval.el
1 ;;; eldoc-eval.el --- Enable eldoc support when minibuffer is in use.
2
3 ;; Copyright (C) 2011, 2012 Free Software Foundation, Inc.
4
5 ;; Author: Thierry Volpiatto <thierry.volpiatto@gmail.com>
6 ;; Version: 0.1
7
8 ;; This file is part of GNU Emacs.
9
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.
14
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.
19
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/>.
22
23 ;;; Commentary:
24 ;;
25 ;; This package enables eldoc support when minibuffer is in use.
26 ;;
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').
30 ;;
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'.
34 ;;
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'.
38 ;;
39 ;; Users of own minibuffer frame will have to set
40 ;; `eldoc-in-minibuffer-own-frame-p' to non-nil.
41 ;;
42 ;; You can turn off eldoc support in minibuffer any time
43 ;; by setting `eldoc-in-minibuffer' to nil.
44
45 ;;; Code:
46 (require 'eldoc)
47
48
49 ;;; Minibuffer support.
50 ;; Enable displaying eldoc info in something else
51 ;; Than minibuffer when this one is in use.
52 ;;
53 (defcustom eldoc-in-minibuffer t
54 "Turn on eldoc in minibuffer."
55 :group 'eldoc
56 :type 'bolean)
57
58 (defcustom eldoc-in-minibuffer-show-fn 'eldoc-show-in-mode-line
59 "A function to display eldoc info.
60 Should take one arg: the string to display"
61 :group 'eldoc
62 :type 'function)
63
64 (defcustom eldoc-show-in-mode-line-delay 12
65 "The time we show eldoc when Emacs is idle."
66 :group 'eldoc
67 :type 'number)
68
69 (defcustom eval-preferred-function 'pp-eval-expression
70 "Preferred function to use with `M-:'."
71 :group 'lisp
72 :type 'function)
73
74 (defcustom eldoc-in-minibuffer-own-frame-p nil
75 "Whether minibuffer has its own frame or not."
76 :group 'lisp
77 :type 'boolean)
78
79 ;; Internal.
80 (defvar eldoc-active-minibuffers-list nil
81 "List of active minibuffers with eldoc enabled.")
82 (defvar eldoc-mode-line-rolling-flag nil)
83
84 (defun eldoc-store-minibuffer ()
85 "Store minibuffer buffer name in `eldoc-active-minibuffers-list'.
86 This function is called by each minibuffer started with eldoc support.
87 See `with-eldoc-in-minibuffer'."
88 (with-selected-window (minibuffer-window)
89 (push (buffer-name) eldoc-active-minibuffers-list)))
90
91 (defmacro with-eldoc-in-minibuffer (&rest body)
92 "Enable eldoc support for minibuffer input that runs in BODY."
93 (declare (indent 0) (debug t))
94 `(let ((timer (and eldoc-in-minibuffer
95 (run-with-idle-timer
96 eldoc-idle-delay
97 'repeat 'eldoc-mode-in-minibuffer))))
98 (unwind-protect
99 (minibuffer-with-setup-hook
100 ;; When minibuffer is activated in body,
101 ;; store it.
102 'eldoc-store-minibuffer
103 ,@body)
104 (and timer (cancel-timer timer))
105 ;; Each time a minibuffer exits or aborts
106 ;; its buffer is removed from stack,
107 ;; assuming we can only exit the active minibuffer
108 ;; on top of stack.
109 (setq eldoc-active-minibuffers-list
110 (cdr eldoc-active-minibuffers-list)))))
111
112 (defun eldoc-current-buffer ()
113 "Return the current buffer prior to activating the minibuffer."
114 (with-selected-frame (last-nonminibuffer-frame)
115 (window-buffer
116 (cond (eldoc-in-minibuffer-own-frame-p
117 (selected-window))
118 ((fboundp 'window-in-direction)
119 (window-in-direction
120 'above (minibuffer-window)))
121 (t (minibuffer-selected-window))))))
122
123 (defun eldoc-show-in-mode-line (str)
124 "Display string STR in the mode-line next to minibuffer."
125 (let (mode-line-in-non-selected-windows)
126 (with-current-buffer (eldoc-current-buffer)
127 (make-local-variable 'mode-line-format)
128 (let ((mode-line-format (concat " " str)))
129 (eldoc-maybe-roll-message-in-mode-line mode-line-format))
130 (force-mode-line-update))))
131
132 (defun eldoc-maybe-roll-message-in-mode-line (str)
133 (let* ((max (window-width (get-buffer-window (eldoc-current-buffer))))
134 (len (length str))
135 (tmp-str str))
136 (if (and (> len max) eldoc-mode-line-rolling-flag)
137 (while (sit-for 0.3)
138 (setq tmp-str (substring tmp-str 2)
139 mode-line-format (concat tmp-str " [<]" str))
140 (force-mode-line-update nil)
141 (when (< (length tmp-str) 2) (setq tmp-str str)))
142 (force-mode-line-update nil)
143 (sit-for eldoc-show-in-mode-line-delay))))
144
145 (defun eldoc-mode-line-toggle-rolling ()
146 (interactive)
147 (setq eldoc-mode-line-rolling-flag (not eldoc-mode-line-rolling-flag)))
148 (define-key minibuffer-local-map (kbd "<C-M-right>") 'eldoc-mode-line-toggle-rolling)
149
150 (defun eldoc-mode-in-minibuffer ()
151 "Show eldoc for current minibuffer input."
152 (let ((buf (with-selected-window (minibuffer-window)
153 (buffer-name))))
154 ;; If this minibuffer have been started with
155 ;;`with-eldoc-in-minibuffer' give it eldoc support
156 ;; and update mode-line, otherwise do nothing.
157 (when (member buf eldoc-active-minibuffers-list)
158 (let* ((str-all (with-current-buffer buf
159 (minibuffer-completion-contents)))
160 (sym (when str-all
161 (with-temp-buffer
162 (insert str-all)
163 (goto-char (point-max))
164 (unless (looking-back ")\\|\"")
165 (forward-char -1))
166 (eldoc-current-symbol))))
167 (info-fn (eldoc-fnsym-in-current-sexp))
168 (doc (or (eldoc-get-var-docstring sym)
169 (eldoc-get-fnsym-args-string
170 (car info-fn) (cadr info-fn)))))
171 (when doc (funcall eldoc-in-minibuffer-show-fn doc))))))
172
173 (defun eval-expression-with-eldoc ()
174 "Eval expression with eldoc support in mode-line."
175 (interactive)
176 (with-eldoc-in-minibuffer
177 (call-interactively eval-preferred-function)))
178
179 ;; Bind it to `M-:'.
180 (global-set-key [remap eval-expression] 'eval-expression-with-eldoc)
181
182
183 (provide 'eldoc-eval)
184 ;;; eldoc-eval.el ends here