diff options
| author | Chong Yidong | 2009-09-05 20:45:54 +0000 |
|---|---|---|
| committer | Chong Yidong | 2009-09-05 20:45:54 +0000 |
| commit | cea2906fcfa53be62fe2d79b30f44eff8685581d (patch) | |
| tree | 4f7847fb30f1a30528f1c5011e2b59132e2f3158 | |
| parent | 06b434594e3894899a2e224926db91ae681c1a70 (diff) | |
| download | emacs-cea2906fcfa53be62fe2d79b30f44eff8685581d.tar.gz emacs-cea2906fcfa53be62fe2d79b30f44eff8685581d.zip | |
lisp/cedet/semantic/decorate/include.el:
lisp/cedet/semantic/decorate/mode.el: New files.
| -rw-r--r-- | lisp/cedet/semantic/decorate/include.el | 764 | ||||
| -rw-r--r-- | lisp/cedet/semantic/decorate/mode.el | 562 |
2 files changed, 1326 insertions, 0 deletions
diff --git a/lisp/cedet/semantic/decorate/include.el b/lisp/cedet/semantic/decorate/include.el new file mode 100644 index 00000000000..5265aa90d0c --- /dev/null +++ b/lisp/cedet/semantic/decorate/include.el | |||
| @@ -0,0 +1,764 @@ | |||
| 1 | ;;; semantic/decorate/include.el --- Decoration modes for include statements | ||
| 2 | |||
| 3 | ;; Copyright (C) 2008, 2009 Free Software Foundation, Inc. | ||
| 4 | |||
| 5 | ;; Author: Eric M. Ludlam <zappo@gnu.org> | ||
| 6 | |||
| 7 | ;; This file is part of GNU Emacs. | ||
| 8 | |||
| 9 | ;; GNU Emacs is free software: you can redistribute it and/or modify | ||
| 10 | ;; it under the terms of the GNU General Public License as published by | ||
| 11 | ;; the Free Software Foundation, either version 3 of the License, or | ||
| 12 | ;; (at your option) any later version. | ||
| 13 | |||
| 14 | ;; GNU Emacs is distributed in the hope that it will be useful, | ||
| 15 | ;; but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 16 | ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 17 | ;; GNU General Public License for more details. | ||
| 18 | |||
| 19 | ;; You should have received a copy of the GNU General Public License | ||
| 20 | ;; along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. | ||
| 21 | |||
| 22 | ;;; Commentary: | ||
| 23 | ;; | ||
| 24 | ;; Highlight any include that is in a state the user may care about. | ||
| 25 | ;; The basic idea is to have the state be highly visible so users will | ||
| 26 | ;; as 'what is this?" and get the info they need to fix problems that | ||
| 27 | ;; are otherwises transparent when trying to get smart completion | ||
| 28 | ;; working. | ||
| 29 | |||
| 30 | (require 'semantic/decorate/mode) | ||
| 31 | (require 'semantic/db) | ||
| 32 | (require 'semantic/db-ref) | ||
| 33 | (require 'semantic/db-find) | ||
| 34 | |||
| 35 | (eval-when-compile | ||
| 36 | (require 'semantic/find)) | ||
| 37 | |||
| 38 | (defvar semantic-dependency-system-include-path) | ||
| 39 | |||
| 40 | ;;; Code: | ||
| 41 | |||
| 42 | ;;; FACES AND KEYMAPS | ||
| 43 | (defvar semantic-decoratiton-mouse-3 (if (featurep 'xemacs) [ button3 ] [ mouse-3 ]) | ||
| 44 | "The keybinding lisp object to use for binding the right mouse button.") | ||
| 45 | |||
| 46 | ;;; Includes that that are in a happy state! | ||
| 47 | ;; | ||
| 48 | (defface semantic-decoration-on-includes | ||
| 49 | nil | ||
| 50 | "*Overlay Face used on includes that are not in some other state. | ||
| 51 | Used by the decoration style: `semantic-decoration-on-includes'." | ||
| 52 | :group 'semantic-faces) | ||
| 53 | |||
| 54 | (defvar semantic-decoration-on-include-map | ||
| 55 | (let ((km (make-sparse-keymap))) | ||
| 56 | (define-key km semantic-decoratiton-mouse-3 'semantic-decoration-include-menu) | ||
| 57 | km) | ||
| 58 | "Keymap used on includes.") | ||
| 59 | |||
| 60 | |||
| 61 | (defvar semantic-decoration-on-include-menu nil | ||
| 62 | "Menu used for include headers.") | ||
| 63 | |||
| 64 | (easy-menu-define | ||
| 65 | semantic-decoration-on-include-menu | ||
| 66 | semantic-decoration-on-include-map | ||
| 67 | "Include Menu" | ||
| 68 | (list | ||
| 69 | "Include" | ||
| 70 | (semantic-menu-item | ||
| 71 | ["What Is This?" semantic-decoration-include-describe | ||
| 72 | :active t | ||
| 73 | :help "Describe why this include has been marked this way." ]) | ||
| 74 | (semantic-menu-item | ||
| 75 | ["Visit This Include" semantic-decoration-include-visit | ||
| 76 | :active t | ||
| 77 | :help "Visit this include file." ]) | ||
| 78 | "---" | ||
| 79 | (semantic-menu-item | ||
| 80 | ["Summarize includes current buffer" semantic-decoration-all-include-summary | ||
| 81 | :active t | ||
| 82 | :help "Show a summary for the current buffer containing this include." ]) | ||
| 83 | (semantic-menu-item | ||
| 84 | ["List found includes (load unparsed)" semanticdb-find-test-translate-path | ||
| 85 | :active t | ||
| 86 | :help "List all includes found for this file, and parse unparsed files." ]) | ||
| 87 | (semantic-menu-item | ||
| 88 | ["List found includes (no loading)" semanticdb-find-test-translate-path-no-loading | ||
| 89 | :active t | ||
| 90 | :help "List all includes found for this file, do not parse unparsed files." ]) | ||
| 91 | (semantic-menu-item | ||
| 92 | ["List all unknown includes" semanticdb-find-adebug-lost-includes | ||
| 93 | :active t | ||
| 94 | :help "Show a list of all includes semantic cannot find for this file." ]) | ||
| 95 | "---" | ||
| 96 | (semantic-menu-item | ||
| 97 | ["Customize System Include Path" semantic-customize-system-include-path | ||
| 98 | :active (get 'semantic-dependency-system-include-path major-mode) | ||
| 99 | :help "Run customize for the system include path for this major mode." ]) | ||
| 100 | (semantic-menu-item | ||
| 101 | ["Add a System Include Path" semantic-add-system-include | ||
| 102 | :active t | ||
| 103 | :help "Add an include path for this session." ]) | ||
| 104 | (semantic-menu-item | ||
| 105 | ["Remove a System Include Path" semantic-remove-system-include | ||
| 106 | :active t | ||
| 107 | :help "Add an include path for this session." ]) | ||
| 108 | ;;["" semantic-decoration-include- | ||
| 109 | ;; :active t | ||
| 110 | ;; :help "" ] | ||
| 111 | )) | ||
| 112 | |||
| 113 | ;;; Unknown Includes! | ||
| 114 | ;; | ||
| 115 | (defface semantic-decoration-on-unknown-includes | ||
| 116 | '((((class color) (background dark)) | ||
| 117 | (:background "#900000")) | ||
| 118 | (((class color) (background light)) | ||
| 119 | (:background "#ff5050"))) | ||
| 120 | "*Face used to show includes that cannot be found. | ||
| 121 | Used by the decoration style: `semantic-decoration-on-unknown-includes'." | ||
| 122 | :group 'semantic-faces) | ||
| 123 | |||
| 124 | (defvar semantic-decoration-on-unknown-include-map | ||
| 125 | (let ((km (make-sparse-keymap))) | ||
| 126 | ;(define-key km [ mouse-2 ] 'semantic-decoration-unknown-include-describe) | ||
| 127 | (define-key km semantic-decoratiton-mouse-3 'semantic-decoration-unknown-include-menu) | ||
| 128 | km) | ||
| 129 | "Keymap used on unparsed includes.") | ||
| 130 | |||
| 131 | (defvar semantic-decoration-on-unknown-include-menu nil | ||
| 132 | "Menu used for unparsed include headers.") | ||
| 133 | |||
| 134 | (easy-menu-define | ||
| 135 | semantic-decoration-on-unknown-include-menu | ||
| 136 | semantic-decoration-on-unknown-include-map | ||
| 137 | "Unknown Include Menu" | ||
| 138 | (list | ||
| 139 | "Unknown Include" | ||
| 140 | (semantic-menu-item | ||
| 141 | ["What Is This?" semantic-decoration-unknown-include-describe | ||
| 142 | :active t | ||
| 143 | :help "Describe why this include has been marked this way." ]) | ||
| 144 | (semantic-menu-item | ||
| 145 | ["List all unknown includes" semanticdb-find-adebug-lost-includes | ||
| 146 | :active t | ||
| 147 | :help "Show a list of all includes semantic cannot find for this file." ]) | ||
| 148 | "---" | ||
| 149 | (semantic-menu-item | ||
| 150 | ["Summarize includes current buffer" semantic-decoration-all-include-summary | ||
| 151 | :active t | ||
| 152 | :help "Show a summary for the current buffer containing this include." ]) | ||
| 153 | (semantic-menu-item | ||
| 154 | ["List found includes (load unparsed)" semanticdb-find-test-translate-path | ||
| 155 | :active t | ||
| 156 | :help "List all includes found for this file, and parse unparsed files." ]) | ||
| 157 | (semantic-menu-item | ||
| 158 | ["List found includes (no loading)" semanticdb-find-test-translate-path-no-loading | ||
| 159 | :active t | ||
| 160 | :help "List all includes found for this file, do not parse unparsed files." ]) | ||
| 161 | "---" | ||
| 162 | (semantic-menu-item | ||
| 163 | ["Customize System Include Path" semantic-customize-system-include-path | ||
| 164 | :active (get 'semantic-dependency-system-include-path major-mode) | ||
| 165 | :help "Run customize for the system include path for this major mode." ]) | ||
| 166 | (semantic-menu-item | ||
| 167 | ["Add a System Include Path" semantic-add-system-include | ||
| 168 | :active t | ||
| 169 | :help "Add an include path for this session." ]) | ||
| 170 | (semantic-menu-item | ||
| 171 | ["Remove a System Include Path" semantic-remove-system-include | ||
| 172 | :active t | ||
| 173 | :help "Add an include path for this session." ]) | ||
| 174 | )) | ||
| 175 | |||
| 176 | ;;; Includes that need to be parsed. | ||
| 177 | ;; | ||
| 178 | (defface semantic-decoration-on-unparsed-includes | ||
| 179 | '((((class color) (background dark)) | ||
| 180 | (:background "#555500")) | ||
| 181 | (((class color) (background light)) | ||
| 182 | (:background "#ffff55"))) | ||
| 183 | "*Face used to show includes that have not yet been parsed. | ||
| 184 | Used by the decoration style: `semantic-decoration-on-unparsed-includes'." | ||
| 185 | :group 'semantic-faces) | ||
| 186 | |||
| 187 | (defvar semantic-decoration-on-unparsed-include-map | ||
| 188 | (let ((km (make-sparse-keymap))) | ||
| 189 | (define-key km semantic-decoratiton-mouse-3 'semantic-decoration-unparsed-include-menu) | ||
| 190 | km) | ||
| 191 | "Keymap used on unparsed includes.") | ||
| 192 | |||
| 193 | |||
| 194 | (defvar semantic-decoration-on-unparsed-include-menu nil | ||
| 195 | "Menu used for unparsed include headers.") | ||
| 196 | |||
| 197 | (easy-menu-define | ||
| 198 | semantic-decoration-on-unparsed-include-menu | ||
| 199 | semantic-decoration-on-unparsed-include-map | ||
| 200 | "Unparsed Include Menu" | ||
| 201 | (list | ||
| 202 | "Unparsed Include" | ||
| 203 | (semantic-menu-item | ||
| 204 | ["What Is This?" semantic-decoration-unparsed-include-describe | ||
| 205 | :active t | ||
| 206 | :help "Describe why this include has been marked this way." ]) | ||
| 207 | (semantic-menu-item | ||
| 208 | ["Visit This Include" semantic-decoration-include-visit | ||
| 209 | :active t | ||
| 210 | :help "Visit this include file so that header file's tags can be used." ]) | ||
| 211 | (semantic-menu-item | ||
| 212 | ["Parse This Include" semantic-decoration-unparsed-include-parse-include | ||
| 213 | :active t | ||
| 214 | :help "Parse this include file so that header file's tags can be used." ]) | ||
| 215 | (semantic-menu-item | ||
| 216 | ["Parse All Includes" semantic-decoration-unparsed-include-parse-all-includes | ||
| 217 | :active t | ||
| 218 | :help "Parse all the includes so the contents can be used." ]) | ||
| 219 | "---" | ||
| 220 | (semantic-menu-item | ||
| 221 | ["Summarize includes current buffer" semantic-decoration-all-include-summary | ||
| 222 | :active t | ||
| 223 | :help "Show a summary for the current buffer containing this include." ]) | ||
| 224 | (semantic-menu-item | ||
| 225 | ["List found includes (load unparsed)" semanticdb-find-test-translate-path | ||
| 226 | :active t | ||
| 227 | :help "List all includes found for this file, and parse unparsed files." ]) | ||
| 228 | (semantic-menu-item | ||
| 229 | ["List found includes (no loading)" semanticdb-find-test-translate-path-no-loading | ||
| 230 | :active t | ||
| 231 | :help "List all includes found for this file, do not parse unparsed files." ]) | ||
| 232 | (semantic-menu-item | ||
| 233 | ["List all unknown includes" semanticdb-find-adebug-lost-includes | ||
| 234 | :active t | ||
| 235 | :help "Show a list of all includes semantic cannot find for this file." ]) | ||
| 236 | "---" | ||
| 237 | (semantic-menu-item | ||
| 238 | ["Customize System Include Path" semantic-customize-system-include-path | ||
| 239 | :active (get 'semantic-dependency-system-include-path major-mode) | ||
| 240 | :help "Run customize for the system include path for this major mode." ]) | ||
| 241 | (semantic-menu-item | ||
| 242 | ["Add a System Include Path" semantic-add-system-include | ||
| 243 | :active t | ||
| 244 | :help "Add an include path for this session." ]) | ||
| 245 | (semantic-menu-item | ||
| 246 | ["Remove a System Include Path" semantic-remove-system-include | ||
| 247 | :active t | ||
| 248 | :help "Add an include path for this session." ]) | ||
| 249 | ;;["" semantic-decoration-unparsed-include- | ||
| 250 | ;; :active t | ||
| 251 | ;; :help "" ] | ||
| 252 | )) | ||
| 253 | |||
| 254 | |||
| 255 | ;;; MODES | ||
| 256 | |||
| 257 | ;;; Include statement Decorate Mode | ||
| 258 | ;; | ||
| 259 | ;; This mode handles the three states of an include statements | ||
| 260 | ;; | ||
| 261 | (define-semantic-decoration-style semantic-decoration-on-includes | ||
| 262 | "Highlight class members that are includes. | ||
| 263 | This mode provides a nice context menu on the include statements." | ||
| 264 | :enabled t) | ||
| 265 | |||
| 266 | (defun semantic-decoration-on-includes-p-default (tag) | ||
| 267 | "Return non-nil if TAG has is an includes that can't be found." | ||
| 268 | (semantic-tag-of-class-p tag 'include)) | ||
| 269 | |||
| 270 | (defun semantic-decoration-on-includes-highlight-default (tag) | ||
| 271 | "Highlight the include TAG to show that semantic can't find it." | ||
| 272 | (let* ((file (semantic-dependency-tag-file tag)) | ||
| 273 | (table (when file | ||
| 274 | (semanticdb-file-table-object file t))) | ||
| 275 | (face nil) | ||
| 276 | (map nil) | ||
| 277 | ) | ||
| 278 | (cond | ||
| 279 | ((not file) | ||
| 280 | ;; Cannot find this header. | ||
| 281 | (setq face 'semantic-decoration-on-unknown-includes | ||
| 282 | map semantic-decoration-on-unknown-include-map) | ||
| 283 | ) | ||
| 284 | ((and table (number-or-marker-p (oref table pointmax))) | ||
| 285 | ;; A found and parsed file. | ||
| 286 | (setq face 'semantic-decoration-on-includes | ||
| 287 | map semantic-decoration-on-include-map) | ||
| 288 | ) | ||
| 289 | (t | ||
| 290 | ;; An unparsed file. | ||
| 291 | (setq face 'semantic-decoration-on-unparsed-includes | ||
| 292 | map semantic-decoration-on-unparsed-include-map) | ||
| 293 | (when table | ||
| 294 | ;; Set ourselves up for synchronization | ||
| 295 | (semanticdb-cache-get | ||
| 296 | table 'semantic-decoration-unparsed-include-cache) | ||
| 297 | ;; Add a dependancy. | ||
| 298 | (let ((table semanticdb-current-table)) | ||
| 299 | (semanticdb-add-reference table tag)) | ||
| 300 | ) | ||
| 301 | )) | ||
| 302 | |||
| 303 | (let ((ol (semantic-decorate-tag tag | ||
| 304 | (semantic-tag-start tag) | ||
| 305 | (semantic-tag-end tag) | ||
| 306 | face)) | ||
| 307 | ) | ||
| 308 | (semantic-overlay-put ol 'mouse-face 'highlight) | ||
| 309 | (semantic-overlay-put ol 'keymap map) | ||
| 310 | (semantic-overlay-put ol 'help-echo | ||
| 311 | "Header File : mouse-3 - Context menu") | ||
| 312 | ))) | ||
| 313 | |||
| 314 | ;;; Regular Include Functions | ||
| 315 | ;; | ||
| 316 | (defun semantic-decoration-include-describe () | ||
| 317 | "Describe what unparsed includes are in the current buffer. | ||
| 318 | Argument EVENT is the mouse clicked event." | ||
| 319 | (interactive) | ||
| 320 | (let* ((tag (or (semantic-current-tag) | ||
| 321 | (error "No tag under point"))) | ||
| 322 | (file (semantic-dependency-tag-file tag)) | ||
| 323 | (table (when file | ||
| 324 | (semanticdb-file-table-object file t)))) | ||
| 325 | (with-output-to-temp-buffer (help-buffer) ; "*Help*" | ||
| 326 | (help-setup-xref (list #'semantic-decoration-include-describe) | ||
| 327 | (interactive-p)) | ||
| 328 | (princ "Include File: ") | ||
| 329 | (princ (semantic-format-tag-name tag nil t)) | ||
| 330 | (princ "\n") | ||
| 331 | (princ "This include file was found at:\n ") | ||
| 332 | (princ (semantic-dependency-tag-file tag)) | ||
| 333 | (princ "\n\n") | ||
| 334 | (princ "Semantic knows where this include file is, and has parsed | ||
| 335 | its contents. | ||
| 336 | |||
| 337 | ") | ||
| 338 | (let ((inc (semantic-find-tags-by-class 'include table)) | ||
| 339 | (ok 0) | ||
| 340 | (unknown 0) | ||
| 341 | (unparsed 0) | ||
| 342 | (all 0)) | ||
| 343 | (dolist (i inc) | ||
| 344 | (let* ((fileinner (semantic-dependency-tag-file i)) | ||
| 345 | ) | ||
| 346 | (cond ((not fileinner) | ||
| 347 | (setq unknown (1+ unknown))) | ||
| 348 | ((number-or-marker-p (oref table pointmax)) | ||
| 349 | (setq ok (1+ ok))) | ||
| 350 | (t | ||
| 351 | (setq unparsed (1+ unparsed)))))) | ||
| 352 | (setq all (+ ok unknown unparsed)) | ||
| 353 | (if (= 0 all) | ||
| 354 | (princ "There are no other includes in this file.\n") | ||
| 355 | (princ (format "There are %d more includes in this file.\n" | ||
| 356 | all)) | ||
| 357 | (princ (format " Unknown Includes: %d\n" unknown)) | ||
| 358 | (princ (format " Unparsed Includes: %d\n" unparsed)) | ||
| 359 | (princ (format " Parsed Includes: %d\n" ok))) | ||
| 360 | ) | ||
| 361 | ;; Get the semanticdb statement, and display it's contents. | ||
| 362 | (princ "\nDetails for header file...\n") | ||
| 363 | (princ "\nMajor Mode: ") | ||
| 364 | (princ (oref table :major-mode)) | ||
| 365 | (princ "\nTags: ") | ||
| 366 | (princ (format "%s entries" (length (oref table :tags)))) | ||
| 367 | (princ "\nFile Size: ") | ||
| 368 | (princ (format "%s chars" (oref table :pointmax))) | ||
| 369 | (princ "\nSave State: ") | ||
| 370 | (cond ((oref table dirty) | ||
| 371 | (princ "Table needs to be saved.")) | ||
| 372 | (t | ||
| 373 | (princ "Table is saved on disk.")) | ||
| 374 | ) | ||
| 375 | (princ "\nExternal References:") | ||
| 376 | (dolist (r (oref table db-refs)) | ||
| 377 | (princ "\n ") | ||
| 378 | (princ (oref r file))) | ||
| 379 | ))) | ||
| 380 | |||
| 381 | ;;;;###autoload | ||
| 382 | (defun semantic-decoration-include-visit () | ||
| 383 | "Visit the included file at point." | ||
| 384 | (interactive) | ||
| 385 | (let ((tag (semantic-current-tag))) | ||
| 386 | (unless (eq (semantic-tag-class tag) 'include) | ||
| 387 | (error "Point is not on an include tag")) | ||
| 388 | (let ((file (semantic-dependency-tag-file tag))) | ||
| 389 | (cond | ||
| 390 | ((or (not file) (not (file-exists-p file))) | ||
| 391 | (error "Could not location include %s" | ||
| 392 | (semantic-tag-name tag))) | ||
| 393 | ((get-file-buffer file) | ||
| 394 | (switch-to-buffer (get-file-buffer file))) | ||
| 395 | ((stringp file) | ||
| 396 | (find-file file)) | ||
| 397 | )))) | ||
| 398 | |||
| 399 | (defun semantic-decoration-include-menu (event) | ||
| 400 | "Popup a menu that can help a user understand unparsed includes. | ||
| 401 | Argument EVENT describes the event that caused this function to be called." | ||
| 402 | (interactive "e") | ||
| 403 | (let* ((startwin (selected-window)) | ||
| 404 | (win (semantic-event-window event)) | ||
| 405 | ) | ||
| 406 | (select-window win t) | ||
| 407 | (save-excursion | ||
| 408 | ;(goto-char (window-start win)) | ||
| 409 | (mouse-set-point event) | ||
| 410 | (sit-for 0) | ||
| 411 | (semantic-popup-menu semantic-decoration-on-include-menu) | ||
| 412 | ) | ||
| 413 | (select-window startwin))) | ||
| 414 | |||
| 415 | |||
| 416 | ;;; Unknown Include functions | ||
| 417 | ;; | ||
| 418 | (defun semantic-decoration-unknown-include-describe () | ||
| 419 | "Describe what unknown includes are in the current buffer. | ||
| 420 | Argument EVENT is the mouse clicked event." | ||
| 421 | (interactive) | ||
| 422 | (let ((tag (semantic-current-tag)) | ||
| 423 | (mm major-mode)) | ||
| 424 | (with-output-to-temp-buffer (help-buffer) ; "*Help*" | ||
| 425 | (help-setup-xref (list #'semantic-decoration-unknown-include-describe) | ||
| 426 | (interactive-p)) | ||
| 427 | (princ "Include File: ") | ||
| 428 | (princ (semantic-format-tag-name tag nil t)) | ||
| 429 | (princ "\n\n") | ||
| 430 | (princ "This header file has been marked \"Unknown\". | ||
| 431 | This means that Semantic has not been able to locate this file on disk. | ||
| 432 | |||
| 433 | When Semantic cannot find an include file, this means that the | ||
| 434 | idle summary mode and idle completion modes cannot use the contents of | ||
| 435 | that file to provide coding assistance. | ||
| 436 | |||
| 437 | If this is a system header and you want it excluded from Semantic's | ||
| 438 | searches (which may be desirable for speed reasons) then you can | ||
| 439 | safely ignore this state. | ||
| 440 | |||
| 441 | If this is a system header, and you want to include it in Semantic's | ||
| 442 | searches, then you will need to use: | ||
| 443 | |||
| 444 | M-x semantic-add-system-include RET /path/to/includes RET | ||
| 445 | |||
| 446 | or, in your .emacs file do: | ||
| 447 | |||
| 448 | (semantic-add-system-include \"/path/to/include\" '") | ||
| 449 | (princ (symbol-name mm)) | ||
| 450 | (princ ") | ||
| 451 | |||
| 452 | to add the path to Semantic's search. | ||
| 453 | |||
| 454 | If this is an include file that belongs to your project, then you may | ||
| 455 | need to update `semanticdb-project-roots' or better yet, use `ede' | ||
| 456 | to manage your project. See the ede manual for projects that will | ||
| 457 | wrap existing project code for Semantic's benifit. | ||
| 458 | ") | ||
| 459 | |||
| 460 | (when (or (eq mm 'c++-mode) (eq mm 'c-mode)) | ||
| 461 | (princ " | ||
| 462 | For C/C++ includes located within a a project, you can use a special | ||
| 463 | EDE project that will wrap an existing build system. You can do that | ||
| 464 | like this in your .emacs file: | ||
| 465 | |||
| 466 | (ede-cpp-root-project \"NAME\" :file \"FILENAME\" :locate-fcn 'MYFCN) | ||
| 467 | |||
| 468 | See the CEDET manual, the EDE manual, or the commentary in | ||
| 469 | ede-cpp-root.el for more. | ||
| 470 | |||
| 471 | If you think this header tag is marked in error, you may need to do: | ||
| 472 | |||
| 473 | C-u M-x bovinate RET | ||
| 474 | |||
| 475 | to refresh the tags in this buffer, and recalculate the state.")) | ||
| 476 | |||
| 477 | (princ " | ||
| 478 | See the Semantic manual node on SemanticDB for more about search paths.") | ||
| 479 | ))) | ||
| 480 | |||
| 481 | (defun semantic-decoration-unknown-include-menu (event) | ||
| 482 | "Popup a menu that can help a user understand unparsed includes. | ||
| 483 | Argument EVENT describes the event that caused this function to be called." | ||
| 484 | (interactive "e") | ||
| 485 | (let* ((startwin (selected-window)) | ||
| 486 | ;; This line has an issue in XEmacs. | ||
| 487 | (win (semantic-event-window event)) | ||
| 488 | ) | ||
| 489 | (select-window win t) | ||
| 490 | (save-excursion | ||
| 491 | ;(goto-char (window-start win)) | ||
| 492 | (mouse-set-point event) | ||
| 493 | (sit-for 0) | ||
| 494 | (semantic-popup-menu semantic-decoration-on-unknown-include-menu) | ||
| 495 | ) | ||
| 496 | (select-window startwin))) | ||
| 497 | |||
| 498 | |||
| 499 | ;;; Interactive parts of unparsed includes | ||
| 500 | ;; | ||
| 501 | (defun semantic-decoration-unparsed-include-describe () | ||
| 502 | "Describe what unparsed includes are in the current buffer. | ||
| 503 | Argument EVENT is the mouse clicked event." | ||
| 504 | (interactive) | ||
| 505 | (let ((tag (semantic-current-tag))) | ||
| 506 | (with-output-to-temp-buffer (help-buffer); "*Help*" | ||
| 507 | (help-setup-xref (list #'semantic-decoration-unparsed-include-describe) | ||
| 508 | (interactive-p)) | ||
| 509 | |||
| 510 | (princ "Include File: ") | ||
| 511 | (princ (semantic-format-tag-name tag nil t)) | ||
| 512 | (princ "\n") | ||
| 513 | (princ "This include file was found at:\n ") | ||
| 514 | (princ (semantic-dependency-tag-file tag)) | ||
| 515 | (princ "\n\n") | ||
| 516 | (princ "This header file has been marked \"Unparsed\". | ||
| 517 | This means that Semantic has located this header file on disk | ||
| 518 | but has not yet opened and parsed this file. | ||
| 519 | |||
| 520 | So long as this header file is unparsed, idle summary and | ||
| 521 | idle completion will not be able to reference the details in this | ||
| 522 | header. | ||
| 523 | |||
| 524 | To resolve this, use the context menu to parse this include file, | ||
| 525 | or all include files referred to in ") | ||
| 526 | (princ (buffer-name)) | ||
| 527 | (princ ". | ||
| 528 | This can take a while in large projects. | ||
| 529 | |||
| 530 | Alternately, you can call: | ||
| 531 | |||
| 532 | M-x semanticdb-find-test-translate-path RET | ||
| 533 | |||
| 534 | to search path Semantic uses to perform completion. | ||
| 535 | |||
| 536 | |||
| 537 | If you think this header tag is marked in error, you may need to do: | ||
| 538 | |||
| 539 | C-u M-x bovinate RET | ||
| 540 | |||
| 541 | to refresh the tags in this buffer, and recalculate the state. | ||
| 542 | If you find a repeatable case where a header is marked in error, | ||
| 543 | report it to cedet-devel@lists.sf.net.") ))) | ||
| 544 | |||
| 545 | |||
| 546 | (defun semantic-decoration-unparsed-include-menu (event) | ||
| 547 | "Popup a menu that can help a user understand unparsed includes. | ||
| 548 | Argument EVENT describes the event that caused this function to be called." | ||
| 549 | (interactive "e") | ||
| 550 | (let* ((startwin (selected-window)) | ||
| 551 | (win (semantic-event-window event)) | ||
| 552 | ) | ||
| 553 | (select-window win t) | ||
| 554 | (save-excursion | ||
| 555 | ;(goto-char (window-start win)) | ||
| 556 | (mouse-set-point event) | ||
| 557 | (sit-for 0) | ||
| 558 | (semantic-popup-menu semantic-decoration-on-unparsed-include-menu) | ||
| 559 | ) | ||
| 560 | (select-window startwin))) | ||
| 561 | |||
| 562 | (defun semantic-decoration-unparsed-include-parse-include () | ||
| 563 | "Parse the include file the user menu-selected from." | ||
| 564 | (interactive) | ||
| 565 | (let* ((file (semantic-dependency-tag-file (semantic-current-tag)))) | ||
| 566 | (semanticdb-file-table-object file) | ||
| 567 | (semantic-decoration-unparsed-include-do-reset))) | ||
| 568 | |||
| 569 | |||
| 570 | (defun semantic-decoration-unparsed-include-parse-all-includes () | ||
| 571 | "Parse the include file the user menu-selected from." | ||
| 572 | (interactive) | ||
| 573 | (semanticdb-find-translate-path nil nil) | ||
| 574 | ) | ||
| 575 | |||
| 576 | |||
| 577 | ;;; General Includes Information | ||
| 578 | ;; | ||
| 579 | (defun semantic-decoration-all-include-summary () | ||
| 580 | "Provide a general summary for the state of all includes." | ||
| 581 | (interactive) | ||
| 582 | (require 'semantic/dep) | ||
| 583 | (let* ((table semanticdb-current-table) | ||
| 584 | (tags (semantic-fetch-tags)) | ||
| 585 | (inc (semantic-find-tags-by-class 'include table)) | ||
| 586 | ) | ||
| 587 | (with-output-to-temp-buffer (help-buffer) ;"*Help*" | ||
| 588 | (help-setup-xref (list #'semantic-decoration-all-include-summary) | ||
| 589 | (interactive-p)) | ||
| 590 | |||
| 591 | (princ "Include Summary for File: ") | ||
| 592 | (princ (file-truename (buffer-file-name))) | ||
| 593 | (princ "\n") | ||
| 594 | |||
| 595 | (when (oref table db-refs) | ||
| 596 | (princ "\nExternal Database References to this buffer:") | ||
| 597 | (dolist (r (oref table db-refs)) | ||
| 598 | (princ "\n ") | ||
| 599 | (princ (oref r file))) | ||
| 600 | ) | ||
| 601 | |||
| 602 | (princ (format "\nThis file contains %d tags, %d of which are includes.\n" | ||
| 603 | (length tags) (length inc))) | ||
| 604 | (let ((ok 0) | ||
| 605 | (unknown 0) | ||
| 606 | (unparsed 0) | ||
| 607 | (all 0)) | ||
| 608 | (dolist (i inc) | ||
| 609 | (let* ((fileinner (semantic-dependency-tag-file i)) | ||
| 610 | (tableinner (when fileinner | ||
| 611 | (semanticdb-file-table-object fileinner t)))) | ||
| 612 | (cond ((not fileinner) | ||
| 613 | (setq unknown (1+ unknown))) | ||
| 614 | ((number-or-marker-p (oref tableinner pointmax)) | ||
| 615 | (setq ok (1+ ok))) | ||
| 616 | (t | ||
| 617 | (setq unparsed (1+ unparsed)))))) | ||
| 618 | (setq all (+ ok unknown unparsed)) | ||
| 619 | (when (not (= 0 all)) | ||
| 620 | (princ (format " Unknown Includes: %d\n" unknown)) | ||
| 621 | (princ (format " Unparsed Includes: %d\n" unparsed)) | ||
| 622 | (princ (format " Parsed Includes: %d\n" ok))) | ||
| 623 | ) | ||
| 624 | |||
| 625 | (princ "\nInclude Path Summary:\n\n") | ||
| 626 | (when ede-object | ||
| 627 | (princ " This file's project include search is handled by the EDE object:\n") | ||
| 628 | (princ " Buffer Target: ") | ||
| 629 | (princ (object-print ede-object)) | ||
| 630 | (princ "\n") | ||
| 631 | (when (not (eq ede-object ede-object-project)) | ||
| 632 | (princ " Buffer Project: ") | ||
| 633 | (princ (object-print ede-object-project)) | ||
| 634 | (princ "\n") | ||
| 635 | ) | ||
| 636 | (when ede-object-project | ||
| 637 | (let ((loc (ede-get-locator-object ede-object-project))) | ||
| 638 | (princ " Backup in-project Locator: ") | ||
| 639 | (princ (object-print loc)) | ||
| 640 | (princ "\n"))) | ||
| 641 | (let ((syspath (ede-system-include-path ede-object-project))) | ||
| 642 | (if (not syspath) | ||
| 643 | (princ " EDE Project system include path: Empty\n") | ||
| 644 | (princ " EDE Project system include path:\n") | ||
| 645 | (dolist (dir syspath) | ||
| 646 | (princ " ") | ||
| 647 | (princ dir) | ||
| 648 | (princ "\n")) | ||
| 649 | ))) | ||
| 650 | |||
| 651 | (princ "\n This file's system include path is:\n") | ||
| 652 | (dolist (dir semantic-dependency-system-include-path) | ||
| 653 | (princ " ") | ||
| 654 | (princ dir) | ||
| 655 | (princ "\n")) | ||
| 656 | |||
| 657 | (let ((unk semanticdb-find-lost-includes)) | ||
| 658 | (when unk | ||
| 659 | (princ "\nAll unknown includes:\n") | ||
| 660 | (dolist (tag unk) | ||
| 661 | (princ " ") | ||
| 662 | (princ (semantic-tag-name tag)) | ||
| 663 | (princ "\n")) | ||
| 664 | )) | ||
| 665 | |||
| 666 | (let* ((semanticdb-find-default-throttle | ||
| 667 | (if (featurep 'semanticdb-find) | ||
| 668 | (remq 'unloaded semanticdb-find-default-throttle) | ||
| 669 | nil)) | ||
| 670 | (path (semanticdb-find-translate-path nil nil))) | ||
| 671 | (if (<= (length path) (length inc)) | ||
| 672 | (princ "\nThere are currently no includes found recursively.\n") | ||
| 673 | ;; List the full include list. | ||
| 674 | (princ "\nSummary of all includes needed by ") | ||
| 675 | (princ (buffer-name)) | ||
| 676 | (dolist (p path) | ||
| 677 | (if (slot-boundp p 'tags) | ||
| 678 | (princ (format "\n %s :\t%d tags, %d are includes. %s" | ||
| 679 | (object-name-string p) | ||
| 680 | (length (oref p tags)) | ||
| 681 | (length (semantic-find-tags-by-class | ||
| 682 | 'include p)) | ||
| 683 | (cond | ||
| 684 | ((condition-case nil | ||
| 685 | (oref p dirty) | ||
| 686 | (error nil)) | ||
| 687 | " dirty.") | ||
| 688 | ((not (number-or-marker-p (oref table pointmax))) | ||
| 689 | " Needs to be parsed.") | ||
| 690 | (t "")))) | ||
| 691 | (princ (format "\n %s :\tUnparsed" | ||
| 692 | (object-name-string p)))) | ||
| 693 | ))) | ||
| 694 | ))) | ||
| 695 | |||
| 696 | |||
| 697 | ;;; Unparsed Include Features | ||
| 698 | ;; | ||
| 699 | ;; This section handles changing states of unparsed include | ||
| 700 | ;; decorations base on what happens in other files. | ||
| 701 | ;; | ||
| 702 | |||
| 703 | (defclass semantic-decoration-unparsed-include-cache (semanticdb-abstract-cache) | ||
| 704 | () | ||
| 705 | "Class used to reset decorated includes. | ||
| 706 | When an include's referring file is parsed, we need to undecorate | ||
| 707 | any decorated referring includes.") | ||
| 708 | |||
| 709 | |||
| 710 | (defmethod semantic-reset ((obj semantic-decoration-unparsed-include-cache)) | ||
| 711 | "Reset OBJ back to it's empty settings." | ||
| 712 | (let ((table (oref obj table))) | ||
| 713 | ;; This is a hack. Add in something better? | ||
| 714 | (semanticdb-notify-references | ||
| 715 | table (lambda (tab me) | ||
| 716 | (semantic-decoration-unparsed-include-refrence-reset tab) | ||
| 717 | )) | ||
| 718 | )) | ||
| 719 | |||
| 720 | (defmethod semanticdb-partial-synchronize ((cache semantic-decoration-unparsed-include-cache) | ||
| 721 | new-tags) | ||
| 722 | "Synchronize CACHE with some NEW-TAGS." | ||
| 723 | (if (semantic-find-tags-by-class 'include new-tags) | ||
| 724 | (semantic-reset cache))) | ||
| 725 | |||
| 726 | (defmethod semanticdb-synchronize ((cache semantic-decoration-unparsed-include-cache) | ||
| 727 | new-tags) | ||
| 728 | "Synchronize a CACHE with some NEW-TAGS." | ||
| 729 | (semantic-reset cache)) | ||
| 730 | |||
| 731 | (defun semantic-decoration-unparsed-include-refrence-reset (table) | ||
| 732 | "Refresh any highlighting in buffers referred to by TABLE. | ||
| 733 | If TABLE is not in a buffer, do nothing." | ||
| 734 | ;; This cache removal may seem odd in that we are "creating one", but | ||
| 735 | ;; since we cant get in the fcn unless one exists, this ought to be | ||
| 736 | ;; ok. | ||
| 737 | (let ((c (semanticdb-cache-get | ||
| 738 | table 'semantic-decoration-unparsed-include-cache))) | ||
| 739 | (semanticdb-cache-remove table c)) | ||
| 740 | |||
| 741 | (let ((buf (semanticdb-in-buffer-p table))) | ||
| 742 | (when buf | ||
| 743 | (semantic-decorate-add-pending-decoration | ||
| 744 | 'semantic-decoration-unparsed-include-do-reset | ||
| 745 | buf) | ||
| 746 | ))) | ||
| 747 | |||
| 748 | ;;;;###autoload | ||
| 749 | (defun semantic-decoration-unparsed-include-do-reset () | ||
| 750 | "Do a reset of unparsed includes in the current buffer." | ||
| 751 | (let* ((style (assoc "semantic-decoration-on-includes" | ||
| 752 | semantic-decoration-styles))) | ||
| 753 | (when (cdr style) | ||
| 754 | (let ((allinc (semantic-find-tags-included | ||
| 755 | (semantic-fetch-tags-fast)))) | ||
| 756 | ;; This will do everything, but it should be speedy since it | ||
| 757 | ;; would have been done once already. | ||
| 758 | (semantic-decorate-add-decorations allinc) | ||
| 759 | )))) | ||
| 760 | |||
| 761 | |||
| 762 | (provide 'semantic/decorate/include) | ||
| 763 | |||
| 764 | ;;; semantic/decorate/include.el ends here | ||
diff --git a/lisp/cedet/semantic/decorate/mode.el b/lisp/cedet/semantic/decorate/mode.el new file mode 100644 index 00000000000..a02d4c388fb --- /dev/null +++ b/lisp/cedet/semantic/decorate/mode.el | |||
| @@ -0,0 +1,562 @@ | |||
| 1 | ;;; semantic/decorate/mode.el --- Minor mode for decorating tags | ||
| 2 | |||
| 3 | ;;; Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2007, 2008 | ||
| 4 | ;;; Free Software Foundation, Inc. | ||
| 5 | |||
| 6 | ;; Author: Eric M. Ludlam <zappo@gnu.org> | ||
| 7 | ;; Keywords: syntax | ||
| 8 | |||
| 9 | ;; This file is part of GNU Emacs. | ||
| 10 | |||
| 11 | ;; GNU Emacs 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 3 of the License, or | ||
| 14 | ;; (at your option) any later version. | ||
| 15 | |||
| 16 | ;; GNU Emacs 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. If not, see <http://www.gnu.org/licenses/>. | ||
| 23 | |||
| 24 | ;;; Commentary: | ||
| 25 | ;; | ||
| 26 | ;; A minor mode for use in decorating tags. | ||
| 27 | ;; | ||
| 28 | ;; There are two types of decorations that can be performed on a tag. | ||
| 29 | ;; You can either highlight the full tag, or you can add an | ||
| 30 | ;; independent decoration on some part of the tag body. | ||
| 31 | ;; | ||
| 32 | ;; For independent decoration in particular, managing them so that they | ||
| 33 | ;; do not get corrupted is challenging. This major mode and | ||
| 34 | ;; corresponding macros will make handling those types of decorations | ||
| 35 | ;; easier. | ||
| 36 | ;; | ||
| 37 | |||
| 38 | ;;; Code: | ||
| 39 | (require 'semantic) | ||
| 40 | (require 'semantic/decorate) | ||
| 41 | (require 'semantic/tag-ls) | ||
| 42 | (require 'semantic/util-modes) | ||
| 43 | (eval-when-compile (require 'cl)) | ||
| 44 | |||
| 45 | ;;; Styles List | ||
| 46 | ;; | ||
| 47 | (defcustom semantic-decoration-styles nil | ||
| 48 | "*List of active decoration styles. | ||
| 49 | It is an alist of \(NAME . FLAG) elements, where NAME is a style name | ||
| 50 | and FLAG is non-nil if the style is enabled. | ||
| 51 | See also `define-semantic-decoration-style' which will automatically | ||
| 52 | add items to this list." | ||
| 53 | :group 'semantic | ||
| 54 | :type '(repeat (cons (string :tag "Decoration Name") | ||
| 55 | (boolean :tag "Enabled"))) | ||
| 56 | ) | ||
| 57 | |||
| 58 | ;;; Misc. | ||
| 59 | ;; | ||
| 60 | (defsubst semantic-decorate-style-predicate (style) | ||
| 61 | "Return the STYLE's predicate function." | ||
| 62 | (intern (format "%s-p" style))) | ||
| 63 | |||
| 64 | (defsubst semantic-decorate-style-highlighter (style) | ||
| 65 | "Return the STYLE's highlighter function." | ||
| 66 | (intern (format "%s-highlight" style))) | ||
| 67 | |||
| 68 | ;;; Base decoration API | ||
| 69 | ;; | ||
| 70 | (defsubst semantic-decoration-p (object) | ||
| 71 | "Return non-nil if OBJECT is a tag decoration." | ||
| 72 | (and (semantic-overlay-p object) | ||
| 73 | (semantic-overlay-get object 'semantic-decoration))) | ||
| 74 | |||
| 75 | (defsubst semantic-decoration-set-property (deco property value) | ||
| 76 | "Set the DECO decoration's PROPERTY to VALUE. | ||
| 77 | Return DECO." | ||
| 78 | (assert (semantic-decoration-p deco)) | ||
| 79 | (semantic-overlay-put deco property value) | ||
| 80 | deco) | ||
| 81 | |||
| 82 | (defsubst semantic-decoration-get-property (deco property) | ||
| 83 | "Return the DECO decoration's PROPERTY value." | ||
| 84 | (assert (semantic-decoration-p deco)) | ||
| 85 | (semantic-overlay-get deco property)) | ||
| 86 | |||
| 87 | (defsubst semantic-decoration-set-face (deco face) | ||
| 88 | "Set the face of the decoration DECO to FACE. | ||
| 89 | Return DECO." | ||
| 90 | (semantic-decoration-set-property deco 'face face)) | ||
| 91 | |||
| 92 | (defsubst semantic-decoration-face (deco) | ||
| 93 | "Return the face of the decoration DECO." | ||
| 94 | (semantic-decoration-get-property deco 'face)) | ||
| 95 | |||
| 96 | (defsubst semantic-decoration-set-priority (deco priority) | ||
| 97 | "Set the priority of the decoration DECO to PRIORITY. | ||
| 98 | Return DECO." | ||
| 99 | (assert (natnump priority)) | ||
| 100 | (semantic-decoration-set-property deco 'priority priority)) | ||
| 101 | |||
| 102 | (defsubst semantic-decoration-priority (deco) | ||
| 103 | "Return the priority of the decoration DECO." | ||
| 104 | (semantic-decoration-get-property deco 'priority)) | ||
| 105 | |||
| 106 | (defsubst semantic-decoration-move (deco begin end) | ||
| 107 | "Move the decoration DECO on the region between BEGIN and END. | ||
| 108 | Return DECO." | ||
| 109 | (assert (semantic-decoration-p deco)) | ||
| 110 | (semantic-overlay-move deco begin end) | ||
| 111 | deco) | ||
| 112 | |||
| 113 | ;;; Tag decoration | ||
| 114 | ;; | ||
| 115 | (defun semantic-decorate-tag (tag begin end &optional face) | ||
| 116 | "Add a new decoration on TAG on the region between BEGIN and END. | ||
| 117 | If optional argument FACE is non-nil, set the decoration's face to | ||
| 118 | FACE. | ||
| 119 | Return the overlay that makes up the new decoration." | ||
| 120 | (let ((deco (semantic-tag-create-secondary-overlay tag))) | ||
| 121 | ;; We do not use the unlink property because we do not want to | ||
| 122 | ;; save the highlighting information in the DB. | ||
| 123 | (semantic-overlay-put deco 'semantic-decoration t) | ||
| 124 | (semantic-decoration-move deco begin end) | ||
| 125 | (semantic-decoration-set-face deco face) | ||
| 126 | deco)) | ||
| 127 | |||
| 128 | (defun semantic-decorate-clear-tag (tag &optional deco) | ||
| 129 | "Remove decorations from TAG. | ||
| 130 | If optional argument DECO is non-nil, remove only that decoration." | ||
| 131 | (assert (or (null deco) (semantic-decoration-p deco))) | ||
| 132 | ;; Clear primary decorations. | ||
| 133 | ;; For now, just unhighlight the tag. How to deal with other | ||
| 134 | ;; primary decorations like invisibility, etc. ? Maybe just | ||
| 135 | ;; restoring default values will suffice? | ||
| 136 | (semantic-unhighlight-tag tag) | ||
| 137 | (semantic-tag-delete-secondary-overlay | ||
| 138 | tag (or deco 'semantic-decoration))) | ||
| 139 | |||
| 140 | (defun semantic-decorate-tag-decoration (tag) | ||
| 141 | "Return decoration found on TAG." | ||
| 142 | (semantic-tag-get-secondary-overlay tag 'semantic-decoration)) | ||
| 143 | |||
| 144 | ;;; Global setup of active decorations | ||
| 145 | ;; | ||
| 146 | (defun semantic-decorate-flush-decorations (&optional buffer) | ||
| 147 | "Flush decorations found in BUFFER. | ||
| 148 | BUFFER defaults to the current buffer. | ||
| 149 | Should be used to flush decorations that might remain in BUFFER, for | ||
| 150 | example, after tags have been refreshed." | ||
| 151 | (with-current-buffer (or buffer (current-buffer)) | ||
| 152 | (dolist (o (semantic-overlays-in (point-min) (point-max))) | ||
| 153 | (and (semantic-decoration-p o) | ||
| 154 | (semantic-overlay-delete o))))) | ||
| 155 | |||
| 156 | (defun semantic-decorate-clear-decorations (tag-list) | ||
| 157 | "Remove decorations found in tags in TAG-LIST." | ||
| 158 | (dolist (tag tag-list) | ||
| 159 | (semantic-decorate-clear-tag tag) | ||
| 160 | ;; recurse over children | ||
| 161 | (semantic-decorate-clear-decorations | ||
| 162 | (semantic-tag-components-with-overlays tag)))) | ||
| 163 | |||
| 164 | (defun semantic-decorate-add-decorations (tag-list) | ||
| 165 | "Add decorations to tags in TAG-LIST. | ||
| 166 | Also make sure old decorations in the area are completely flushed." | ||
| 167 | (dolist (tag tag-list) | ||
| 168 | ;; Cleanup old decorations. | ||
| 169 | (when (semantic-decorate-tag-decoration tag) | ||
| 170 | ;; Note on below comment. This happens more as decorations are refreshed | ||
| 171 | ;; mid-way through their use. Remove the message. | ||
| 172 | |||
| 173 | ;; It would be nice if this never happened, but it still does | ||
| 174 | ;; once in a while. Print a message to help flush these | ||
| 175 | ;; situations | ||
| 176 | ;;(message "Decorations still on %s" (semantic-format-tag-name tag)) | ||
| 177 | (semantic-decorate-clear-tag tag)) | ||
| 178 | ;; Add new decorations. | ||
| 179 | (dolist (style semantic-decoration-styles) | ||
| 180 | (let ((pred (semantic-decorate-style-predicate (car style))) | ||
| 181 | (high (semantic-decorate-style-highlighter (car style)))) | ||
| 182 | (and (cdr style) | ||
| 183 | (fboundp pred) | ||
| 184 | (funcall pred tag) | ||
| 185 | (fboundp high) | ||
| 186 | (funcall high tag)))) | ||
| 187 | ;; Recurse on the children of all tags | ||
| 188 | (semantic-decorate-add-decorations | ||
| 189 | (semantic-tag-components-with-overlays tag)))) | ||
| 190 | |||
| 191 | ;;; PENDING DECORATIONS | ||
| 192 | ;; | ||
| 193 | ;; Activities in Emacs may cause a decoration to change state. Any | ||
| 194 | ;; such identified change ought to be setup as PENDING. This means | ||
| 195 | ;; that the next idle step will do the decoration change, but at the | ||
| 196 | ;; time of the state change, minimal work would be done. | ||
| 197 | (defvar semantic-decorate-pending-decoration-hooks nil | ||
| 198 | "Functions to call with pending decoration changes.") | ||
| 199 | |||
| 200 | (defun semantic-decorate-add-pending-decoration (fcn &optional buffer) | ||
| 201 | "Add a pending decoration change represented by FCN. | ||
| 202 | Applies only to the current BUFFER. | ||
| 203 | The setting of FCN will be removed after it is run." | ||
| 204 | (save-excursion | ||
| 205 | (when buffer (set-buffer buffer)) | ||
| 206 | (semantic-make-local-hook 'semantic-decorate-flush-pending-decorations) | ||
| 207 | (add-hook 'semantic-decorate-pending-decoration-hooks fcn nil t))) | ||
| 208 | |||
| 209 | ;;;;###autoload | ||
| 210 | (defun semantic-decorate-flush-pending-decorations (&optional buffer) | ||
| 211 | "Flush any pending decorations for BUFFER. | ||
| 212 | Flush functions from `semantic-decorate-pending-decoration-hooks'." | ||
| 213 | (save-excursion | ||
| 214 | (when buffer (set-buffer buffer)) | ||
| 215 | (run-hooks 'semantic-decorate-pending-decoration-hooks) | ||
| 216 | ;; Always reset the hooks | ||
| 217 | (setq semantic-decorate-pending-decoration-hooks nil))) | ||
| 218 | |||
| 219 | |||
| 220 | ;;; DECORATION MODE | ||
| 221 | ;; | ||
| 222 | ;; Generic mode for handling basic highlighting and decorations. | ||
| 223 | ;; | ||
| 224 | |||
| 225 | (defcustom global-semantic-decoration-mode nil | ||
| 226 | "*If non-nil, enable global use of command `semantic-decoration-mode'. | ||
| 227 | When this mode is activated, decorations specified by | ||
| 228 | `semantic-decoration-styles'." | ||
| 229 | :group 'semantic | ||
| 230 | :group 'semantic-modes | ||
| 231 | :type 'boolean | ||
| 232 | :require 'semantic/decorate/mode | ||
| 233 | :initialize 'custom-initialize-default | ||
| 234 | :set (lambda (sym val) | ||
| 235 | (global-semantic-decoration-mode (if val 1 -1)))) | ||
| 236 | |||
| 237 | (defun global-semantic-decoration-mode (&optional arg) | ||
| 238 | "Toggle global use of option `semantic-decoration-mode'. | ||
| 239 | Decoration mode turns on all active decorations as specified | ||
| 240 | by `semantic-decoration-styles'. | ||
| 241 | If ARG is positive, enable, if it is negative, disable. | ||
| 242 | If ARG is nil, then toggle." | ||
| 243 | (interactive "P") | ||
| 244 | (setq global-semantic-decoration-mode | ||
| 245 | (semantic-toggle-minor-mode-globally | ||
| 246 | 'semantic-decoration-mode arg))) | ||
| 247 | |||
| 248 | (defcustom semantic-decoration-mode-hook nil | ||
| 249 | "*Hook run at the end of function `semantic-decoration-mode'." | ||
| 250 | :group 'semantic | ||
| 251 | :type 'hook) | ||
| 252 | |||
| 253 | ;;;;###autoload | ||
| 254 | (defvar semantic-decoration-mode nil | ||
| 255 | "Non-nil if command `semantic-decoration-mode' is enabled. | ||
| 256 | Use the command `semantic-decoration-mode' to change this variable.") | ||
| 257 | (make-variable-buffer-local 'semantic-decoration-mode) | ||
| 258 | |||
| 259 | (defun semantic-decoration-mode-setup () | ||
| 260 | "Setup the `semantic-decoration-mode' minor mode. | ||
| 261 | The minor mode can be turned on only if the semantic feature is available | ||
| 262 | and the current buffer was set up for parsing. Return non-nil if the | ||
| 263 | minor mode is enabled." | ||
| 264 | (if semantic-decoration-mode | ||
| 265 | (if (not (and (featurep 'semantic) (semantic-active-p))) | ||
| 266 | (progn | ||
| 267 | ;; Disable minor mode if semantic stuff not available | ||
| 268 | (setq semantic-decoration-mode nil) | ||
| 269 | (error "Buffer %s was not set up for parsing" | ||
| 270 | (buffer-name))) | ||
| 271 | ;; Add hooks | ||
| 272 | (semantic-make-local-hook 'semantic-after-partial-cache-change-hook) | ||
| 273 | (add-hook 'semantic-after-partial-cache-change-hook | ||
| 274 | 'semantic-decorate-tags-after-partial-reparse nil t) | ||
| 275 | (semantic-make-local-hook 'semantic-after-toplevel-cache-change-hook) | ||
| 276 | (add-hook 'semantic-after-toplevel-cache-change-hook | ||
| 277 | 'semantic-decorate-tags-after-full-reparse nil t) | ||
| 278 | ;; Add decorations to available tags. The above hooks ensure | ||
| 279 | ;; that new tags will be decorated when they become available. | ||
| 280 | (semantic-decorate-add-decorations (semantic-fetch-available-tags)) | ||
| 281 | ) | ||
| 282 | ;; Remove decorations from available tags. | ||
| 283 | (semantic-decorate-clear-decorations (semantic-fetch-available-tags)) | ||
| 284 | ;; Cleanup any leftover crap too. | ||
| 285 | (semantic-decorate-flush-decorations) | ||
| 286 | ;; Remove hooks | ||
| 287 | (remove-hook 'semantic-after-partial-cache-change-hook | ||
| 288 | 'semantic-decorate-tags-after-partial-reparse t) | ||
| 289 | (remove-hook 'semantic-after-toplevel-cache-change-hook | ||
| 290 | 'semantic-decorate-tags-after-full-reparse t) | ||
| 291 | ) | ||
| 292 | semantic-decoration-mode) | ||
| 293 | |||
| 294 | ;;;;###autoload | ||
| 295 | (defun semantic-decoration-mode (&optional arg) | ||
| 296 | "Minor mode for decorating tags. | ||
| 297 | Decorations are specified in `semantic-decoration-styles'. | ||
| 298 | You can define new decoration styles with | ||
| 299 | `define-semantic-decoration-style'. | ||
| 300 | With prefix argument ARG, turn on if positive, otherwise off. The | ||
| 301 | minor mode can be turned on only if semantic feature is available and | ||
| 302 | the current buffer was set up for parsing. Return non-nil if the | ||
| 303 | minor mode is enabled." | ||
| 304 | ;; | ||
| 305 | ;;\\{semantic-decoration-map}" | ||
| 306 | (interactive | ||
| 307 | (list (or current-prefix-arg | ||
| 308 | (if semantic-decoration-mode 0 1)))) | ||
| 309 | (setq semantic-decoration-mode | ||
| 310 | (if arg | ||
| 311 | (> | ||
| 312 | (prefix-numeric-value arg) | ||
| 313 | 0) | ||
| 314 | (not semantic-decoration-mode))) | ||
| 315 | (semantic-decoration-mode-setup) | ||
| 316 | (run-hooks 'semantic-decoration-mode-hook) | ||
| 317 | (if (interactive-p) | ||
| 318 | (message "decoration-mode minor mode %sabled" | ||
| 319 | (if semantic-decoration-mode "en" "dis"))) | ||
| 320 | (semantic-mode-line-update) | ||
| 321 | semantic-decoration-mode) | ||
| 322 | |||
| 323 | (semantic-add-minor-mode 'semantic-decoration-mode | ||
| 324 | "" | ||
| 325 | nil) | ||
| 326 | |||
| 327 | (defun semantic-decorate-tags-after-full-reparse (tag-list) | ||
| 328 | "Add decorations after a complete reparse of the current buffer. | ||
| 329 | TAG-LIST is the list of tags recently parsed. | ||
| 330 | Flush all existing decorations and call `semantic-decorate-add-decorations' to | ||
| 331 | add decorations. | ||
| 332 | Called from `semantic-after-toplevel-cache-change-hook'." | ||
| 333 | ;; Flush everything | ||
| 334 | (semantic-decorate-flush-decorations) | ||
| 335 | ;; Add it back on | ||
| 336 | (semantic-decorate-add-decorations tag-list)) | ||
| 337 | |||
| 338 | (defun semantic-decorate-tags-after-partial-reparse (tag-list) | ||
| 339 | "Add decorations when new tags are created in the current buffer. | ||
| 340 | TAG-LIST is the list of newly created tags. | ||
| 341 | Call `semantic-decorate-add-decorations' to add decorations. | ||
| 342 | Called from `semantic-after-partial-cache-change-hook'." | ||
| 343 | (semantic-decorate-add-decorations tag-list)) | ||
| 344 | |||
| 345 | |||
| 346 | ;;; Enable/Disable toggling | ||
| 347 | ;; | ||
| 348 | (defun semantic-decoration-style-enabled-p (style) | ||
| 349 | "Return non-nil if STYLE is currently enabled. | ||
| 350 | Return nil if the style is disabled, or does not exist." | ||
| 351 | (let ((pair (assoc style semantic-decoration-styles))) | ||
| 352 | (and pair (cdr pair)))) | ||
| 353 | |||
| 354 | (defun semantic-toggle-decoration-style (name &optional arg) | ||
| 355 | "Turn on/off the decoration style with NAME. | ||
| 356 | Decorations are specified in `semantic-decoration-styles'. | ||
| 357 | With prefix argument ARG, turn on if positive, otherwise off. | ||
| 358 | Return non-nil if the decoration style is enabled." | ||
| 359 | (interactive | ||
| 360 | (list (completing-read "Decoration style: " | ||
| 361 | semantic-decoration-styles nil t) | ||
| 362 | current-prefix-arg)) | ||
| 363 | (setq name (format "%s" name)) ;; Ensure NAME is a string. | ||
| 364 | (unless (equal name "") | ||
| 365 | (let* ((style (assoc name semantic-decoration-styles)) | ||
| 366 | (flag (if arg | ||
| 367 | (> (prefix-numeric-value arg) 0) | ||
| 368 | (not (cdr style))))) | ||
| 369 | (unless (eq (cdr style) flag) | ||
| 370 | ;; Store the new flag. | ||
| 371 | (setcdr style flag) | ||
| 372 | ;; Refresh decorations is `semantic-decoration-mode' is on. | ||
| 373 | (when semantic-decoration-mode | ||
| 374 | (semantic-decoration-mode -1) | ||
| 375 | (semantic-decoration-mode 1)) | ||
| 376 | (when (interactive-p) | ||
| 377 | (message "Decoration style %s turned %s" (car style) | ||
| 378 | (if flag "on" "off")))) | ||
| 379 | flag))) | ||
| 380 | |||
| 381 | (defvar semantic-decoration-menu-cache nil | ||
| 382 | "Cache of the decoration menu.") | ||
| 383 | |||
| 384 | (defun semantic-decoration-build-style-menu (style) | ||
| 385 | "Build a menu item for controlling a specific decoration STYLE." | ||
| 386 | (vector (car style) | ||
| 387 | `(lambda () (interactive) | ||
| 388 | (semantic-toggle-decoration-style | ||
| 389 | ,(car style))) | ||
| 390 | :style 'toggle | ||
| 391 | :selected `(semantic-decoration-style-enabled-p ,(car style)) | ||
| 392 | )) | ||
| 393 | |||
| 394 | ;;;;###autoload | ||
| 395 | (defun semantic-build-decoration-mode-menu (&rest ignore) | ||
| 396 | "Create a menu listing all the known decorations for toggling. | ||
| 397 | IGNORE any input arguments." | ||
| 398 | (or semantic-decoration-menu-cache | ||
| 399 | (setq semantic-decoration-menu-cache | ||
| 400 | (mapcar 'semantic-decoration-build-style-menu | ||
| 401 | (reverse semantic-decoration-styles)) | ||
| 402 | ))) | ||
| 403 | |||
| 404 | |||
| 405 | ;;; Defining decoration styles | ||
| 406 | ;; | ||
| 407 | (defmacro define-semantic-decoration-style (name doc &rest flags) | ||
| 408 | "Define a new decoration style with NAME. | ||
| 409 | DOC is a documentation string describing the decoration style NAME. | ||
| 410 | It is appended to auto-generated doc strings. | ||
| 411 | An Optional list of FLAGS can also be specified. Flags are: | ||
| 412 | :enabled <value> - specify the default enabled value for NAME. | ||
| 413 | |||
| 414 | |||
| 415 | This defines two new overload functions respectively called `NAME-p' | ||
| 416 | and `NAME-highlight', for which you must provide a default | ||
| 417 | implementation in respectively the functions `NAME-p-default' and | ||
| 418 | `NAME-highlight-default'. Those functions are passed a tag. `NAME-p' | ||
| 419 | must return non-nil to indicate that the tag should be decorated by | ||
| 420 | `NAME-highlight'. | ||
| 421 | |||
| 422 | To put primary decorations on a tag `NAME-highlight' must use | ||
| 423 | functions like `semantic-set-tag-face', `semantic-set-tag-intangible', | ||
| 424 | etc., found in the semantic-decorate library. | ||
| 425 | |||
| 426 | To add other kind of decorations on a tag, `NAME-highlight' must use | ||
| 427 | `semantic-decorate-tag', and other functions of the semantic | ||
| 428 | decoration API found in this library." | ||
| 429 | (let ((predicate (semantic-decorate-style-predicate name)) | ||
| 430 | (highlighter (semantic-decorate-style-highlighter name)) | ||
| 431 | (defaultenable (if (plist-member flags :enabled) | ||
| 432 | (plist-get flags :enabled) | ||
| 433 | t)) | ||
| 434 | ) | ||
| 435 | `(progn | ||
| 436 | ;; Clear the menu cache so that new items are added when | ||
| 437 | ;; needed. | ||
| 438 | (setq semantic-decoration-menu-cache nil) | ||
| 439 | ;; Create an override method to specify if a given tag belongs | ||
| 440 | ;; to this type of decoration | ||
| 441 | (define-overloadable-function ,predicate (tag) | ||
| 442 | ,(format "Return non-nil to decorate TAG with `%s' style.\n%s" | ||
| 443 | name doc)) | ||
| 444 | ;; Create an override method that will perform the highlight | ||
| 445 | ;; operation if the -p method returns non-nil. | ||
| 446 | (define-overloadable-function ,highlighter (tag) | ||
| 447 | ,(format "Decorate TAG with `%s' style.\n%s" | ||
| 448 | name doc)) | ||
| 449 | ;; Add this to the list of primary decoration modes. | ||
| 450 | (add-to-list 'semantic-decoration-styles | ||
| 451 | (cons ',(symbol-name name) | ||
| 452 | ,defaultenable)) | ||
| 453 | ))) | ||
| 454 | |||
| 455 | ;;; Predefined decoration styles | ||
| 456 | ;; | ||
| 457 | |||
| 458 | ;;; Tag boundaries highlighting | ||
| 459 | ;; | ||
| 460 | (define-semantic-decoration-style semantic-tag-boundary | ||
| 461 | "Place an overline in front of each long tag. | ||
| 462 | Does not provide overlines for prototypes.") | ||
| 463 | |||
| 464 | (defface semantic-tag-boundary-face | ||
| 465 | '((((class color) (background dark)) | ||
| 466 | (:overline "cyan")) | ||
| 467 | (((class color) (background light)) | ||
| 468 | (:overline "blue"))) | ||
| 469 | "*Face used to show long tags in. | ||
| 470 | Used by decoration style: `semantic-tag-boundary'." | ||
| 471 | :group 'semantic-faces) | ||
| 472 | |||
| 473 | (defun semantic-tag-boundary-p-default (tag) | ||
| 474 | "Return non-nil if TAG is a type, or a non-prototype function." | ||
| 475 | (let ((c (semantic-tag-class tag))) | ||
| 476 | (and | ||
| 477 | (or | ||
| 478 | ;; All types get a line? | ||
| 479 | (eq c 'type) | ||
| 480 | ;; Functions which aren't prototypes get a line. | ||
| 481 | (and (eq c 'function) | ||
| 482 | (not (semantic-tag-get-attribute tag :prototype-flag))) | ||
| 483 | ) | ||
| 484 | ;; Note: The below restriction confused users. | ||
| 485 | ;; | ||
| 486 | ;; Nothing smaller than a few lines | ||
| 487 | ;;(> (- (semantic-tag-end tag) (semantic-tag-start tag)) 150) | ||
| 488 | ;; Random truth | ||
| 489 | t) | ||
| 490 | )) | ||
| 491 | |||
| 492 | (defun semantic-tag-boundary-highlight-default (tag) | ||
| 493 | "Highlight the first line of TAG as a boundary." | ||
| 494 | (when (bufferp (semantic-tag-buffer tag)) | ||
| 495 | (with-current-buffer (semantic-tag-buffer tag) | ||
| 496 | (semantic-decorate-tag | ||
| 497 | tag | ||
| 498 | (semantic-tag-start tag) | ||
| 499 | (save-excursion | ||
| 500 | (goto-char (semantic-tag-start tag)) | ||
| 501 | (end-of-line) | ||
| 502 | (forward-char 1) | ||
| 503 | (point)) | ||
| 504 | 'semantic-tag-boundary-face)) | ||
| 505 | )) | ||
| 506 | |||
| 507 | ;;; Private member highlighting | ||
| 508 | ;; | ||
| 509 | (define-semantic-decoration-style semantic-decoration-on-private-members | ||
| 510 | "Highlight class members that are designated as PRIVATE access." | ||
| 511 | :enabled nil) | ||
| 512 | |||
| 513 | (defface semantic-decoration-on-private-members-face | ||
| 514 | '((((class color) (background dark)) | ||
| 515 | (:background "#200000")) | ||
| 516 | (((class color) (background light)) | ||
| 517 | (:background "#8fffff"))) | ||
| 518 | "*Face used to show privately scoped tags in. | ||
| 519 | Used by the decoration style: `semantic-decoration-on-private-members'." | ||
| 520 | :group 'semantic-faces) | ||
| 521 | |||
| 522 | (defun semantic-decoration-on-private-members-highlight-default (tag) | ||
| 523 | "Highlight TAG as designated to have PRIVATE access. | ||
| 524 | Use a primary decoration." | ||
| 525 | (semantic-set-tag-face | ||
| 526 | tag 'semantic-decoration-on-private-members-face)) | ||
| 527 | |||
| 528 | (defun semantic-decoration-on-private-members-p-default (tag) | ||
| 529 | "Return non-nil if TAG has PRIVATE access." | ||
| 530 | (and (member (semantic-tag-class tag) '(function variable)) | ||
| 531 | (eq (semantic-tag-protection tag) 'private))) | ||
| 532 | |||
| 533 | ;;; Protected member highlighting | ||
| 534 | ;; | ||
| 535 | (defface semantic-decoration-on-protected-members-face | ||
| 536 | '((((class color) (background dark)) | ||
| 537 | (:background "#000020")) | ||
| 538 | (((class color) (background light)) | ||
| 539 | (:background "#fffff8"))) | ||
| 540 | "*Face used to show protected scoped tags in. | ||
| 541 | Used by the decoration style: `semantic-decoration-on-protected-members'." | ||
| 542 | :group 'semantic-faces) | ||
| 543 | |||
| 544 | (define-semantic-decoration-style semantic-decoration-on-protected-members | ||
| 545 | "Highlight class members that are designated as PROTECTED access." | ||
| 546 | :enabled nil) | ||
| 547 | |||
| 548 | (defun semantic-decoration-on-protected-members-p-default (tag) | ||
| 549 | "Return non-nil if TAG has PROTECTED access." | ||
| 550 | (and (member (semantic-tag-class tag) '(function variable)) | ||
| 551 | (eq (semantic-tag-protection tag) 'protected))) | ||
| 552 | |||
| 553 | (defun semantic-decoration-on-protected-members-highlight-default (tag) | ||
| 554 | "Highlight TAG as designated to have PROTECTED access. | ||
| 555 | Use a primary decoration." | ||
| 556 | (semantic-set-tag-face | ||
| 557 | tag 'semantic-decoration-on-protected-members-face)) | ||
| 558 | |||
| 559 | (provide 'semantic/decorate/mode) | ||
| 560 | |||
| 561 | ;;; semantic/decorate/mode.el ends here | ||
| 562 | |||