Emacs as a C++ IDE

Introduction

In my last post I went over my reconfiguring my Emacs as a Rust IDE. In this post I'll do the same for C & C++. Whereas in that case merely navigating the landscape of available packages was a major part of the problem, in this case the choices are straightforward. The bulk of this post will be getting those packages setup & working.

cc-mode

Contra Rust the choice of major mode is simple: cc-mode. This inveterate package provides major modes for C, C++ and a number of related languages (Objective C, Java CORBA IDL, and others).

hooks

cc-mode defines multiple hooks:

  • c-initialization-hook: "Hook run only once per Emacs session, when CC Mode is initialized. This is a good place to change key bindings (or add new ones) in any of the CC Mode key maps."
  • c-mode-common-hook: "Common hook across all languages. It’s run immediately before the language specific hook."
  • language-specific hooks: these are c-mode-hook, c++-mode-hook and so forth

Let's set these up. There are two additional packages I setup last time, one built-in & one external. The built-in package is hideshow and it provides code folding. The external package is smartparens; it provides paredit-like balanced expresions for non-Lisps.

(setq hs-isearch-open t
      hs-set-up-overlay 
      (defun sp1ff/hs/display-code-line-counts (ov)
        (when (eq 'code (overlay-get ov 'hs))
          (overlay-put ov 'display
                       (format "... / %d"
                               (count-lines (overlay-start ov)
                                            (overlay-end ov)))))))

(use-package smartparens :ensure t
  :config
  (progn
    (require 'smartparens-c)
    (require 'smartparens-rust)))

With this setup, let's use c-initialization-hook to setup keybindings:

(defun sp1ff/cc/initialization-hook ()
  "Hook run when CC Mode is initialized."
  (define-key c-mode-base-map "\C-c="             'align-regexp)
  (define-key c-mode-base-map "\C-c<"             'hs-hide-all)
  (define-key c-mode-base-map "\C-c;"             'hs-toggle-hiding)
  (define-key c-mode-base-map "\C-c'"             'hs-hide-level)
  (define-key c-mode-base-map (kbd "C-<right>")   'sp-forward-slurp-sexp)
  (define-key c-mode-base-map (kbd "C-<left>")    'sp-forward-barf-sexp)
  (define-key c-mode-base-map (kbd "C-M-<right>") 'sp-backward-slurp-sexp)
  (define-key c-mode-base-map (kbd "C-M-<left>")  'sp-backward-barf-sexp))

(add-hook 'c-initialization-hook #'sp1ff/cc/initialization-hook)

and c-mode-common-hook for common initialization:

(defun sp1ff/cc/common-hook ()
  "Hook common across all languages supported in `cc-mode'"
  (column-number-mode)
  (display-line-numbers-mode)
  (hs-minor-mode)
  (smartparens-mode))

  (add-hook 'c-mode-common-hook #'sp1ff/cc/common-hook)

styles

cc-mode provides a very flexible indentation engine… very flexible. A full description thereof is beyond the scope of this post. I'd planned on writing a bit about setting-up a custom cc-mode indentation style, but as I began to write I realized I didn't know enough to justify saying anything at all. Damnit, now I'm going to have to figure it out.

project-specific configuration

ls's

lsp-modes

clangd

compile_commands.json

debugging "Failed to compile…" messages

  • clangd –compiler-database-dir=$(pwd) –check <path-to-file>
  • apt-file search llvm-symbolizer
  • sudo apt install llvm-14
  • docker-tramp

build containers

all together

08/03/23 20:24