First commit.
This commit is contained in:
162
lisp/modes/c-c++.el
Normal file
162
lisp/modes/c-c++.el
Normal file
@@ -0,0 +1,162 @@
|
||||
;;; c-c++.el --- initializes C/C++ modes -*- lexical-binding: t; -*-
|
||||
;;; Commentary:
|
||||
;;; Code:
|
||||
|
||||
(require 'cl)
|
||||
(require 'lsp)
|
||||
|
||||
(defun user--c-format-before-save ()
|
||||
"C/C++ cleanup and format before save buffer."
|
||||
(delete-trailing-whitespace)
|
||||
;; Format buffer.
|
||||
(indent-region (point-min) (point-max) nil)
|
||||
)
|
||||
|
||||
;; From https://www.emacswiki.org/emacs/CompileCommand
|
||||
(defun* user--c-get-closest-pathname (&optional (file "Makefile"))
|
||||
"Determine the pathname of the first instance of FILE starting from the current directory towards root.
|
||||
This may not do the correct thing in presence of links. If it does not find FILE, then it shall return the name
|
||||
of FILE in the current directory, suitable for creation"
|
||||
(let ((root (expand-file-name "/"))) ; the win32 builds should translate this correctly
|
||||
(expand-file-name file
|
||||
(loop
|
||||
for d = default-directory then (expand-file-name ".." d)
|
||||
if (file-exists-p (expand-file-name file d))
|
||||
return d
|
||||
if (equal d root)
|
||||
return nil))))
|
||||
|
||||
(defun user--c-lsp-set-priority (server priority)
|
||||
(setf (lsp--client-priority (gethash server lsp-clients)) priority))
|
||||
|
||||
(defun user--c-mode-common-hook ()
|
||||
"C-like languages mode hook."
|
||||
(add-many-to-list 'c-default-style '(c-mode . "bsd") '(c++-mode . "bsd"))
|
||||
|
||||
(setq tab-width 4)
|
||||
|
||||
;; Propertize "#if 0" regions as comments.
|
||||
(font-lock-add-keywords
|
||||
nil
|
||||
'((user/c-mode-font-lock-if0 (0 font-lock-comment-face prepend)))
|
||||
'add-to-end)
|
||||
|
||||
;; Change compile-command.
|
||||
(set
|
||||
(make-local-variable 'compile-command)
|
||||
(format "make -C %s" (directory-file-name (file-name-directory (user--c-get-closest-pathname)))))
|
||||
;; Avoid to hit enter after compile-command to build.
|
||||
(setq compilation-read-command nil)
|
||||
|
||||
;; Separate camel-case into separate words.
|
||||
(subword-mode t)
|
||||
|
||||
(when (feature-p 'mic-paren)
|
||||
;; Match context to open parentheses.
|
||||
(paren-toggle-open-paren-context t))
|
||||
|
||||
(setq flycheck-checker-error-threshold 1000)
|
||||
|
||||
(setq flycheck-local-checkers '((lsp . ((next-checkers . (flawfinder))))))
|
||||
;; (flycheck-add-next-checker 'clang-analyzer 'flawfinder)
|
||||
|
||||
(user/smartparens-enable))
|
||||
|
||||
(defun user/c-mode-font-lock-if0 (limit)
|
||||
"Propertize '#if 0' regions, up to LIMIT in size, as comments."
|
||||
(save-restriction
|
||||
(widen)
|
||||
(save-excursion
|
||||
(goto-char (point-min))
|
||||
(let ((depth 0) str start start-depth)
|
||||
(while (re-search-forward "^\\s-*#\\s-*\\(if\\|else\\|endif\\)" limit 'move)
|
||||
(setq str (match-string 1))
|
||||
(if (string= str "if")
|
||||
(progn
|
||||
(setq depth (1+ depth))
|
||||
(when (and (null start) (looking-at "\\s-+0"))
|
||||
(setq start (match-end 0)
|
||||
start-depth depth)))
|
||||
(when (and start (= depth start-depth))
|
||||
(c-put-font-lock-face start (match-beginning 0) 'font-lock-comment-face)
|
||||
(setq start nil))
|
||||
(when (string= str "endif")
|
||||
(setq depth (1- depth)))))
|
||||
(when (and start (> depth 0))
|
||||
(c-put-font-lock-face start (point) 'font-lock-comment-face)))))
|
||||
nil)
|
||||
|
||||
|
||||
(defun user/c++-header-file-p ()
|
||||
"Return non-nil if in a C++ header."
|
||||
(and (string-match "\\.h$" (or (buffer-file-name) (buffer-name)))
|
||||
(save-excursion (re-search-forward "\\_<class\\_>" nil t))))
|
||||
|
||||
;; https://www.gnu.org/software/emacs/manual/html_mono/ccmode.html
|
||||
(use-package cc-mode
|
||||
:defer
|
||||
:hook
|
||||
(c-mode-common-hook . user--c-mode-common-hook)
|
||||
(c-mode-common-hook . hs-minor-mode)
|
||||
(c-mode-common-hook . lsp-deferred)
|
||||
(c-mode-common-hook . (lambda ()
|
||||
(add-hook 'before-save-hook #'user--c-format-before-save nil t)))
|
||||
:init
|
||||
;; Detect if inside a C++ header file.
|
||||
(add-magic-mode 'c++-mode 'user/c++-header-file-p)
|
||||
:config
|
||||
(add-many-to-list 'c-default-style '(c-mode . "bsd") '(c++-mode . "bsd")
|
||||
)
|
||||
|
||||
;;; (Packages) ;;;
|
||||
;; https://github.com/emacs-mirror/emacs/blob/master/lisp/progmodes/cc-vars.el
|
||||
;; user customization variables for CC Mod
|
||||
(use-package cc-vars
|
||||
:disabled
|
||||
:ensure cc-mode
|
||||
:config
|
||||
(validate-setq
|
||||
;; Support completion using tab.
|
||||
c-tab-always-indent nil
|
||||
c-insert-tab-function 'indent-for-tab-command)
|
||||
)
|
||||
|
||||
;; https://github.com/randomphrase/company-c-headers
|
||||
;; Auto-completion for C/C++ headers using Company
|
||||
(use-package company-c-headers
|
||||
:after (company))
|
||||
|
||||
;; https://github.com/emacs-lsp/lsp-mode/blob/master/clients/lsp-clangd.el
|
||||
;; LSP clients for the C Languages Family
|
||||
(use-package lsp-clangd
|
||||
:after (company lsp)
|
||||
;; :defer t
|
||||
:config
|
||||
;; set priority to ensure the use of clangd
|
||||
(setq company-backends '(company-capf))
|
||||
(user--c-lsp-set-priority 'clangd 1))
|
||||
|
||||
;; https://github.com/MaskRay/emacs-ccls
|
||||
;; Emacs client for ccls, a C/C++ language server
|
||||
(use-package ccls
|
||||
:if (executable-find "ccls")
|
||||
:after lsp
|
||||
:config
|
||||
(user--c-lsp-set-priority 'ccls -1)
|
||||
(validate-setq
|
||||
ccls-initialization-options
|
||||
'(:index (:comments 1) :cacheFormat "msgpack")))
|
||||
|
||||
;; https://github.com/alexmurray/flycheck-flawfinder
|
||||
;; Integrate flawfinder with flycheck to automatically check for possible security weaknesses
|
||||
;; within your C/C++ code on the fly.
|
||||
(use-package flycheck-flawfinder
|
||||
:disabled
|
||||
:ensure t
|
||||
:if (executable-find "flawfinder")
|
||||
:config
|
||||
(flycheck-flawfinder-setup))
|
||||
)
|
||||
|
||||
(provide 'modes/c-c++)
|
||||
;;; c-c++.el ends here
|
Reference in New Issue
Block a user