doomemacs/modules/lang/cc/config.el

251 lines
8.1 KiB
EmacsLisp
Raw Normal View History

;;; lang/cc/config.el --- c, c++, and obj-c -*- lexical-binding: t; -*-
2015-06-15 09:06:10 +02:00
(defvar +cc-include-paths (list "include/")
2017-09-20 14:25:35 +02:00
"A list of paths, relative to a project root, to search for headers in C/C++.
Paths can be absolute.
The purpose of this variable is to ensure syntax checkers and code-completion
knows where to look for headers.")
(defvar +cc-compiler-options
`((c-mode . nil)
(c++-mode
. ,(list "-std=c++11" ; use C++11 by default
(when IS-MAC
;; NOTE beware: you'll get abi-inconsistencies when passing
2017-09-20 14:25:35 +02:00
;; std-objects to libraries linked with libstdc++ (e.g. if you
;; use boost which wasn't compiled with libc++)
(list "-stdlib=libc++"))))
(objc-mode . nil))
"A list of default compiler options for the C family. These are ignored if a
compilation database is present in the project.")
;;
;; Plugins
;;
(def-package! cc-mode
2015-06-15 09:06:10 +02:00
:commands (c-mode c++-mode objc-mode java-mode)
:mode ("\\.mm" . objc-mode)
:preface
(defun +cc-c++-header-file-p ()
2017-06-23 18:13:33 +02:00
(and buffer-file-name
(equal (file-name-extension buffer-file-name) "h")
(or (file-exists-p (expand-file-name
(concat (file-name-sans-extension buffer-file-name)
".cpp")))
(when-let* ((file (car-safe (projectile-get-other-files
buffer-file-name
(projectile-current-project-files)))))
2017-06-23 18:13:33 +02:00
(equal (file-name-extension file) "cpp")))))
(defun +cc-objc-header-file-p ()
2017-06-23 18:13:33 +02:00
(and buffer-file-name
(equal (file-name-extension buffer-file-name) "h")
(re-search-forward "@\\<interface\\>" magic-mode-regexp-match-limit t)))
2017-09-20 14:25:35 +02:00
(push (cons #'+cc-c++-header-file-p 'c++-mode) magic-mode-alist)
(push (cons #'+cc-objc-header-file-p 'objc-mode) magic-mode-alist)
:init
(setq-default c-basic-offset tab-width)
:config
(set! :electric '(c-mode c++-mode objc-mode java-mode)
2017-02-20 20:55:21 -05:00
:chars '(?\n ?\}))
(set! :company-backend
2017-02-19 18:57:16 -05:00
'(c-mode c++-mode objc-mode)
2017-04-17 02:19:20 -04:00
'(company-irony-c-headers company-irony))
;;; Style/formatting
2017-02-19 18:57:16 -05:00
;; C/C++ style settings
(c-toggle-electric-state -1)
(c-toggle-auto-newline -1)
2017-09-20 14:25:35 +02:00
(c-set-offset 'substatement-open '0) ; don't indent brackets
(c-set-offset 'inline-open '+)
(c-set-offset 'block-open '+)
(c-set-offset 'brace-list-open '+)
(c-set-offset 'case-label '+)
(c-set-offset 'access-label '-)
(c-set-offset 'arglist-intro '+)
(c-set-offset 'arglist-close '0)
;; Indent privacy keywords at same level as class properties
;; (c-set-offset 'inclass #'+cc-c-lineup-inclass)
;;; Better fontification (also see `modern-cpp-font-lock')
(add-hook 'c-mode-common-hook #'rainbow-delimiters-mode)
(add-hook! (c-mode c++-mode) #'highlight-numbers-mode)
(add-hook! (c-mode c++-mode) #'+cc|fontify-constants)
;; Improve indentation of inline lambdas in C++11
(advice-add #'c-lineup-arglist :around #'+cc*align-lambda-arglist)
2017-02-19 18:57:16 -05:00
;;; Keybindings
;; Completely disable electric keys because it interferes with smartparens and
;; custom bindings. We'll do this ourselves.
(setq c-tab-always-indent nil
c-electric-flag nil)
(dolist (key '("#" "{" "}" "/" "*" ";" "," ":" "(" ")"))
(define-key c-mode-base-map key nil))
;; Smartparens and cc-mode both try to autoclose angle-brackets intelligently.
;; The result isn't very intelligent (causes redundant characters), so just do
;; it ourselves.
(map! :map c++-mode-map
2017-02-19 18:57:16 -05:00
"<" nil
:i ">" #'+cc/autoclose->-maybe)
;; ...and leave it to smartparens
(sp-with-modes '(c-mode c++-mode objc-mode java-mode)
(sp-local-pair "<" ">" :when '(+cc-sp-point-is-template-p +cc-sp-point-after-include-p))
(sp-local-pair "/*" "*/" :post-handlers '(("||\n[i]" "RET") ("| " "SPC")))
;; Doxygen blocks
(sp-local-pair "/**" "*/" :post-handlers '(("||\n[i]" "RET") ("||\n[i]" "SPC")))
(sp-local-pair "/*!" "*/" :post-handlers '(("||\n[i]" "RET") ("[d-1]< | " "SPC")))))
2017-02-19 18:57:16 -05:00
(def-package! modern-cpp-font-lock
:hook (c++-mode . modern-c++-font-lock-mode))
2017-02-19 18:57:16 -05:00
(def-package! irony
:after cc-mode
2017-05-25 20:11:24 +02:00
:commands irony-install-server
:preface (setq irony-server-install-prefix (concat doom-etc-dir "irony-server/"))
:hook ((c-mode c++-mode objc-mode) . irony-mode)
:config
(unless (file-directory-p irony-server-install-prefix)
(warn "irony-mode: server isn't installed; run M-x irony-install-server"))
;; Initialize compilation database, if present. Otherwise, fall back on
;; `+cc-compiler-options'.
(add-hook 'irony-mode-hook #'+cc|irony-init-compile-options))
2017-04-08 23:37:40 -04:00
(def-package! irony-eldoc
:after irony
:hook (irony-mode . irony-eldoc))
(def-package! flycheck-irony
:when (featurep! :feature syntax-checker)
:after irony
:config
(add-hook 'irony-mode-hook #'flycheck-mode)
(flycheck-irony-setup))
;;
2017-02-19 18:57:16 -05:00
;; Tools
;;
(def-package! disaster :commands disaster)
2017-02-19 18:57:16 -05:00
;;
;; Major modes
;;
(def-package! cmake-mode
:mode "/CMakeLists\\.txt$"
:mode "\\.cmake\\$"
2017-02-19 18:57:16 -05:00
:config
(set! :company-backend 'cmake-mode '(company-cmake company-yasnippet)))
2015-06-15 09:06:10 +02:00
(def-package! cuda-mode :mode "\\.cuh?$")
2015-06-15 09:06:10 +02:00
(def-package! opencl-mode :mode "\\.cl$")
(def-package! demangle-mode
:hook llvm-mode)
2017-07-06 12:44:03 +02:00
(def-package! glsl-mode
:mode "\\.glsl$"
:mode "\\.vert$"
:mode "\\.frag$"
:mode "\\.geom$")
;;
2017-12-26 14:14:36 -05:00
;; Company plugins
2017-07-06 12:44:03 +02:00
;;
2017-12-26 14:14:36 -05:00
(def-package! company-cmake
:when (featurep! :completion company)
:after cmake-mode)
(def-package! company-irony
:when (featurep! :completion company)
:after irony)
2017-07-06 12:44:03 +02:00
2017-12-26 14:14:36 -05:00
(def-package! company-irony-c-headers
:when (featurep! :completion company)
:after company-irony)
(def-package! company-glsl
:when (featurep! :completion company)
:after glsl-mode
:config
(if (executable-find "glslangValidator")
(warn "glsl-mode: couldn't find glslangValidator, disabling company-glsl")
(set! :company-backend 'glsl-mode '(company-glsl))))
2017-07-06 12:44:03 +02:00
2017-12-26 18:12:36 -05:00
;;
;; Rtags Support
;;
(def-package! rtags
:after cc-mode
:config
(setq rtags-autostart-diagnostics t
rtags-use-bookmarks nil
rtags-completions-enabled nil
;; If not using ivy or helm to view results, use a pop-up window rather
;; than displaying it in the current window...
rtags-results-buffer-other-window t
;; ...and don't auto-jump to first match before making a selection.
rtags-jump-to-first-match nil)
(defun +cc|init-rtags-server-maybe ()
"Start the rtags server if it isn't already running."
(unless (or (processp rtags-rdm-process)
(cl-loop for proc in (list-system-processes)
for cmd = (cdr (assq 'args (process-attributes proc)))
if (string-match-p "/rdm\\_>" cmd)
return t))
(message "Starting rtags server")
(rtags-start-process-unless-running)
;; Emacs-spawned rdm should be temporary
(add-hook! kill-emacs (ignore-errors (rtags-cancel-process)))))
(let ((bins (cl-remove-if-not #'executable-find '("rdm" "rc"))))
(if (/= (length bins) 2)
(warn "cc-mode: couldn't find %s, disabling rtags support" bins)
(add-hook! (c-mode c++-mode) #'+cc|init-rtags-server-maybe)
(set! :jump '(c-mode c++-mode)
:definition #'rtags-find-symbol-at-point
:references #'rtags-find-references-at-point)))
(add-hook 'doom-cleanup-hook #'rtags-cancel-process)
;; Use rtags-imenu instead of imenu/counsel-imenu
(map! :map (c-mode-map c++-mode-map) [remap imenu] #'rtags-imenu)
2017-12-26 18:12:36 -05:00
(add-hook 'rtags-jump-hook #'evil-set-jump)
(add-hook 'rtags-after-find-file-hook #'recenter))
(def-package! ivy-rtags
:when (featurep! :completion ivy)
:after rtags
:init
;; NOTE Ivy integration breaks when rtags is byte-compiled with Emacs 26 or
;; later, so we un-byte-compile it before we load it.
(eval-when-compile
(when (>= emacs-major-version 26)
(when-let* ((elc-file (locate-library "rtags.elc" t doom--package-load-path)))
(delete-file elc-file))))
:config (setq rtags-display-result-backend 'ivy))
(def-package! helm-rtags
:when (featurep! :completion helm)
:after rtags
:config (setq rtags-display-result-backend 'helm))