This article doesn't pretend to represent detailed description of customization of Emacs as development environment (this is theme for separate article). I just tried to provide a small description of "How to customize Cedet to work with C & C++", although most of this description will also applicable for other languages, supported by Cedet.
The Cedet package is a collection of several libraries, implementing different commands, but used for one task — provide functionality for work with source code written in different programming languages:
Currently it's better to use development version of the Cedet, that is available from repository at Sourceforge.net. After downloading of code, you need to change to cedet directory and compile the package with following command:
emacs -Q -l cedet-build.el -f cedet-build
or, to compile in terminal window, and exit after compilation, you can use following command:
emacs -Q -nw -l cedet-build.el -f cedet-build -f save-buffers-kill-terminal
The loading of package is performed by cedet.el
script, so all you need to do — is just add following line to the your Emacs initialization file2:
(load-file "~/emacs/cedet/common/cedet.el")
If you plan to use projects, then you need to switch on corresponding mode — it's implemented by EDE package:
(global-ede-mode t)
Depending on your requirements, you can use one of the commands, described below, to load corresponding set of features (these commands are listed in increasing order, and each command include features of previous commands):
semantic-load-enable-minimum-features
— enables only minimum of necessary features — keep syntactic information for current buffer up-to date, storing of syntactic information for later use (Semanticdb), and loading of corresponding information with Semanticdb and Ebrowse;semantic-load-enable-code-helpers
— enables senator-minor-mode
for navigation in buffer, semantic-mru-bookmark-mode
for storing positions of visited tags, and semantic-idle-summary-mode
, that shows information about tag under point;semantic-load-enable-gaudy-code-helpers
— enables semantic-stickyfunc-name
that displays name of current function in topmost line of buffer, semantic-decoration-mode
to decorate tags, using different faces, and semantic-idle-completion-mode
for automatic generation of possible names completions, if user stops his work for some time;semantic-load-enable-excessive-code-helpers
— enables which-func-mode
, that shows name of current function in status line;semantic-load-enable-semantic-debugging-helpers
— enables several modes, that are useful when you debugging Semantic — displaying of parsing errors, its state, etc.So, you need to add call to one of these commands right after command, that performs loading of Cedet. For example:
(semantic-load-enable-excessive-code-helpers)
The rest of this section assumes that the minimal Semantic features have been loaded.
To use additional features for names completion, and displaying of information for tags & classes, you also need to load the semantic-ia
package. This could be performed with following command:
(require 'semantic-ia)
After loading of this package, you'll get access to commands, described below.
To normal work with system-wide libraries, Semantic should has access to system include files, that contain information about functions & data types, implemented by these libraries.
If you use GCC for programming in C & C++, then Semantic can automatically find path, where system include files are located. To do this, you need to load semantic-gcc
package with following command:
(require 'semantic-gcc)
You can also explicitly specify additional paths for look up of include files (and these paths also could vary for specific modes). To add some path to list of system include paths, you can use the semantic-add-system-include
command, that accepts two parameters — string with path to include files, and symbol, representing name of major mode, for which this path will used. For example:
(semantic-add-system-include "~/exp/include/boost_1_37" 'c++-mode)
To optimize work with tags, you can use several techniques:
/usr/include
, /usr/local/include
, etc.) with the semanticdb-create-ebrowse-database
or semanticdb-create-cscope-database
commands;semanticdb-find-default-throttle
variable for concrete modes — for example, don't use information from system include files, by removing system
symbol from list of objects to search for c-mode
:(setq-mode-local c-mode semanticdb-find-default-throttle
'(project unloaded system recursive))
Semantic extracts syntactic information when Emacs is idle. You can customize the semantic-idle-scheduler-idle-time
variable to specify idle time (in seconds), if you don't want to use default value.
The Semantic package can be integrated with the imenu package. This enables the display of a menu with a list of functions, variables, and other tags. To enable this feature you can either use semantic-load-enable-code-helpers
, or, you need to add following code into your initialization file:
(defun my-semantic-hook ()
(imenu-add-to-menubar "TAGS"))
(add-hook 'semantic-init-hooks 'my-semantic-hook)
If you use standard procedure for loading of Cedet, then Semanticdb will loaded automatically. Otherwise, you can load and enable it with following commands:
(require 'semanticdb)
(global-semanticdb-minor-mode 1)
To customize Semanticdb you need to specify some number of variables, that are used to specify path, where databases will stored, and some other parameters. These variables could be set via semanticdb
customization group.
Besides this, Semanticdb can use databases generated by external utilities — gtags
from GNU Global, ctags
, ebrowse
& cscope
. To activate this you can use following code:
;; if you want to enable support for gnu global
(require 'semanticdb-global)
(semanticdb-enable-gnu-global-databases 'c-mode)
(semanticdb-enable-gnu-global-databases 'c++-mode)
;; enable ctags for some languages:
;; Unix Shell, Perl, Pascal, Tcl, Fortran, Asm
(semantic-load-enable-primary-exuberent-ctags-support)
To proper work of Semantic with С & C++ code is recommended to use the EDE package (work with projects, etc.). For these languages, EDE package defines special project type — ede-cpp-root-project
, that provides additional information to Semantic, that will be used to analyze source code of your project.
To define a project, you need to use following code:
(ede-cpp-root-project "Test"
:name "Test Project"
:file "~/work/project/CMakeLists.txt"
:include-path '("/"
"/Common"
"/Interfaces"
"/Libs"
)
:system-include-path '("~/exp/include")
:spp-table '(("isUnix" . "")
("BOOST_TEST_DYN_LINK" . "")))
You can use any file at root directory of the project, as a :file
parameter. This file isn't parsed, but it's used only as an anchor to search a files in projects.
To search include files, Semantic uses directories from two lists, that could be specified for project. The :system-include-path
parameter is used to specify list of the full paths that will searched for "system" include files. Another parameter — :include-path
specifies the list of directories, relative to the project's root directory, that will searched for your include files (if names are starting with /
, this means, that path is specified relative to project's root directory). Instead of specifying paths as lists, you can also provide function, that will perform a search for include files in your project. You can read about it in the EDE's manual.
Another parameter, that could be specified in project's definition is a list of definitions, that will be used during preprocessing of the code. The :spp-table
parameter allows to specify list of pairs, consisting from symbol's name & value, defined for given name. In our example above, we define two symbols — isUnix
and BOOST_TEST_DYN_LINK
, that will passed to preprocessor, and this allows to perform proper parsing of the code.
User, if this need, can redefine some variables for files inside project. This could be done by specifying the :local-variables
parameter, and passing to it list of pairs symbol name/value, and these values will set for files in project.
More information about definitions for preprocessor you can find in documentation for the semantic-lex-c-preprocessor-symbol-map
variable. List of preprocessor symbols defined for some file with source code you can obtain with the semantic-lex-spp-describe
command, and use its result to customize :spp-table
parameter or semantic-lex-c-preprocessor-symbol-map
variable.
Many libraries list all defined macros in one of include files, so you can use these definitions. To do this you need to list these files in the semantic-lex-c-preprocessor-symbol-file
variables, and when Cedet will perform analysis, this values will taken into account. By default, this variable has only one value — file with definitions for C++ standard library. As example, I want to show Cedet's configuration for work with Qt4:
(setq qt4-base-dir "/usr/include/qt4")
(semantic-add-system-include qt4-base-dir 'c++-mode)
(add-to-list 'auto-mode-alist (cons qt4-base-dir 'c++-mode))
(add-to-list 'semantic-lex-c-preprocessor-symbol-file (concat qt4-base-dir "/Qt/qconfig.h"))
(add-to-list 'semantic-lex-c-preprocessor-symbol-file (concat qt4-base-dir "/Qt/qconfig-dist.h"))
(add-to-list 'semantic-lex-c-preprocessor-symbol-file (concat qt4-base-dir "/Qt/qglobal.h"))
After adding of these lines to your initialization file, you'll be able to use name completion for classes, defined in Qt4 library. Example of this you can see on picture below.
From the user's point of view, Semantic implements several major commands — name completions, obtaining information about tags (variables, functions, etc.), and navigation in source code. Some of commands are implemented by semantic-ia
package, while some other are implemented in Senator, and rest of them, are implemented by Semantic's kernel.
Some of commands have no standard key bindings, so you it's better to select key bindings, that are comfortable to you, and bind needed commands to them, for example, like this:
(defun my-cedet-hook ()
(local-set-key [(control return)] 'semantic-ia-complete-symbol)
(local-set-key "\C-c?" 'semantic-ia-complete-symbol-menu)
(local-set-key "\C-c>" 'semantic-complete-analyze-inline)
(local-set-key "\C-cp" 'semantic-analyze-proto-impl-toggle))
(add-hook 'c-mode-common-hook 'my-cedet-hook)
I want to mention, that Semantic's development is pretty active, and if something doesn't work, or works wrong, then please, send examples of code to the cedet-devel mailing list — the Cedet's author usually answers very quickly.
Name completions for names of functions, variables & classes is pretty often used feature when you work with source code3. There are two packages inside Semantic that implement this functionality — semantic-ia
and Senator. Commands, implemented by semantic-ia
use the semantic-analyze-possible-completions
function to create a list of all possible names completion, and this function take into account many parameters, and it could be also extended by user to provide more precise list of names. At the same time, commands from Senator package use more simple methods to create a list of all possibles completions (usually use information about only definitions in current file), and this sometime lead to the wrong completion of names.
If you execute the semantic-ia-complete-symbol
command when you typing code, then its execution will lead to completion of corresponding name — name of function, variable, or class member, depending on current context. If there are several variants of name, then this name will completed to most common part of it, and if you'll call this command second time, then buffer with all possible completions will shown. User can also use the semantic-ia-complete-symbol-menu
command, that also analyze current context, and displays list of possible completions as a graphical menu, from which the needed name could be selected by user4. Besides this, there is semantic-ia-complete-tip
command, that displays list of possible completions as tooltip.
As was mentioned above, the Senator package, also provides commands for names completion, that work fast, but with less precision, as they use few parameters during computation of names for completions. The senator-complete-symbol
command (C-c , TAB
) completes name for current tag, and insert first found completion as result. If it substitute wrong name, then you can insert second name from completion list by repeating this command, and so on. If there are lot of the possible names, or you want to see full list of functions and variables for some class, then it's better to use the senator-completion-menu-popup
command (C-c , SPC
), that displays list of all possible completions as a graphical menu.
Besides these commands, for some languages user can use special mode — semantic-idle-completions-mode
(it loaded when you use emantic-load-enable-gaudy-code-helpers
, or you can enable it explicitly) — in this mode names completions are shown automatically if user stops its work for a some time (idle time). By default, only first possible completion is shown, and user can use the TAB
key to navigate through list of possible completions.
For C-like languages, user can use the semantic-complete-self-insert
command, bound to the .
and/or >
keys, as this show below:
(defun my-c-mode-cedet-hook ()
(local-set-key "." 'semantic-complete-self-insert)
(local-set-key ">" 'semantic-complete-self-insert))
(add-hook 'c-mode-common-hook 'my-c-mode-cedet-hook)
Use of this setting will lead to execution of semantic-complete-self-insert
command when user will press .
or >
after variables, that are class or structure instances, and displaying of list of possible completions for given class or structure.
The semantic-ia
package implements several commands, that allows to get information about classes, functions & variables. As documentation are used comments, extracted from source code, including comments, written for Doxygen. Now following commands are implemented:
semantic-ia-show-doc
semantic-ia-show-summary
semantic-ia-describe-class
One of the most useful commands for navigation in source code is the semantic-ia-fast-jump
command, that allows to jump to declaration of variable or function, whose name is under point. You can return back by using the semantic-mrub-switch-tag
command (C-x B
), that is available when you use the semantic-mru-bookmark-mode
minor mode.
Semantic also provides two additional commands for jumping to function or variable: defined in current file — semantic-complete-jump-local
(C-c , j
), or defined in current project — semantic-complete-jump
(C-c , J
). Both commands allow to enter name of function or variable (including local variables for functions) and jump to given definition (you can use name completion when entering the name).
The main difference between semantic-ia-fast-jump
& semantic-complete-jump
commands is that the first properly handles complex names, like this::that->foo()
, while the second, can find only simple names, like foo
.
The semantic-analyze-proto-impl-toggle
command allows to switch between function's declaration and its implementation in languages, that allow to have separate declaration and implementation of functions. Another useful command is semantic-decoration-include-visit
, that allows to switch to the include file, whose name is under point.
Senator also implements several commands for navigation in source code. This is senator-next-tag
(C-c , n
) and senator-previous-tag
(C-c , p
) commands, that move cursor to next or previous tag, and also the senator-go-to-up-reference
command (C-c , u
), that move cursor to the "parent" tag (for example, for class member function, "parent" tag is class declaration).
Not so long ago a very useful command was implemented in Semantic — semantic-symref
, that allows to find places, where symbol, whose name is under point, is used in your project. If you want to find usage of symbol with any name, you can use the semantic-symref-symbol
, that allows to explicitly specify name of the symbol.
If references to given name weren't found in corresponding database (GNU Global, etc.), then this command tries to find them with the find-grep
command. As result of execution of these commands, a new buffer with results will created, and user can use them to jump to corresponding places:
As Semantic has almost full syntactic information about source code, this allows it to implement folding functionality, similar to functionality implemented by hideshow package. To enable this feature, you need to do customization of the global-semantic-tag-folding-mode
variable. When you'll enable it, this will lead to displaying of small triangles at the fringle field, and you'll able to fold and unfold pieces of code pressing on them (not only pieces source code, but also comments, and other objects).
Senator also has similar functionality, but it usually used for top-level objects — functions, class declarations, etc. You can fold piece of code with the senator-fold-tag
command (C-c , -
), and unfold with senator-unfold-tag
(C-c , +
).
The Senator package defines number of commands for work with tags, that allow user to cut or copy tag, and insert it in another place, etc. To cut current tag (usually this is declaration of some function or its implementation) the senator-kill-tag
command (C-c , C-w
) is defined. You can insert tag with standard key binding C-y
, while the senator-yank-tag
command (C-c , C-y
) inserts only tag declaration, without body. Another useful command is senator-copy-tag
(C-c , M-w
), that copies current tag — this is very handy when you want to insert declaration of function into include file, for example.
Senator allows to change behaviour of standard search commands (re-search-forward
, isearch-forward
and other), when you work with source code, such way, so they will perform search only in given tags. To enable this mode you can use the senator-isearch-toggle-semantic-mode
command(C-c , i
), and with the senator-search-set-tag-class-filter
command (C-c , f
) you can limit search to given tag types — function
for functions, variable
for variables, etc.
You can also perform tags search without enabling this mode — you just need to call corresponding command: senator-search-forward
or senator-search-backward
.
The Srecode package allows user to define different code templates, but it differs from other packages, that provide insertion of templates, as far as list of available templates could vary depending on current context. For example, insertion of get/set
functions will happen only when you inside class declaration. Or, insertion of function declaration, could happen only outside of other function.
The main command, that is used to insert templates, is the srecode-insert
, that bound to the C-c / /
keys. This command will ask user for name of template to insert (you can enter it using name completion). List of available templates will vary, depending on current context. If you want to insert the same template once again, then you can use the srecode-insert-again
command (C-c / .
).
Templates, defined by user, could also use they own key bindings. They can use lower-case symbols from range C-c / [a..z]
, and user can specify template's declaration, which key will assigned to it. For example, for C++ you can use the C-c / c
key binding to insert declaration of class.
Key bindings, that use upper-case symbols, are reserved for templates & commands defined in Srecode. For example, C-c / G
(srecode-insert-getset
) inserts pair of functions get/set
for some class member variable, while C-c / E
(srecode-edit
) is used to edit templates. List of this commands vary from time to time, so you need to look into documentation to get actual list of commands.
Besides templates, supplied with Cedet, user can define their own templates, and store them in the ~/.srecode
directory, where Cedet finds them automatically. You can read about templates creation in the Srecode manual, that comes together with other documentation in Cedet distribution.
Together with Cedet the number of additional packages is supplied. Some of them are located in the contrib
subdirectory, that also will added to package search list, when you load Cedet, so you don't need to do anything special to load them.
The eassist package implements several additional commands, that for their work use information obtained from Semantic. By default, these commands have no predefined key bindings, so you need to select them yourself.
The eassist-list-methods
command, executed in file with source code, will show you a list of functions, defined in current buffer, and allows you to perform quick jump to selected function.
If you develop code in C and/or C++ languages, then the eassist-switch-h-cpp
command, could be very useful to you — it jumps between include file and file, that contains implementation (if they have same names, but different extensions).