Refactor lang/cc

+ Fix ffap integration
+ Code reduction for irony, rtags and lsp init hooks
+ Use c-add-style instead of unless+push
+ Log that irony server isn't installed
This commit is contained in:
Henrik Lissner 2019-03-02 01:51:51 -05:00
parent e11ea611cf
commit 0bd576673c
No known key found for this signature in database
GPG key ID: 5F6C0EA160557395
2 changed files with 83 additions and 50 deletions

View file

@ -93,6 +93,14 @@ simpler."
(funcall +cc-default-header-file-mode)) (funcall +cc-default-header-file-mode))
((c-mode))))) ((c-mode)))))
(defun +cc-resolve-include-paths ()
(cl-loop with path = (or buffer-file-name default-directory)
for dir in +cc-default-include-paths
if (file-name-absolute-p dir)
collect dir
else if (projectile-locate-dominating-file path dir)
collect (expand-file-name dir it)))
;; ;;
;; Commands ;; Commands
@ -139,8 +147,9 @@ simpler."
("\\<[A-Z]\\{3,\\}\\>" . font-lock-constant-face)) ("\\<[A-Z]\\{3,\\}\\>" . font-lock-constant-face))
t))) t)))
(defvar +cc--project-includes-alist nil)
;;;###autoload ;;;###autoload
(defun +cc|irony-init-compile-options () (defun +cc|init-irony-compile-options ()
"Initialize compiler options for irony-mode. It searches for the nearest "Initialize compiler options for irony-mode. It searches for the nearest
compilation database and initailizes it, otherwise falling back on compilation database and initailizes it, otherwise falling back on
`+cc-default-compiler-options' and `+cc-default-include-paths'. `+cc-default-compiler-options' and `+cc-default-include-paths'.
@ -150,33 +159,47 @@ compilation dbs."
(when (memq major-mode '(c-mode c++-mode objc-mode)) (when (memq major-mode '(c-mode c++-mode objc-mode))
(require 'irony-cdb) (require 'irony-cdb)
(unless (irony-cdb-autosetup-compile-options) (unless (irony-cdb-autosetup-compile-options)
(let ((project-root (doom-project-root))
(include-paths (+cc-resolve-include-paths)))
(setf (alist-get project-root +cc--project-includes-alist)
include-paths)
(irony-cdb--update-compile-options (irony-cdb--update-compile-options
(delq nil (append (delq nil (cdr-safe (assq major-mode +cc-default-compiler-options)))
(append (cdr-safe (assq major-mode +cc-default-compiler-options)) (cl-loop for path in include-paths
(cl-loop with path = (or buffer-file-name default-directory) collect (format "-I%s" path)))
for dir in '("include" "includes") project-root)))))
if (projectile-locate-dominating-file path dir)
collect it) ;; ;;;###autoload
(cl-loop for path in +cc-default-include-paths ;; (defun +cc|init-ccls-compile-options ()
if (stringp path) ;; "TODO"
nconc (list "-I" path)))) ;; (when (memq major-mode '(c-mode c++-mode objc-mode))
(doom-project-root))) ;; (when-let* ((include-paths (+cc-resolve-include-paths)))
;; Make ffap aware of include paths ;; (let ((args (delq nil (cdr-safe (assq major-mode +cc-default-compiler-options)))))
(when irony--working-directory ;; (setf (alist-get (or (lsp-workspace-root)
;; (lsp--suggest-project-root)
;; (doom-project-root))
;; +cc--project-includes-alist)
;; include-paths)
;; (setq ccls-initialization-options
;; `(:clang (:extraArgs
;; [,@(cl-loop for path in include-paths
;; collect (format "-I%s" path))])))))))
;;;###autoload
(defun +cc|init-ffap-integration ()
"Takes the local project include paths and registers them with ffap.
This way, `find-file-at-point' (and `+lookup/file') will know where to find most
header files."
(when-let* ((project-root (or (bound-and-true-p irony--working-directory)
(and (featurep 'lsp)
(or (lsp-workspace-root)
(doom-project-root))))))
(require 'ffap) (require 'ffap)
(make-local-variable 'ffap-c-path) (make-local-variable 'ffap-c-path)
(make-local-variable 'ffap-c++-path) (make-local-variable 'ffap-c++-path)
(cl-loop for opt in irony--compile-options (cl-loop for dir in (or (cdr (assoc project-root +cc--project-includes-alist))
if (and (stringp opt) (+cc-resolve-include-paths))
(string-match "^-I\\(.+\\)" opt))
do (add-to-list (pcase major-mode do (add-to-list (pcase major-mode
(`c-mode 'ffap-c-path) (`c-mode 'ffap-c-path)
(`c++-mode 'ffap-c++-path)) (`c++-mode 'ffap-c++-path))
(expand-file-name (match-string 1 opt) (expand-file-name dir project-root)))))
irony--working-directory))))))
;;;###autoload
(defun +cc|cleanup-rtags ()
"Kill rtags server(s) if there are no C/C++ buffers open."
(unless (doom-buffers-in-mode '(c-mode c++-mode) (buffer-list))
(rtags-cancel-process)))

View file

@ -1,9 +1,13 @@
;;; lang/cc/config.el --- c, c++, and obj-c -*- lexical-binding: t; -*- ;;; lang/cc/config.el --- c, c++, and obj-c -*- lexical-binding: t; -*-
(defvar +cc-default-include-paths (list "include/") (defvar +cc-default-include-paths
"A list of default paths, relative to a project root, to search for headers in (list "include"
C/C++. Paths can be absolute. This is ignored if your project has a compilation "includes")
database.") "A list of default relative paths which will be searched for up from the
current file, to be passed to irony as extra header search paths. Paths can be
absolute. This is ignored if your project has a compilation database.
This is ignored by ccls.")
(defvar +cc-default-header-file-mode 'c-mode (defvar +cc-default-header-file-mode 'c-mode
"Fallback major mode for .h files if all other heuristics fail (in "Fallback major mode for .h files if all other heuristics fail (in
@ -20,7 +24,9 @@ database.")
"-stdlib=libc++"))) "-stdlib=libc++")))
(objc-mode . nil)) (objc-mode . nil))
"A list of default compiler options for the C family. These are ignored if a "A list of default compiler options for the C family. These are ignored if a
compilation database is present in the project.") compilation database is present in the project.
This is ignored by ccls.")
;; ;;
@ -42,6 +48,11 @@ compilation database is present in the project.")
;; Activate `c-mode', `c++-mode' or `objc-mode' depending on heuristics ;; Activate `c-mode', `c++-mode' or `objc-mode' depending on heuristics
(add-to-list 'auto-mode-alist '("\\.h\\'" . +cc-c-c++-objc-mode)) (add-to-list 'auto-mode-alist '("\\.h\\'" . +cc-c-c++-objc-mode))
;; Ensure find-file-at-point works in C modes, must be added before irony
;; and/or lsp hooks are run.
(add-hook! (c-mode-local-vars c++-mode-local-vars objc-mode-local-vars)
#'+cc|init-ffap-integration)
:config :config
(set-electric! '(c-mode c++-mode objc-mode java-mode) :chars '(?\n ?\} ?\{)) (set-electric! '(c-mode c++-mode objc-mode java-mode) :chars '(?\n ?\} ?\{))
(set-docsets! 'c-mode "C") (set-docsets! 'c-mode "C")
@ -69,12 +80,11 @@ compilation database is present in the project.")
;;; Better fontification (also see `modern-cpp-font-lock') ;;; Better fontification (also see `modern-cpp-font-lock')
(add-hook 'c-mode-common-hook #'rainbow-delimiters-mode) (add-hook 'c-mode-common-hook #'rainbow-delimiters-mode)
(add-hook! '(c-mode-hook c++-mode-hook) #'+cc|fontify-constants) (add-hook! (c-mode c++-mode) #'+cc|fontify-constants)
;; Custom style, based off of linux ;; Custom style, based off of linux
(unless (assoc "doom" c-style-alist) (c-add-style
(push '("doom" "doom" '((c-basic-offset . tab-width)
(c-basic-offset . tab-width)
(c-comment-only-line-offset . 0) (c-comment-only-line-offset . 0)
(c-hanging-braces-alist (brace-list-open) (c-hanging-braces-alist (brace-list-open)
(brace-entry-open) (brace-entry-open)
@ -102,8 +112,7 @@ compilation database is present in the project.")
;; another level ;; another level
(access-label . -) (access-label . -)
(inclass +cc-c++-lineup-inclass +) (inclass +cc-c++-lineup-inclass +)
(label . 0))) (label . 0))))
c-style-alist))
;;; Keybindings ;;; Keybindings
;; Smartparens and cc-mode both try to autoclose angle-brackets intelligently. ;; Smartparens and cc-mode both try to autoclose angle-brackets intelligently.
@ -131,16 +140,17 @@ compilation database is present in the project.")
(setq irony-server-install-prefix (concat doom-etc-dir "irony-server/")) (setq irony-server-install-prefix (concat doom-etc-dir "irony-server/"))
:init :init
(defun +cc|init-irony-mode () (defun +cc|init-irony-mode ()
(when (and (memq major-mode '(c-mode c++-mode objc-mode)) (if (file-directory-p irony-server-install-prefix)
(file-directory-p irony-server-install-prefix)) (irony-mode +1)
(irony-mode +1))) (message "Irony server isn't installed")))
(add-hook 'c-mode-common-hook #'+cc|init-irony-mode) (add-hook! (c-mode-local-vars c++-mode-local-vars objc-mode-local-vars)
#'+cc|init-irony-mode)
:config :config
(setq irony-cdb-search-directory-list '("." "build" "build-conda")) (setq irony-cdb-search-directory-list '("." "build" "build-conda"))
;; Initialize compilation database, if present. Otherwise, fall back on ;; Initialize compilation database, if present. Otherwise, fall back on
;; `+cc-default-compiler-options'. ;; `+cc-default-compiler-options'.
(add-hook 'irony-mode-hook #'+cc|irony-init-compile-options) (add-hook 'irony-mode-hook #'+cc|init-irony-compile-options)
(def-package! irony-eldoc (def-package! irony-eldoc
:hook (irony-mode . irony-eldoc)) :hook (irony-mode . irony-eldoc))
@ -188,11 +198,11 @@ compilation database is present in the project.")
:init :init
(defun +cc|init-rtags () (defun +cc|init-rtags ()
"Start an rtags server in c-mode and c++-mode buffers." "Start an rtags server in c-mode and c++-mode buffers."
(when (and (memq major-mode '(c-mode c++-mode)) (when (and (require 'rtags nil t)
(require 'rtags nil t)
(rtags-executable-find rtags-rdm-binary-name)) (rtags-executable-find rtags-rdm-binary-name))
(rtags-start-process-unless-running))) (rtags-start-process-unless-running)))
(add-hook 'c-mode-common-hook #'+cc|init-rtags) (add-hook! (c-mode-local-vars c++-mode-local-vars objc-mode-local-vars)
#'+cc|init-rtags)
:config :config
(setq rtags-autostart-diagnostics t (setq rtags-autostart-diagnostics t
rtags-use-bookmarks nil rtags-use-bookmarks nil
@ -226,9 +236,9 @@ compilation database is present in the project.")
(def-package! ccls (def-package! ccls
:when (featurep! +lsp) :when (featurep! +lsp)
:hook ((c-mode c++-mode objc-mode) . +lsp|init-ccls) :hook ((c-mode-local-vars c++-mode-local-vars objc-mode-local-vars) . +cc|init-ccls)
:config :config
(defun +lsp|init-ccls () (defun +cc|init-ccls ()
(setq-local company-transformers nil) (setq-local company-transformers nil)
(setq-local company-lsp-async t) (setq-local company-lsp-async t)
(setq-local company-lsp-cache-candidates nil) (setq-local company-lsp-cache-candidates nil)