Skip to content
purcell's emacs configuration plus C/C++ support
Emacs Lisp Common Lisp Python TeX Groff Scheme Other
Find file
Pull request Compare This branch is 86 commits ahead, 960 commits behind redguardtoo:master.
Latest commit fb72966 @Cheukyin add sml-mode
Failed to load latest commit information.
defuns some handy buffer tools from magnars
elpa Update cpputils-cmake
site-lisp add sml-mode
snippets fix org-c-exported-html bug in init-cc-mode.el
.custom.el Add Path Completion
.gitignore Add archive-contents in .gitignore
.viper Move .viper to .emacs.d directory Add compiling guidance in
cdlatex.el Add auctex and cdlatex plugin
cl-lib.el cl-lib, helm plugins
core Add ECB
init-ace-jump-mode.el light weight emacs
init-artbollocks-mode.el artbollocks-mode, thanks to Sacha Chua
init-auctex.el Change the Tex-Engine to xelatex
init-auto-complete.el Add the c/c++ header file on x86_64 machine & comment out the i386's
init-bbdb.el remove obsolete bbdb code
init-cc-mode.el fix org-c-exported-html bug in init-cc-mode.el
init-cmake-mode.el cmake mode
init-company.el Abandon auto-complete && Adopt company-mode
init-compat.el fake emacs24.3 API
init-cperl-mode.el add c++, yasnippet stuff
init-crontab.el Remove redundant crontab-mode config
init-csharp-mode.el csharp-mode in elpa now, optimize loading speed
init-css.el init-css.el should be compatible with web-mode
init-csv.el Move settings from custom.el so that file can be ignored and used for…
init-ctags.el remove package ctags
init-dired.el dired mime optimized for different OS
init-doxygen.el doxygen.el
init-ecb.el Add ECB
init-eim.el clean emacs.d, cut of 50% start up time
init-elisp.el flymake temp file should be in /tmp/
init-elnode.el use elnode
init-elpa.el install flx-ido package
init-emacs-w3m.el remove delicious-mode
init-emacspeak.el emacspeak
init-erlang.el Remove redundant erlang config
init-evil.el add ,cp evil-shortcut for compiling file
init-exec-path.el Fix argument order
init-flx-ido.el configured flx-dio
init-flycheck.el Add flycheck && Comment out the flyspell
init-flymake.el flymake elisp
init-fonts.el Clarify 'increment-default-font-height
init-frame-hooks.el Extract remaining config blocks in init.el into separate init files b…
init-ggtags.el Add ggtags
init-git.el updated clipboard api
init-gnus.el gnus set up
init-gtags.el use ggtags set up
init-gud.el gud set up
init-gui-frames.el Make 'increment-default-font-height work in full-screen windows
init-haml.el Revert "remove flymake for coffee, css and haml, install flycheck"
init-haskell.el upgrade haskell stuff
init-helm.el Add xcscope.el && Comment out helm-gtags in init-helm.el
init-hippie-expand.el clean code
init-ibuffer.el use web-mode instead of nxml-mode
init-ido.el lock smex to v2.1 because v3.0 requires emacs24.3
init-isearch.el Use now-standard 'isearch-occur in place of hand-rolled code
init-javascript.el use jshint for js-mode
init-jedi.el Use pyvenv.el and can change the virtualenv of jedi now
init-keyfreq.el add missing init-keyfreq.el
init-linum-mode.el no linum on log-edit-mode
init-lisp.el clean code, fix some regression
init-locales.el Don't fail with an error when starting in a terminal environment with…
init-lua-mode.el lua-mode config
init-markdown.el merged from purcell
init-maxframe.el When creating a new frame, maximize it iff previous frame was maximized
init-minimap.el Add minimap
init-misc.el autload for some packages
init-modeline.el simpler mode-line
init-move-window-buffer.el move window and buffer
init-moz.el typo in moz-setup
init-org-jekyll.el modify init-org-jekyll.el to publish org to html
init-org-mime.el use the org-mime from 20130503 and org 20130805
init-org.el set org-intend-mode in init-org.el
init-osx-keys.el use web-mode instead of nxml-mode
init-pomodoro.el pomodoro config
init-powerline.el Abandon company-mode && use auto-complete
init-projectile.el configured projectile
init-proxies.el Add (and use) a new string-rtrim function
init-python-mode.el Comment out anaconda-eldoc part in init-python-mode.el
init-rainbow.el enable rainbow-mode
init-recentf.el clean emacs.d, cut of 50% start up time
init-ruby-mode.el clean ruby-mode
init-semantic.el comment on semantic plus complete-symbol
init-sessions.el save history of evil-ex
init-sh.el sh-mode supports more files
init-site-lisp.el nxml-mode is fully functional now
init-slime.el slime api changed
init-smartparens.el use smartparens everywhere
init-smex.el lock smex to v2.1 because v3.0 requires emacs24.3
init-sml.el add sml-mode
init-smooth-scroll.el Add mouse-wheel acceleration to make mouse-scrolling more smooth
init-spelling.el camel case word could be very long
init-sr-speedbar.el tweak sr-speedbar, no refresh
init-stripe-buffer.el use stripe-buffer
init-term-mode.el remove goto-address. I donot use mouse
init-textile.el merged from purcell
init-uniquify.el Extract remaining config blocks in init.el into separate init files b…
init-utils.el open current html file in firefox
init-web-mode.el support more html templates
init-which-func.el which-func-mode
init-windows.el new hotkeys for undo/redo windows layout
init-workgroups2.el use workgroups2
init-xcscope.el Add xcscope.el && Comment out helm-gtags in init-helm.el
init-xterm.el (mwheel-install) in GUI only, make emacsclient under cygwin work
init-yari.el use web-mode instead of nxml-mode
init-yasnippet.el update init-yasnippet.el
init-zencoding-mode.el use web-mode instead of nxml-mode
init.el add sml-mode
init.el.before_ecb_2.40 Add ECB


  • I’m using Vim key binding. Please see section Tips if you prefer the Emacs key binding.
  • People in Mainland China may need goagent to download packages from ELPA. Run command “http_proxy= emacs -nw” after starting goagent server (or any proxy server).
  • C++/C developers, you need tell Emacs location of header files. You MUST see section `clang` now!
  • I suggest Windows users using Cygwin version Emacs to avoid overhead of setting up third party tools. But this configuration is still usable even in native windows Emacs if you set up environment variable HOME.
  • I whitelist packages from melpa because it is too cutting edge. Modify variable “melpa-include-packages” in init-elpa.el if prefer some package from it.
  • If you not are willing to or cannot fetch packages from remote repositories, see the section Install packages without elpa/marmalade/melpa.
  • In your bug report, please include details of environment (OS, Emacs version …) and the full output of `emacs –debug-init`.
  • Remove bundled emacs 22 at first if you are using OS X!
  • If you don’t want to use Emacs’ own package manager, please extract the your package’s source code at ~/.emacs.d/site-lisp. There are many samples there.


My first priority is stable. So I use fewer cutting-edge packages from melpa. If you want to get all the latest package from melpa, search the line containing “(setq package-filter-function nil)” in “init-elpa.el” and un-comment it.

Most modern popular programming languages are supported (C/C++/Java/Ruby/Perl/Python/C#/Lua/Javascript …).


  • All key binding and plugins are usable in terminal
  • Real time HTML syntax checker enabled (you need install tidy or tidy-html5). I recommend tidy-html5.
  • git or subversion is NOT needed. You DONOT need run ‘git submodule update’.
  • optimized for cross-platform C++ development with CMake and wxWidgets
  • emacs-w3m (console browser)
  • eim (Chinese pinyin input method)
  • org2blog (post wordpress blog with org-mode)
  • make the configuration work on ALL platforms (Linux/Cygwin/Mac).
  • The configuration work with Emacs version >=24 but still usable with Emacs version 23 (tested with Emacs 23.4.1).
  • evil-mode and its plugins (Vim key binding)
  • yasnippet and my customized snippets (insert code snippet by typing less keys)


Download this zip file and extract its content into ~/.emacs.d. Ensure that the ‘init.el’ contained in this repo ends up at ~/.emacs.d/init.el and old ~/.emacs IS REMOVED.

You possibly need run the below command in the terminal at least once to update the content from package repositories:

emacs -nw --batch -l ~/.emacs.d/init.el -f package-refresh-contents

If you cannot download packages from remote repository (for example, you are behind company firewall), don’t panic!

You do have USB stick, right?

Check the section Install packages without elpa/marmalade/melpa for solutions.

Quick guide

Step 1, Learn basic knowledge about OS

  • Know what’s environment variable
  • Know what’s pipe, stdout, stdin

Step 2, Read Emacs official tutorial at least once

Press “C-h t” (C means Ctrl) and start read tutorial.

  • Know how to move cursor
  • Know how to open help. Press “C-h v” and “C-h f”.

Step 3, Learn org-mode basics

Org-mode is a for notes-keeping and planning. Please watch the Carsten Dominik’s talk. It’s really simple. The only hot key you need remember is “Tab”.

Step 4, use Emacs to solve your first specific problem

For that specific problem, you can visit EmacsWiki for the solution. Newbies can ask for help on

Directory structure

init.el is main file which include all the other *.el files.

init-elpa define how and what packages will be installed from elpa/marmalade/melpa by package manager.

The package manager will extract packages into ~/.emacs.d/elpa/.

I also manually download and extract some packages into ~/.emacs.d/site-lisp/. Packages in ~/.emacs.d/site-lisp/ is not visible to Emacs package manager.

My own snippets for Yasnippet is in ~/.emacs.d/snippets.

Other directoris do not matter.

Third party command line tools

These tools are OPTIONAL. Your Emacs will NOT crash if they are not installed.

w3m (web browser in console)

  • needed by `w3m` (w3m is emacs package name written in elisp)
  • install through OS package manager
  • please note only emacs with GUI can display image


  • required by `flymake-lua`
  • install through OS package manager

aspell (RECOMMENDED) or hunspell, and corresponding dictionary (aspell-en, for example)

  • needed by `flyspell`
  • hunspell is the alternative of `aspell`. So you need only install either aspell or hunspell.
  • install through OS package manager
  • I force the dictionary to “en_US” in init-spelling.el. You can modify it in init-spelling.el.

sbcl (lisp environment)

  • needed by lisp `slime`
  • install through OS package manager

tidy (html tidy program) or html5-tidy (RECOMMENDED)

  • needed by `web-mode` for real time HTML syntax check
  • install through OS package manager
  • For html5-tidy, you need download its source code and build it manually


  • install `node.js` through OS package manager, then `sudo npm install -g csslint`

zip and unzip

  • needed by `org-mode` to export org to odt
  • install through OS package manager

jshint (if you use js-mode instead js2-mode)

  • install `node.js` through OS package manager, then `sudo npm install -g jshint`


  • needed by my clipboard command `copy-to-x-clipboard` and `paste-from-x-clipboard` under Linux
  • install through OS package manager


  • needed by `cpputils-cmake`, `flymake`, `company-clang`
  • install through OS package manager
  • If you use `cpputils-cmake` and `cmake`, `cpputils-cmake` will do all the set up for you. You don’t need read next item!
  • If you use `company-clang`, add `(setq company-clang-arguments ‘(“-I/example1/dir” “-I/example2/dir”))` into ~/.emacs.d/init.el
  • P.S. Abandon ‘company-mode’, Use ‘auto-complete-mode’ now, see the commments in ‘init-auto.complete.el’

MozRepl (Firefox addon)


GNU Global

  • needed by `ggtags.el`
  • it creates index files for code navigation
  • more advanced than ctags, supports references and better performance
  • install through OS package manager


  • You need pyflakes for real time python syntax checker like `flymake-python`
  • Install pip through OS package manager, then `pip install pyflakes`
  • On cygwin you need install `setuptool` in order to install `pip`.


  • Only one executable `soffice` needed when converting odt file into doc (Microsoft Word 97)
  • conversion will happen automatically when exporting org-mode to odt
  • The conversion command is in variable `org-export-odt-convert-processes`
  • Install through OS package manager


  • To beautify javascript code (insert extra space, for example)
  • Install pip through OS package manager, then `pip install jsbeautifier`

OS package manager recommended

Install packages without elpa/marmalade/melpa

Solution 1

Here are the exact steps you need follow:

  • Go to
  • Click “Download ZIP”
  • Extract zip somewhere say “~/myelpa”.
  • Double check that there is a file name “archive-contents” in the directory “~/myelpa”.
  • uncomment below code in ~/.emacs.d/init-elpa.el.
(setq package-archives '(("myelpa" . "~/myelpa/")))

That’s it. You will never need internet connection in the future.

Please note that all your packages are locked to the versions I’m using. So you can’t upgrade package online in the future.

I don’t recommend advanced users locking their package version.

Solution 2

If you are too lazy to download ZIP file, you can uncomment below code in ~/.emacs.d/init-elpa.el,

(setq package-archives '(("myelpa" . "")))

Then you are good to go. Obviously you need internet connection to access

Report bug

Please file bug report at Don’t send me email!


By default EVIL (Vim emulation in Emacs) is used. You can comment out line containing “(require ‘init-evil)” in init.el to unload it.

Some package cannot be downloaded automatically because of network problem.

You need manually `M-x list-packages` and install it or just `M-x package-refresh-content` and restart Emacs.

If you use `gnus` for email (Gmail, for example). Check ~/.emacs.d/init-gnus.el which includes my most settings except my private stuff. Here is my Gnus tutorial.

To toggle Chinese input method (eim, for example), press `C-` or run command `M-x toggle-input-method`(I bind it to `C-<SPC>` in evil-insert-state)


  • completion: `C-M-i`
  • keep tags balanced and input the end-tag at the same time as the start-tag: `C-c C-i`
  • for block-level elements: `C-c C-b`
  • `/` automatically inserts the rest of the end-tag when it occurs after `<`

Mutlti-Window WorkingFlow

  • M-o to show the window-number
  • M-(num) to switch to the (num)th window
  • (C-x 1) to minimize the current window
  • (C-x 4 u) or “,wu” to undo the window-operation
  • (C-x 4 r) or “,wr” to redo the window-operation

Version Controll

  • Magit Install magit , then M-x magit-blahblah….


Configure your shotcuts in init-evil-leader.el.


Providing a nice set of features operating on a project level.See

Requiring find, xargs, git installed.

If your project directory isn’t gitted, you can touch .projectile in you project’s root directory.

The common commands:

  • “,pf” ‘projectile-find-file
  • “,pg” ‘projectile-grep
  • “,sp” ‘projectile-switch-project
  • “,pd” ‘projectile-find-dir-other-window
  • “,pD” ‘projectile-dired
  • “,p!” ‘projectile-run-shell-command-in-root

If you’d like to instruct Projectile to ignore certain files in a project, when indexing it you can do so in the .projectile file by adding each path to ignore, where the paths all are relative to the root directory and start with a slash. Everything ignored should be preceded with a - sign. Alternatively, not having any prefix at all also means to ignore the directory or file pattern that follows. Here’s an example for a typical Rails application:



Make your emacs closer to IDE. The shortcuts for ecb have been set in init-ecb.el

The layout of ECB can be modified in site-lisp/ecb/ecb-layout-defs.el And after you change the layout, you may `M-x ecb-byte-compile` to recompile the [yas] elisp error! Symbol’s function definition is void: ca-with-commentle

If you want to activate ECB, `M-x ecb-activate` or `,ea’ , then , when emacs shuts down , REMEMBER TO `m-X ECB-DEACTIVATE’ OR `,ED` TO SHUTDOWN ECB

Word Completion

  • type some prefix characters, then M-/

Path Completion

  • C-c C-i to input the path && C-j to insert it.
  • type some prefix characters, then M-/


You can configure your own window transparency in .custom.el


You can use company-mode or auto-complete-mode. Comment out the “init-company” or “init-auto-complete” in init.el to choose either. The default is “company-[yas] elisp error! Symbol’s function definition is void: ca-with-comment”


  • Grammar flycheck

`M-x python-check

  • Jedi

Jedi.el is a Python auto-completion package for Emacs. See

Virtualenv is needed. Then, `M-x jedi:install-server RET

<C-tab> jedi:complete Complete code at point.

C-c ? jedi:show-doc Show the documentation of the object at point.

C-c . jedi:goto-definition Goto the definition of the object at point.

C-c , jedi:goto-definition-pop-marker Goto the last point where jedi:goto-definition was called.

  • Pyvenv

Jedi uses the variable VIRTUAL_ENV to determine which the virtualenv to use(the default is .emacs.d/.python-enviroments), So I use pyvenv to change the workon virtualenv.

Firstly, install virtualenvwrapper

Pust the following code in your .bashrc/.zshrc:

if [ `id -u` != '0' ]; then
export VIRTUALENV_USE_DISTRIBUTE=1        # <-- Always use pip/distribute
export WORKON_HOME=$HOME/.virtualenvs       # <-- Where all virtualenvs will be stored
source /usr/local/bin/

mkdir .virtualenvs in you home directory, and put your virtualenv in it. if you virtualenvs is system-wide spreaded, you may make a symbolic link in .virtualenvs.

When you’re in python-mode, Jedi uses .emacs/.python-enviroments as the default virtualenv, you can change it by M-x pyvenv-workon and choose the one you want, then `M-x jedi:stop-sever` to restart jedi (the words underscored is not necessarily if you use my pyvenv.el, because I’ve refined it and it will restart jedi automatically)

Auto-completion Popup Face

  • In the elpa/popup/popup.el,modify the color of the “popup-face” & “popup-menu-selection-face” “popup-tip-face”
 (defface popup-face
'((t (:background "yellow" :foreground "black"))))

 (defface popup-menu-selection-face
'((t (:background "orange" :foreground "black"))))

 (defface popup-tip-face
'((t (:background "orange" :foreground "black"))))
  • In the auto-complete-clang.el, modify the color of the “ac-clang-candidate-face” & “ac-clang-selection-face”
  • In the auto-complete-config.el, modify the color of yasnippet & gtags face.
  • After modification, you must `M-x byte-recompile-file`

Code Map

  • M-x minimap-mode

Source Reading


  • n/p navigates over individual results
  • k kills individual results
  • N/P or M-n/M-p navigates over file results
  • M-k kills file results
  • M-N/M-P navigates over result sets
  • M-K kills result sets
  • Navigation from outside the cscope buffer (C-c s n/p/N/P) is restricted to the result set at (point)
  • Keybindings:

All keybindings use the “C-c s” prefix:

C-c s sFind symbol.
C-c s =Find assignments to this symbol
C-c s dFind global definition.
C-c s gFind global definition (alternate binding).
C-c s GFind global definition without prompting.
C-c s cFind functions calling a function.
C-c s CFind called functions (list functions called from a function).
C-c s tFind text string.
C-c s eFind egrep pattern.
C-c s fFind a file.
C-c s iFind files #including a file.

These pertain to navigation through the search results:

C-c s bDisplay cscope buffer.
C-c s BAuto display cscope buffer toggle.
C-c s nNext symbol.
C-c s NNext file.
C-c s pPrevious symbol.
C-c s PPrevious file.
C-c s uPop mark.

These pertain to setting and unsetting the variable, `cscope-initial-directory’, (location searched for the cscope database directory):

C-c s aSet initial directory.
C-c s AUnset initial directory.

These pertain to cscope database maintenance:

C-c s LCreate list of files to index.
C-c s ICreate list and index.
C-c s EEdit list of files to index.
C-c s WLocate this buffer’s cscope directory (“W” –> “where”).
C-c s SLocate this buffer’s cscope directory. (alternate binding: “S” –> “show”).
C-c s TLocate this buffer’s cscope directory. (alternate binding: “T” –> “tell”).
C-c s DDired this buffer’s directory.


  • ctags -R -e *.h *.cpp
  • C-] to find-definition , C-t to pop


To replace cscope, global is required.

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

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

Basic movements

  • %: move around over a balanced expression that can be a pair or a symbol
  • v%: rusn mark-sexp, put mark after following expression that can be a pair or a symbol
  • C-M-a: runs beginning-of-defun, which moves point to beginning of a function
  • C-M-e: runs end-of-defun, which moves point to end of a function
  • C-M-h: runs mark-defun, which put a region around whole current or following function

Find definitions in current buffer

semantic-mode should be enabled. You can add it to the specific mode you want in init-ggtags.el, like this:

(add-hook 'c-mode-hook 'semantic-mode)
(add-hook 'c++-mode-hook 'semantic-mode)
(add-hook 'python-mode-hook 'semantic-mode)
(add-hook 'asm-mode-hook 'semantic-mode)

M-x helm-semantic-or-imenu or <evil-leader>gcd , please notice the “pattern: ” prompt in the minibuffer, you can type func to narrow the candidates that are functions, class for that are classes and var that are variables.

Find definitions in project

  • <evil-leader>gt, which runs ggtags-find-tag-dwim, this command jump to tag base on context:
    • If the tag at point is a definition, ggtags jumps to a reference. If there is more than one reference, it displays a list of references.
    • If the tag at point is a reference, ggtags jumps to tag definition.
    • If the tag at point is an include header, it jumps to that header.

    M-n and M-p to go to the next and previous file.

    M-< and M-> for the first and the last.

    M-* to abort and go back to the location where the search was started

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

  • M-, , which runs pop-tag-mark to jump back to original location

Find files in project

If point is on an included header file, <evil-leader>gt or ggtags-find-tag-dwim automatically jumps to the file.

View visited tags with tag stack

<evil-leader>gp, which runs ggtags-prev-mark <evil-leader>gn, which runs ggtags-next-mark <evil-leader>gsh, which runs ggtags-view-tag-history that shows visited tags from newest to oldest, from top to bottom.

Update Tags

When file is saved, tags will be automatically updated. If failed, “<evil-leader>gu” to update it manually.

Source Editing


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, using flush-lines command. But if you do so, you will also delete printf outside 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:

  • narrow-to-defun, Narrow buffer to current function at point
  • narrow-to-region
  • widen, Widen buffer

Source Compilation

When you want to compile the source code, you can type `M-x compile` or type `,cp`, then type the compiling command, such as `gcc blabla` for c/c++ source code, or `python blabla` for python code.

About Emacs23

Emacs23 support will be dropped in one year <2015-04-24 Thu>. Currently Emacs 23 will not support below packages:

  • helm
  • org-mode and its third party packages
  • company-mode
Something went wrong with that request. Please try again.