* cedet/ede/system.el (ede-upload-html-documentation)
[bpt/emacs.git] / lisp / cedet / semantic / util-modes.el
1 ;;; semantic/util-modes.el --- Semantic minor modes
2
3 ;;; Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2007, 2008, 2009
4 ;;; Free Software Foundation, Inc.
5
6 ;; Authors: Eric M. Ludlam <zappo@gnu.org>
7 ;; David Ponce <david@dponce.com>
8 ;; Keywords: syntax
9
10 ;; This file is part of GNU Emacs.
11
12 ;; GNU Emacs is free software: you can redistribute it and/or modify
13 ;; it under the terms of the GNU General Public License as published by
14 ;; the Free Software Foundation, either version 3 of the License, or
15 ;; (at your option) any later version.
16
17 ;; GNU Emacs is distributed in the hope that it will be useful,
18 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
19 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 ;; GNU General Public License for more details.
21
22 ;; You should have received a copy of the GNU General Public License
23 ;; along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>.
24
25 ;;; Commentary:
26 ;;
27 ;; Semantic utility minor modes.
28 ;;
29
30 ;;; Code:
31 (require 'semantic)
32
33 (eval-when-compile
34 (require 'semantic/decorate)
35 )
36
37 ;;; Compatibility
38 (if (fboundp 'propertize)
39 (defalias 'semantic-propertize 'propertize)
40 (defsubst semantic-propertize (string &rest properties)
41 "Return a copy of STRING with text properties added.
42 Dummy implementation for compatibility which just return STRING and
43 ignore PROPERTIES."
44 string)
45 )
46
47 ;;; Group for all semantic enhancing modes
48 (defgroup semantic-modes nil
49 "Minor modes associated with the Semantic architecture."
50 :group 'semantic)
51
52 ;;;;
53 ;;;; Semantic minor modes stuff
54 ;;;;
55 (defcustom semantic-update-mode-line t
56 "*If non-nil, show enabled minor modes in the mode line.
57 Only minor modes that are not turned on globally are shown in the mode
58 line."
59 :group 'semantic
60 :type 'boolean
61 :require 'semantic/util-modes
62 :initialize 'custom-initialize-default
63 :set (lambda (sym val)
64 (set-default sym val)
65 ;; Update status of all Semantic enabled buffers
66 (semantic-map-buffers
67 #'semantic-mode-line-update)))
68
69 (defcustom semantic-mode-line-prefix
70 (semantic-propertize "S" 'face 'bold)
71 "*Prefix added to minor mode indicators in the mode line."
72 :group 'semantic
73 :type 'string
74 :require 'semantic/util-modes
75 :initialize 'custom-initialize-default)
76
77 (defvar semantic-minor-modes-status nil
78 "String showing Semantic minor modes which are locally enabled.
79 It is displayed in the mode line.")
80 (make-variable-buffer-local 'semantic-minor-modes-status)
81
82 (defvar semantic-minor-mode-alist nil
83 "Alist saying how to show Semantic minor modes in the mode line.
84 Like variable `minor-mode-alist'.")
85
86 (defun semantic-mode-line-update ()
87 "Update display of Semantic minor modes in the mode line.
88 Only minor modes that are locally enabled are shown in the mode line."
89 (setq semantic-minor-modes-status nil)
90 (if semantic-update-mode-line
91 (let ((ml semantic-minor-mode-alist)
92 mm ms see)
93 (while ml
94 (setq mm (car ml)
95 ms (cadr mm)
96 mm (car mm)
97 ml (cdr ml))
98 (when (and (symbol-value mm)
99 ;; Only show local minor mode status
100 (not (memq mm semantic-init-hook)))
101 (and ms
102 (symbolp ms)
103 (setq ms (symbol-value ms)))
104 (and (stringp ms)
105 (not (member ms see)) ;; Don't duplicate same status
106 (setq see (cons ms see)
107 ms (if (string-match "^[ ]*\\(.+\\)" ms)
108 (match-string 1 ms)))
109 (setq semantic-minor-modes-status
110 (if semantic-minor-modes-status
111 (concat semantic-minor-modes-status "/" ms)
112 ms)))))
113 (if semantic-minor-modes-status
114 (setq semantic-minor-modes-status
115 (concat
116 " "
117 (if (string-match "^[ ]*\\(.+\\)"
118 semantic-mode-line-prefix)
119 (match-string 1 semantic-mode-line-prefix)
120 "S")
121 "/"
122 semantic-minor-modes-status))))))
123
124 (defun semantic-desktop-ignore-this-minor-mode (buffer)
125 "Installed as a minor-mode initializer for Desktop mode.
126 BUFFER is the buffer to not initialize a Semantic minor mode in."
127 nil)
128
129 (defun semantic-add-minor-mode (toggle name &optional keymap)
130 "Register a new Semantic minor mode.
131 TOGGLE is a symbol which is the name of a buffer-local variable that
132 is toggled on or off to say whether the minor mode is active or not.
133 It is also an interactive function to toggle the mode.
134
135 NAME specifies what will appear in the mode line when the minor mode
136 is active. NAME should be either a string starting with a space, or a
137 symbol whose value is such a string.
138
139 Optional KEYMAP is the keymap for the minor mode that will be added to
140 `minor-mode-map-alist'."
141 ;; Add a dymmy semantic minor mode to display the status
142 (or (assq 'semantic-minor-modes-status minor-mode-alist)
143 (setq minor-mode-alist (cons (list 'semantic-minor-modes-status
144 'semantic-minor-modes-status)
145 minor-mode-alist)))
146 (if (fboundp 'add-minor-mode)
147 ;; Emacs 21 & XEmacs
148 (add-minor-mode toggle "" keymap)
149 ;; Emacs 20
150 (or (assq toggle minor-mode-alist)
151 (setq minor-mode-alist (cons (list toggle "") minor-mode-alist)))
152 (or (not keymap)
153 (assq toggle minor-mode-map-alist)
154 (setq minor-mode-map-alist (cons (cons toggle keymap)
155 minor-mode-map-alist))))
156 ;; Record how to display this minor mode in the mode line
157 (let ((mm (assq toggle semantic-minor-mode-alist)))
158 (if mm
159 (setcdr mm (list name))
160 (setq semantic-minor-mode-alist (cons (list toggle name)
161 semantic-minor-mode-alist))))
162
163 ;; Semantic minor modes don't work w/ Desktop restore.
164 ;; This line will disable this minor mode from being restored
165 ;; by Desktop.
166 (when (boundp 'desktop-minor-mode-handlers)
167 (add-to-list 'desktop-minor-mode-handlers
168 (cons toggle 'semantic-desktop-ignore-this-minor-mode)))
169 )
170
171 (defun semantic-toggle-minor-mode-globally (mode &optional arg)
172 "Toggle minor mode MODE in every Semantic enabled buffer.
173 Return non-nil if MODE is turned on in every Semantic enabled buffer.
174 If ARG is positive, enable, if it is negative, disable. If ARG is
175 nil, then toggle. Otherwise do nothing. MODE must be a valid minor
176 mode defined in `minor-mode-alist' and must be too an interactive
177 function used to toggle the mode."
178 (or (and (fboundp mode) (assq mode minor-mode-alist))
179 (error "Semantic minor mode %s not found" mode))
180 (if (not arg)
181 (if (memq mode semantic-init-hook)
182 (setq arg -1)
183 (setq arg 1)))
184 ;; Add or remove the MODE toggle function from
185 ;; `semantic-init-hook'. Then turn MODE on or off in every
186 ;; Semantic enabled buffer.
187 (cond
188 ;; Turn off if ARG < 0
189 ((< arg 0)
190 (remove-hook 'semantic-init-hook mode)
191 (semantic-map-buffers #'(lambda () (funcall mode -1)))
192 nil)
193 ;; Turn on if ARG > 0
194 ((> arg 0)
195 (add-hook 'semantic-init-hook mode)
196 (semantic-map-buffers #'(lambda () (funcall mode 1)))
197 t)
198 ;; Otherwise just check MODE state
199 (t
200 (memq mode semantic-init-hook))
201 ))
202 \f
203 ;;;;
204 ;;;; Minor mode to highlight areas that a user edits.
205 ;;;;
206
207 ;;;###autoload
208 (defun global-semantic-highlight-edits-mode (&optional arg)
209 "Toggle global use of option `semantic-highlight-edits-mode'.
210 If ARG is positive, enable, if it is negative, disable.
211 If ARG is nil, then toggle."
212 (interactive "P")
213 (setq global-semantic-highlight-edits-mode
214 (semantic-toggle-minor-mode-globally
215 'semantic-highlight-edits-mode arg)))
216
217 ;;;###autoload
218 (defcustom global-semantic-highlight-edits-mode nil
219 "*If non-nil enable global use of variable `semantic-highlight-edits-mode'.
220 When this mode is enabled, changes made to a buffer are highlighted
221 until the buffer is reparsed."
222 :group 'semantic
223 :group 'semantic-modes
224 :type 'boolean
225 :require 'semantic/util-modes
226 :initialize 'custom-initialize-default
227 :set (lambda (sym val)
228 (global-semantic-highlight-edits-mode (if val 1 -1))))
229
230 (defcustom semantic-highlight-edits-mode-hook nil
231 "*Hook run at the end of function `semantic-highlight-edits-mode'."
232 :group 'semantic
233 :type 'hook)
234
235 (defface semantic-highlight-edits-face
236 '((((class color) (background dark))
237 ;; Put this back to something closer to black later.
238 (:background "gray20"))
239 (((class color) (background light))
240 (:background "gray90")))
241 "*Face used to show dirty tokens in `semantic-highlight-edits-mode'."
242 :group 'semantic-faces)
243
244 (defun semantic-highlight-edits-new-change-hook-fcn (overlay)
245 "Function set into `semantic-edits-new-change-hook'.
246 Argument OVERLAY is the overlay created to mark the change.
247 This function will set the face property on this overlay."
248 (semantic-overlay-put overlay 'face 'semantic-highlight-edits-face))
249
250 (defvar semantic-highlight-edits-mode-map
251 (let ((km (make-sparse-keymap)))
252 km)
253 "Keymap for highlight-edits minor mode.")
254
255 (defvar semantic-highlight-edits-mode nil
256 "Non-nil if highlight-edits minor mode is enabled.
257 Use the command `semantic-highlight-edits-mode' to change this variable.")
258 (make-variable-buffer-local 'semantic-highlight-edits-mode)
259
260 (defun semantic-highlight-edits-mode-setup ()
261 "Setup option `semantic-highlight-edits-mode'.
262 The minor mode can be turned on only if semantic feature is available
263 and the current buffer was set up for parsing. When minor mode is
264 enabled parse the current buffer if needed. Return non-nil if the
265 minor mode is enabled."
266 (if semantic-highlight-edits-mode
267 (if (not (and (featurep 'semantic) (semantic-active-p)))
268 (progn
269 ;; Disable minor mode if semantic stuff not available
270 (setq semantic-highlight-edits-mode nil)
271 (error "Buffer %s was not set up for parsing"
272 (buffer-name)))
273 (semantic-make-local-hook 'semantic-edits-new-change-hooks)
274 (add-hook 'semantic-edits-new-change-hooks
275 'semantic-highlight-edits-new-change-hook-fcn nil t)
276 )
277 ;; Remove hooks
278 (remove-hook 'semantic-edits-new-change-hooks
279 'semantic-highlight-edits-new-change-hook-fcn t)
280 )
281 semantic-highlight-edits-mode)
282
283 ;;;###autoload
284 (defun semantic-highlight-edits-mode (&optional arg)
285 "Minor mode for highlighting changes made in a buffer.
286 Changes are tracked by semantic so that the incremental parser can work
287 properly.
288 This mode will highlight those changes as they are made, and clear them
289 when the incremental parser accounts for those edits.
290 With prefix argument ARG, turn on if positive, otherwise off. The
291 minor mode can be turned on only if semantic feature is available and
292 the current buffer was set up for parsing. Return non-nil if the
293 minor mode is enabled."
294 (interactive
295 (list (or current-prefix-arg
296 (if semantic-highlight-edits-mode 0 1))))
297 (setq semantic-highlight-edits-mode
298 (if arg
299 (>
300 (prefix-numeric-value arg)
301 0)
302 (not semantic-highlight-edits-mode)))
303 (semantic-highlight-edits-mode-setup)
304 (run-hooks 'semantic-highlight-edits-mode-hook)
305 (if (interactive-p)
306 (message "highlight-edits minor mode %sabled"
307 (if semantic-highlight-edits-mode "en" "dis")))
308 (semantic-mode-line-update)
309 semantic-highlight-edits-mode)
310
311 (semantic-add-minor-mode 'semantic-highlight-edits-mode
312 "e"
313 semantic-highlight-edits-mode-map)
314
315 \f
316 ;;;;
317 ;;;; Minor mode to show unmatched-syntax elements
318 ;;;;
319
320 ;;;###autoload
321 (defun global-semantic-show-unmatched-syntax-mode (&optional arg)
322 "Toggle global use of option `semantic-show-unmatched-syntax-mode'.
323 If ARG is positive, enable, if it is negative, disable.
324 If ARG is nil, then toggle."
325 (interactive "P")
326 (setq global-semantic-show-unmatched-syntax-mode
327 (semantic-toggle-minor-mode-globally
328 'semantic-show-unmatched-syntax-mode arg)))
329
330 ;;;###autoload
331 (defcustom global-semantic-show-unmatched-syntax-mode nil
332 "*If non-nil, enable global use of `semantic-show-unmatched-syntax-mode'.
333 When this mode is enabled, syntax in the current buffer which the
334 semantic parser cannot match is highlighted with a red underline."
335 :group 'semantic
336 :group 'semantic-modes
337 :type 'boolean
338 :require 'semantic/util-modes
339 :initialize 'custom-initialize-default
340 :set (lambda (sym val)
341 (global-semantic-show-unmatched-syntax-mode (if val 1 -1))))
342
343 (defcustom semantic-show-unmatched-syntax-mode-hook nil
344 "*Hook run at the end of function `semantic-show-unmatched-syntax-mode'."
345 :group 'semantic
346 :type 'hook)
347
348 (defface semantic-unmatched-syntax-face
349 '((((class color) (background dark))
350 (:underline "red"))
351 (((class color) (background light))
352 (:underline "red")))
353 "*Face used to show unmatched syntax in.
354 The face is used in `semantic-show-unmatched-syntax-mode'."
355 :group 'semantic-faces)
356
357 (defsubst semantic-unmatched-syntax-overlay-p (overlay)
358 "Return non-nil if OVERLAY is an unmatched syntax one."
359 (eq (semantic-overlay-get overlay 'semantic) 'unmatched))
360
361 (defun semantic-showing-unmatched-syntax-p ()
362 "Return non-nil if an unmatched syntax overlay was found in buffer."
363 (let ((ol (semantic-overlays-in (point-min) (point-max)))
364 found)
365 (while (and ol (not found))
366 (setq found (semantic-unmatched-syntax-overlay-p (car ol))
367 ol (cdr ol)))
368 found))
369
370 (defun semantic-show-unmatched-lex-tokens-fetch ()
371 "Fetch a list of unmatched lexical tokens from the current buffer.
372 Uses the overlays which have accurate bounds, and rebuilds what was
373 originally passed in."
374 (let ((ol (semantic-overlays-in (point-min) (point-max)))
375 (ustc nil))
376 (while ol
377 (if (semantic-unmatched-syntax-overlay-p (car ol))
378 (setq ustc (cons (cons 'thing
379 (cons (semantic-overlay-start (car ol))
380 (semantic-overlay-end (car ol))))
381 ustc)))
382 (setq ol (cdr ol)))
383 (nreverse ustc))
384 )
385
386 (defun semantic-clean-unmatched-syntax-in-region (beg end)
387 "Remove all unmatched syntax overlays between BEG and END."
388 (let ((ol (semantic-overlays-in beg end)))
389 (while ol
390 (if (semantic-unmatched-syntax-overlay-p (car ol))
391 (semantic-overlay-delete (car ol)))
392 (setq ol (cdr ol)))))
393
394 (defsubst semantic-clean-unmatched-syntax-in-buffer ()
395 "Remove all unmatched syntax overlays found in current buffer."
396 (semantic-clean-unmatched-syntax-in-region
397 (point-min) (point-max)))
398
399 (defsubst semantic-clean-token-of-unmatched-syntax (token)
400 "Clean the area covered by TOKEN of unmatched syntax markers."
401 (semantic-clean-unmatched-syntax-in-region
402 (semantic-tag-start token) (semantic-tag-end token)))
403
404 (defun semantic-show-unmatched-syntax (syntax)
405 "Function set into `semantic-unmatched-syntax-hook'.
406 This will highlight elements in SYNTAX as unmatched syntax."
407 ;; This is called when `semantic-show-unmatched-syntax-mode' is
408 ;; enabled. Highlight the unmatched syntax, and then add a semantic
409 ;; property to that overlay so we can add it to the official list of
410 ;; semantic supported overlays. This gets it cleaned up for errors,
411 ;; buffer cleaning, and the like.
412 (semantic-clean-unmatched-syntax-in-buffer) ;Clear previous highlighting
413 (if syntax
414 (let (o)
415 (while syntax
416 (setq o (semantic-make-overlay (semantic-lex-token-start (car syntax))
417 (semantic-lex-token-end (car syntax))))
418 (semantic-overlay-put o 'semantic 'unmatched)
419 (semantic-overlay-put o 'face 'semantic-unmatched-syntax-face)
420 (setq syntax (cdr syntax))))
421 ))
422
423 (defun semantic-next-unmatched-syntax (point &optional bound)
424 "Find the next overlay for unmatched syntax after POINT.
425 Do not search past BOUND if non-nil."
426 (save-excursion
427 (goto-char point)
428 (let ((os point) (ol nil))
429 (while (and os (< os (or bound (point-max))) (not ol))
430 (setq os (semantic-overlay-next-change os))
431 (when os
432 ;; Get overlays at position
433 (setq ol (semantic-overlays-at os))
434 ;; find the overlay that belongs to semantic
435 ;; and starts at the found position.
436 (while (and ol (listp ol))
437 (and (semantic-unmatched-syntax-overlay-p (car ol))
438 (setq ol (car ol)))
439 (if (listp ol)
440 (setq ol (cdr ol))))))
441 ol)))
442
443 (defvar semantic-show-unmatched-syntax-mode-map
444 (let ((km (make-sparse-keymap)))
445 (define-key km "\C-c,`" 'semantic-show-unmatched-syntax-next)
446 km)
447 "Keymap for command `semantic-show-unmatched-syntax-mode'.")
448
449 (defvar semantic-show-unmatched-syntax-mode nil
450 "Non-nil if show-unmatched-syntax minor mode is enabled.
451 Use the command `semantic-show-unmatched-syntax-mode' to change this
452 variable.")
453 (make-variable-buffer-local 'semantic-show-unmatched-syntax-mode)
454
455 (defun semantic-show-unmatched-syntax-mode-setup ()
456 "Setup the `semantic-show-unmatched-syntax' minor mode.
457 The minor mode can be turned on only if semantic feature is available
458 and the current buffer was set up for parsing. When minor mode is
459 enabled parse the current buffer if needed. Return non-nil if the
460 minor mode is enabled."
461 (if semantic-show-unmatched-syntax-mode
462 (if (not (and (featurep 'semantic) (semantic-active-p)))
463 (progn
464 ;; Disable minor mode if semantic stuff not available
465 (setq semantic-show-unmatched-syntax-mode nil)
466 (error "Buffer %s was not set up for parsing"
467 (buffer-name)))
468 ;; Add hooks
469 (semantic-make-local-hook 'semantic-unmatched-syntax-hook)
470 (add-hook 'semantic-unmatched-syntax-hook
471 'semantic-show-unmatched-syntax nil t)
472 (semantic-make-local-hook 'semantic-pre-clean-token-hooks)
473 (add-hook 'semantic-pre-clean-token-hooks
474 'semantic-clean-token-of-unmatched-syntax nil t)
475 ;; Show unmatched syntax elements
476 (if (not (semantic--umatched-syntax-needs-refresh-p))
477 (semantic-show-unmatched-syntax
478 (semantic-unmatched-syntax-tokens))))
479 ;; Remove hooks
480 (remove-hook 'semantic-unmatched-syntax-hook
481 'semantic-show-unmatched-syntax t)
482 (remove-hook 'semantic-pre-clean-token-hooks
483 'semantic-clean-token-of-unmatched-syntax t)
484 ;; Cleanup unmatched-syntax highlighting
485 (semantic-clean-unmatched-syntax-in-buffer))
486 semantic-show-unmatched-syntax-mode)
487
488 ;;;###autoload
489 (defun semantic-show-unmatched-syntax-mode (&optional arg)
490 "Minor mode to highlight unmatched lexical syntax tokens.
491 When a parser executes, some elements in the buffer may not match any
492 parser rules. These text characters are considered unmatched syntax.
493 Often time, the display of unmatched syntax can expose coding
494 problems before the compiler is run.
495
496 With prefix argument ARG, turn on if positive, otherwise off. The
497 minor mode can be turned on only if semantic feature is available and
498 the current buffer was set up for parsing. Return non-nil if the
499 minor mode is enabled.
500
501 \\{semantic-show-unmatched-syntax-mode-map}"
502 (interactive
503 (list (or current-prefix-arg
504 (if semantic-show-unmatched-syntax-mode 0 1))))
505 (setq semantic-show-unmatched-syntax-mode
506 (if arg
507 (>
508 (prefix-numeric-value arg)
509 0)
510 (not semantic-show-unmatched-syntax-mode)))
511 (semantic-show-unmatched-syntax-mode-setup)
512 (run-hooks 'semantic-show-unmatched-syntax-mode-hook)
513 (if (interactive-p)
514 (message "show-unmatched-syntax minor mode %sabled"
515 (if semantic-show-unmatched-syntax-mode "en" "dis")))
516 (semantic-mode-line-update)
517 semantic-show-unmatched-syntax-mode)
518
519 (semantic-add-minor-mode 'semantic-show-unmatched-syntax-mode
520 "u"
521 semantic-show-unmatched-syntax-mode-map)
522
523 (defun semantic-show-unmatched-syntax-next ()
524 "Move forward to the next occurrence of unmatched syntax."
525 (interactive)
526 (let ((o (semantic-next-unmatched-syntax (point))))
527 (if o
528 (goto-char (semantic-overlay-start o)))))
529
530 \f
531 ;;;;
532 ;;;; Minor mode to display the parser state in the modeline.
533 ;;;;
534
535 ;;;###autoload
536 (defcustom global-semantic-show-parser-state-mode nil
537 "*If non-nil enable global use of `semantic-show-parser-state-mode'.
538 When enabled, the current parse state of the current buffer is displayed
539 in the mode line. See `semantic-show-parser-state-marker' for details
540 on what is displayed."
541 :group 'semantic
542 :type 'boolean
543 :require 'semantic/util-modes
544 :initialize 'custom-initialize-default
545 :set (lambda (sym val)
546 (global-semantic-show-parser-state-mode (if val 1 -1))))
547
548 ;;;###autoload
549 (defun global-semantic-show-parser-state-mode (&optional arg)
550 "Toggle global use of option `semantic-show-parser-state-mode'.
551 If ARG is positive, enable, if it is negative, disable.
552 If ARG is nil, then toggle."
553 (interactive "P")
554 (setq global-semantic-show-parser-state-mode
555 (semantic-toggle-minor-mode-globally
556 'semantic-show-parser-state-mode arg)))
557
558 (defcustom semantic-show-parser-state-mode-hook nil
559 "*Hook run at the end of function `semantic-show-parser-state-mode'."
560 :group 'semantic
561 :type 'hook)
562
563 (defvar semantic-show-parser-state-mode-map
564 (let ((km (make-sparse-keymap)))
565 km)
566 "Keymap for show-parser-state minor mode.")
567
568 (defvar semantic-show-parser-state-mode nil
569 "Non-nil if show-parser-state minor mode is enabled.
570 Use the command `semantic-show-parser-state-mode' to change this variable.")
571 (make-variable-buffer-local 'semantic-show-parser-state-mode)
572
573 (defun semantic-show-parser-state-mode-setup ()
574 "Setup option `semantic-show-parser-state-mode'.
575 The minor mode can be turned on only if semantic feature is available
576 and the current buffer was set up for parsing. When minor mode is
577 enabled parse the current buffer if needed. Return non-nil if the
578 minor mode is enabled."
579 (if semantic-show-parser-state-mode
580 (if (not (and (featurep 'semantic) (semantic-active-p)))
581 (progn
582 ;; Disable minor mode if semantic stuff not available
583 (setq semantic-show-parser-state-mode nil)
584 (error "Buffer %s was not set up for parsing"
585 (buffer-name)))
586 ;; Set up mode line
587
588 (when (not
589 (memq 'semantic-show-parser-state-string mode-line-modified))
590 (setq mode-line-modified
591 (append mode-line-modified
592 '(semantic-show-parser-state-string))))
593 ;; Add hooks
594 (semantic-make-local-hook 'semantic-edits-new-change-hooks)
595 (add-hook 'semantic-edits-new-change-hooks
596 'semantic-show-parser-state-marker nil t)
597 (semantic-make-local-hook 'semantic-edits-incremental-reparse-failed-hook)
598 (add-hook 'semantic-edits-incremental-reparse-failed-hook
599 'semantic-show-parser-state-marker nil t)
600 (semantic-make-local-hook 'semantic-after-partial-cache-change-hook)
601 (add-hook 'semantic-after-partial-cache-change-hook
602 'semantic-show-parser-state-marker nil t)
603 (semantic-make-local-hook 'semantic-after-toplevel-cache-change-hook)
604 (add-hook 'semantic-after-toplevel-cache-change-hook
605 'semantic-show-parser-state-marker nil t)
606 (semantic-show-parser-state-marker)
607
608 (semantic-make-local-hook 'semantic-before-auto-parse-hooks)
609 (add-hook 'semantic-before-auto-parse-hooks
610 'semantic-show-parser-state-auto-marker nil t)
611 (semantic-make-local-hook 'semantic-after-auto-parse-hooks)
612 (add-hook 'semantic-after-auto-parse-hooks
613 'semantic-show-parser-state-marker nil t)
614
615 (semantic-make-local-hook 'semantic-before-idle-scheduler-reparse-hook)
616 (add-hook 'semantic-before-idle-scheduler-reparse-hook
617 'semantic-show-parser-state-auto-marker nil t)
618 (semantic-make-local-hook 'semantic-after-idle-scheduler-reparse-hook)
619 (add-hook 'semantic-after-idle-scheduler-reparse-hook
620 'semantic-show-parser-state-marker nil t)
621 )
622 ;; Remove parts of mode line
623 (setq mode-line-modified
624 (delq 'semantic-show-parser-state-string mode-line-modified))
625 ;; Remove hooks
626 (remove-hook 'semantic-edits-new-change-hooks
627 'semantic-show-parser-state-marker t)
628 (remove-hook 'semantic-edits-incremental-reparse-failed-hook
629 'semantic-show-parser-state-marker t)
630 (remove-hook 'semantic-after-partial-cache-change-hook
631 'semantic-show-parser-state-marker t)
632 (remove-hook 'semantic-after-toplevel-cache-change-hook
633 'semantic-show-parser-state-marker t)
634
635 (remove-hook 'semantic-before-auto-parse-hooks
636 'semantic-show-parser-state-auto-marker t)
637 (remove-hook 'semantic-after-auto-parse-hooks
638 'semantic-show-parser-state-marker t)
639
640 (remove-hook 'semantic-before-idle-scheduler-reparse-hook
641 'semantic-show-parser-state-auto-marker t)
642 (remove-hook 'semantic-after-idle-scheduler-reparse-hook
643 'semantic-show-parser-state-marker t)
644 )
645 semantic-show-parser-state-mode)
646
647 ;;;###autoload
648 (defun semantic-show-parser-state-mode (&optional arg)
649 "Minor mode for displaying parser cache state in the modeline.
650 The cache can be in one of three states. They are
651 Up to date, Partial reprase needed, and Full reparse needed.
652 The state is indicated in the modeline with the following characters:
653 `-' -> The cache is up to date.
654 `!' -> The cache requires a full update.
655 `~' -> The cache needs to be incrementally parsed.
656 `%' -> The cache is not currently parseable.
657 `@' -> Auto-parse in progress (not set here.)
658 With prefix argument ARG, turn on if positive, otherwise off. The
659 minor mode can be turned on only if semantic feature is available and
660 the current buffer was set up for parsing. Return non-nil if the
661 minor mode is enabled."
662 (interactive
663 (list (or current-prefix-arg
664 (if semantic-show-parser-state-mode 0 1))))
665 (setq semantic-show-parser-state-mode
666 (if arg
667 (>
668 (prefix-numeric-value arg)
669 0)
670 (not semantic-show-parser-state-mode)))
671 (semantic-show-parser-state-mode-setup)
672 (run-hooks 'semantic-show-parser-state-mode-hook)
673 (if (interactive-p)
674 (message "show-parser-state minor mode %sabled"
675 (if semantic-show-parser-state-mode "en" "dis")))
676 (semantic-mode-line-update)
677 semantic-show-parser-state-mode)
678
679 (semantic-add-minor-mode 'semantic-show-parser-state-mode
680 ""
681 semantic-show-parser-state-mode-map)
682
683 (defvar semantic-show-parser-state-string nil
684 "String showing the parser state for this buffer.
685 See `semantic-show-parser-state-marker' for details.")
686 (make-variable-buffer-local 'semantic-show-parser-state-string)
687
688 (defun semantic-show-parser-state-marker (&rest ignore)
689 "Set `semantic-show-parser-state-string' to indicate parser state.
690 This marker is one of the following:
691 `-' -> The cache is up to date.
692 `!' -> The cache requires a full update.
693 `~' -> The cache needs to be incrementally parsed.
694 `%' -> The cache is not currently parseable.
695 `@' -> Auto-parse in progress (not set here.)
696 Arguments IGNORE are ignored, and accepted so this can be used as a hook
697 in many situations."
698 (setq semantic-show-parser-state-string
699 (cond ((semantic-parse-tree-needs-rebuild-p)
700 "!")
701 ((semantic-parse-tree-needs-update-p)
702 "^")
703 ((semantic-parse-tree-unparseable-p)
704 "%")
705 (t
706 "-")))
707 ;;(message "Setup mode line indicator to [%s]" semantic-show-parser-state-string)
708 (semantic-mode-line-update))
709
710 (defun semantic-show-parser-state-auto-marker ()
711 "Hook function run before an autoparse.
712 Set up `semantic-show-parser-state-marker' to show `@'
713 to indicate a parse in progress."
714 (unless (semantic-parse-tree-up-to-date-p)
715 (setq semantic-show-parser-state-string "@")
716 (semantic-mode-line-update)
717 ;; For testing.
718 ;;(sit-for 1)
719 ))
720
721 \f
722 ;;;;
723 ;;;; Minor mode to make function decls sticky.
724 ;;;;
725
726 ;;;###autoload
727 (defun global-semantic-stickyfunc-mode (&optional arg)
728 "Toggle global use of option `semantic-stickyfunc-mode'.
729 If ARG is positive, enable, if it is negative, disable.
730 If ARG is nil, then toggle."
731 (interactive "P")
732 (setq global-semantic-stickyfunc-mode
733 (semantic-toggle-minor-mode-globally
734 'semantic-stickyfunc-mode arg)))
735
736 ;;;###autoload
737 (defcustom global-semantic-stickyfunc-mode nil
738 "*If non-nil, enable global use of `semantic-stickyfunc-mode'.
739 This minor mode only works for Emacs 21 or later.
740 When enabled, the header line is enabled, and the first line
741 of the current function or method is displayed in it.
742 This makes it appear that the first line of that tag is
743 `sticky' to the top of the window."
744 :group 'semantic
745 :group 'semantic-modes
746 :type 'boolean
747 :require 'semantic/util-modes
748 :initialize 'custom-initialize-default
749 :set (lambda (sym val)
750 (global-semantic-stickyfunc-mode (if val 1 -1))))
751
752 (defcustom semantic-stickyfunc-mode-hook nil
753 "*Hook run at the end of function `semantic-stickyfunc-mode'."
754 :group 'semantic
755 :type 'hook)
756
757 (defvar semantic-stickyfunc-mode-map
758 (let ((km (make-sparse-keymap)))
759 (define-key km [ header-line down-mouse-1 ] 'semantic-stickyfunc-menu)
760 km)
761 "Keymap for stickyfunc minor mode.")
762
763 (defvar semantic-stickyfunc-popup-menu nil
764 "Menu used if the user clicks on the header line used by stickyfunc mode.")
765
766 (easy-menu-define
767 semantic-stickyfunc-popup-menu
768 semantic-stickyfunc-mode-map
769 "Stickyfunc Menu"
770 '("Stickyfunc Mode" :visible (progn nil)
771 [ "Copy Headerline Tag" senator-copy-tag
772 :active (semantic-current-tag)
773 :help "Copy the current tag to the tag ring"]
774 [ "Kill Headerline Tag" senator-kill-tag
775 :active (semantic-current-tag)
776 :help "Kill tag text to the kill ring, and copy the tag to the tag ring"
777 ]
778 [ "Copy Headerline Tag to Register" senator-copy-tag-to-register
779 :active (semantic-current-tag)
780 :help "Copy the current tag to a register"
781 ]
782 [ "Narrow To Headerline Tag" senator-narrow-to-defun
783 :active (semantic-current-tag)
784 :help "Narrow to the bounds of the current tag."]
785 [ "Fold Headerline Tag" senator-fold-tag-toggle
786 :active (semantic-current-tag)
787 :style toggle
788 :selected (let ((tag (semantic-current-tag)))
789 (and tag (semantic-tag-folded-p tag)))
790 :help "Fold the current tag to one line"
791 ]
792 "---"
793 [ "About This Header Line"
794 (lambda () (interactive)
795 (describe-function 'semantic-stickyfunc-mode)) t])
796 )
797
798 (defvar semantic-stickyfunc-mode nil
799 "Non-nil if stickyfunc minor mode is enabled.
800 Use the command `semantic-stickyfunc-mode' to change this variable.")
801 (make-variable-buffer-local 'semantic-stickyfunc-mode)
802
803 (defcustom semantic-stickyfunc-indent-string
804 (if (and window-system (not (featurep 'xemacs)))
805 (concat
806 (condition-case nil
807 ;; Test scroll bar location
808 (let ((charwidth (frame-char-width))
809 (scrollpos (frame-parameter (selected-frame)
810 'vertical-scroll-bars))
811 )
812 (if (or (eq scrollpos 'left)
813 ;; Now wait a minute. If you turn scroll-bar-mode
814 ;; on, then off, the new value is t, not left.
815 ;; Will this mess up older emacs where the default
816 ;; was on the right? I don't think so since they don't
817 ;; support a header line.
818 (eq scrollpos t))
819 (let ((w (when (boundp 'scroll-bar-width)
820 (symbol-value 'scroll-bar-width))))
821
822 (if (not w)
823 (setq w (frame-parameter (selected-frame)
824 'scroll-bar-width)))
825
826 ;; in 21.2, the frame parameter is sometimes empty
827 ;; so we need to get the value here.
828 (if (not w)
829 (setq w (+ (get 'scroll-bar-width 'x-frame-parameter)
830 ;; In 21.4, or perhaps 22.1 the x-frame
831 ;; parameter is different from the frame
832 ;; parameter by only 1 pixel.
833 1)))
834
835 (if (not w)
836 " "
837 (setq w (+ 2 w)) ; Some sort of border around
838 ; the scrollbar.
839 (make-string (/ w charwidth) ? )))
840 ""))
841 (error ""))
842 (condition-case nil
843 ;; Test fringe size.
844 (let* ((f (window-fringes))
845 (fw (car f))
846 (numspace (/ fw (frame-char-width)))
847 )
848 (make-string numspace ? ))
849 (error
850 ;; Well, the fancy new Emacs functions failed. Try older
851 ;; tricks.
852 (condition-case nil
853 ;; I'm not so sure what's up with the 21.1-21.3 fringe.
854 ;; It looks to be about 1 space wide.
855 (if (get 'fringe 'face)
856 " "
857 "")
858 (error ""))))
859 )
860 ;; Not Emacs or a window system means no scrollbar or fringe,
861 ;; and perhaps not even a header line to worry about.
862 "")
863 "*String used to indent the stickyfunc header.
864 Customize this string to match the space used by scrollbars and
865 fringe so it does not appear that the code is moving left/right
866 when it lands in the sticky line."
867 :group 'semantic
868 :type 'string)
869
870 (defvar semantic-stickyfunc-old-hlf nil
871 "Value of the header line when entering sticky func mode.")
872
873 (defconst semantic-stickyfunc-header-line-format
874 (cond ((featurep 'xemacs)
875 nil)
876 ((>= emacs-major-version 22)
877 '(:eval (list
878 ;; Magic bit I found on emacswiki.
879 (propertize " " 'display '((space :align-to 0)))
880 (semantic-stickyfunc-fetch-stickyline))))
881 ((= emacs-major-version 21)
882 '(:eval (list semantic-stickyfunc-indent-string
883 (semantic-stickyfunc-fetch-stickyline))))
884 (t nil))
885 "The header line format used by sticky func mode.")
886
887 (defun semantic-stickyfunc-mode-setup ()
888 "Setup option `semantic-stickyfunc-mode'.
889 For semantic enabled buffers, make the function declaration for the top most
890 function \"sticky\". This is accomplished by putting the first line of
891 text for that function in Emacs 21's header line."
892 (if semantic-stickyfunc-mode
893 (progn
894 (unless (and (featurep 'semantic) (semantic-active-p))
895 ;; Disable minor mode if semantic stuff not available
896 (setq semantic-stickyfunc-mode nil)
897 (error "Buffer %s was not set up for parsing" (buffer-name)))
898 (unless (boundp 'default-header-line-format)
899 ;; Disable if there are no header lines to use.
900 (setq semantic-stickyfunc-mode nil)
901 (error "Sticky Function mode requires Emacs 21"))
902 ;; Enable the mode
903 ;; Save previous buffer local value of header line format.
904 (when (and (local-variable-p 'header-line-format (current-buffer))
905 (not (eq header-line-format
906 semantic-stickyfunc-header-line-format)))
907 (set (make-local-variable 'semantic-stickyfunc-old-hlf)
908 header-line-format))
909 (setq header-line-format semantic-stickyfunc-header-line-format)
910 )
911 ;; Disable sticky func mode
912 ;; Restore previous buffer local value of header line format if
913 ;; the current one is the sticky func one.
914 (when (eq header-line-format semantic-stickyfunc-header-line-format)
915 (kill-local-variable 'header-line-format)
916 (when (local-variable-p 'semantic-stickyfunc-old-hlf (current-buffer))
917 (setq header-line-format semantic-stickyfunc-old-hlf)
918 (kill-local-variable 'semantic-stickyfunc-old-hlf))))
919 semantic-stickyfunc-mode)
920
921 ;;;###autoload
922 (defun semantic-stickyfunc-mode (&optional arg)
923 "Minor mode to show the title of a tag in the header line.
924 Enables/disables making the header line of functions sticky.
925 A function (or other tag class specified by
926 `semantic-stickyfunc-sticky-classes') has a header line, meaning the
927 first line which describes the rest of the construct. This first
928 line is what is displayed in the Emacs 21 header line.
929
930 With prefix argument ARG, turn on if positive, otherwise off. The
931 minor mode can be turned on only if semantic feature is available and
932 the current buffer was set up for parsing. Return non-nil if the
933 minor mode is enabled."
934 (interactive
935 (list (or current-prefix-arg
936 (if semantic-stickyfunc-mode 0 1))))
937 (setq semantic-stickyfunc-mode
938 (if arg
939 (>
940 (prefix-numeric-value arg)
941 0)
942 (not semantic-stickyfunc-mode)))
943 (semantic-stickyfunc-mode-setup)
944 (run-hooks 'semantic-stickyfunc-mode-hook)
945 (if (interactive-p)
946 (message "Stickyfunc minor mode %sabled"
947 (if semantic-stickyfunc-mode "en" "dis")))
948 (semantic-mode-line-update)
949 semantic-stickyfunc-mode)
950
951 (defvar semantic-stickyfunc-sticky-classes
952 '(function type)
953 "List of tag classes which sticky func will display in the header line.")
954 (make-variable-buffer-local 'semantic-stickyfunc-sticky-classes)
955
956 (defun semantic-stickyfunc-tag-to-stick ()
957 "Return the tag to stick at the current point."
958 (let ((tags (nreverse (semantic-find-tag-by-overlay (point)))))
959 ;; Get rid of non-matching tags.
960 (while (and tags
961 (not (member
962 (semantic-tag-class (car tags))
963 semantic-stickyfunc-sticky-classes))
964 )
965 (setq tags (cdr tags)))
966 (car tags)))
967
968 (defun semantic-stickyfunc-fetch-stickyline ()
969 "Make the function at the top of the current window sticky.
970 Capture it's function declaration, and place it in the header line.
971 If there is no function, disable the header line."
972 (let ((str
973 (save-excursion
974 (goto-char (window-start (selected-window)))
975 (forward-line -1)
976 (end-of-line)
977 ;; Capture this function
978 (let* ((tag (semantic-stickyfunc-tag-to-stick)))
979 ;; TAG is nil if there was nothing of the apropriate type there.
980 (if (not tag)
981 ;; Set it to be the text under the header line
982 (buffer-substring (point-at-bol) (point-at-eol))
983 ;; Get it
984 (goto-char (semantic-tag-start tag))
985 ;; Klaus Berndl <klaus.berndl@sdm.de>:
986 ;; goto the tag name; this is especially needed for languages
987 ;; like c++ where a often used style is like:
988 ;; void
989 ;; ClassX::methodM(arg1...)
990 ;; {
991 ;; ...
992 ;; }
993 ;; Without going to the tag-name we would get"void" in the
994 ;; header line which is IMHO not really useful
995 (search-forward (semantic-tag-name tag) nil t)
996 (buffer-substring (point-at-bol) (point-at-eol))
997 ))))
998 (start 0))
999 (while (string-match "%" str start)
1000 (setq str (replace-match "%%" t t str 0)
1001 start (1+ (match-end 0)))
1002 )
1003 ;; In 21.4 (or 22.1) the heder doesn't expand tabs. Hmmmm.
1004 ;; We should replace them here.
1005 ;;
1006 ;; This hack assumes that tabs are kept smartly at tab boundaries
1007 ;; instead of in a tab boundary where it might only represent 4 spaces.
1008 (while (string-match "\t" str start)
1009 (setq str (replace-match " " t t str 0)))
1010 str))
1011
1012 (defun semantic-stickyfunc-menu (event)
1013 "Popup a menu that can help a user understand stickyfunc-mode.
1014 Argument EVENT describes the event that caused this function to be called."
1015 (interactive "e")
1016 (let* ((startwin (selected-window))
1017 (win (car (car (cdr event))))
1018 )
1019 (select-window win t)
1020 (save-excursion
1021 (goto-char (window-start win))
1022 (sit-for 0)
1023 (popup-menu semantic-stickyfunc-popup-menu event)
1024 )
1025 (select-window startwin)))
1026
1027
1028 (semantic-add-minor-mode 'semantic-stickyfunc-mode
1029 "" ;; Don't need indicator. It's quite visible
1030 semantic-stickyfunc-mode-map)
1031
1032
1033 \f
1034 ;;;;
1035 ;;;; Minor mode to make highlight the current function
1036 ;;;;
1037
1038 ;; Highlight the first like of the function we are in if it is different
1039 ;; from the the tag going off the top of the screen.
1040
1041 ;;;###autoload
1042 (defun global-semantic-highlight-func-mode (&optional arg)
1043 "Toggle global use of option `semantic-highlight-func-mode'.
1044 If ARG is positive, enable, if it is negative, disable.
1045 If ARG is nil, then toggle."
1046 (interactive "P")
1047 (setq global-semantic-highlight-func-mode
1048 (semantic-toggle-minor-mode-globally
1049 'semantic-highlight-func-mode arg)))
1050
1051 ;;;###autoload
1052 (defcustom global-semantic-highlight-func-mode nil
1053 "*If non-nil, enable global use of `semantic-highlight-func-mode'.
1054 When enabled, the first line of the current tag is highlighted."
1055 :group 'semantic
1056 :group 'semantic-modes
1057 :type 'boolean
1058 :require 'semantic/util-modes
1059 :initialize 'custom-initialize-default
1060 :set (lambda (sym val)
1061 (global-semantic-highlight-func-mode (if val 1 -1))))
1062
1063 (defcustom semantic-highlight-func-mode-hook nil
1064 "*Hook run at the end of function `semantic-highlight-func-mode'."
1065 :group 'semantic
1066 :type 'hook)
1067
1068 (defvar semantic-highlight-func-mode-map
1069 (let ((km (make-sparse-keymap))
1070 (m3 (if (featurep 'xemacs) [ button3 ] [ mouse-3 ]))
1071 )
1072 (define-key km m3 'semantic-highlight-func-menu)
1073 km)
1074 "Keymap for highlight-func minor mode.")
1075
1076 (defvar semantic-highlight-func-popup-menu nil
1077 "Menu used if the user clicks on the header line used by `semantic-highlight-func-mode'.")
1078
1079 (easy-menu-define
1080 semantic-highlight-func-popup-menu
1081 semantic-highlight-func-mode-map
1082 "Highlight-Func Menu"
1083 '("Highlight-Func Mode" :visible (progn nil)
1084 [ "Copy Tag" senator-copy-tag
1085 :active (semantic-current-tag)
1086 :help "Copy the current tag to the tag ring"]
1087 [ "Kill Tag" senator-kill-tag
1088 :active (semantic-current-tag)
1089 :help "Kill tag text to the kill ring, and copy the tag to the tag ring"
1090 ]
1091 [ "Copy Tag to Register" senator-copy-tag-to-register
1092 :active (semantic-current-tag)
1093 :help "Copy the current tag to a register"
1094 ]
1095 [ "Narrow To Tag" senator-narrow-to-defun
1096 :active (semantic-current-tag)
1097 :help "Narrow to the bounds of the current tag."]
1098 [ "Fold Tag" senator-fold-tag-toggle
1099 :active (semantic-current-tag)
1100 :style toggle
1101 :selected (let ((tag (semantic-stickyfunc-tag-to-stick)))
1102 (and tag (semantic-tag-folded-p tag)))
1103 :help "Fold the current tag to one line"
1104 ]
1105 "---"
1106 [ "About This Tag" semantic-describe-tag t])
1107 )
1108
1109 (defun semantic-highlight-func-menu (event)
1110 "Popup a menu that displays things to do to the current tag.
1111 Argument EVENT describes the event that caused this function to be called."
1112 (interactive "e")
1113 (let* ((startwin (selected-window))
1114 (win (semantic-event-window event))
1115 )
1116 (select-window win t)
1117 (save-excursion
1118 ;(goto-char (window-start win))
1119 (mouse-set-point event)
1120 (sit-for 0)
1121 (semantic-popup-menu semantic-highlight-func-popup-menu)
1122 )
1123 (select-window startwin)))
1124
1125 (defvar semantic-highlight-func-mode nil
1126 "Non-nil if highlight-func minor mode is enabled.
1127 Use the command `semantic-highlight-func-mode' to change this variable.")
1128 (make-variable-buffer-local 'semantic-highlight-func-mode)
1129
1130 (defvar semantic-highlight-func-ct-overlay nil
1131 "Overlay used to highlight the tag the cursor is in.")
1132 (make-variable-buffer-local 'semantic-highlight-func-ct-overlay)
1133
1134 (defface semantic-highlight-func-current-tag-face
1135 '((((class color) (background dark))
1136 ;; Put this back to something closer to black later.
1137 (:background "gray20"))
1138 (((class color) (background light))
1139 (:background "gray90")))
1140 "Face used to show the top of current function."
1141 :group 'semantic-faces)
1142
1143
1144 (defun semantic-highlight-func-mode-setup ()
1145 "Setup option `semantic-highlight-func-mode'.
1146 For semantic enabled buffers, highlight the first line of the
1147 current tag declaration."
1148 (if semantic-highlight-func-mode
1149 (progn
1150 (unless (and (featurep 'semantic) (semantic-active-p))
1151 ;; Disable minor mode if semantic stuff not available
1152 (setq semantic-highlight-func-mode nil)
1153 (error "Buffer %s was not set up for parsing" (buffer-name)))
1154 ;; Setup our hook
1155 (add-hook 'post-command-hook 'semantic-highlight-func-highlight-current-tag nil t)
1156 )
1157 ;; Disable highlight func mode
1158 (remove-hook 'post-command-hook 'semantic-highlight-func-highlight-current-tag t)
1159 (semantic-highlight-func-highlight-current-tag t)
1160 )
1161 semantic-highlight-func-mode)
1162
1163 ;;;###autoload
1164 (defun semantic-highlight-func-mode (&optional arg)
1165 "Minor mode to highlight the first line of the current tag.
1166 Enables/disables making the header line of functions sticky.
1167 A function (or other tag class specified by
1168 `semantic-stickyfunc-sticky-classes') is highlighted, meaning the
1169 first line which describes the rest of the construct.
1170
1171 See `semantic-stickyfunc-mode' for putting a function in the
1172 header line. This mode recycles the stickyfunc configuration
1173 classes list.
1174
1175 With prefix argument ARG, turn on if positive, otherwise off. The
1176 minor mode can be turned on only if semantic feature is available and
1177 the current buffer was set up for parsing. Return non-nil if the
1178 minor mode is enabled."
1179 (interactive
1180 (list (or current-prefix-arg
1181 (if semantic-highlight-func-mode 0 1))))
1182 (setq semantic-highlight-func-mode
1183 (if arg
1184 (>
1185 (prefix-numeric-value arg)
1186 0)
1187 (not semantic-highlight-func-mode)))
1188 (semantic-highlight-func-mode-setup)
1189 (run-hooks 'semantic-highlight-func-mode-hook)
1190 (if (interactive-p)
1191 (message "Highlight-Func minor mode %sabled"
1192 (if semantic-highlight-func-mode "en" "dis")))
1193 semantic-highlight-func-mode)
1194
1195 (defun semantic-highlight-func-highlight-current-tag (&optional disable)
1196 "Highlight the current tag under point.
1197 Optional argument DISABLE will turn off any active highlight.
1198 If the current tag for this buffer is different from the last time this
1199 function was called, move the overlay."
1200 (when (and (not (minibufferp))
1201 (or (not semantic-highlight-func-ct-overlay)
1202 (eq (semantic-overlay-buffer
1203 semantic-highlight-func-ct-overlay)
1204 (current-buffer))))
1205 (let* ((tag (semantic-stickyfunc-tag-to-stick))
1206 (ol semantic-highlight-func-ct-overlay))
1207 (when (not ol)
1208 ;; No overlay in this buffer. Make one.
1209 (setq ol (semantic-make-overlay (point-min) (point-min)
1210 (current-buffer) t nil))
1211 (semantic-overlay-put ol 'highlight-func t)
1212 (semantic-overlay-put ol 'face 'semantic-highlight-func-current-tag-face)
1213 (semantic-overlay-put ol 'keymap semantic-highlight-func-mode-map)
1214 (semantic-overlay-put ol 'help-echo
1215 "Current Function : mouse-3 - Context menu")
1216 (setq semantic-highlight-func-ct-overlay ol)
1217 )
1218
1219 ;; TAG is nil if there was nothing of the apropriate type there.
1220 (if (or (not tag) disable)
1221 ;; No tag, make the overlay go away.
1222 (progn
1223 (semantic-overlay-put ol 'tag nil)
1224 (semantic-overlay-move ol (point-min) (point-min) (current-buffer))
1225 )
1226
1227 ;; We have a tag, if it is the same, do nothing.
1228 (unless (eq (semantic-overlay-get ol 'tag) tag)
1229 (save-excursion
1230 (goto-char (semantic-tag-start tag))
1231 (search-forward (semantic-tag-name tag) nil t)
1232 (semantic-overlay-put ol 'tag tag)
1233 (semantic-overlay-move ol (point-at-bol) (point-at-eol))
1234 )
1235 )
1236 )))
1237 nil)
1238
1239 (semantic-add-minor-mode 'semantic-highlight-func-mode
1240 "" ;; Don't need indicator. It's quite visible
1241 nil)
1242
1243 (provide 'semantic/util-modes)
1244
1245 ;; Local variables:
1246 ;; generated-autoload-file: "loaddefs.el"
1247 ;; generated-autoload-feature: semantic/loaddefs
1248 ;; generated-autoload-load-name: "semantic/util-modes"
1249 ;; End:
1250
1251 ;;; semantic/util-modes.el ends here