I’ve been running Emacs for like 25 years. But I’ve never really configured it with anything fancy.

Sure, I’ve set some shortcut keys, and enabled global-font-lock-mode and set indent size, but that’s almost it.

Ok, so I also once made an ASCII 3D demo of a spinning cube in Emacs-lisp, but that wasn’t really about Emacs.

All my coding is done in tmux&Emacs. One project gets exactly one tmux session. Window 0 is emacs. Window 1 is make && ./a.out (sometimes split panes to tail logs or run both server and client), and to run git commands. The remaining windows are used for various things like reading manpages etc….

I have that same workflow whether I’m editing a blog post or doing kernel programming.

This way I can work at my desk with large and plentiful screens, and then move to my laptop and everything continues working exactly the same.

tmux I’ve customized, but not done as much with Emacs.

So, step one to get my coding environment to be less 1995, and more 2020: make my editor understand my code, and show me stuff about it.

I’m learning as I’m going, and writing what I’m learning. As always if you see something wrong then please leave a comment.

Code annotations and other semantic understanding

The way to do this is to make your editor talk the Language Server Protocol (LSP) with something that understands the language. For C++ that’s clangd.

apt install clangd lsp-mode

Then we need to make this LSP thingy understand how to compile the code. That’s a bit tricky since there may be system-local defines and stuff. You may have had to provide flags to ./configure to make it build, for example, and without it the code will not make sense to the checker.

This build information needs to end up in a file called compile_commands.json

The way I found to do this is using scan-build.

pip install scan-build
cat >> Makefile.am
lsp:
	~/.local/bin/intercept-build make
^D
./bootstrap.sh && ./configure && make clean && make lsp

Now we just need to activate LSP mode in Emacs. That’s done by (lsp t). But better yet, let’s trigger it when loading C++ code.

Let’s add this to ~/.emacs.d/init.el:

(add-hook 'c++-mode-hook 'development-mode)
(defun development-mode ()
  "Start dev stuff"
  (interactive)
  (lsp t)
  (setq show-trailing-whitespace t)
  (setq indent-tabs-mode nil))

Ok, that looks WHAT THE FUCK?!

Ugly colors

Ok, after some searching let’s add this to ~/.emacs.d/init.el too:

(custom-set-faces
 '(lsp-face-highlight-read ((t (:background "gray"))))
 '(lsp-face-highlight-textual ((t (:background "gray"))))
 '(lsp-face-highlight-write ((t (:background "SteelBlue1"))))
 '(lsp-ui-doc-background ((t (:background "black")))))

Good colors

Ok, that’s better. And we get nice context aware tab completion. Ok, now I feel like I’ve joined the 21st century.

Code completion

Auto-format code on save

clang again comes to the rescue. Specifically clang-format.

apt install clang-format

And more for ~/.emacs.d/init.el:

(defun clang-format-save-hook-for-this-buffer ()
  "Create a buffer local save hook."
  (add-hook 'before-save-hook
    (lambda ()
      (progn
        (when (locate-dominating-file "." ".clang-format")
          (clang-format-buffer))
        ;; Continue to save.
        nil))
    nil
    ;; Buffer local hook.
  t)
)
(add-hook 'c++-mode-hook (lambda () (clang-format-save-hook-for-this-buffer)))

From Stackoverflow.

You’ll need a .clang-format file in your project directory. I took the one from GNU Radio. It’s not exactly perfect for my tastes, but it’s very close. In any case as long as it’s not awful it doesn’t matter.

This “let’s stop with the style wars” that Go started I think is great. Here at least within a project it’s great to not even get to decide what the brace style is, but even making it impossible to do it wrong. It’s less thinking, less tweaking. Just focus on the code.

Summary

There, now I’ve advanced the state of my programming environment by about 20 years. If you were already doing this in 1995, then good for you.