Initial Commit
[packages] / xemacs-packages / semantic / semantic-idle.el
1 ;;; semantic-idle.el --- Schedule parsing tasks in idle time
2
3 ;;; Copyright (C) 2003, 2004, 2005, 2006 Eric M. Ludlam
4
5 ;; Author: Eric M. Ludlam <zappo@gnu.org>
6 ;; Keywords: syntax
7 ;; X-RCS: $Id: semantic-idle.el,v 1.1 2007-11-26 15:10:38 michaels Exp $
8
9 ;; This file is not part of GNU Emacs.
10
11 ;; Semantic is free software; you can redistribute it and/or modify
12 ;; it under the terms of the GNU General Public License as published by
13 ;; the Free Software Foundation; either version 2, or (at your option)
14 ;; any later version.
15
16 ;; This software is distributed in the hope that it will be useful,
17 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
18 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19 ;; GNU General Public License for more details.
20
21 ;; You should have received a copy of the GNU General Public License
22 ;; along with GNU Emacs; see the file COPYING.  If not, write to the
23 ;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
24 ;; Boston, MA 02110-1301, USA.
25
26 ;;; Commentary:
27 ;;
28 ;; Originally, `semantic-auto-parse-mode' handled refreshing the
29 ;; tags in a buffer in idle time.  Other activities can be scheduled
30 ;; in idle time, all of which require up-to-date tag tables.
31 ;; Having a specialized idle time scheduler that first refreshes
32 ;; the tags buffer, and then enables other idle time tasks reduces
33 ;; the amount of work needed.  Any specialized idle tasks need not
34 ;; ask for a fresh tags list.
35 ;;
36 ;; NOTE ON SEMANTIC_ANALYZE
37 ;;
38 ;; Some of the idle modes use the semantic analyzer.  The analyzer
39 ;; automatically caches the created context, so it is shared amongst
40 ;; all idle modes that will need it.
41
42 (require 'semantic-util-modes)
43 (require 'timer)
44
45 ;;; Code:
46
47 ;;; TIMER RELATED FUNCTIONS
48 ;;
49 (defvar semantic-idle-scheduler-timer nil
50   "Timer used to schedule tasks in idle time.")
51
52 (defcustom semantic-idle-scheduler-verbose-flag nil
53   "*Non-nil means that the idle scheduler should provide debug messages.
54 Use this setting to debug idle activities."
55   :group 'semantic
56   :type 'boolean)
57
58 (defcustom semantic-idle-scheduler-idle-time 2
59   "*Time in seconds of idle before scheduling events.
60 This time should be short enough to ensure that idle-scheduler will be
61 run as soon as Emacs is idle."
62   :group 'semantic
63   :type 'number
64   :set (lambda (sym val)
65          (set-default sym val)
66          (when (timerp semantic-idle-scheduler-timer)
67            (cancel-timer semantic-idle-scheduler-timer)
68            (setq semantic-idle-scheduler-timer nil)
69            (semantic-idle-scheduler-setup-timer))))
70
71 (defun semantic-idle-scheduler-setup-timer ()
72   "Lazy initialization of the auto parse idle timer."
73   ;; REFRESH THIS FUNCTION for XEMACS FOIBLES
74   (or (timerp semantic-idle-scheduler-timer)
75       (setq semantic-idle-scheduler-timer
76             (run-with-idle-timer
77              semantic-idle-scheduler-idle-time t
78              #'semantic-idle-scheduler-function))))
79
80 (defun semantic-idle-scheduler-kill-timer ()
81   "Kill the auto parse idle timer."
82   (if (timerp semantic-idle-scheduler-timer)
83       (cancel-timer semantic-idle-scheduler-timer))
84   (setq semantic-idle-scheduler-timer nil))
85
86 \f
87 ;;; MINOR MODE
88 ;;
89 ;; The minor mode portion of this code just sets up the minor mode
90 ;; which does the initial scheduling of the idle timers.
91 ;;
92 ;;;###autoload
93 (defcustom global-semantic-idle-scheduler-mode nil
94   "*If non-nil, enable global use of idle-scheduler mode."
95   :group 'semantic
96   :group 'semantic-modes
97   :type 'boolean
98   :require 'semantic-idle
99   :initialize 'custom-initialize-default
100   :set (lambda (sym val)
101          (global-semantic-idle-scheduler-mode (if val 1 -1))))
102
103 ;;;###autoload
104 (defun global-semantic-idle-scheduler-mode (&optional arg)
105   "Toggle global use of option `semantic-idle-scheduler-mode'.
106 The idle scheduler with automatically reparse buffers in idle time,
107 and then schedule other jobs setup with `semantic-idle-scheduler-add'.
108 If ARG is positive, enable, if it is negative, disable.
109 If ARG is nil, then toggle."
110   (interactive "P")
111   (setq global-semantic-idle-scheduler-mode
112         (semantic-toggle-minor-mode-globally
113          'semantic-idle-scheduler-mode arg)))
114
115 (defcustom semantic-idle-scheduler-mode-hook nil
116   "*Hook run at the end of function `semantic-idle-scheduler-mode'."
117   :group 'semantic
118   :type 'hook)
119
120 ;;;###autoload
121 (defvar semantic-idle-scheduler-mode nil
122   "Non-nil if idle-scheduler minor mode is enabled.
123 Use the command `semantic-idle-scheduler-mode' to change this variable.")
124 (make-variable-buffer-local 'semantic-idle-scheduler-mode)
125
126 (defcustom semantic-idle-scheduler-max-buffer-size 0
127   "*Maximum size in bytes of buffers where idle-scheduler is enabled.
128 If this value is less than or equal to 0, idle-scheduler is enabled in
129 all buffers regardless of their size."
130   :group 'semantic
131   :type 'number)
132
133 (defsubst semantic-idle-scheduler-enabled-p ()
134   "Return non-nil if idle-scheduler is enabled for this buffer.
135 idle-scheduler is disabled when debugging or if the buffer size
136 exceeds the `semantic-idle-scheduler-max-buffer-size' threshold."
137   (and semantic-idle-scheduler-mode
138        (not semantic-debug-enabled)
139        (not semantic-lex-debug)
140        (or (<= semantic-idle-scheduler-max-buffer-size 0)
141            (< (buffer-size) semantic-idle-scheduler-max-buffer-size))))
142
143 (defun semantic-idle-scheduler-mode-setup ()
144   "Setup option `semantic-idle-scheduler-mode'.
145 The minor mode can be turned on only if semantic feature is available
146 and the current buffer was set up for parsing.  When minor mode is
147 enabled parse the current buffer if needed.  Return non-nil if the
148 minor mode is enabled."
149   (if semantic-idle-scheduler-mode
150       (if (not (and (featurep 'semantic) (semantic-active-p)))
151           (progn
152             ;; Disable minor mode if semantic stuff not available
153             (setq semantic-idle-scheduler-mode nil)
154             (error "Buffer %s was not set up idle time scheduling"
155                    (buffer-name)))
156         (semantic-idle-scheduler-setup-timer)))
157   semantic-idle-scheduler-mode)
158
159 ;;;###autoload
160 (defun semantic-idle-scheduler-mode (&optional arg)
161   "Minor mode to auto parse buffer following a change.
162 When this mode is off, a buffer is only rescanned for tokens when
163 some command requests the list of available tokens.  When idle-scheduler
164 is enabled, Emacs periodically checks to see if the buffer is out of
165 date, and reparses while the user is idle (not typing.)
166
167 With prefix argument ARG, turn on if positive, otherwise off.  The
168 minor mode can be turned on only if semantic feature is available and
169 the current buffer was set up for parsing.  Return non-nil if the
170 minor mode is enabled."
171   (interactive
172    (list (or current-prefix-arg
173              (if semantic-idle-scheduler-mode 0 1))))
174   (setq semantic-idle-scheduler-mode
175         (if arg
176             (>
177              (prefix-numeric-value arg)
178              0)
179           (not semantic-idle-scheduler-mode)))
180   (semantic-idle-scheduler-mode-setup)
181   (run-hooks 'semantic-idle-scheduler-mode-hook)
182   (if (interactive-p)
183       (message "idle-scheduler minor mode %sabled"
184                (if semantic-idle-scheduler-mode "en" "dis")))
185   (semantic-mode-line-update)
186   semantic-idle-scheduler-mode)
187
188 (semantic-add-minor-mode 'semantic-idle-scheduler-mode
189                          "ARP"
190                          nil)
191
192 (semantic-alias-obsolete 'semantic-auto-parse-mode
193                          'semantic-idle-scheduler-mode)
194 (semantic-alias-obsolete 'global-semantic-auto-parse-mode
195                          'global-semantic-idle-scheduler-mode)
196
197 \f
198 ;;; SERVICES services
199 ;;
200 ;; These are services for managing idle services.
201 ;;
202 (defvar semantic-idle-scheduler-queue nil
203   "List of functions to execute during idle time.
204 These functions will be called in the current buffer after that
205 buffer has had its tags made up to date.  These functions
206 will not be called if there are errors parsing the
207 current buffer.")
208
209 ;;;###autoload
210 (defun semantic-idle-scheduler-add (function)
211   "Schedule FUNCTION to occur during idle time."
212   (add-to-list 'semantic-idle-scheduler-queue function))
213
214 ;;;###autoload
215 (defun semantic-idle-scheduler-remove (function)
216   "Unschedule FUNCTION to occur during idle time."
217   (setq semantic-idle-scheduler-queue
218         (delete function semantic-idle-scheduler-queue)))
219
220 ;;; IDLE Function
221 ;;
222 (defun semantic-idle-core-handler ()
223   "Core idle function that handles reparsing.
224 And also manages services that depend on tag values."
225   (when semantic-idle-scheduler-verbose-flag
226     (working-temp-message "IDLE: Core handler..."))
227   (semantic-exit-on-input 'idle-timer
228     (let* ((inhibit-quit nil)
229            (buffers (delq (current-buffer)
230                           (delq nil
231                                 (mapcar #'(lambda (b)
232                                             (and (buffer-file-name b)
233                                                  b))
234                                         (buffer-list)))))
235            others safe mode)
236       (when (semantic-idle-scheduler-enabled-p)
237         (save-excursion
238           ;; First, reparse the current buffer.
239           (setq mode major-mode
240                 safe (semantic-idle-scheduler-refresh-tags))
241           ;; Now loop over other buffers with same major mode, trying to
242           ;; update them as well.  Stop on keypress.
243           (dolist (b buffers)
244             (semantic-throw-on-input 'parsing-mode-buffers)
245             (with-current-buffer b
246               (if (eq major-mode mode)
247                   (and (semantic-idle-scheduler-enabled-p)
248                        (semantic-idle-scheduler-refresh-tags))
249                 (push (current-buffer) others))))
250           (setq buffers others))
251         ;; If re-parse of current buffer completed, evaluate all other
252         ;; services.  Stop on keypress.
253
254         ;; NOTE ON COMMENTED SAFE HERE
255         ;; We used to not execute the services if the buffer wsa
256         ;; unparseable.  We now assume that they are lexically
257         ;; safe to do, because we have marked the buffer unparseable
258         ;; if there was a problem.
259         ;;(when safe
260           (save-excursion
261             (dolist (service semantic-idle-scheduler-queue)
262               (semantic-throw-on-input 'idle-queue)
263               (when semantic-idle-scheduler-verbose-flag
264                 (working-temp-message "IDLE: execture service %s..." service))
265               (funcall service)
266               (when semantic-idle-scheduler-verbose-flag
267                 (working-temp-message "IDLE: execture service %s...done" service))
268               )))
269         ;;)
270       ;; Finally loop over remaining buffers, trying to update them as
271       ;; well.  Stop on keypress.
272       (save-excursion
273         (dolist (b buffers)
274           (semantic-throw-on-input 'parsing-other-buffers)
275           (with-current-buffer b
276             (and (semantic-idle-scheduler-enabled-p)
277                  (semantic-idle-scheduler-refresh-tags)))))
278       ))
279   (when semantic-idle-scheduler-verbose-flag
280     (working-temp-message "IDLE: Core handler...done")))
281
282 (defun semantic-idle-scheduler-function ()
283   "Function run when after `semantic-idle-scheduler-idle-time'.
284 This function will reparse the current buffer, and if successful,
285 call additional functions registered with the timer calls."
286   (when (zerop (recursion-depth))
287     (unwind-protect
288         (semantic-safe "idle error: %S"
289           ;; Handle re-parsing and other scheduled services
290           (save-match-data (semantic-idle-core-handler)))
291       )))
292 \f
293 ;;; REPARSING
294 ;;
295 ;; Reparsing is installed as semantic idle service.
296 ;; This part ALWAYS happens, and other services occur
297 ;; afterwards.
298
299 (defcustom semantic-idle-scheduler-no-working-message t
300   "*If non-nil, disable display of working messages during parse."
301   :group 'semantic
302   :type 'boolean)
303
304 (defcustom semantic-idle-scheduler-working-in-modeline-flag nil
305   "*Non-nil means show working messages in the mode line.
306 Typically, parsing will show messages in the minibuffer.
307 This will move the parse message into the modeline."
308   :group 'semantic
309   :type 'boolean)
310
311 (defvar semantic-before-idle-scheduler-reparse-hooks nil
312   "Hooks run before option `semantic-idle-scheduler' begins parsing.
313 If any hook throws an error, this variable is reset to nil.
314 This hook is not protected from lexical errors.")
315
316 (defvar semantic-after-idle-scheduler-reparse-hooks nil
317   "Hooks run after option `semantic-idle-scheduler' has parsed.
318 If any hook throws an error, this variable is reset to nil.
319 This hook is not protected from lexical errors.")
320
321 (defun semantic-idle-scheduler-refresh-tags ()
322   "Refreshes the current buffer's tags.
323 This is called by `semantic-idle-scheduler-function' to update the
324 tags in the current buffer.
325
326 Return non-nil if the refresh was successful.
327 Return nil if there is some sort of syntax error preventing a full
328 reparse.
329
330 Does nothing if the current buffer doesn't need reparsing."
331
332   ;; These checks actually occur in `semantic-fetch-tags', but if we
333   ;; do them here, then all the bovination hooks are not run, and
334   ;; we save lots of time.
335   (cond
336    ;; If the buffer was previously marked unparseable,
337    ;; then don't waste our time.
338    ((semantic-parse-tree-unparseable-p)
339     nil)
340    ;; The parse tree is already ok.
341    ((semantic-parse-tree-up-to-date-p)
342     t)
343    (t
344     ;; If these cases are true, then don't do any additional work.
345     (let* ((semantic-working-type nil)
346            (inhibit-quit nil)
347            (working-use-echo-area-p
348             (not semantic-idle-scheduler-working-in-modeline-flag))
349            (working-status-dynamic-type
350             (if semantic-idle-scheduler-no-working-message
351                 nil
352               working-status-dynamic-type))
353            (working-status-percentage-type
354             (if semantic-idle-scheduler-no-working-message
355                 nil
356               working-status-percentage-type))
357            (lexically-safe t)
358            )
359       ;; Let people hook into this, but don't let them hose
360       ;; us over!
361       (condition-case nil
362           (run-hooks 'semantic-before-idle-scheduler-reparse-hooks)
363         (error (setq semantic-before-idle-scheduler-reparse-hooks nil)))
364
365       (unwind-protect
366           ;; Perform the parsing.
367           (progn
368             (when semantic-idle-scheduler-verbose-flag
369               (working-temp-message "IDLE: reparse %s..." (buffer-name)))
370             (when (semantic-lex-catch-errors idle-scheduler
371                     (save-excursion (semantic-fetch-tags))
372                     nil)
373               ;; If we are here, it is because the lexical step failed,
374               ;; proably due to unterminated lists or something like that.
375             
376               ;; We do nothing, and just wait for the next idle timer
377               ;; to go off.  In the meantime, remember this, and make sure
378               ;; no other idle services can get executed.
379               (setq lexically-safe nil))
380             (when semantic-idle-scheduler-verbose-flag
381               (working-temp-message "IDLE: reparse %s...done" (buffer-name))))
382         ;; Let people hook into this, but don't let them hose
383         ;; us over!
384         (condition-case nil
385             (run-hooks 'semantic-after-idle-scheduler-reparse-hooks)
386           (error (setq semantic-after-idle-scheduler-reparse-hooks nil))))
387       ;; Return if we are lexically safe
388       lexically-safe))))
389
390 \f
391 ;;; IDLE SERVICES
392 ;;
393 ;; Idle Services are minor modes which enable or disable a services in
394 ;; the idle scheduler.  Creating a new services only requires calling
395 ;; `semantic-create-idle-services' which does all the setup
396 ;; needed to create the minor mode that will enable or disable
397 ;; a services.  The services must provide a single function.
398
399 (defmacro define-semantic-idle-service (name doc &rest forms)
400   "Create a new idle services with NAME.
401 DOC will be a documentation string describing FORMS.
402 FORMS will be called during idle time after the current buffer's
403 semantic tag information has been updated.
404 This routines creates the following functions and variables:"
405   (let ((global (intern (concat "global-" (symbol-name name) "-mode")))
406         (mode   (intern (concat (symbol-name name) "-mode")))
407         (hook   (intern (concat (symbol-name name) "-mode-hook")))
408         (map    (intern (concat (symbol-name name) "-mode-map")))
409         (setup  (intern (concat (symbol-name name) "-mode-setup")))
410         (func   (intern (concat (symbol-name name) "-idle-function")))
411         )
412
413     `(eval-and-compile
414        (defun ,global (&optional arg)
415          ,(concat "Toggle global use of option `" (symbol-name mode) "'.
416 If ARG is positive, enable, if it is negative, disable.
417 If ARG is nil, then toggle.")
418          (interactive "P")
419          (setq ,global
420                (semantic-toggle-minor-mode-globally
421                 ',mode arg)))
422
423        (defcustom ,global nil
424          (concat "*If non-nil, enable global use of `" (symbol-name ',mode) "'.
425 " ,doc)
426          :group 'semantic
427          :group 'semantic-modes
428          :type 'boolean
429          :require 'semantic-idle
430          :initialize 'custom-initialize-default
431          :set (lambda (sym val)
432                 (,global (if val 1 -1))))
433
434        (defcustom ,hook nil
435          (concat "*Hook run at the end of function `" (symbol-name ',mode) "'.")
436          :group 'semantic
437          :type 'hook)
438
439        (defvar ,map
440          (let ((km (make-sparse-keymap)))
441            km)
442          (concat "Keymap for `" (symbol-name ',mode) "'."))
443
444        (defvar ,mode nil
445          (concat "Non-nil if summary minor mode is enabled.
446 Use the command `" (symbol-name ',mode) "' to change this variable."))
447        (make-variable-buffer-local ',mode)
448
449        (defun ,setup ()
450          ,(concat "Setup option `" (symbol-name mode) "'.
451 The minor mode can be turned on only if semantic feature is available
452 and the idle scheduler is active.
453 Return non-nil if the minor mode is enabled.")
454          (if ,mode
455              (if (not (and (featurep 'semantic) (semantic-active-p)))
456                  (progn
457                    ;; Disable minor mode if semantic stuff not available
458                    (setq ,mode nil)
459                    (error "Buffer %s was not set up for parsing"
460                           (buffer-name)))
461                ;; Enable the mode mode
462                (semantic-idle-scheduler-add #',func)
463                )
464            ;; Disable the mode mode
465            (semantic-idle-scheduler-remove #',func)
466            )
467          ,mode)
468
469 ;;;###autoload
470        (defun ,mode (&optional arg)
471          ,(concat doc "
472 This is a minor mode which performs actions during idle time.
473 With prefix argument ARG, turn on if positive, otherwise off.  The
474 minor mode can be turned on only if semantic feature is available and
475 the current buffer was set up for parsing.  Return non-nil if the
476 minor mode is enabled.")
477          (interactive
478           (list (or current-prefix-arg
479                     (if ,mode 0 1))))
480          (setq ,mode
481                (if arg
482                    (>
483                     (prefix-numeric-value arg)
484                     0)
485                  (not ,mode)))
486          (,setup)
487          (run-hooks ,hook)
488          (if (interactive-p)
489              (message "%s %sabled"
490                       (symbol-name ',mode)
491                       (if ,mode "en" "dis")))
492          (semantic-mode-line-update)
493          ,mode)
494
495        (semantic-add-minor-mode ',mode
496                                 ""      ; idle schedulers are quiet?
497                                 ,map)
498     
499        (defun ,func ()
500          ,doc
501          ,@forms)
502     
503        )))
504 (put 'define-semantic-idle-service 'lisp-indent-function 1)
505
506 \f
507 ;;; SUMMARY MODE
508 ;;
509 ;; A mode similar to eldoc using semantic
510 (require 'semantic-ctxt)
511
512 (defcustom semantic-idle-summary-function 'semantic-format-tag-summarize
513   "*Function to use when displaying tag information during idle time.
514 Some useful functions are found in `semantic-format-tag-functions'."
515   :group 'semantic
516   :type semantic-format-tag-custom-list)
517
518 (defsubst semantic-idle-summary-find-current-symbol-tag (sym)
519   "Search for a semantic tag with name SYM in database tables.
520 Return the tag found or nil if not found.
521 If semanticdb is not in use, use the current buffer only."
522   (car (if (and (featurep 'semanticdb) semanticdb-current-database)
523            (cdar (semanticdb-deep-find-tags-by-name sym))
524          (semantic-deep-find-tags-by-name sym (current-buffer)))))
525
526 (defun semantic-idle-summary-current-symbol-info-brutish ()
527   "Return a string message describing the current context.
528 Gets a symbol with `semantic-ctxt-current-thing' and then
529 trys to find it with a deep targetted search."
530   ;; Try the current "thing".
531   (let ((sym (car (semantic-ctxt-current-thing))))
532     (when sym
533       (semantic-idle-summary-find-current-symbol-tag sym))))
534
535 (defun semantic-idle-summary-current-symbol-keyword ()
536   "Return a string message describing the current symbol.
537 Returns a value only if it is a keyword."
538   ;; Try the current "thing".
539   (let ((sym (car (semantic-ctxt-current-thing))))
540     (if (and sym (semantic-lex-keyword-p sym))
541         (semantic-lex-keyword-get sym 'summary))))
542
543 (defun semantic-idle-summary-current-symbol-info-context ()
544   "Return a string message describing the current context.
545 Use the semantic analyzer to find the symbol information."
546   (let ((analysis (condition-case nil
547                       (semantic-analyze-current-context (point))
548                     (error nil))))
549     (when analysis
550       (semantic-analyze-interesting-tag analysis))))
551
552 (defun semantic-idle-summary-current-symbol-info-default ()
553   "Return a string message describing the current context."
554   ;; use whicever has success first.
555   (or
556    (semantic-idle-summary-current-symbol-keyword)
557
558    (semantic-idle-summary-current-symbol-info-context)
559
560    (semantic-idle-summary-current-symbol-info-brutish)
561    ))
562
563 (defvar semantic-idle-summary-out-of-context-faces
564   '(
565     font-lock-comment-face
566     font-lock-string-face
567     font-lock-doc-string-face           ; XEmacs.
568     font-lock-doc-face                  ; Emacs 21 and later.
569     )
570   "List of font-lock faces that indicate a useless summary context.
571 Those are generally faces used to highlight comments.
572
573 It might be useful to override this variable to add comment faces
574 specific to a major mode.  For example, in jde mode:
575
576 \(defvar-mode-local jde-mode semantic-idle-summary-out-of-context-faces
577    (append (default-value 'semantic-idle-summary-out-of-context-faces)
578            '(jde-java-font-lock-doc-tag-face
579              jde-java-font-lock-link-face
580              jde-java-font-lock-bold-face
581              jde-java-font-lock-underline-face
582              jde-java-font-lock-pre-face
583              jde-java-font-lock-code-face)))")
584
585 (defun semantic-idle-summary-useful-context-p ()
586   "Non-nil of we should show a summary based on context."
587   (if (and (boundp 'font-lock-mode)
588            font-lock-mode
589            (memq (get-text-property (point) 'face)
590                  semantic-idle-summary-out-of-context-faces))
591       ;; The best I can think of at the moment is to disable
592       ;; in comments by detecting with font-lock.
593       nil
594     t))
595
596 (define-overload semantic-idle-summary-current-symbol-info ()
597   "Return a string message describing the current context.")
598
599 (make-obsolete-overload 'semantic-eldoc-current-symbol-info
600                         'semantic-idle-summary-current-symbol-info)
601
602 (define-semantic-idle-service semantic-idle-summary
603   "Display a tag summary of the lexical token under the cursor.
604 Call `semantic-idle-summary-current-symbol-info' for getting the
605 current tag to display information."
606   (or (eq major-mode 'emacs-lisp-mode)
607       (not (semantic-idle-summary-useful-context-p))
608       (let* ((found (semantic-idle-summary-current-symbol-info))
609              (str (cond ((stringp found) found)
610                         ((semantic-tag-p found)
611                          (funcall semantic-idle-summary-function
612                                   found nil t)))))
613         (require 'eldoc)
614         (unless (and str (boundp 'eldoc-echo-area-use-multiline-p)
615                      eldoc-echo-area-use-multiline-p)
616           (let ((w (1- (window-width (minibuffer-window)))))
617             (if (> (length str) w)
618                 (setq str (substring str 0 w)))))
619         (eldoc-message str))))
620
621 (semantic-alias-obsolete 'semantic-summary-mode
622                          'semantic-idle-summary-mode)
623 (semantic-alias-obsolete 'global-semantic-summary-mode
624                          'global-semantic-idle-summary-mode)
625 \f
626 ;;; Completion Popup Mode
627 ;;
628 ;; This mode uses tooltips to display a (hopefully) short list of possible
629 ;; completions available for the text under point.  It provides
630 ;; NO provision for actually filling in the values from those completions.
631
632 (defun semantic-idle-completion-list-default ()
633   "Calculate and display a list of completions."
634   (if (or (not (featurep 'tooltip)) tooltip-use-echo-area)
635       ;; If tooltips aren't available, turn this off.
636       (global-semantic-idle-completions-mode -1)
637     (when (semantic-idle-summary-useful-context-p)
638       ;; This mode can be fragile.  Ignore problems.
639       ;; If something doesn't do what you expect, run
640       ;; the below command by hand instead.
641       (condition-case nil
642           (progn
643             (semantic-complete-analyze-inline)
644             (when (semantic-completion-inline-active-p)
645               (semantic-complete-inline-force-display)))
646         (error nil))
647       )))
648
649 (define-semantic-idle-service semantic-idle-completions
650   "Display a list of possible completions in a tooltip."
651   ;; Add the ability to override sometime.
652   (semantic-idle-completion-list-default))
653
654 (provide 'semantic-idle)
655
656 ;;; semantic-idle.el ends here