2010-03-13 10:49:54 -05:00
|
|
|
;;; semantic/imenu.el --- Use Semantic as an imenu tag generator
|
|
|
|
|
2015-01-01 14:26:41 -08:00
|
|
|
;; Copyright (C) 2000-2005, 2007-2008, 2010-2015 Free Software
|
|
|
|
;; Foundation, Inc.
|
2010-03-13 10:49:54 -05:00
|
|
|
|
|
|
|
;; Author: Eric M. Ludlam <zappo@gnu.org>
|
|
|
|
;; Maintainer: Eric Ludlam
|
|
|
|
|
|
|
|
;; This file is part of GNU Emacs.
|
|
|
|
|
|
|
|
;; GNU Emacs is free software: you can redistribute it and/or modify
|
|
|
|
;; it under the terms of the GNU General Public License as published by
|
|
|
|
;; the Free Software Foundation, either version 3 of the License, or
|
|
|
|
;; (at your option) any later version.
|
|
|
|
|
|
|
|
;; GNU Emacs is distributed in the hope that it will be useful,
|
|
|
|
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
;; GNU General Public License for more details.
|
|
|
|
|
|
|
|
;; You should have received a copy of the GNU General Public License
|
|
|
|
;; along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
|
|
|
|
;;; Commentary:
|
|
|
|
;;
|
|
|
|
;; This support function can be used in any buffer which supports
|
|
|
|
;; the bovinator to create the imenu index.
|
|
|
|
;;
|
|
|
|
;; To use this in a buffer, do this in a hook.
|
|
|
|
;;
|
|
|
|
;; (add-hook 'mode-hook
|
|
|
|
;; (lambda ()
|
|
|
|
;; (setq imenu-create-index-function 'semantic-create-imenu-index)
|
|
|
|
;; ))
|
|
|
|
|
|
|
|
(require 'semantic)
|
|
|
|
(require 'semantic/format)
|
|
|
|
(require 'semantic/db)
|
|
|
|
(require 'semantic/db-file)
|
|
|
|
(require 'semantic/sort)
|
|
|
|
(require 'imenu)
|
|
|
|
|
|
|
|
(declare-function pulse-momentary-highlight-one-line "pulse" (o &optional face))
|
|
|
|
(declare-function semanticdb-semantic-init-hook-fcn "db-mode")
|
|
|
|
|
|
|
|
;; Because semantic imenu tags will hose the current imenu handling
|
|
|
|
;; code in speedbar, force semantic/sb in.
|
|
|
|
(if (featurep 'speedbar)
|
|
|
|
(require 'semantic/sb)
|
|
|
|
(add-hook 'speedbar-load-hook (lambda () (require 'semantic/sb))))
|
|
|
|
|
|
|
|
(defgroup semantic-imenu nil
|
|
|
|
"Semantic interface to Imenu."
|
|
|
|
:group 'semantic
|
|
|
|
:group 'imenu
|
|
|
|
)
|
|
|
|
|
|
|
|
;;;###autoload
|
|
|
|
(defcustom semantic-imenu-summary-function 'semantic-format-tag-abbreviate
|
|
|
|
"*Function to use when creating items in Imenu.
|
|
|
|
Some useful functions are found in `semantic-format-tag-functions'."
|
|
|
|
:group 'semantic-imenu
|
|
|
|
:type semantic-format-tag-custom-list)
|
|
|
|
(make-variable-buffer-local 'semantic-imenu-summary-function)
|
|
|
|
|
|
|
|
;;;###autoload
|
|
|
|
(defcustom semantic-imenu-bucketize-file t
|
|
|
|
"*Non-nil if tags in a file are to be grouped into buckets."
|
|
|
|
:group 'semantic-imenu
|
|
|
|
:type 'boolean)
|
|
|
|
(make-variable-buffer-local 'semantic-imenu-bucketize-file)
|
|
|
|
|
|
|
|
(defcustom semantic-imenu-adopt-external-members t
|
|
|
|
"*Non-nil if types in a file should adopt externally defined members.
|
|
|
|
C++ and CLOS can define methods that are not in the body of a class
|
|
|
|
definition."
|
|
|
|
:group 'semantic-imenu
|
|
|
|
:type 'boolean)
|
|
|
|
|
|
|
|
(defcustom semantic-imenu-buckets-to-submenu t
|
|
|
|
"*Non-nil if buckets of tags are to be turned into submenus.
|
|
|
|
This option is ignored if `semantic-imenu-bucketize-file' is nil."
|
|
|
|
:group 'semantic-imenu
|
|
|
|
:type 'boolean)
|
|
|
|
(make-variable-buffer-local 'semantic-imenu-buckets-to-submenu)
|
|
|
|
|
|
|
|
;;;###autoload
|
|
|
|
(defcustom semantic-imenu-expand-type-members t
|
|
|
|
"*Non-nil if types should have submenus with members in them."
|
|
|
|
:group 'semantic-imenu
|
|
|
|
:type 'boolean)
|
|
|
|
(make-variable-buffer-local 'semantic-imenu-expand-type-members)
|
|
|
|
(semantic-varalias-obsolete 'semantic-imenu-expand-type-parts
|
|
|
|
'semantic-imenu-expand-type-members "23.2")
|
|
|
|
|
|
|
|
(defcustom semantic-imenu-bucketize-type-members t
|
|
|
|
"*Non-nil if members of a type should be grouped into buckets.
|
2010-04-02 04:25:19 +02:00
|
|
|
A nil value means to keep them in the same order.
|
2011-11-13 22:27:12 -08:00
|
|
|
Overridden to nil if `semantic-imenu-bucketize-file' is nil."
|
2010-03-13 10:49:54 -05:00
|
|
|
:group 'semantic-imenu
|
|
|
|
:type 'boolean)
|
Synch Semantic to CEDET 1.0.
Move CEDET ChangeLog entries to new file lisp/cedet/ChangeLog.
* semantic.el (semantic-version): Update to 2.0.
(semantic-mode-map): Add "," and "m" bindings.
(navigate-menu): Update.
* semantic/symref.el (semantic-symref-calculate-rootdir):
New function.
(semantic-symref-detect-symref-tool): Use it.
* semantic/symref/grep.el (semantic-symref-grep-shell): New var.
(semantic-symref-perform-search): Use it. Calculate root dir with
semantic-symref-calculate-rootdir.
(semantic-symref-derive-find-filepatterns): Improve error message.
* semantic/symref/list.el
(semantic-symref-results-mode-map): New bindings.
(semantic-symref-auto-expand-results): New option.
(semantic-symref-results-dump): Obey auto-expand.
(semantic-symref-list-expand-all, semantic-symref-regexp)
(semantic-symref-list-contract-all)
(semantic-symref-list-map-open-hits)
(semantic-symref-list-update-open-hits)
(semantic-symref-list-create-macro-on-open-hit)
(semantic-symref-list-call-macro-on-open-hits): New functions.
(semantic-symref-list-menu-entries)
(semantic-symref-list-menu): New vars.
(semantic-symref-list-map-open-hits): Move cursor to beginning of
match before calling the mapped function.
* semantic/doc.el
(semantic-documentation-comment-preceeding-tag): Do nothing if the
mode doesn't provide comment-start-skip.
* semantic/scope.el
(semantic-analyze-scope-nested-tags-default): Strip duplicates.
(semantic-analyze-scoped-inherited-tag-map): Take the tag we are
looking for as part of the scoped tags list.
* semantic/html.el (semantic-default-html-setup): Add
senator-step-at-tag-classes.
* semantic/decorate/include.el
(semantic-decoration-on-unknown-includes): Change light bgcolor.
(semantic-decoration-on-includes-highlight-default): Check that
the include tag has a postion.
* semantic/complete.el (semantic-collector-local-members):
(semantic-complete-read-tag-local-members)
(semantic-complete-jump-local-members): New class and functions.
(semantic-complete-self-insert): Save excursion before completing.
* semantic/analyze/complete.el
(semantic-analyze-possible-completions-default): If no completions
are found, return the raw by-name-only completion list. Add FLAGS
arguments. Add support for 'no-tc (type constraint) and
'no-unique, or no stripping duplicates.
(semantic-analyze-possible-completions-default): Add FLAGS arg.
* semantic/util-modes.el
(semantic-stickyfunc-show-only-functions-p): New option.
(semantic-stickyfunc-fetch-stickyline): Don't show stickytext for
the very first line in a buffer.
* semantic/util.el (semantic-hack-search)
(semantic-recursive-find-nonterminal-by-name)
(semantic-current-tag-interactive): Deleted.
(semantic-describe-buffer): Fix expand-nonterminal. Add
lex-syntax-mods, type relation separator char, and command
separation char.
(semantic-sanity-check): Only message if called interactively.
* semantic/tag.el (semantic-tag-deep-copy-one-tag): Copy the
:filename property and the tag position.
* semantic/lex-spp.el (semantic-lex-spp-lex-text-string):
Add recursion limit.
* semantic/imenu.el (semantic-imenu-bucketize-type-members):
Make this buffer local, not the obsoleted variable.
* semantic/idle.el: Add breadcrumbs support.
(semantic-idle-summary-current-symbol-info-default)
(semantic-idle-tag-highlight)
(semantic-idle-completion-list-default): Use
semanticdb-without-unloaded-file-searches for speed, and to
conform to the controls that specify if the idle timer is supposed
to be parsing unparsed includes.
(semantic-idle-symbol-highlight-face)
(semantic-idle-symbol-maybe-highlight): Rename from *-summary-*.
Callers changed.
(semantic-idle-work-parse-neighboring-files-flag): Default to nil.
(semantic-idle-work-update-headers-flag): New var.
(semantic-idle-work-for-one-buffer): Use it.
(semantic-idle-local-symbol-highlight): Rename from
semantic-idle-tag-highlight.
(semantic-idle-truncate-long-summaries): New option.
* semantic/ia.el (semantic-ia-cache)
(semantic-ia-get-completions): Deleted. Callers changed.
(semantic-ia-show-variants): New command.
(semantic-ia-show-doc): If doc is empty, don't make a temp buffer.
(semantic-ia-show-summary): If there isn't anything to show, say so.
* semantic/grammar.el (semantic-grammar-create-package):
Save the buffer even in batch mode.
* semantic/fw.el
(semanticdb-without-unloaded-file-searches): New macro.
* semantic/dep.el (semantic-dependency-find-file-on-path):
Fix case dereferencing ede-object when it is a list.
* semantic/db-typecache.el (semanticdb-expand-nested-tag)
(semanticdb-typecache-faux-namespace): New functions.
(semanticdb-typecache-file-tags)
(semanticdb-typecache-merge-streams): Use them.
(semanticdb-typecache-file-tags): When deriving tags from a file,
give the mode a chance to monkey with the tag copy.
(semanticdb-typecache-find-default): Wrap find in save-excursion.
(semanticdb-typecache-find-by-name-helper): Merge found names down.
* semantic/db-global.el
(semanticdb-enable-gnu-global-in-buffer): Don't show messages if
GNU Global is not available and we don't want to throw an error.
* semantic/db-find.el (semanticdb-find-result-nth-in-buffer):
When trying to normalize the tag to a buffer, don't error if
set-buffer method doesn't exist.
* semantic/db-file.el (semanticdb-save-db): Simplify msg.
* semantic/db.el (semanticdb-refresh-table): If forcing a
refresh on a file not in a buffer, use semantic-find-file-noselect
and delete the buffer after use.
(semanticdb-current-database-list): When calculating root via
hooks, force it through true-filename and skip the list of
possible roots.
* semantic/ctxt.el (semantic-ctxt-imported-packages): New.
* semantic/analyze/debug.el
(semantic-analyzer-debug-insert-tag): Reset standard output to
current buffer.
(semantic-analyzer-debug-global-symbol)
(semantic-analyzer-debug-missing-innertype): Change "prefix" to
"symbol" in messages.
* semantic/analyze/refs.el: (semantic-analyze-refs-impl)
(semantic-analyze-refs-proto): When calculating value, make sure
the found tag is 'similar' to the originating tag.
(semantic--analyze-refs-find-tags-with-parent): Attempt to
identify matches via imported symbols of parents.
(semantic--analyze-refs-full-lookup-with-parents): Do a deep
search during the brute search.
* semantic/analyze.el
(semantic-analyze-find-tag-sequence-default): Be robust to
calculated scopes being nil.
* semantic/bovine/c.el (semantic-c-describe-environment): Add
project macro symbol array.
(semantic-c-parse-lexical-token): Add recursion limit.
(semantic-ctxt-imported-packages, semanticdb-expand-nested-tag):
New overrides.
(semantic-expand-c-tag-namelist): Split a full type from a typedef
out to its own tag.
(semantic-expand-c-tag-namelist): Do not split out a typedef'd
inline type if it is an anonymous type.
(semantic-c-reconstitute-token): Use the optional initializers as
a clue that some function is probably a constructor. When
defining the type of these constructors, split the parent name,
and use only the class part, if applicable.
* semantic/bovine/c-by.el:
* semantic/wisent/python-wy.el: Regenerate.
2010-09-18 22:49:54 -04:00
|
|
|
(make-variable-buffer-local 'semantic-imenu-bucketize-type-members)
|
2010-03-13 10:49:54 -05:00
|
|
|
(semantic-varalias-obsolete 'semantic-imenu-bucketize-type-parts
|
|
|
|
'semantic-imenu-bucketize-type-members "23.2")
|
|
|
|
|
|
|
|
(defcustom semantic-imenu-sort-bucket-function nil
|
|
|
|
"*Function to use when sorting tags in the buckets of functions.
|
|
|
|
See `semantic-bucketize' and the FILTER argument for more details on this function."
|
|
|
|
:group 'semantic-imenu
|
|
|
|
:type '(radio (const :tag "No Sorting" nil)
|
|
|
|
(const semantic-sort-tags-by-name-increasing)
|
|
|
|
(const semantic-sort-tags-by-name-decreasing)
|
|
|
|
(const semantic-sort-tags-by-type-increasing)
|
|
|
|
(const semantic-sort-tags-by-type-decreasing)
|
|
|
|
(const semantic-sort-tags-by-name-increasing-ci)
|
|
|
|
(const semantic-sort-tags-by-name-decreasing-ci)
|
|
|
|
(const semantic-sort-tags-by-type-increasing-ci)
|
|
|
|
(const semantic-sort-tags-by-type-decreasing-ci)
|
|
|
|
(function)))
|
|
|
|
(make-variable-buffer-local 'semantic-imenu-sort-bucket-function)
|
|
|
|
|
|
|
|
(defcustom semantic-imenu-index-directory nil
|
|
|
|
"*Non nil to index the entire directory for tags.
|
|
|
|
Doesn't actually parse the entire directory, but displays tags for all files
|
|
|
|
currently listed in the current Semantic database.
|
|
|
|
This variable has no meaning if semanticdb is not active."
|
|
|
|
:group 'semantic-imenu
|
|
|
|
:type 'boolean)
|
|
|
|
|
|
|
|
(defcustom semantic-imenu-auto-rebuild-directory-indexes nil
|
|
|
|
"*If non-nil automatically rebuild directory index imenus.
|
|
|
|
That is when a directory index imenu is updated, automatically rebuild
|
|
|
|
other buffer local ones based on the same semanticdb."
|
|
|
|
:group 'semantic-imenu
|
|
|
|
:type 'boolean)
|
|
|
|
|
|
|
|
(defvar semantic-imenu-directory-current-file nil
|
|
|
|
"When building a file index, this is the file name currently being built.")
|
|
|
|
|
|
|
|
(defvar semantic-imenu-auto-rebuild-running nil
|
|
|
|
"Non-nil if `semantic-imenu-rebuild-directory-indexes' is running.")
|
|
|
|
|
|
|
|
;;;###autoload
|
|
|
|
(defvar semantic-imenu-expandable-tag-classes '(type)
|
|
|
|
"List of expandable tag classes.
|
|
|
|
Tags of those classes will be given submenu with children.
|
|
|
|
By default, a `type' has interesting children. In Texinfo, however, a
|
|
|
|
`section' has interesting children.")
|
|
|
|
(make-variable-buffer-local 'semantic-imenu-expandable-tag-classes)
|
|
|
|
(semantic-varalias-obsolete 'semantic-imenu-expandable-token
|
|
|
|
'semantic-imenu-expandable-tag-classes "23.2")
|
|
|
|
|
|
|
|
;;; Code:
|
|
|
|
(defun semantic-imenu-tag-overlay (tag)
|
|
|
|
"Return the overlay belonging to tag.
|
|
|
|
If TAG doesn't have an overlay, and instead as a vector of positions,
|
|
|
|
concoct a combination of file name, and position."
|
|
|
|
(let ((o (semantic-tag-overlay tag)))
|
|
|
|
(if (not (semantic-overlay-p o))
|
|
|
|
(let ((v (make-vector 3 nil)))
|
|
|
|
(aset v 0 semantic-imenu-directory-current-file)
|
|
|
|
(aset v 1 (aref o 0))
|
|
|
|
(aset v 2 (aref o 1))
|
|
|
|
v)
|
|
|
|
o)))
|
|
|
|
|
|
|
|
|
|
|
|
(defun semantic-imenu-goto-function (name position &optional rest)
|
|
|
|
"Move point associated with NAME to POSITION.
|
2010-04-02 04:25:19 +02:00
|
|
|
Used to override function `imenu-default-goto-function' so that
|
|
|
|
we can continue to use overlays to maintain the current position.
|
2010-03-13 10:49:54 -05:00
|
|
|
Optional argument REST is some extra stuff."
|
|
|
|
(require 'pulse)
|
|
|
|
(if (semantic-overlay-p position)
|
|
|
|
(let ((os (semantic-overlay-start position))
|
|
|
|
(ob (semantic-overlay-buffer position)))
|
|
|
|
(if os
|
|
|
|
(progn
|
|
|
|
(if (not (eq ob (current-buffer)))
|
|
|
|
(switch-to-buffer ob))
|
|
|
|
(imenu-default-goto-function name os rest)
|
|
|
|
(pulse-momentary-highlight-one-line (point))
|
|
|
|
)
|
|
|
|
;; This should never happen, but check anyway.
|
|
|
|
(message "Imenu is out of date, try again. (internal bug)")
|
|
|
|
(setq imenu--index-alist nil)))
|
|
|
|
;; When the POSITION is actually a pair of numbers in an array, then
|
|
|
|
;; the file isn't loaded into the current buffer.
|
|
|
|
(if (vectorp position)
|
|
|
|
(let ((file (aref position 0))
|
|
|
|
(pos (aref position 1)))
|
|
|
|
(and file (find-file file))
|
|
|
|
(imenu-default-goto-function name pos rest)
|
|
|
|
(pulse-momentary-highlight-one-line (point))
|
|
|
|
)
|
|
|
|
;; When the POSITION is the symbol 'file-only' it means that this
|
|
|
|
;; is a directory index entry and there is no tags in this
|
|
|
|
;; file. So just jump to the beginning of the file.
|
|
|
|
(if (eq position 'file-only)
|
|
|
|
(progn
|
|
|
|
(find-file name)
|
|
|
|
(imenu-default-goto-function name (point-min) rest)
|
|
|
|
(pulse-momentary-highlight-one-line (point))
|
|
|
|
)
|
|
|
|
;; Probably POSITION don't came from a semantic imenu. Try
|
|
|
|
;; the default imenu goto function.
|
|
|
|
(condition-case nil
|
|
|
|
(progn
|
|
|
|
(imenu-default-goto-function name position rest)
|
|
|
|
(pulse-momentary-highlight-one-line (point))
|
|
|
|
)
|
|
|
|
(error
|
|
|
|
(message "Semantic Imenu override problem. (Internal bug)")
|
|
|
|
(setq imenu--index-alist nil)))))
|
|
|
|
))
|
|
|
|
|
|
|
|
(defun semantic-imenu-flush-fcn (&optional ignore)
|
|
|
|
"This function is called as a hook to clear the imenu cache.
|
|
|
|
It is cleared after any parsing.
|
|
|
|
IGNORE arguments."
|
|
|
|
(if (eq imenu-create-index-function 'semantic-create-imenu-index)
|
|
|
|
(setq imenu--index-alist nil
|
|
|
|
imenu-menubar-modified-tick 0))
|
|
|
|
(remove-hook 'semantic-after-toplevel-cache-change-hook
|
|
|
|
'semantic-imenu-flush-fcn t)
|
|
|
|
(remove-hook 'semantic-after-partial-cache-change-hook
|
|
|
|
'semantic-imenu-flush-fcn t)
|
|
|
|
)
|
|
|
|
|
|
|
|
;;;###autoload
|
|
|
|
(defun semantic-create-imenu-index (&optional stream)
|
|
|
|
"Create an imenu index for any buffer which supports Semantic.
|
|
|
|
Uses the output of the Semantic parser to create the index.
|
|
|
|
Optional argument STREAM is an optional stream of tags used to create menus."
|
|
|
|
(setq imenu-default-goto-function 'semantic-imenu-goto-function)
|
|
|
|
(prog1
|
|
|
|
(if (and semantic-imenu-index-directory
|
2010-09-29 12:09:21 -04:00
|
|
|
(featurep 'semantic/db)
|
2010-03-13 10:49:54 -05:00
|
|
|
(semanticdb-minor-mode-p))
|
|
|
|
(semantic-create-imenu-directory-index
|
|
|
|
(or stream (semantic-fetch-tags-fast)))
|
|
|
|
(semantic-create-imenu-index-1
|
|
|
|
(or stream (semantic-fetch-tags-fast)) nil))
|
|
|
|
(semantic-make-local-hook 'semantic-after-toplevel-cache-change-hook)
|
|
|
|
(add-hook 'semantic-after-toplevel-cache-change-hook
|
|
|
|
'semantic-imenu-flush-fcn nil t)
|
|
|
|
(semantic-make-local-hook 'semantic-after-partial-cache-change-hook)
|
|
|
|
(add-hook 'semantic-after-partial-cache-change-hook
|
|
|
|
'semantic-imenu-flush-fcn nil t)))
|
|
|
|
|
|
|
|
(defun semantic-create-imenu-directory-index (&optional stream)
|
2010-04-02 04:25:19 +02:00
|
|
|
"Create an imenu tag index based on all files active in semanticdb.
|
2010-03-13 10:49:54 -05:00
|
|
|
Optional argument STREAM is the stream of tags for the current buffer."
|
|
|
|
(if (not semanticdb-current-database)
|
|
|
|
(semantic-create-imenu-index-1 stream nil)
|
|
|
|
;; We have a database, list all files, with the current file on top.
|
|
|
|
(let ((index (list
|
|
|
|
(cons (oref semanticdb-current-table file)
|
|
|
|
(or (semantic-create-imenu-index-1 stream nil)
|
|
|
|
;; No tags in this file
|
|
|
|
'file-only))))
|
|
|
|
(tables (semanticdb-get-database-tables semanticdb-current-database)))
|
|
|
|
(while tables
|
|
|
|
(let ((semantic-imenu-directory-current-file
|
|
|
|
(oref (car tables) file))
|
|
|
|
tags)
|
|
|
|
(when (and (not (eq (car tables) semanticdb-current-table))
|
|
|
|
(semanticdb-live-p (car tables))
|
|
|
|
(semanticdb-equivalent-mode (car tables))
|
|
|
|
)
|
|
|
|
(setq tags (oref (car tables) tags)
|
|
|
|
index (cons (cons semantic-imenu-directory-current-file
|
|
|
|
(or (and tags
|
|
|
|
;; don't pass nil stream because
|
|
|
|
;; it will use the current
|
|
|
|
;; buffer
|
|
|
|
(semantic-create-imenu-index-1
|
|
|
|
(oref (car tables) tags)
|
|
|
|
nil))
|
|
|
|
;; no tags in the file
|
|
|
|
'file-only))
|
|
|
|
index)))
|
|
|
|
(setq tables (cdr tables))))
|
|
|
|
|
|
|
|
;; If enabled automatically rebuild other imenu directory
|
|
|
|
;; indexes based on the same Semantic database
|
|
|
|
(or (not semantic-imenu-auto-rebuild-directory-indexes)
|
|
|
|
;; If auto rebuild already in progress does nothing
|
|
|
|
semantic-imenu-auto-rebuild-running
|
|
|
|
(unwind-protect
|
|
|
|
(progn
|
|
|
|
(setq semantic-imenu-auto-rebuild-running t)
|
|
|
|
(semantic-imenu-rebuild-directory-indexes
|
|
|
|
semanticdb-current-database))
|
|
|
|
(setq semantic-imenu-auto-rebuild-running nil)))
|
|
|
|
|
|
|
|
(nreverse index))))
|
|
|
|
|
|
|
|
(defun semantic-create-imenu-index-1 (stream &optional parent)
|
|
|
|
"Create an imenu index for any buffer which supports Semantic.
|
|
|
|
Uses the output of the Semantic parser to create the index.
|
|
|
|
STREAM is a stream of tags used to create menus.
|
|
|
|
Optional argument PARENT is a tag parent of STREAM."
|
|
|
|
(let ((tags stream)
|
|
|
|
(semantic-imenu-adopt-external-members
|
|
|
|
semantic-imenu-adopt-external-members))
|
|
|
|
;; If we should regroup, do so.
|
|
|
|
(if semantic-imenu-adopt-external-members
|
|
|
|
(setq tags (semantic-adopt-external-members tags)
|
|
|
|
;; Don't allow recursion here.
|
|
|
|
semantic-imenu-adopt-external-members nil))
|
|
|
|
;; Test for bucketing vs not.
|
|
|
|
(if semantic-imenu-bucketize-file
|
|
|
|
(let ((buckets (semantic-bucketize
|
|
|
|
tags parent
|
|
|
|
semantic-imenu-sort-bucket-function))
|
|
|
|
item name
|
|
|
|
index)
|
|
|
|
(cond
|
|
|
|
((null buckets)
|
|
|
|
nil)
|
|
|
|
((or (cdr-safe buckets) ;; if buckets has more than one item in it.
|
|
|
|
(not semantic-imenu-buckets-to-submenu)) ;; to force separators between buckets
|
|
|
|
(while buckets
|
|
|
|
(setq name (car (car buckets))
|
|
|
|
item (cdr (car buckets)))
|
|
|
|
(if semantic-imenu-buckets-to-submenu
|
|
|
|
(progn
|
|
|
|
;; Make submenus
|
|
|
|
(if item
|
|
|
|
(setq index
|
|
|
|
(cons (cons name
|
|
|
|
(semantic-create-imenu-subindex item))
|
|
|
|
index))))
|
|
|
|
;; Glom everything together with "---" between
|
|
|
|
(if item
|
|
|
|
(setq index
|
|
|
|
(append index
|
|
|
|
;; do not create a menu separator in the parent menu
|
|
|
|
;; when creating a sub-menu
|
|
|
|
(if (memq (semantic-tag-class (car item))
|
|
|
|
semantic-imenu-expandable-tag-classes)
|
|
|
|
(semantic-create-imenu-subindex item)
|
|
|
|
(cons
|
|
|
|
'("---")
|
|
|
|
(semantic-create-imenu-subindex item)))))
|
|
|
|
))
|
|
|
|
(setq buckets (cdr buckets)))
|
|
|
|
(if semantic-imenu-buckets-to-submenu
|
|
|
|
(nreverse index)
|
|
|
|
index))
|
|
|
|
(t
|
|
|
|
(setq name (car (car buckets))
|
|
|
|
item (cdr (car buckets)))
|
|
|
|
(semantic-create-imenu-subindex item))))
|
|
|
|
;; Else, group everything together
|
|
|
|
(semantic-create-imenu-subindex tags))))
|
|
|
|
|
|
|
|
(defun semantic-create-imenu-subindex (tags)
|
|
|
|
"From TAGS, create an imenu index of interesting things."
|
|
|
|
(let ((notypecheck (not semantic-imenu-expand-type-members))
|
|
|
|
children index tag parts)
|
|
|
|
(while tags
|
|
|
|
(setq tag (car tags)
|
|
|
|
children (semantic-tag-components-with-overlays tag))
|
|
|
|
(if (and (not notypecheck)
|
|
|
|
(memq (semantic-tag-class tag)
|
|
|
|
semantic-imenu-expandable-tag-classes)
|
|
|
|
children
|
|
|
|
)
|
2011-11-19 18:29:42 -08:00
|
|
|
;; to keep an homogeneous menu organization, type menu items
|
2010-03-13 10:49:54 -05:00
|
|
|
;; always have a sub-menu with at least the *definition*
|
|
|
|
;; item (even if the tag has no type components)
|
|
|
|
(progn
|
|
|
|
(setq parts children)
|
|
|
|
;; There is options which create the submenu
|
|
|
|
;; * Type has an overlay, but children do.
|
|
|
|
;; The type doesn't have to have it's own overlay,
|
|
|
|
;; but a type with no overlay and no children should be
|
|
|
|
;; invalid.
|
|
|
|
(setq index
|
|
|
|
(cons
|
|
|
|
(cons
|
|
|
|
(funcall semantic-imenu-summary-function tag)
|
|
|
|
;; Add a menu for getting at the type definitions
|
|
|
|
(if (and parts
|
|
|
|
;; Note to self: enable menu items for
|
|
|
|
;; sub parts even if they are not proper
|
|
|
|
;; tags.
|
|
|
|
(semantic-tag-p (car parts)))
|
|
|
|
(let ((submenu
|
|
|
|
(if (and semantic-imenu-bucketize-type-members
|
|
|
|
semantic-imenu-bucketize-file)
|
|
|
|
(semantic-create-imenu-index-1 parts tag)
|
|
|
|
(semantic-create-imenu-subindex parts))))
|
2011-11-14 22:00:24 +01:00
|
|
|
;; Only add a *definition* if we have a position
|
2010-03-13 10:49:54 -05:00
|
|
|
;; in that type tag.
|
|
|
|
(if (semantic-tag-with-position-p tag)
|
|
|
|
(cons
|
|
|
|
(cons "*definition*"
|
|
|
|
(semantic-imenu-tag-overlay tag))
|
|
|
|
submenu)
|
|
|
|
submenu))
|
|
|
|
;; There were no parts, or something like that, so
|
|
|
|
;; instead just put the definition here.
|
|
|
|
(if (semantic-tag-with-position-p tag)
|
|
|
|
(semantic-imenu-tag-overlay tag)
|
|
|
|
nil)
|
|
|
|
))
|
|
|
|
index)))
|
|
|
|
(if (semantic-tag-with-position-p tag)
|
|
|
|
(setq index (cons
|
|
|
|
(cons
|
|
|
|
(funcall semantic-imenu-summary-function tag)
|
|
|
|
(semantic-imenu-tag-overlay tag))
|
|
|
|
index))))
|
|
|
|
(setq tags (cdr tags)))
|
|
|
|
;; `imenu--split-submenus' sort submenus according to
|
|
|
|
;; `imenu-sort-function' setting and split them up if they are
|
|
|
|
;; longer than `imenu-max-items'.
|
|
|
|
(imenu--split-submenus (nreverse index))))
|
|
|
|
|
|
|
|
;;; directory imenu rebuilding.
|
|
|
|
;;
|
|
|
|
(defun semantic-imenu-rebuild-directory-indexes (db)
|
|
|
|
"Rebuild directory index imenus based on Semantic database DB."
|
|
|
|
(let ((l (buffer-list))
|
|
|
|
b)
|
|
|
|
(while l
|
|
|
|
(setq b (car l)
|
|
|
|
l (cdr l))
|
|
|
|
(if (and (not (eq b (current-buffer)))
|
|
|
|
(buffer-live-p b))
|
|
|
|
(with-current-buffer b
|
|
|
|
;; If there is a buffer local Semantic index directory
|
|
|
|
;; imenu
|
|
|
|
(when (and (eq imenu-create-index-function
|
|
|
|
'semantic-create-imenu-index)
|
|
|
|
semanticdb-current-database
|
|
|
|
(eq semanticdb-current-database db))
|
|
|
|
;; Rebuild the imenu
|
|
|
|
(imenu--cleanup)
|
|
|
|
(setq imenu--index-alist nil)
|
|
|
|
(funcall
|
|
|
|
(if (fboundp 'imenu-menu-filter)
|
|
|
|
;; XEmacs imenu
|
|
|
|
'imenu-menu-filter
|
|
|
|
;; Emacs imenu
|
|
|
|
'imenu-update-menubar))))))))
|
|
|
|
|
|
|
|
(defun semantic-imenu-semanticdb-hook ()
|
|
|
|
"Function to be called from `semanticdb-mode-hook'.
|
|
|
|
Clears all imenu menus that may be depending on the database."
|
|
|
|
(require 'semantic/db-mode)
|
|
|
|
(semantic-map-buffers
|
|
|
|
#'(lambda ()
|
|
|
|
;; Set up semanticdb environment if enabled.
|
|
|
|
(if (semanticdb-minor-mode-p)
|
|
|
|
(semanticdb-semantic-init-hook-fcn))
|
|
|
|
;; Clear imenu cache to redraw the imenu.
|
|
|
|
(semantic-imenu-flush-fcn))))
|
|
|
|
|
|
|
|
(add-hook 'semanticdb-mode-hook 'semantic-imenu-semanticdb-hook)
|
|
|
|
|
|
|
|
;;; Interactive Utilities
|
|
|
|
;;
|
|
|
|
(defun semantic-imenu-toggle-bucketize-file ()
|
|
|
|
"Toggle the ability of imenu to bucketize the current file."
|
|
|
|
(interactive)
|
|
|
|
(setq semantic-imenu-bucketize-file (not semantic-imenu-bucketize-file))
|
|
|
|
;; Force a rescan
|
|
|
|
(setq imenu--index-alist nil))
|
|
|
|
|
|
|
|
(defun semantic-imenu-toggle-buckets-to-submenu ()
|
|
|
|
"Toggle the ability of imenu to turn buckets into submenus."
|
|
|
|
(interactive)
|
|
|
|
(setq semantic-imenu-buckets-to-submenu (not semantic-imenu-buckets-to-submenu))
|
|
|
|
;; Force a rescan
|
|
|
|
(setq imenu--index-alist nil))
|
|
|
|
|
|
|
|
(defun semantic-imenu-toggle-bucketize-type-parts ()
|
|
|
|
"Toggle the ability of imenu to bucketize the current file."
|
|
|
|
(interactive)
|
|
|
|
(setq semantic-imenu-bucketize-type-members (not semantic-imenu-bucketize-type-members))
|
|
|
|
;; Force a rescan
|
|
|
|
(setq imenu--index-alist nil))
|
|
|
|
|
|
|
|
;;; Which function support
|
|
|
|
;;
|
|
|
|
;; The which-function library will display the current function in the
|
|
|
|
;; mode line. It tries do do this through imenu. With a semantic parsed
|
|
|
|
;; buffer, there is a much more efficient way of doing this.
|
|
|
|
;; Advise `which-function' so that we optionally use semantic tags
|
|
|
|
;; instead, and get better stuff.
|
|
|
|
(require 'advice)
|
|
|
|
|
|
|
|
(defvar semantic-which-function 'semantic-default-which-function
|
|
|
|
"Function to convert semantic tags into `which-function' text.")
|
|
|
|
|
|
|
|
(defcustom semantic-which-function-use-color nil
|
|
|
|
"*Use color when displaying the current function with `which-function'."
|
|
|
|
:group 'semantic-imenu
|
|
|
|
:type 'boolean)
|
|
|
|
|
|
|
|
(defun semantic-default-which-function (taglist)
|
|
|
|
"Convert TAGLIST into a string usable by `which-function'.
|
|
|
|
Returns the first tag name in the list, unless it is a type,
|
|
|
|
in which case it concatenates them together."
|
|
|
|
(cond ((eq (length taglist) 1)
|
|
|
|
(semantic-format-tag-abbreviate
|
|
|
|
(car taglist) nil semantic-which-function-use-color))
|
|
|
|
((memq (semantic-tag-class (car taglist))
|
|
|
|
semantic-imenu-expandable-tag-classes)
|
|
|
|
(concat (semantic-format-tag-name
|
|
|
|
(car taglist) nil semantic-which-function-use-color)
|
|
|
|
(car semantic-type-relation-separator-character)
|
|
|
|
;; recurse until we no longer have a type
|
|
|
|
;; or any tags left.
|
|
|
|
(semantic-default-which-function (cdr taglist))))
|
|
|
|
(t (semantic-format-tag-abbreviate
|
|
|
|
(car taglist) nil semantic-which-function-use-color))))
|
|
|
|
|
|
|
|
;; (defadvice which-function (around semantic-which activate)
|
|
|
|
;; "Choose the function to display via semantic if it is currently active."
|
|
|
|
;; (if (and (featurep 'semantic) semantic--buffer-cache)
|
|
|
|
;; (let ((ol (semantic-find-tag-by-overlay)))
|
|
|
|
;; (setq ad-return-value (funcall semantic-which-function ol)))
|
|
|
|
;; ad-do-it))
|
|
|
|
|
|
|
|
(provide 'semantic/imenu)
|
|
|
|
|
|
|
|
;; Local variables:
|
|
|
|
;; generated-autoload-file: "loaddefs.el"
|
|
|
|
;; generated-autoload-load-name: "semantic/imenu"
|
|
|
|
;; End:
|
|
|
|
|
|
|
|
;;; semantic/imenu.el ends here
|