This repository has been archived on 2024-10-22. You can view files and clone it, but cannot push or open issues or pull requests.
spacemacs/layers/+lang/c-c++/funcs.el
2021-04-12 20:47:11 +00:00

402 lines
13 KiB
EmacsLisp
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

;;; funcs.el --- C/C++ Layer functions File for Spacemacs
;;
;; Copyright (c) 2012-2021 Sylvain Benner & Contributors
;;
;; Author: Sylvain Benner <sylvain.benner@gmail.com>
;; URL: https://github.com/syl20bnr/spacemacs
;;
;; This file is not part of GNU Emacs.
;;
;; This program is free software; you can redistribute it and/or modify
;; it under the terms of the GNU General Public License as published by
;; the Free Software Foundation, either version 3 of the License, or
;; (at your option) any later version.
;;
;; This program is distributed in the hope that it will be useful,
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
;; GNU General Public License for more details.
;;
;; You should have received a copy of the GNU General Public License
;; along with this program. If not, see <http://www.gnu.org/licenses/>.
(require 'cl-lib)
(require 'subr-x)
(defun spacemacs//c-c++-setup-backend ()
"Conditionally setup c-c++ backend."
(pcase c-c++-backend
('lsp-clangd (spacemacs//c-c++-setup-lsp-clangd))
('lsp-ccls (spacemacs//c-c++-setup-lsp-ccls))
('rtags (spacemacs//c-c++-setup-rtags))
('ycmd (spacemacs//c-c++-setup-ycmd))))
(defun spacemacs//c-c++-setup-company ()
"Conditionally setup C/C++ company integration based on backend."
(pcase c-c++-backend
('rtags (spacemacs//c-c++-setup-rtags-company))
('ycmd (spacemacs//c-c++-setup-ycmd-company))))
(defun spacemacs//c-c++-setup-dap ()
"Conditionally setup C/C++ DAP integration based on backend."
;; currently DAP is only available using LSP
(pcase c-c++-backend
('lsp-clangd (spacemacs//c-c++-setup-lsp-dap))
('lsp-ccls (spacemacs//c-c++-setup-lsp-dap))))
(defun spacemacs//c-c++-setup-eldoc ()
"Conditionally setup C/C++ eldoc integration based on backend."
;; lsp setup eldoc on its own
(when (eq c-c++-backend 'ycmd)
(spacemacs//c-c++-setup-ycmd-eldoc)))
(defun spacemacs//c-c++-setup-flycheck ()
"Conditionally setup C/C++ flycheck integration based on backend."
(pcase c-c++-backend
('rtags (spacemacs//c-c++-setup-rtags-flycheck))
('ycmd (spacemacs//c-c++-setup-ycmd-flycheck))))
(defun spacemacs//c-c++-setup-format ()
"Conditionally setup format based on backend."
(pcase c-c++-backend
('lsp-clangd (spacemacs//c-c++-setup-clang-format))
('lsp-ccls (spacemacs//c-c++-setup-clang-format))))
(defun spacemacs//c-c++-setup-semantic ()
"Conditionally setup semantic based on backend."
(pcase c-c++-backend
('rtags (spacemacs//c-c++-setup-rtags-semantic))
('ycmd (spacemacs//c-c++-setup-ycmd-semantic))))
;; lsp
;; clang
(defun spacemacs//c-c++-setup-lsp-clangd ()
"Setup LSP clangd."
;; extensions
(spacemacs/lsp-define-extensions
"c-c++" "lsp-clangd"
'clangd-other-file "textDocument/switchSourceHeader" 'buffer-file-name)
(setq-local lsp-disabled-clients '(ccls))
(lsp))
;; ccls
(defun spacemacs//c-c++-setup-lsp-ccls ()
"Setup LSP ccls."
(require 'ccls)
;; semantic highlight
(when c-c++-lsp-enable-semantic-highlight
(setq ccls-sem-highlight-method c-c++-lsp-semantic-highlight-method)
(when (eq 'rainbow c-c++-lsp-enable-semantic-highlight)
(ccls-use-default-rainbow-sem-highlight)))
;; extensions
(spacemacs/lsp-define-extensions
"c-c++" "lsp-ccls"
'refs-address "textDocument/references" '(:role 128))
(spacemacs/lsp-define-extensions
"c-c++" "lsp-ccls"
'refs-read "textDocument/references" '(:role 8))
(spacemacs/lsp-define-extensions
"c-c++" "lsp-ccls"
'refs-write "textDocument/references" '(:role 16))
(spacemacs/lsp-define-extensions
"c-c++" "lsp-ccls"
'callers "$ccls/call")
(spacemacs/lsp-define-extensions
"c-c++" "lsp-ccls"
'callees "$ccls/call" '(:callee t))
(spacemacs/lsp-define-extensions
"c-c++" "lsp-ccls"
'base "$ccls/inheritance")
(spacemacs/lsp-define-extensions
"c-c++" "lsp-ccls"
'derived "$ccls/inheritance" '(:derived t))
(spacemacs/lsp-define-extensions
"c-c++" "lsp-ccls"
'member-types "$ccls/member" `(:kind 2))
(spacemacs/lsp-define-extensions
"c-c++" "lsp-ccls"
'member-functions "$ccls/member" `(:kind 3))
(spacemacs/lsp-define-extensions
"c-c++" "lsp-ccls"
'member-vars "$ccls/member" `(:kind 0))
;; key bindings
(dolist (mode c-c++-modes)
(spacemacs/set-leader-keys-for-major-mode mode
;; backend
"bf" 'ccls-reload
"bp" 'ccls-preprocess-file
;; goto
"gf" 'find-file-at-point
"gF" 'ffap-other-window
;; hierarchy
"ghc" 'ccls-call-hierarchy
"ghC" 'spacemacs/c-c++-lsp-ccls-call-hierarchy-inv
"ghi" 'ccls-inheritance-hierarchy
"ghI" 'spacemacs/c-c++-lsp-ccls-inheritance-hierarchy-inv
;; members
"gmh" 'ccls-member-hierarchy)
(spacemacs/lsp-bind-extensions-for-mode
mode "c-c++" "lsp-ccls"
"&" 'refs-address
"R" 'refs-read
"W" 'refs-write
"c" 'callers
"C" 'callees
"v" 'vars
"hb" 'base)
(spacemacs/lsp-bind-extensions-for-mode
mode "c-c++" "lsp-ccls"
"hd" 'derived
"mt" 'member-types
"mf" 'member-functions
"mv" 'member-vars))
;;(evil-set-initial-state 'ccls--tree-mode 'emacs)
;;(evil-make-overriding-map 'ccls-tree-mode-map)
(setq-local lsp-disabled-clients '(clangd))
(lsp))
(defun spacemacs//c-c++-setup-lsp-dap ()
"Setup DAP integration."
(mapc #'require c-c++-dap-adapters))
;; rtags
(defun spacemacs//c-c++-setup-rtags ()
"Setup rtags backend."
(setq rtags-autostart-diagnostics t)
(add-hook 'rtags-jump-hook 'evil-set-jump)
(rtags-diagnostics)
;; key bindings
(evil-define-key 'normal rtags-mode-map
(kbd "RET") 'rtags-select-other-window
(kbd "M-RET") 'rtags-select
(kbd "q") 'rtags-bury-or-delete)
;; TODO check for consistency with gtags key bindings
;; see https://github.com/syl20bnr/spacemacs/blob/develop/layers/+tags/gtags/funcs.el#L70
(dolist (mode c-c++-modes)
(spacemacs/set-leader-keys-for-major-mode mode
"g." 'spacemacs/c-c++-tags-find-symbol-at-point
"g," 'spacemacs/c-c++-tags-find-references-at-point
"g;" 'spacemacs/c-c++-tags-find-file
"g/" 'rtags-find-all-references-at-point
"g[" 'rtags-location-stack-back
"g]" 'rtags-location-stack-forward
"g>" 'spacemacs/c-c++-tags-find-symbol
"g<" 'spacemacs/c-c++-tags-find-references
"gB" 'rtags-show-rtags-buffer
"gd" 'rtags-print-dependencies
"gD" 'rtags-diagnostics
"ge" 'rtags-reparse-file
"gE" 'rtags-preprocess-file
"gf" 'rtags-find-dead-functions
"gF" 'rtags-fixit
"gG" 'rtags-guess-function-at-point
"gh" 'rtags-print-class-hierarchy
"gI" 'spacemacs/c-c++-tags-imenu
"gL" 'rtags-copy-and-print-current-location
"gM" 'rtags-symbol-info
"gO" 'rtags-goto-offset
"gp" 'rtags-set-current-project
"gr" 'rtags-references-tree
"gR" 'rtags-rename-symbol
"gs" 'rtags-print-source-arguments
"gS" 'rtags-display-summary
"gt" 'rtags-symbol-type
"gT" 'rtags-taglist
"gu" 'rtags-dependency-tree
"gv" 'rtags-find-virtuals-at-point
"gV" 'rtags-print-enum-value-at-point
"gX" 'rtags-fix-fixit-at-point
"gY" 'rtags-cycle-through-diagnostics)))
(defun spacemacs//c-c++-setup-rtags-company ()
"Setup rtags auto-completion."
(when c-c++-enable-rtags-completion
(setq rtags-completions-enabled t)
(spacemacs|add-company-backends
:backends company-rtags
:modes c-mode-common
:append-hooks nil
:call-hooks t)))
(defun spacemacs//c-c++-setup-rtags-flycheck ()
"Setup rtags syntax checking."
(when (or (spacemacs/enable-flycheck 'c-mode)
(spacemacs/enable-flycheck 'c++-mode))
(require 'flycheck-rtags)
(flycheck-mode)))
(defun spacemacs//c-c++-setup-rtags-semantic ()
"Setup semantic for rtags."
(semantic-mode)
(spacemacs//disable-semantic-idle-summary-mode))
(defun spacemacs/c-c++-use-rtags (&optional useFileManager)
"Return non-nil if rtags function should be used."
;; this function is used to fallback on gtags function if rtags is not
;; supported. So if gtags layer is not used we disable the fallback by
;; returning always t.
(or (not (configuration-layer/layer-used-p 'gtags))
(and (rtags-executable-find "rc")
(cond ((not (gtags-get-rootpath)) t)
((and (not (eq major-mode 'c++-mode))
(not (eq major-mode 'c-mode))) (rtags-has-filemanager))
(useFileManager (rtags-has-filemanager))
(t (rtags-is-indexed))))))
(defun spacemacs/c-c++-tags-find-symbol-at-point (&optional prefix)
(interactive "P")
(if (and (not (rtags-find-symbol-at-point prefix))
rtags-last-request-not-indexed)
(gtags-find-tag)))
(defun spacemacs/c-c++-tags-find-references-at-point (&optional prefix)
(interactive "P")
(if (and (not (rtags-find-references-at-point prefix))
rtags-last-request-not-indexed)
(gtags-find-rtag)))
(defun spacemacs/c-c++-tags-find-symbol ()
(interactive)
(call-interactively (if (spacemacs/c-c++-use-rtags)
'rtags-find-symbol 'gtags-find-symbol)))
(defun spacemacs/c-c++-tags-find-references ()
(interactive)
(call-interactively (if (spacemacs/c-c++-use-rtags)
'rtags-find-references 'gtags-find-rtag)))
(defun spacemacs/c-c++-tags-find-file ()
(interactive)
(call-interactively (if (spacemacs/c-c++-use-rtags t)
'rtags-find-file 'gtags-find-file)))
(defun spacemacs/c-c++-tags-imenu ()
(interactive)
(call-interactively (if (spacemacs/c-c++-use-rtags t)
'rtags-imenu 'idomenu)))
;; ycmd
(defun spacemacs//c-c++-setup-ycmd ()
"Setup ycmd backend."
(add-to-list 'spacemacs-jump-handlers-c++-mode '(ycmd-goto :async t))
(add-to-list 'spacemacs-jump-handlers-c-mode '(ycmd-goto :async t))
(dolist (mode c-c++-modes)
(spacemacs/set-leader-keys-for-major-mode mode
"gG" 'ycmd-goto-imprecise))
(ycmd-mode))
(defun spacemacs//c-c++-setup-ycmd-company ()
"Setup ycmd auto-completion."
(spacemacs|add-company-backends
:backends company-ycmd
:modes c-mode-common
:append-hooks nil
:call-hooks t))
(defun spacemacs//c-c++-setup-ycmd-eldoc ()
"Setup ycmd eldoc integration."
(ycmd-eldoc-setup))
(defun spacemacs//c-c++-setup-ycmd-flycheck ()
"Setup ycmd syntax checking."
(when (or (spacemacs/enable-flycheck 'c-mode)
(spacemacs/enable-flycheck 'c++-mode))
(flycheck-ycmd-setup)
(flycheck-mode)))
(defun spacemacs//c-c++-setup-ycmd-semantic ()
"Setup semantic for ycmd."
(semantic-mode))
;; style
(defun spacemacs//c-toggle-auto-newline ()
"Toggle auto-newline."
(c-toggle-auto-newline 1))
;; clang
(defun spacemacs//c-c++-setup-clang-format ()
"Setup clang format."
(when c-c++-enable-clang-format-on-save
(spacemacs/add-to-hooks 'spacemacs/clang-format-on-save c-c++-mode-hooks))
(dolist (mode c-c++-modes)
(spacemacs/declare-prefix-for-mode mode "m=" "format")
(spacemacs/set-leader-keys-for-major-mode mode
"==" 'spacemacs/clang-format-region-or-buffer
"=f" 'spacemacs/clang-format-function)))
(defun spacemacs/clang-format-function (&optional style)
"Format the current function with clang-format according to STYLE."
(interactive)
(save-excursion
(c-mark-function)
(clang-format (region-beginning) (region-end) style)
(deactivate-mark) ; If the function is already formatted, then remove the mark
(message "Formatted function %s" (c-defun-name))))
(defun spacemacs/clang-format-region-or-buffer (&optional style)
"Format the current region or buffer with clang-format according to STYLE."
(interactive)
(save-excursion
(if (region-active-p)
(progn
(clang-format-region (region-beginning) (region-end) style)
(message "Formatted region"))
(clang-format-buffer style)
(message "Formatted buffer %s" (buffer-name)))))
(defun spacemacs//clang-format-on-save ()
"Format the current buffer with clang-format on save when
`c-c++-enable-clang-format-on-save' is non-nil."
(when c-c++-enable-clang-format-on-save
(spacemacs/clang-format-region-or-buffer)))
(defun spacemacs/clang-format-on-save ()
"Add before-save hook for clang-format."
(add-hook 'before-save-hook 'spacemacs//clang-format-on-save nil t))
;; ccls
(defun spacemacs/c-c++-lsp-ccls-call-hierarchy-inv ()
(interactive)
(ccls-call-hierarchy t))
(defun spacemacs/c-c++-lsp-ccls-inheritance-hierarchy-inv ()
(interactive)
(ccls-inheritance-hierarchy t))
;; cpp-auto-include
(defalias 'spacemacs/c-c++-organize-includes 'cpp-auto-include)
(defun spacemacs//c-c++-organize-includes-on-save ()
"Organize the includes on save when `c-c++-enable-organize-includes-on-save'
is non-nil."
(when c-c++-enable-organize-includes-on-save
(spacemacs/c-c++-organize-includes)))
(defun spacemacs/c-c++-organize-includes-on-save ()
"Add before-save hook for c-c++-organize-includes."
(add-hook 'before-save-hook
#'spacemacs//c-c++-organize-includes-on-save nil t))