From 0bd576673c1d8436aab2f12b85aa87720bcae142 Mon Sep 17 00:00:00 2001 From: Henrik Lissner Date: Sat, 2 Mar 2019 01:51:51 -0500 Subject: [PATCH] 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 --- modules/lang/cc/autoload.el | 81 ++++++++++++++++++++++++------------- modules/lang/cc/config.el | 52 ++++++++++++++---------- 2 files changed, 83 insertions(+), 50 deletions(-) diff --git a/modules/lang/cc/autoload.el b/modules/lang/cc/autoload.el index 3aabe17fe..c442c2028 100644 --- a/modules/lang/cc/autoload.el +++ b/modules/lang/cc/autoload.el @@ -93,6 +93,14 @@ simpler." (funcall +cc-default-header-file-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 @@ -139,8 +147,9 @@ simpler." ("\\<[A-Z]\\{3,\\}\\>" . font-lock-constant-face)) t))) +(defvar +cc--project-includes-alist nil) ;;;###autoload -(defun +cc|irony-init-compile-options () +(defun +cc|init-irony-compile-options () "Initialize compiler options for irony-mode. It searches for the nearest compilation database and initailizes it, otherwise falling back on `+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)) (require 'irony-cdb) (unless (irony-cdb-autosetup-compile-options) - (irony-cdb--update-compile-options - (delq nil - (append (cdr-safe (assq major-mode +cc-default-compiler-options)) - (cl-loop with path = (or buffer-file-name default-directory) - for dir in '("include" "includes") - if (projectile-locate-dominating-file path dir) - collect it) - (cl-loop for path in +cc-default-include-paths - if (stringp path) - nconc (list "-I" path)))) - (doom-project-root))) - ;; Make ffap aware of include paths - (when irony--working-directory - (require 'ffap) - (make-local-variable 'ffap-c-path) - (make-local-variable 'ffap-c++-path) - (cl-loop for opt in irony--compile-options - if (and (stringp opt) - (string-match "^-I\\(.+\\)" opt)) - do (add-to-list (pcase major-mode - (`c-mode 'ffap-c-path) - (`c++-mode 'ffap-c++-path)) - (expand-file-name (match-string 1 opt) - irony--working-directory)))))) + (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 + (append (delq nil (cdr-safe (assq major-mode +cc-default-compiler-options))) + (cl-loop for path in include-paths + collect (format "-I%s" path))) + project-root))))) + +;; ;;;###autoload +;; (defun +cc|init-ccls-compile-options () +;; "TODO" +;; (when (memq major-mode '(c-mode c++-mode objc-mode)) +;; (when-let* ((include-paths (+cc-resolve-include-paths))) +;; (let ((args (delq nil (cdr-safe (assq major-mode +cc-default-compiler-options))))) +;; (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|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))) +(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) + (make-local-variable 'ffap-c-path) + (make-local-variable 'ffap-c++-path) + (cl-loop for dir in (or (cdr (assoc project-root +cc--project-includes-alist)) + (+cc-resolve-include-paths)) + do (add-to-list (pcase major-mode + (`c-mode 'ffap-c-path) + (`c++-mode 'ffap-c++-path)) + (expand-file-name dir project-root))))) diff --git a/modules/lang/cc/config.el b/modules/lang/cc/config.el index 035dea19a..c53273bea 100644 --- a/modules/lang/cc/config.el +++ b/modules/lang/cc/config.el @@ -1,9 +1,13 @@ ;;; lang/cc/config.el --- c, c++, and obj-c -*- lexical-binding: t; -*- -(defvar +cc-default-include-paths (list "include/") - "A list of default paths, relative to a project root, to search for headers in -C/C++. Paths can be absolute. This is ignored if your project has a compilation -database.") +(defvar +cc-default-include-paths + (list "include" + "includes") + "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 "Fallback major mode for .h files if all other heuristics fail (in @@ -20,7 +24,9 @@ database.") "-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.") +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 (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 (set-electric! '(c-mode c++-mode objc-mode java-mode) :chars '(?\n ?\} ?\{)) (set-docsets! 'c-mode "C") @@ -69,12 +80,11 @@ compilation database is present in the project.") ;;; Better fontification (also see `modern-cpp-font-lock') (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 - (unless (assoc "doom" c-style-alist) - (push '("doom" - (c-basic-offset . tab-width) + (c-add-style + "doom" '((c-basic-offset . tab-width) (c-comment-only-line-offset . 0) (c-hanging-braces-alist (brace-list-open) (brace-entry-open) @@ -102,8 +112,7 @@ compilation database is present in the project.") ;; another level (access-label . -) (inclass +cc-c++-lineup-inclass +) - (label . 0))) - c-style-alist)) + (label . 0)))) ;;; Keybindings ;; 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/")) :init (defun +cc|init-irony-mode () - (when (and (memq major-mode '(c-mode c++-mode objc-mode)) - (file-directory-p irony-server-install-prefix)) - (irony-mode +1))) - (add-hook 'c-mode-common-hook #'+cc|init-irony-mode) + (if (file-directory-p irony-server-install-prefix) + (irony-mode +1) + (message "Irony server isn't installed"))) + (add-hook! (c-mode-local-vars c++-mode-local-vars objc-mode-local-vars) + #'+cc|init-irony-mode) :config (setq irony-cdb-search-directory-list '("." "build" "build-conda")) ;; Initialize compilation database, if present. Otherwise, fall back on ;; `+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 :hook (irony-mode . irony-eldoc)) @@ -188,11 +198,11 @@ compilation database is present in the project.") :init (defun +cc|init-rtags () "Start an rtags server in c-mode and c++-mode buffers." - (when (and (memq major-mode '(c-mode c++-mode)) - (require 'rtags nil t) + (when (and (require 'rtags nil t) (rtags-executable-find rtags-rdm-binary-name)) (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 (setq rtags-autostart-diagnostics t rtags-use-bookmarks nil @@ -226,9 +236,9 @@ compilation database is present in the project.") (def-package! ccls :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 - (defun +lsp|init-ccls () + (defun +cc|init-ccls () (setq-local company-transformers nil) (setq-local company-lsp-async t) (setq-local company-lsp-cache-candidates nil)