/exordium

An Emacs configuration that will make your C++ IDE jealous.

Primary LanguageEmacs LispMIT LicenseMIT

Exordium

What is this repo

A portable Emacs configuration focused on adding IDE-level features for C++ and Lisp/Clojure programming. It is only intended to work with Emacs 24 on Linux and OS X including in -nw mode, but it should work on Windows as well. It is modular and customizable. It is not a starter kit, it is a hacker kit.

If you are looking for a good generic Emacs configuration to start with, you might want to check these links: Emacs Prelude, Steve Purcell's config, Spacemacs, Awesome Emacs.

Table Of Contents

Features

  • Usability: IDO (turned on by default); Auto Complete; Expand Region (increase selected region by semantic units); Fill Column Indicator (80 character column marker); Project Explorer (directory tree); etc.
  • Projects: Projectile a project-based file management tool; Helm an alternative to IDO.
  • Git: Magit (git UI); Git Gutter (diffs in buffer).
  • C++:
    • RTags: a LLVM/Clang-based code indexer providing goto definition, find references, refactoring, compilation errors in buffer, auto-complete etc.
    • Formatting keys and snippets for the BDE code style.
  • JavaScript: JS2-mode.
  • Clojure: Cider and Lein.
  • Eye candy: a few themes that do not look like an "angry fruit salad", and PowerLine.

Installation

Backup any .emacs file or .emacs.d directory you may have, and then clone this repo:

$ git clone https://github.com/philippe-grenet/exordium.git ~/.emacs.d

The first time you start Emacs it will download and compile the required packages, which may take a couple of minutes. If your machine is behind a proxy server, you should create a file .emacs.d/before-init.el with the address of the proxy before you start Emacs:

(setq url-proxy-services
      '(("no_proxy" . "^\\(localhost\\|10.*\\)")
        ("http"     . "<proxy-name>:<proxy-port>")
        ("https"    . "<proxy-name>:<proxy-port>")))

You can also clone the repository elsewhere, and use the init-test.sh script to try out exordium. init-test.sh will run your default emacs with the current directory as your user-emacs-directory, loading init.el, and no other init files.

Updates

To update Exordium, do M-x update-config. This command pulls from Github and recompiles everything. Restart Emacs after that.

Melpa packages are not updated automatically: you can do it with M-x package-list-packages, then U then x.

Files

The main file is init.el: it load the modules from the modules subdirectory and the default theme from the themes subdirectory. The extensions subdirectory is used for third-party plugins that are not available in Melpa.

3 files can be added in your directory ~/.emacs.d to customize the configuration for the local machine (these files are not tracked by git):

File name Usage
prefs.el Loaded before any module. The module init-prefs.el defines a number of customization variables for fonts, theme etc. prefs.el is where you should override any of these variables.
before-init.el Loaded before anything else. Use it to set up the HTTP proxy for instance.
after-init.el Loaded after everything else. This is where you should add your own features.

You can also have local modules in a directory ~/.emacs.d/local.

See the Customization section below for more details.

Keymap

General:

Keybinding Description
ESC Quit command (keyboard-quit), also bound to C-g. You can disable this if you like.
C-z Undo! (undo).
C-` kill-this-buffer (faster than C-x k).
C-x C-r Open recent file (completes open file with C-x C-f).
M-g goto-line (prompts for a line number).
C-+ Increase font size (text-scale-increase).
C-- Decrease font size (text-scale-decrease).
M-C-l Switch back and forth between the 2 top buffers (from XEmacs).

Editing:

Keybinding Description
RETURN Return and indent by default; use S-RETURN for just return.
M-BCKSP backward-kill-word (e.g. the opposite of M-d kill-word).
C-\ Delete spaces after cursor (delete-horizontal-space-forward).
C-BCKSP Delete spaces before cursor (delete-horizontal-space-backward).
M-\ Delete all spaces around cursor.
M-LEFT and M-RIGHT Move cursor by semantic units (use C-LEFT and C-RIGHT to move by words).
C-c d Duplicate line.
C-= Expand region by semantic units.
M-C-= Contract region by semantic units.
C-| Toggle the 80-column ruler (fill column indicator).

Navigation:

Keybinding Description
C-x C-\ Goto last change in buffer. Repeat to go to the second most recent edit, etc.
C-x C-| Goto last change in reverse direction (e.g. add shift).
C-c s Push point onto position stack (e.g. bookmarks).
C-c b Pop point from position stack.

Window manager:

Keybinding Description
C-c ARROW Move cursor between windows.
C-c S-ARROW Move the windows themselves.

Auto-complete:

Keybinding Description
C-. Force trigger auto-complete.
ESC Abort auto-complete.

Projectile

Projectile adds the notion of "projects" to Emacs. It provides many keys to find files within a project, grep in all files etc. Projectile maintains an index of files for each project it knows about; this list is created by scanning the project root directory. The main usage is to jump to a file using a partial name without having to remember in which directory it is, but it also supports grep/ack and replace in project. Projectile works with Helm or IDO, so you can use either one with different keys.

Here is an example: C-c h shows the list of buffers and files in the current project using Helm; to find a file you just need to type a few letters and the list shrinks as it performs fuzzy matching:

Helm

Setting up projects

A .git repo or a .projectile file defines the root directory of a project. Even if you have a git repo, you can create a .projectile file at the root of your project: it allows for filtering out the files you don't care about, such as binaries, scripts etc. For example, suppose you have a workspace directory containing among other things the BDE library and a project "bar"; you could create .projectile file like this:

+/bde/groups
+/bar
-.*
-*.md
-*.cap
-*.mem
-*.dep
-*.opts
-*.defs

The plus sign is used to ignore everything except specific directories; alternatively the minus sign is used to indicate what directories to ignore, starting at the root of the project. The minus sign can also ignore file patterns. If both directories to keep and ignore are specified, the directories to keep first apply, restricting what files are considered. The paths and patterns to ignore are then applied to that set. Refer to the Projectile documentation for details.

Now you need to teach Projectile where your projects are. You can do that by:

1. Simply opening the project's root dir in Dired, and then pretending to search a file with Helm (C-c h), or switching project with IDO (C-c p p). The top of the Helm buffer should show the list of projects including yours.

2. Sometimes method 1 works for the current session, but then Projectile forgets your projects as soon as you restart Emacs. In this case try to restart Emacs in the project's root directory for Projectile to find it. You should only need to do this one time for each project, after that it is cached.

3. The brute force method which is guaranteed to work is to edit the file where Projectile saves the list of projects. This file is ~/.emacs.d/projectile-bookmarks.eld. Since it is constantly written by Emacs itself, you need to exit emacs and restart it with emacs -Q (so that Projectile does not run). Edit the file, save and restart Emacs normally. Here is my bookmark file:

("/bb/mbig7/mbig2387/workspaces/rsp/" "/bb/mbig7/mbig2387/workspaces/si-core/" "/home12/pgrenet/.emacs.d/" "/bb/mbig7/mbig2387/workspaces/bsl-internal/" "/bb/mbig7/mbig2387/workspaces/bde-core/")

Using Projectile

The name of the current project is displayed in the mode line, between square brackets. There are only 2 keys to remember:

  • To open a file in the current project using Helm, type C-c h. This will display the Helm buffer. Start typing for a partial name to narrow the selection until you find what you were looking for. Note that it performs fuzzy matching.
  • If you want to open a file from a different project, type C-c C-h instead. The Helm buffer will initially display just the list of projects. Choose your project and press enter; Helm will now display all indexed files in that project.

C-c p C-h displays the list of keys for Projectile. Below are the most important ones.

Keybinding Description
C-c h Find file in current project with helm
C-c C-h Same, but first select project
C-c p p IDO: switch project
C-c p f IDO: find file in current project
C-c p s g Grep in current project
C-c p s a Same but using ack
C-c p r Interactive query-replace on all files in project
C-c p i Invalidate cache

See Projectile documentation for other keys.

Project Explorer

Projectile is linked with Project Explorer which displays the project directory structure on the left side:

Project Explorer

Keybinding Description
C-c e Open project explorer on the left side.

With the cursor in the Project Explorer window, you can use these keys: q to quit. s to change directory. TAB to toggle folding, S-TAB to fold all. RETURN open file. w Show path and copy it to clipboard.

Other Helm tools

  • C-S-s or M-x helm-swoop: search for text in current buffer using Helm Swoop. Start typing text: the Helm window shows all matching lines, and you can jump from one to another using the arrow keys.
  • M-x helm-multiple-swoop-all: same but search within all buffers.

Git

All git-related keys use prefix C-c g plus one more key. For example C-c g s runs Magit status:

magit

The bottom window shows the current git status. Use the tab key on any file to fold or unfold its diff. Use the s key to stage or unstage a file, and the capital S to stage all of them. Use the k key to revert a file. Type c twice to commit; it will ask for the commit message (C-c C-c to close the window and commit). Finally the q key quits magit. There are a lot of other keys which are described here.

The screenshot above also shows git gutter in the top buffer. Git gutter displays a git diff of the file in the left-side fringe (you can customize it). Git gutter defines a few keys for navigating between hunks, diffing and reverting.

Magit keys:

Keybinding Description
C-c g s Open git status (magit-status).
C-c g l Open git log (magit-log).
C-c g f Open git file log (magit-file-log).
C-c g b Toggles git blame mode on and off (magit-blame-mode).
C-c g g Git grep (vc-git-grep).

Git gutter keys:

Keybinding Description
C-c g down Goto next hunk in buffer (git-gutter:next-hunk).
C-c g up Goto previous hunk in buffer (git-gutter:previous-hunk).
C-c g d Diff the current hunk (git-gutter:popup-diff).
C-c g r Revert the current hunk after confirmation (git-gutter:revert-hunk).
Git Timemachine key Description
C-c g t Enter the git timemachine (git-timemachine-toggle)

C++

Utilities

Keybinding Description
C-TAB Alternate between header file and source file.
C-c ; Rename variable under cursor (non-RTags).

Keys for formatting code according to the BDE style:

Keybinding Description
C-c a Align function arguments (in signature).
C-c f Align function arguments (in function call).
C-c m Align class members (region must be selected).
C-> Right-align end-of-line comment or text after cursor.
C-c i Insert redundant #include guard.
C-c = Insert class definition header.
C-c - Insert class implementation header.

Snippets

YASnippet is a template system which replaces a keyword by a template after you hit the trigger key. YASnippet is only enabled for C++ mode currently. The trigger key is set to C-c y because the default TAB key is already way overused between intention and auto-complete. You can easily use a function key if you prefer by adding this in your after-init.el:

(define-key yas-minor-mode-map (kbd "<f2>") 'yas-expand)

Snippets are stored in ~/.emacs.d/snippets/c++-mode. Here are the snippets.

Note that variable *bde-component-author* defines the default author for a header file template (see modules/init-yasnippet.el). You can set it to your name in after-init.el.

RTags

RTags is a LLVM-based C++ indexer which provides a daemon called "rdm" that maintains a persistent (memory mapped) file-based index. The client for "rdm" is command-line client called "rc". RTags uses a single index for all symbols, but it allows for loading and unloading projects individually.

To use it, first start the daemon:

$ rdm

This will start the daemon on the foreground, using a number of concurrent "rp" jobs that is function of the number of CPUs on the local machine. It starts by reading the saved project indices in ~/.rtags if any. By default it logs to the console but you can make it log to a file instead with -L file or make it silent with -S. There are many options; use --help to see the list. You can also create a file ~/.rdmrc containing the default command line arguments.

Alternatively you can run rdm as an Emacs subprocess: M-x rtags-start-rdm, with logs going into a buffer (in color!). Stop it with M-x rtags-quit-rdm.

Controlling rdm

rdm stores project indices into a directory ~/.rtags and reloads them as needed. rc and rdm communicate with each other using a socket file ~/.rdm.

Command Description
rc -w List projects in the index.
rc -w proj Switch to project "proj" (a regex).
rc -W proj Unload and delete project "proj".
rc -J Reload the compilation DB from the current directory.
rc --find-project-root /path/to/sourcefile.cpp Print what it determines to be the correct project root.
rc -T sourcefile.cpp Say whether this file is indexed or not.
rc -q Shutdown rdm.

Note that a job may crash while trying to index a file. If it does, rdm will retry a few times and then give up with the file it cannot parse.

Setting up your project

If the project root directory does not contain a .git or .svn repo, you need to create a file .rtags-config in the root directory with the specified content:

project: /path/to/project

Then you need to tell rdm how to compile your project, by creating a compilation database in a file named compile_commands.json. The compilation database contains one entry for each file to compile, like the following (simplified for clarity):

{ "directory": "/home/phil/workspaces/foo/",
  "command":   "/usr/bin/clang++ -Irelative
                -I/home/phil/workspaces/bde/groups/bsl/bsl+stdhdrs
                -I/home/phil/workspaces/bde/groups/bsl/bslma
                -I/home/phil/workspaces/bde/groups/bsl/bsls
                -c -o bar.o bar.cpp",
   "file":      "bar.cpp" }

You can generate this compilation database with the command M-x rtags-create-compilation-database. But before you do, it needs a little help: you need to tell it what clang++ command to use to compile any file, with all the -I directives that are necessary for your project.

The command uses a file compile_includes in the project root directory, which specifies how to generate compilation_database.json for your project. It is a simple text file indicating where are all the source files and all the include files. The "src" directives indicate where to find the source files to put in the index (each of them will have its own entry in the compilation database). The "include" directives indicate additional "-I" includes in the clang command line. Both are recursive: any path will be scanned for source files or subdirectories; however the "exclude" directives indicate what patterns (regex) to exclude when scanning the "src" and "include" paths. Finally the "excludesrc" directive is used to specify patterns (regex) of source files names to exclude.

Note that all directives except "src" are optional. Also note that paths are either absolute or relative to the project root. Here is an example:

  # 'compile_includes' file for project foo
  # Patterns to exclude in -I directives and while looking for sources:
  exclude /test$
  exclude /doc$
  exclude /group$
  exclude /package$

  # Where are the source files (there could be multiple directories).
  # We will scan recursively any subdirectories that do not match any
  # 'exclude' regex.
  src .

  # What to put in -I directives (in addition to the source files above).
  # We will scan recursively any subdirectories that do not match any
  # 'exclude' regex.
  include /Users/phil/Code/cpp/include/bsl
  include /Users/phil/Code/cpp/include/bdl

  # If any file name pattern must be excluded from the "src" files, use
  # the "excludesrc" directive. For example this will exclude all test
  # drivers:
  excludesrc \.t\.cpp$

  # -D macros, if any:
  macro BDE_BUILD_TARGET_SAFE

In addition, the creation of a compilation database uses these variables:

Variable Description
*rtags-compile-includes-base-dir* Set this to your workspace path if you want to use relative paths in compile_includes that are not relative to the project's root directory (the default).
*rtags-clang-command-prefix* Default is "/usr/bin/clang++ -Irelative" (note that RTags ignores the clang++ command because it uses libclang).
*rtags-clang-command-suffix* Default is "-c -o".

Once you have created the compile_includes file, run the command M-x rtags-create-compilation-database. It will:

  • Prompt for the project root dir;
  • Read the compile_includes file;
  • Scan all source dirs and include dirs according to what the file says;
  • Create compilation_database.json (note: it overwrites it without asking);
  • Ask if you want to reload it (if rdm is running as an Emacs subprocess).

You can reload the compilation database manually with rc:

$ cd /where/your/compilation/db/is
$ rc -J

Check the output of rdm for any compilation errors and adjust your compilation database accordingly.

The rdm daemon should automatically re-compile any file you edit in Emacs as soon as you save it or otherwise touch it.

Using the index

While RTags uses C-x r as default prefix, this configuration uses C-c r instead because it it less crowded. It also adds a few keys such as M-C-g to display the list of symbols from the current buffer using Helm:

Rtags Helm

Navigation keys:

Keybinding Description
M-. or C-c r . Jump to symbol definition.
M-, or C-c r , Find references to symbol.
C-c r > Find symbol (prompts for symbol name).
C-c r < Find references (prompts for symbol name).
C-c r v Find all implementations of virtual function.
C-c r S Show symbol summary in tooltip (rtags-display-summary).
M-C-g Find symbol in file using Helm.
C-c r ; rtags-find-file using partial name (non IDO).

Any navigation is recorded onto a stack, so it is easy to go back and forth:

Keybinding Description
C-c r LEFT or C-c r [ Go back to previous location.
C-c r RIGHT or C-c r ] Go forward to next location.

Refactoring:

Keybinding Description
C-c r R Rename symbol.

Control:

Keybinding Description
C-c r p Switch project.
C-c r e Reparse file, e.g. recompile.

Debugging utilities:

Keybinding Description
C-c r l Show/hide the rdm log buffer.
C-c r U Show what rdm knows about a symbol.
C-c r P Show all includes for the current file.
C-c r T Show the tag list for the current file.

Using Flymake

The function rtags-diagnostics bound to C-c r D starts an async process to receive compilation warnings and errors from rdm. They are displayed into diagnostics buffer which works with Flymake to put highlighting on code with warnings and errors. By default Powerline displays the name of the buffer in green if the project compiles and in red if there are errors:

RTags diagnostics

Click on the highlighted symbol in your code to view the error message. Click on the error line in the diagnostics buffer to jump to the error location.

Keybinding Description
C-c r D Run rtags-diagnostics if it wasn't and force reparsing of current buffer.
C-c r d Show/hide the diagnostics buffer without force reparsing.
C-c r DOWN Goto next problem (rtags-next-diag).
C-c r UP Goto previous problem.
C-c r F Fix the error using Clang's "did you mean" (try it with "inft x;")
C-c r c Clears all errors and warnings (rtags-clear-diagnostics)
C-c r Q rtags-stop-diagnostics stop the async process.

Autocomplete

You can use RTags as source for auto-complete suggestions. Notes:

  • This feature makes RTags be the only source for auto-complete in C/C++ mode, e.g. all other classic sources such as names in open buffers are disabled. The reasoning being that surely Clang must be more accurate.
  • This feature requires RTags diagnostics to be turned on.

To enable it automatically, set the variable exordium-rtags-auto-complete to true in your prefs.el. Note that auto-complete for #include header files does not work in this case, because it does not know what project you are in.

To enable it manually, type C-c r A. This will take effect for all C++ files you open from that point. This key also sets auto-complete for the #include header files in the current project.

Possible issues:

  • There might be a graphical glitch in the auto-complete popup if the Emacs window is too small. Just enlarge the window a bit if this happens.
  • It's a tiny bit slow and it may trigger rdm a bit often.
  • Auto-complete for header files does not understand when you are switching project.

Lisp

Coming soon: Emacs Lisp, Common Lisp and Clojure.

Customization

The main file of the configuration is init.el. It looks like this:

;;; 1. Load all before-init.el files. The ~/.emacs.d/before-init.el
;;; comes first (if exists), followed by any existing before-init.el
;;; file from all ~/.emacs.d/taps/subdirs.
(dolist (tapped-file exordium-tapped-before-init-files)
  (load tapped-file))

;;; 2. Define the list of Melpa packages that we need, and load any missing
;;; one. Note that they are NOT updated automatically.

;;; 3. Local preferences: load all prefs.el. The ~/.emacs.d/prefs.el
;;; comes first (if exists), followed by any existing prefs.el
;;; file from all ~/.emacs.d/taps/subdirs.
(require 'init-prefs)       ; defines variables that prefs.el can override
(dolist (tapped-file exordium-tapped-prefs-files)
  (load tapped-file))

;;; 4. Load the "modules" in ~/.emacs.d/modules. See below.

;;; 5. Load the default theme in ~/.emacs.d/themes.

;;; 6. Load all after-init.el files.The ~/.emacs.d/after-init.el
;;; comes first (if exists), followed by any existing after-init.el
;;; file from all ~/.emacs.d/taps/subdirs.
(dolist (tapped-file exordium-tapped-after-init-files)
  (load tapped-file))

Modules can be individually commented out if needed:

;;; Uncomment the modules you'd like to use and restart Emacs afterwards,
;;; or evaluate the require expression with M-C-x.

;;; Look and feel
(require 'init-look-and-feel)   ; fonts, UI, keybindings, saving files etc.
(require 'init-linum)           ; line numbers

;;; Usability
(require 'init-util)            ; utilities like match paren, bookmarks...
(require 'init-ido)             ; supercharged completion engine
(require 'init-autocomplete)    ; auto-completion
(when exordium-helm-projectile  ; find files anywhere in project
  (require 'init-helm-projectile))

;;; Magit and git gutter
(require 'init-git)

;;; Themes
(if exordium-nw
    (set-face-background 'highlight nil)
  ;; Using Emacs with GUI:
  (require 'init-themes)
  (require 'init-powerline))

;;; Shell mode
(require 'init-shell)

;;; Major modes
(require 'init-markdown)
(require 'init-org)
(require 'init-xml)

;;; OS-specific things
(when *environment-osx*
  (require 'init-osx))

;;; Etc.

If you are looking for a specific feature or key binding, this page explains the code organization. Each module starts with a commentary including all key bindings.

Local files

3 files can be added in your directory ~/.emacs.d to customize the configuration for the local machine:

File name Usage
prefs.el Loaded before any module. Use it to override fonts, window size etc. See init-prefs.el.
before-init.el Loaded before anything else. Use it to set up the http proxy for instance.
after-init.el Loaded after everything else. Use it to load machine-specific extensions.

Taps

The idea is inspired by taps from Homebrew. You can clone any git repository into ~/.emacs.d/taps/ directory (as a subdirectory of the latter). It is going to be called tap. Anything below taps subdirectory is not tracked by Exordium, although each tap can be a repository itself, allowing for tracked customisation.

When Exordium is initialised, it searches for the three special Local files in each tap. Files are then added to the tapped lists: before, prefs, and after. taps are searched in alphabetical order of their respective names in ~/.emacs.d/taps directory (string-lessp to be exact). This order determines the order of files in each tapped list. This lets you influence the order of processing within each tapped list, i.e., you can rename your tapped repositories (clones). The Local files from your ~/.emacs.d are always first in each respective tapped list. Each tapped list is processed (each file from it is loaded) as a replacement for a respective Local file.

Exordium-specific emacs functions are WIP.

Preferences

modules/init-prefs.el defines the preferences that can be changed in your prefs.el. For example, your prefs.el could contain:

;; Fonts + size in order of preference. First available one will be picked.
(setq exordium-preferred-fonts '("Monospace" . 120) ("Mono" . 120))

;; Default Emacs frame size in chars
(setq exordium-preferred-frame-width  120
      exordium-preferred-frame-height 65)

;; Show line numbers (default t)
(setq exordium-display-line-numbers t)

;; Highlight current line (default t)
(setq exordium-line-mode t)

;; Don't set ESC key to C-g (quit/abort)
(setq exordium-keyboard-escape nil)

;; Disable electric-pair (automatically inserts a closing parenthese,
;; curly brace, etc.)
(setq exordium-enable-electric-pair-mode nil)

;; Don't use Powerline (may cause Emacs to crash on startup sometimes)
(setq exordium-enable-powerline nil)

There are more options, see init-prefs.el.

Themes

Exordium includes several themes that are integrated with Powerline and that should work well in -nw mode. Use M-x switch-theme to change the theme. Otherwise, setting your favorite theme in prefs.el like the following will give you this:

;; Available themes (default is tomorrow-night):
;; - tomorrow-night, tomorrow-night-bright, tomorrow-night-blue,
;;   tomorrow-night-eighties, tomorrow-day
;; - solarized-dark, solarized-light
;; - monokai
;; - zenburn
;; - material
(setq exordium-theme 'material)

;; Powerline theme:
(setq exordium-powerline-theme :wave)

Material

Local modules

You can create a directory ~/.emacs.d/local for your own local modules (this directory is ignored in git). In that case you should use require forms in after-init.el to load them.

Here is an example. Create a file named ~/.emacs.d/local/init-test-local.el with this content:

;;;; Test local module

(message "**** This test local module is loaded! ****")

(provide 'init-test-local)

Then create a file ~/.emacs.d/after-init.el with this content:

;;;; Local stuff

(message "**** after_init ****")

(require 'init-test-local)

Restart Emacs. The message buffer should show two lines:

**** after_init ****
**** This test local module is loaded! ****

Local modules files can be named anything as long as the file name, the symbol in provide and the symbol in require are the same.

Troubleshooting

Bugs

  • Powerline may cause Emacs to crash on startup because of a race condition inside Emacs. A solution is to make it display after one second of idle time in order to guarantee that Emacs has finished initializing. For this, add (setq exordium-display-powerline-after-idle-time 1) in your prefs.el. Another solution is to enable powerline manually using a function like this:
(defun powerline ()
  "Enable powerline."
  (interactive)
  (require 'powerline)
  (powerline-set-selected-window)
  (require 'init-powerline)
  (redraw-display))
  • Sometimes a random bug may occur that displays this error: fringe-helper-modification-func: Invalid search bound (wrong side of point). I'm pretty sure this is a bug in git-gutter-fringe which display git diff icons in the left-side fringe.

    There are two ways to work around it: either add (setq exordium-git-gutter nil) if your prefs.el to disable this feature entirely, or add (setq exordium-git-gutter-non-fringe t) in your prefs.el to display git diffs on the left side of line numbers, e.g. not in the fringe. Note that the latter disables the highlighting of the current line number for now.

  • Editing large comment blocks in C++ can be slow as hell. Unfortunately this is a problem with CC-mode and not with this config. A simple solution is to turn off font lock temporarily with M-x font-lock-mode. Do it again to re-enable font lock after you're done editing your large component-level comment.

  • Sometimes weird bugs may happen after an upgrade or during development on a module. Exordium recompiles any .el file for which the corresponding .elc files is older on startup, but does not try to force any .el file to be compiled. Two functions are useful in this case: M-x uncompile-modules removes all .elc files (if you restart Emacs it will not compile anything). M-x force-recompile-modules recompiles everything.

  • RTags now uses memory mapped files instead of loading projects into memory. It may be slow if your home directory is NFS-mounted, since by default the index is stored in ~/.rtags. The solution is to store the index on a local drive, preferably an SSD. You do this by creating a file ~/.rdmrc with a content like this: --data-dir=/local/drive/.rtags.

Configuration profiling

M-x emacs-init-time shows the time Emacs took to start. You can profile the configuration using this command (this example is for OS X):

$ Applications/Emacs.app/Contents/MacOS/Emacs -Q -l ~/.emacs.d/extensions/profile-dotemacs.el -f profile-dotemacs