C/C++ Development Environment for Emacs (original) (raw)

Quick setup

I've prepared an Emacs repository that is properly configured for demonstration purposes. You can clone it and play with it without having to manually copy and paste all the setup Elisp code throughout the guide. When installed and run the first time, the demo repository will download from melpa, install, and compile all the packages it needs. Note that depending on your internet connection and processor speeds, this may take a while.

  1. Install GNU Global from your distribution's package manager (Linux / Mac) or from the Win32 port (Windows). If none is available, download the sources here and manually build the package.

  2. Backup your ~/.emacs.d elsewhere.

  3. If emacs is not already running, start it.

  4. Update your melpa database: M-x package-list-packages

  5. Clone the repository into your ~/.emacs.d folder.
    git clone https://github.com/tuhdo/emacs-c-ide-demo.git ~/.emacs.d

  6. You may possibly want to edit your new ~/.emacs.d/init.el file for two options.

    1. The demo repository can use either helm-gtags (the default), or ggtags. If you want to use ggtags, comment this line in init.el:
      (require 'setup-helm-gtags)

    And uncomment this line:
    ;; (require 'setup-ggtags)
    2. The demo uses Helm. If you're not already familiar with Helm, readmy guide. If you don't want to use Helm, also comment this line in init.el:

That does it! To start using the demo, just type M-x load-file RET init.el. Continue reading this guide for its operational directions, without needing to bother to perform any more installations or elisp evaluations.

Source code navigation

Prerequisite:

(require 'ggtags) (add-hook 'c-mode-common-hook (lambda () (when (derived-mode-p 'c-mode 'c++-mode 'java-mode 'asm-mode) (ggtags-mode 1))))

(define-key ggtags-mode-map (kbd "C-c g s") 'ggtags-find-other-symbol) (define-key ggtags-mode-map (kbd "C-c g h") 'ggtags-view-tag-history) (define-key ggtags-mode-map (kbd "C-c g r") 'ggtags-find-reference) (define-key ggtags-mode-map (kbd "C-c g f") 'ggtags-find-file) (define-key ggtags-mode-map (kbd "C-c g c") 'ggtags-create-tags) (define-key ggtags-mode-map (kbd "C-c g u") 'ggtags-update-tags)

(define-key ggtags-mode-map (kbd "M-,") 'pop-tag-mark)

(setq helm-gtags-ignore-case t helm-gtags-auto-update t helm-gtags-use-input-at-cursor t helm-gtags-pulse-at-cursor t helm-gtags-prefix-key "\C-cg" helm-gtags-suggested-key-mapping t )

(require 'helm-gtags) ;; Enable helm-gtags-mode (add-hook 'dired-mode-hook 'helm-gtags-mode) (add-hook 'eshell-mode-hook 'helm-gtags-mode) (add-hook 'c-mode-hook 'helm-gtags-mode) (add-hook 'c++-mode-hook 'helm-gtags-mode) (add-hook 'asm-mode-hook 'helm-gtags-mode)

(define-key helm-gtags-mode-map (kbd "C-c g a") 'helm-gtags-tags-in-this-function) (define-key helm-gtags-mode-map (kbd "C-j") 'helm-gtags-select) (define-key helm-gtags-mode-map (kbd "M-.") 'helm-gtags-dwim) (define-key helm-gtags-mode-map (kbd "M-,") 'helm-gtags-pop-stack) (define-key helm-gtags-mode-map (kbd "C-c <") 'helm-gtags-previous-history) (define-key helm-gtags-mode-map (kbd "C-c >") 'helm-gtags-next-history)

Before using the ggtags or helm-gtags, remember to create a GTAGS database by running gtags at your project root in terminal:

$ cd /path/to/project/root $ gtags

After this, a few files are created:

$ ls G* GPATH GRTAGS GTAGS

If you use ggtags, you have a command for creating GTAGS database, that is ggtags-create-tags; this is recommended way when usingggtags, to let it know where the project root is.

Basic movements

Basic concepts of tag

A tag is a name of an entity in source code. An entity can be a variable, a method definition, an include-operator… A tag contains information such as name of the tag (the name of the variable, class, method), location of this tag in source code and which file it belongs to. As an example, GNU Global generates three tag databases:

A definition of a tag is where a tag is implemented. For example, a function definition is the body where it is actually implemented, or a variable definition is where the type and its property (i.e static) is specified.

A reference of a tag is where a tag is used in a source tree, but not where it is defined.

Find definitions in current buffer

The Imenu facility offers a way to find the major definitions, such as function definitions, variable definitions in a file by name. ggtagscan integrate Imenu:

(setq-local imenu-create-index-function #'ggtags-build-imenu-index)

If you use Helm, use moo-jump-local from function-args package. You can use it as an outline tree like in other IDEs. Here is a demo:

moo-jump-local.gif

Find definitions in project

You can jump back to original location where you invokedggtags-find-tag-dwim by M-,, which runs pop-tag-mark (if you follow my key bindings).

You can also find arbitrary tag definition when invoking M-. on blank space. A prompt asks you for tag pattern, which is a regexp.

If ggtags gives you a list of candidates, you can use M-n to move to next candidate and M-p to move back previous candidate. Use M-g s to invoke Isearch on candidate buffer list.

ggtags-definitions.png

(screenshot taken from ggtags)

You can also find arbitrary tag definition when invoking M-. on blank space. A prompt asks you for tag pattern, which is a regexp.

helm-gtags provides a really nice feature that uses Helm to display all available tags in a project and incrementally filtering, and is really fast using helm-gtags-select, which is bound to C-j in my setup above. This is useful when you want to explore tags in unfamiliar project. Demo:

helm-gtags-select.gif

Find references in project

Find functions that calls function is actually a special case of finding references. That is, you gather references for a function.

Find functions that current functions call

If you want to list all the functions that the current function - the function that point is inside - calls, you can do that withhelm-gtags-tags-in-this-function, which is bound to C-c g a in my setup.

Find files in project

Alternatively, you have a more generic solution, that is using Projectile. Projectile is a generic project management tool that you learn later. With Projectile, jumping around version controlled project like Linux kernel is a breeze, since you can jump to any file regardless of where you are standing in the project.

View visited tags with tag stack

Browse source tree with Speedbar file browser

If you want a static outline tree, Emacs also has a more one:Speedbar. To use Speed bar, M-x speedbar and a frame that contains a directory tree appear. In this directory, to the left of a file or directory name is an icon with + sign in it. You can click the icon to open the content of a node. If the node is a file, the children of the files are tags (variable and function definitions) of the file; if the node is a directory, the children of the node are files in that directory. One important thing to remember, Speedbar only lists files that match speedbar-file-regexp, that contains the extensions for common programming languages. If you don't see files in your programming languages listed, consider adding it the regexp list.

Basic usage:

To enable speedbar to show all files:

(setq speedbar-show-unknown-files t)

Package: sr-speedbar

However, you may feel that a frame is difficult to use. To solve this issue, you need sr-speedbar, which can be installed via MELPA.

Best is to use sr-speedbar-toggle only, for simplicity.

sr-speedbar gives the following improvements:

Demo: In the demo, you can see that the function set-cpu-active is being highlighted. That's what happens when you press RET on a tag: Speedbar moves to the location of that tag and highlight it. Looking at the Speedbar, under set-cpu-active node, it contains these children:

sr-speedbar.gif

General completion with company-mode

company-mode is a text completion framework for Emacs. The name stands for "complete anything". It uses pluggable back-ends and front-ends to retrieve and display completion candidates.

It comes with several back-ends such as Elisp, Clang, Semantic, Eclim, Ropemacs, Ispell, CMake, BBDB, Yasnippet, dabbrev, etags, gtags, files, keywords and a few others.

After installing company-mode from MELPA, activate it globally:

(require 'company) (add-hook 'after-init-hook 'global-company-mode)

General Usage: Completion will start automatically after you type a few letters. Use M-n and M-p to select, to complete or**** to complete the common part. Search through the completions with C-s, C-r and C-o. Press M-(digit) to quickly complete with one of the first 10 candidates. When the completion candidates are shown, press to display the documentation for the selected candidate, or C-w to see its source. Not all back-ends support this.

The variable company-backends specifies a list of backends thatcompany-mode uses to retrieves completion candidates for you.

That's the basic. In the later sections, you will configurecompany-mode to provide completion candidates.

Demo project

I uploaded a demo project for you to play with completion featurehere. The project has this structure:

project_root/ Makefile src/ main.c lib.c lib2.c feature1/ feature1.c include1/ lib.h feature1/ feature1.h include2/ lib2.h

For the .h files, all have this content:

void filename_func1(); int filename_func2(int a, int b);

For .c files, except for main.c, all have this template:

#include "filename.h"

void filename_func1() { }

int filename_func2(int a, int b) { }

filename or FILENAME is actual filename like lib1, lib2

The files look silly but good enough for our learning purpose.

Source code completion using Clang

To use company-mode with Clang, add this configuration:

(setq company-backends (delete 'company-semantic company-backends)) (define-key c-mode-map [(tab)] 'company-complete) (define-key c++-mode-map [(tab)] 'company-complete)

You have two commands for completing C/C++ code:

If you put a file with a special name .dir-locals.el in a directory, Emacs will read it when it visits any file in that directory or any of its subdirectories, and apply the settings it specifies to the file’s buffer. If you want to know more, read GNU Emacs Manual - Per-Directory Local Variables. If you use Helm, you can easily insert absolute path by C-c i at the current path in helm-find-files(bound to C-x C-f by default in my demo .emacs.d at the beginning):

helm-files-insertion.gif

In the above example, nil means apply the settings to any file or sub-directory visited. If non-nil, you have to specify a major mode and the settings are applied to major modes only. You setcompany-clang to c-mode and c++-mode anyway, so there's no problem setting major mode to nil. The remaining is a key-value pair of variable and value of that variable. company-clang-arguments is where you can tell include paths, and it takes a list of strings of include paths, as you can see above. After that, company-clang can see include paths in your project. If you add something new, like an include path, to your .dir-locals.el and is editing some source file, reopen the file for the new values to take effect.

Exercise:

Replace <user> with your username.

Header file completion with company-c-headers package

company-c-headers provides auto-completion for C/C++ headers using Company. After installing from MELPA, set it up:

(add-to-list 'company-backends 'company-c-headers)

company-c-header.png

IMPORTANT: If you want to complete C++ header files, you have to add its paths since by default company-c-headers only includes these two system include paths: /usr/include/ and/usr/local/include/. To enable C++ header completion for standard libraries, you have to add its path, for example, like this:

(add-to-list 'company-c-headers-path-system "/usr/include/c++/4.8/")

After that, you can complete C++ header files. To complete project local, use company-c-headers-path-user and put it in.dir-locals.el.

CEDET

What is CEDET?

CEDET is a (C)ollection of (E)macs (D)evelopment (E)nvironment (T)ools written with the end goal of creating an advanced development environment in Emacs. CEDET includes common features such as intelligent completion, source code navigation, project management, code generation with templates . CEDET also provides a framework for working with programming languages; support for new programming languages can be added and use CEDET to provide IDE-like features.

CEDET can give you code completion, but this process takes time and can block your Emacs while it is doing so. If you have large project, you may not want to use CEDET for code completion. But, you can use CEDET perfectly for utilities that work at file scope i.e. refactoring local variables in a function in a file.

Why use CEDET?

CEDET is simple to setup and portable (right winthin Emacs and written entirely with Emacs Lisp). Without CEDET, you have to use external tools and third party Emacs packages. The downside of external tools is that they are not specifically designed for Emacs. They have similar use cases, but not always satisfying. For example, source code indexing tools such as GNU Global and Exuberant Ctags are really good at working static source code, but they do not keep track changes in real time; CEDET does:

auto_complete.gif

As you can see, CEDET recognizes when printk.h is included and provides appropriate completion candidates. In contrast, non-context sentisve completion is like this:

company-clang-company-gtags.gif

In this case, the completion system gets all candidates straight from GNU Global generated database without considering current context.

The disadvantage is that CEDET is written in Emacs Lisp, and it is bound to the performance limitations of Emacs. Even though, CEDET is still really fast for moderate-size source files. CEDET also makes use of external tools like GNU Global or Cscope or Exuberant Ctags for finding symbol references/definition in a project to reduce its workload.

Installation

CEDET was merged into Emacs since 23.2. You do not need to install CEDET manually. However, you can also use the development repository that contains latest bug fixes and more features. Nevertheless, the built-in Emacs is still adequate for daily usage and convenient for trying out before actually cloning and use the development version. Skip this section if you only want to try Emacs. Come back later if you really like it.

If you really want to use the development version with latest feature, checkout this branch:

git clone http://git.code.sf.net/p/cedet/git cedet

Be sure to place the checked out cedet directory in your~/.emacs.d. Then compile it:

cd cedet make # wait for it to complete cd contrib make

Finally, assume that you placed your newly cloned CEDET in~/.emacs.d, load it into your Emacs:

(load-file (concat user-emacs-directory "/cedet/cedet-devel-load.el")) (load-file (concat user-emacs-directory "cedet/contrib/cedet-contrib-load.el"))

Semantic minor modes

Semantic is a package that provides language-aware editing commands based on source code parsers. Parsing is a process of analyzing source code based on programming language syntax. Emacs understands your source code through this process to provides features such as contextual code completion, code navigation. Here is an example how Semantic helps you provides completion for Boost:

semantic-boost-demo.gif

CEDET can do more

This guide only covers a portion of CEDET. Since Semantic parses source code and creates a database for code completion, it would be useful to reuse the database for other features such as code navigation, jump to definition and gather references. These are cool features. For example, CEDET provide nice syntax highlighting for gathering references:

semantic-symref.gif

The above feature is called Semantic Symref. It queries tag references from SemanticDB and display the result in another buffer. Please refer to GNU Manual - Symbol References for more info. If your project is only the size of Emacs or similar, then Semantic Symref is a viable choice. Remember that when entering new files, Semantic takes time to parse and if you gather references for the first time, you will have to wait for a while for Semantic doing its job. After the first time, subsequent uses of Semantic Symref happens instantly.

But, for navigating around the source tree, we already have ggtagsand helm-gtags, which uses GNU Global for much faster indexing for large project like Linux kernel. The only thing that other tools cannot do, is context-sensitive completion. That's why we only use CEDET for code completion in this guide. Nevertheless, Semantic Symref is still a viable choice for small to medium sized projects. Choose the one you prefer.

Other solutions that use clang is quite good but not there yet. For example, auto-complete-clang is fine for getting system header candidates (since clang has system paths by default), but it has no concept of project and is not aware of project include path. You can add more arbitrary include paths to auto-complete-clang, but it won't be pretty: once you add an include path for a project, it is visible to all other projects since the include path is treat as system include path. That means, whenever you try to complete something, you get irrelevant candidates from other projects as well. Quite annoying. company-clang also has the same problem. Another solution is rtags, but it is really complicated to setup, especially if you usemake; I never succeed with it. clang based packages still have a long way to go. CEDET also supports clang for retrieving completion candidates. It also has the limitations of other packages.

CEDET is best used with new project, because Semantic parse code as you write. As a result, you won't have to wait for parsing unknown source files to get completion candidates.

Source code navigation using Senator

Senator is a part of CEDET. Senator stands for SEmantic NAvigaTOR. Senator provides some useful commands for operating on semantic tags in SemanticDB. As you can see, another utility makes use of SemanticDB, aside from smart completion. It is like the heart of CEDET: once Semantic fails to parse, tools centered around it fail as well. If such situation happens, you always have a reserved and simpler solution: use GNU Global with ggtags or helm-gtagsfrontends. The following commands are provided by Senator:

Senator provides commands for navigating by tag.

Semantic also provides a useful command for finding all references of a tag, that is semantic-symref, as demonstrated in previous section. On a symbol, C-c , g and a prompt appear asking for a tag for gathering references, with the default is the symbol at point. Leave prompt blank and RET to use the default or enter another symbol if you change your mind.

Copy/Paste

Obsolete commands

Senator also provides commands for code completion:senator-complete-symbol and senator-completion-menu-popup. Code completion provided by Senator is simpler than the actual completion provided by semantic-ia-complete-symbol command that is used bymoo-complete for a list of candidates with full information, such as complete function interface is displayed correctly. These two completion commands are provided.

(Optional) Project management with EDE

EDE, short for Emacs Development Environment, is a generic interface for managing projects. In EDE, a project hierarchy matches a directory hierarchy. The project's topmost directory is called the project root, and its subdirectories are sub-projects.

EDE can do many things but we will just use it for code completion at project level. To demonstrate the use of EDE, we will create a little project of our own.

To setup EDE:

(require 'ede) (global-ede-mode)

Now, let's try completion in main.c using moo-complete orcompany-semantic. Nothing also happens. It is because Semantic only looks for header files in current directory by default. If you put it elsewhere, you have to tell Semantic where it is. This is not limited to only Semantic; you have to specify project include path in Eclipse as well.

(ede-cpp-root-project "project_root" :file "/dir/to/project_root/Makefile")

The first argument to ede-cpp-root-project is project name. :fileargument specifies path to project root. You must create a file in the project root, since EDE uses that file as an "anchor" to project root; in our case, Makefile is the anchor file. Not sure why EDE just straightly uses root directory.

(ede-cpp-root-project "project_root" :file "/dir/to/project_root/Makefile" :include-path '("/include1" "/include2") ;; add more include ;; paths here :system-include-path '("~/linux"))

:include-path specifies directories local to your projects that EDE should search first when looking for a header file. :incluide-pathis relative to project root specified in :file.

:system-include-path specifies system include paths that do not belong to current project. Note that despite it is calledsystem-include-path, it does not have to be in place like/usr/include. You can specify any include directories outside of your current project as "system headers".

After done setting up your project, save the file and execute thatede-cpp-root-project expression with C-x C-e. Now, Semantic is aware of your project include paths. However, you have to do one last thing: either close the file main.c and reopen it or M-x semantic-force-refresh to tell Semantic to analyze main.cagain. Otherwise, Semantic will still keep the previous parsing result of this file and completion candidates won't be available. As a result, it is important to load EDE projects defined byede-cpp-root-project before opening any project file.

After that, try auto-completion and you will see everything is working fine again:

ede-project.gif

Summary:

(ede-cpp-root-project "project_root" :file "/dir/to/project_root/Makefile" :include-path '("/include1" "/include2") ;; add more include ;; paths here :system-include-path '("~/linux"))

Later, you will also learn another project management tool calledProjectile. You may ask, why another project management tool? The differences are:

Both have some overlapping in features, such as Projectile provides basic tag navigation in project, but in general they support each other. For our basic usage, we use EDE for smart completion as in previous section and Projectile to navigate our project effortlessly.

Code refactoring

You can use this package, Semantic Refactor for refactoring in small scale. The package offers the following feature:

Please follow this link for demos.

Up until now we were only navigating code in a project using GNU Global. How about jumping to system include headers? You have a few options that I know:

Using Semantic with semantic-ia-fast-jump command

Semantic provides a jump command based on the parsed tags produced by the Semantic C/C++ parser. To jump to any code in system include path, you must first tell Semantic where it is:

(semantic-add-system-include "/usr/local/include") (semantic-add-system-include "~/linux/include")

Then, if point is on an include header like #include <iostream> or a tag inside iostream, executing the command semantic-ia-fast-jumpwill jump to into header file or jump to the tag at point earlier that is inside iostream. If the tag is actually within iostream but you do not include iostream, Semantic won't be able to jump because it sees no appropriate header that contains the tag.

The function semantic-add-system-include will add your include paths to semantic-c-dependency-system-include-path variable. By default, it only contains /usr/include. You can add more such as/usr/local/include or your own project, such as~/linux/include.

The disadvantage of using Semantic is that for it may take brief while to parse, but for once; the next time you can jump to parsed source instantly.

Using generated database from GNU Global

GNU Global has an environment variable named GTAGSLIBPATH. This variable holds GTAGS database of external libraries that your project depends on but not inside your project. For example, your project may rely on system headers such as stdio.h, stdlib.h… but these headers are internal to your project. However, remember that you can only jump to tag definitions of external dependencies, and nothing else (such as files or references). But, again, once you are inside the external library, you can start jumping around sicne it becomes your current project.

To make GNU Global sees your system headers, follow these steps:

export GTAGSLIBPATH=$HOME/.gtags/

Create a directory for holding database, since

you cannot create a database in your system paths

mkdir ~/.gtags

Create symbolic links to your external libraries

ln -s /usr/include usr-include ln -s /usr/local/include/ usr-local-include

Generate GNU Global database

gtags -c

The -c option tells GNU Global to generate tag database in compact format. It is necessary because if your project contains C++ headers likeBoost, without -c your GTAGS database can be more than 1 GB. Same goes for ctags. The GNU Global devs explained that it is because the GTAGS database includes the image of tagged line, and the Boostheaders have a lot of very long lines.

After all the above steps, restart with a shell loaded with that variable. To verify Emacs gets the variable, M-x getenv and enterGTAGSLIBPATH and see if your predefined value is available. Executing ggtags-find-tag-dwim or helm-gtags-dwim jumps to the definition of a system tag like a normal tag.

The disadvantage of using GNU Global is that currently it cannot include files without extension. In the C++ system include directory like /usr/include/c++/4.8/, it contains files without extension such as iostream, string, set, map…. so you can write #includedirectives without having to append .h at the end. GNU Global devs are considering to add support for this use case.

Project management with Projectile

Projectile is a project interaction library for Emacs. Its goal is to provide a nice set of features operating on a project level without introducing external dependencies(when feasible). For instance - finding project files has a portable implementation written in pure Emacs Lisp without the use of GNU find (but for performance sake an indexing mechanism backed by external commands exists as well).

Projectile tries to be practical - portability is great, but if some external tools could speed up some task substantially and the tools are available, Projectile will leverage them.

By default, git, mercurial, darcs and bazaar are considered projects. So are lein, maven, sbt, scons, rebar andbundler. If you want to mark a folder manually as a project just create an empty .projectile file in it.

You also install Projectile using MELPA and setup:

Prefix key of Projectile is C-c p. Some notable features:

Useful commands for working with C/C++ projects:

projectile-find-other-file.gif

There are more, you can find it in my Projectile guide. You can also run C-c p C-h for a list of commands with C-c p prefix.

Source code information

Command: global-semantic-idle-summary-mode

This mode, when enabled, displays function interface in the minibuffer:

func_args.jpg

It works well for C but not C++, since C++ can overload function andsemantic-idle-summary-mode can only display one interface at a time. Since this mode is part of Semantic, it also relies on SemanticDB that is created from parsing source files.

Setup:

(global-semantic-idle-summary-mode 1)

Command: global-semantic-stickyfunc-mode

When enable, this mode shows the function point is currently in at the first line of the current buffer. This is useful when you have a very long function that spreads more than a screen, and you don't have to scroll up to read the function name and then scroll down to original position.

Please click here for demos.

Setup:

(add-to-list 'semantic-default-submodes 'global-semantic-stickyfunc-mode)

One of the problem with current semantic-stickyfunc-mode is that it does not display all parameters that are scattered on multiple lines. This package handles that problem: semantic-stickyfunc-enhance. Extra: stock semantic-stickyfunc-mode does not include assigned values to function parameters of Python. This package also fixed that problem. You can click the link to see demos.

You can install the package via MELPA and load it:

(require 'stickyfunc-enhance)

Using ggtags + eldoc

You can also use ggtags for displaying function interface at point in minibuffer:

(setq-local eldoc-documentation-function #'ggtags-eldoc-function)

However, it won't have syntax highlighting.

Source code documentation

Command: man

To read the documentation for symbol at point or a man entry of your choice, invoke M-x man.

Command: helm-man-woman

If you use Helm, you should be able to use the commandhelm-man-woman, which is bound to C-c h m if you follow my Helm guide. The full guide for the command is here.

helm-man-woman.gif

Source code editing

Folding

Emacs has a minor mode called hs-minor-mode that allows users to fold and hide blocks of text. Blocks are defined by regular expressions which match the start and end of a text region. For example, anything in between { and } is a block. The regular expressions are defined in hs-special-modes-alist.

Setup for C/C++:

(add-hook 'c-mode-common-hook 'hs-minor-mode)

Default key bindings:

Key Binding
C-c @ C-c Command: hs-toggle-hiding
Toggle hiding/showing of a block
C-c @ C-h Command: hs-hide-block
Select current block at point and hide it
C-c @ C-l Command: hs-hide-level
Hide all block with indentation levels
below this block
C-c @ C-s Command: hs-show-block
Select current block at point and show it.
C-c @ C-M-h Command: hs-hide-all
Hide all top level blocks, displaying
only first and last lines.
C-c @ C-M-s Command: hs-show-all
Show everything

Demo:

hs-toggle-hiding.gif

Narrowing

Narrowing means making only a text portion in current buffer visible. Narrowing is useful when you want to perform text editing on a small part of the buffer without affecting the others. For example, you want to delete all printf statements in current functions, usingflush-lines command. But if you do so, you will also delete printfoutside the current function, which is undesirable. By narrowing, you can safely remove all those printf and be certain that nothing else is changed accidentally.

Default key bindings:

Key Binding
C-x n d Command: narrow-to-defun
Narrow buffer to current function at point
C-x n r Command: narrow-to-region
C-x n n Narrow buffer to active region
C-x n w Command: widen
Widen buffer

Identation

Setup default C style

Emacs offers some popular C coding styles. Select the one suitable for you:

;; Available C style: ;; “gnu”: The default style for GNU projects ;; “k&r”: What Kernighan and Ritchie, the authors of C used in their book ;; “bsd”: What BSD developers use, aka “Allman style” after Eric Allman. ;; “whitesmith”: Popularized by the examples that came with Whitesmiths C, an early commercial C compiler. ;; “stroustrup”: What Stroustrup, the author of C++ used in his book ;; “ellemtel”: Popular C++ coding standards as defined by “Programming in C++, Rules and Recommendations,” Erik Nyquist and Mats Henricson, Ellemtel ;; “linux”: What the Linux developers use for kernel development ;; “python”: What Python developers use for extension modules ;; “java”: The default style for java-mode (see below) ;; “user”: When you want to define your own style (setq c-default-style "linux" ;; set style to "linux" )

Setup indentation

By default, Emacs won't indent when press RET because the command bound to RET is newline. You can enable automatic indentation by binding RET to newline-and-indent.

(global-set-key (kbd "RET") 'newline-and-indent) ; automatically indent when press RET

When working with source code, we must pay attention to trailng whitespace. It is always useful to view whitespace in current buffer before committing your code.

;; activate whitespace-mode to view all whitespace characters (global-set-key (kbd "C-c w") 'whitespace-mode)

;; show unncessary whitespace that can mess up your diff (add-hook 'prog-mode-hook (lambda () (interactive) (setq show-trailing-whitespace 1)))

;; use space to indent by default (setq-default indent-tabs-mode nil)

;; set appearance of a tab that is represented by 4 spaces (setq-default tab-width 4)

To clean up trailing whitespace, you can also run whitespace-cleanupcommand.

To convert between TAB and space, you also have two commands:tabify to turn an active region to use TAB for indentation, anduntabify to turn an active region to use space for indentation.

Package: clean-aindent-mode

When you press RET to create a newline and got indented byeletric-indent-mode, you have appropriate whitespace for indenting. But, if you leave the line blank and move to the next line, the whitespace becomes useless. This package helps clean up unused whitespace.

View this Emacswiki page for more details.

;; Package: clean-aindent-mode (require 'clean-aindent-mode) (add-hook 'prog-mode-hook 'clean-aindent-mode)

Package: dtrt-indent

A minor mode that guesses the indentation offset originally used for creating source code files and transparently adjusts the corresponding settings in Emacs, making it more convenient to edit foreign files.

This package is really useful when you have to work on many different projects (for example, your project consists of many git submodules) that use different indentation format. One project might use TABfor indentation; another project might use space for indentation. Having to manually switch between TAB and space is tiresome. We should let Emacs take care of it automatically. This package does exactly that. However, if a project mixes TAB andspace, then the package will have a hard time to detect. But then again, if you work on such project, it doesn't matter anyway.

Setup:

;; Package: dtrt-indent (require 'dtrt-indent) (dtrt-indent-mode 1)

If you use Semantic for code completion, you may one to turn offdtrt-indent messages since Semantic may visit many files for parsing, and each file entered a message from dtrt-indent is printed in echo area and might become a constant annoyance.

(setq dtrt-indent-verbosity 0)

Package: ws-butler

ws-butler helps managing whitespace on every line of code written or edited, in an unobtrusive, help you write clean code without noisy whitespace effortlessly. That is:

With clean-aindent-mode and dtrt-indent and ws-butler, you could totally forget about whitespace. If you are careful, turn onwhitespace-mode (bound to C-c w above) and check for whitespace before committing.

Setup:

;; Package: ws-butler (require 'ws-butler) (add-hook 'c-mode-common-hook 'ws-butler-mode)

Code template using yasnippet

YASnippet is a template system for Emacs. It allows you to type an abbreviation and automatically expand it into function templates. Bundled language templates include: C, C++, C#, Perl, Python, Ruby, SQL, LaTeX, HTML, CSS and more. The snippet syntax is inspired from TextMate's syntax, you can even import most TextMate templates to YASnippet.

Setup:

;; Package: yasnippet (require 'yasnippet) (yas-global-mode 1)

Usage:

In major modes where yasnippet has snippets available, typing a certain keyword and TAB insert a predefined snippet. For example, in a C buffer, if you type for and TAB, it expands to:

for (i = 0; i < N; i++) { ...point will be here.... }

You can view supported snippets here.

Package: smartparens

smartparens is a minor mode that provides many features for manipulating pairs. Pair can be simple as parentheses or brackets, or can be programming tokens such as iffi or ifend in many languages. The most basic and essential feature is automatic closing of a pair when user inserts an opening one.

;; Package: smartparens (require 'smartparens-config) (show-smartparens-global-mode +1) (smartparens-global-mode 1)

;; when you press RET, the curly braces automatically ;; add another newline (sp-with-modes '(c-mode c++-mode) (sp-local-pair "{" nil :post-handlers '(("||\n[i]" "RET"))) (sp-local-pair "/" "/" :post-handlers '((" | " "SPC") ("* ||\n[i]" "RET"))))

For complete documentation, please refer to Smartparens manual.

Compilation Support

Compilation mode turns each error message in the buffer into a hyperlink. You can click on each error, or execute a key binding likeRET to jump to the location of that error.

The following key bindings are available:

Key Description
C-o Display matched location, but do not switch point to matched buffer
M-n Move to next error message, but do not visit error location
M-p Move to next previous message, but do not visit error location
M-g n Move to next error message, visit error location
M-g p Move to previous error message, visit error location
RET Visit location of error at poiint
M-{ Move point to the next error message or match occurring in a different file
M-} Move point to the previous error message or match occurring in a different file
q Quit *compilation* buffer

I usually execute the same compilation command many times. It's more convenient if Emacs doesn't ask us to confirm every time we re-execute a command:

(global-set-key (kbd "") (lambda () (interactive) (setq-local compilation-read-command nil) (call-interactively 'compile)))

If you want to enter a new command, add prefix argument before pressing <f5>.

Demo:

compilation-mode.gif

As you can see, output in *compilation* buffer looks much better than in plain terminal with colors and you can also interact with it.

You can also run other shell commands in here, not just compilation commands. A really cool thing with compilation-mode is that it is asynchronous. That is, if your source files contain errors, you don't have to wait for the whole compilation process to finish. You can examine the errors right away in the *compilation* buffer, while the compilation process keeps going.

When you compile with compilation-mode, your shell output is processed and highlighted with beautiful colors to easy your reading:

compilation-compile.gif

TIP: It is useful to open a Dired buffer of the project root and store a window configuration that contains it into a register, so you can always jump back to project root any where, any time and run compilation command. If you do not use know how to use registers to store window configurations, read it here.

Debugging

With GDB Many Windows

Emacs has built-in frontend support for GDB that provides IDE-like interface. It has a layout like this:

gdb-many-windows.gif

Stock Emacs doesn't enable this layout by default. You have to tell Emacs to always use gdb-many-windows:

(setq ;; use gdb-many-windows by default gdb-many-windows t

;; Non-nil means display source file containing the main routine at startup gdb-show-main t )

Now, find a binary built for debugging, and start GDB by M-x gdb. Emacs prompts asking you how to run gdb. By default, the prompt looks like this:

gdb-prompt.gif

To use gdb-many-windows, you must always supply the -i=mi argument to gdb, otherwise gdb-many-windows won't work. By default, as you've seen the layout of gdb-many-windows above, you have the following buffers visible on your screen (ignore the first row):

| | | | | -------------------------- | ------------------------------------ | | 1. GUD interaction buffer | 2. Locals/Registers buffer | | 3. Primary Source buffer | 4. I/O buffer for debugging program | | 5. Stack buffer | 6. Breakpoints/Threads buffer |

Each cell coressponds to the following commands:

There are two useful commands that are not visible ingdb-many-windows:

There are another variants of the above buffers, with gdb-frameprefix instead of gdb-display. When you run commands withgdb-frame prefix, the buffers are opened in a new frame instead of occupying an existing window. This is useful when you have 2 monitors, one is for the standard gdb-many-windows layout and another one is for displaying disassembly buffer and memory buffer in a separate frame.

With Grand Unified Debugger - GUD

The Grand Unified Debugger, or GUD for short, is an Emacs major mode for debugging. It works on top of command line debuggers. GUD handles interaction with gdb, dbx, xdb, sdb, perldb, jdb, and pdb, by default. Emacs provides unified key bindings for those debuggers. We only concern about GDB in this guide.

GUD works by sending text commands to a debugger subprocess, and record its output. As you debug the program, Emacs displays relevant source files with an arrow in the left fringe indicating the current execution line. GUD is simple and stable. When starting GUD, you only have a GDB command buffer and your source file. If you like simplicity, you can use GUD. However, you can still use othergdb-display- or gdb-frame- variants listed in previous section when needed.

gud.gif

As you can see, the default Emacs interface also includes a menu for regular debugging operations, such as Stop, Run, Continue, Next Line, Up/Down Stack…

Refer to a list of commands supported by GUD at GNU Emacs Manual - Commands of GUD. Note that these key bindings not only work with GDB, but any debuggers supported by GUD, since it's a Grand Unified Debugger.

There's an Emacs packages that offers support for more debuggers:emacs-dbgr. Here is the list of supported debuggers. If you have to work with many languages, use GUD.