lang/cc: rewrite C/C++/OBJC header file detection

This commit is contained in:
Henrik Lissner 2018-08-03 03:41:31 +02:00
parent 80eb1dc449
commit 31c8c0c033
No known key found for this signature in database
GPG key ID: 5F6C0EA160557395
2 changed files with 47 additions and 26 deletions

View file

@ -66,6 +66,45 @@ preceded by the opening brace or a comma (disregarding whitespace in between)."
(memq (char-before) (list ?, ?\( ?\;))))
(c-lineup-arglist langlem)))
(defun +cc--re-search-for (regexp)
(save-excursion
(save-restriction
(save-match-data
(widen)
(goto-char (point-min))
(re-search-forward regexp magic-mode-regexp-match-limit t)))))
;;;###autoload
(defun +cc-c-c++-objc-mode (&optional file)
"Sets either `c-mode', `objc-mode' or `c++-mode', whichever is appropriate."
(let ((base (file-name-sans-extension buffer-file-name))
file)
(cond ((file-exists-p! (or (concat base ".cpp")
(concat base ".cc")))
(c++-mode))
((or (file-exists-p! (or (concat base ".m")
(concat base ".mm")))
(+cc--re-search-for
(concat "^[ \t\r]*\\(?:"
"@\\(?:class\\|interface\\|property\\|end\\)\\_>"
"\\|#import +<Foundation/Foundation.h>"
"\\|[-+] ([a-zA-Z0-9_]+)"
"\\)")))
(objc-mode))
((fboundp 'c-or-c++-mode) ; introduced in Emacs 26.1
(c-or-c++-mode))
((+cc--re-search-for ; TODO Remove this along with Emacs 25 support
(let ((id "[a-zA-Z0-9_]+") (ws "[ \t\r]+") (ws-maybe "[ \t\r]*"))
(concat "^" ws-maybe "\\(?:"
"using" ws "\\(?:namespace" ws "std;\\|std::\\)"
"\\|" "namespace" "\\(:?" ws id "\\)?" ws-maybe "{"
"\\|" "class" ws id ws-maybe "[:{\n]"
"\\|" "template" ws-maybe "<.*>"
"\\|" "#include" ws-maybe "<\\(?:string\\|iostream\\|map\\)>"
"\\)")))
(c++-mode))
((c-mode)))))
;;
;; Hooks

View file

@ -26,37 +26,19 @@ compilation database is present in the project.")
(def-package! cc-mode
:commands (c-mode c++-mode objc-mode java-mode)
:mode ("\\.mm\\'" . objc-mode)
:preface
;; The plusses in c++-mode can be annoying to search for ivy/helm (which reads
;; queries as regexps), so wee add these for convenience.
(defalias 'cpp-mode 'c++-mode)
(defvaralias 'cpp-mode-map 'c++-mode-map)
(defun +cc-c++-header-file-p ()
(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)))))
(equal (file-name-extension file) "cpp")))))
(defun +cc-objc-header-file-p ()
(and buffer-file-name
(equal (file-name-extension buffer-file-name) "h")
(re-search-forward "@\\<interface\\>" magic-mode-regexp-match-limit t)))
(unless (assq '+cc-c++-header-file-p magic-mode-alist)
(push '(+cc-c++-header-file-p . c++-mode) magic-mode-alist)
(push '(+cc-objc-header-file-p . objc-mode) magic-mode-alist))
:init
(setq-default c-basic-offset tab-width
c-backspace-function #'delete-backward-char
c-default-style "doom")
;; The plusses in c++-mode can be annoying to search for ivy/helm (which reads
;; queries as regexps), so we add these for convenience.
(defalias 'cpp-mode 'c++-mode)
(defvaralias 'cpp-mode-map 'c++-mode-map)
;; Activate `c-mode', `c++-mode' or `objc-mode' depending on heuristics
(add-to-list 'auto-mode-alist '("\\.h\\'" . +cc-c-c++-objc-mode))
:config
(set-electric! '(c-mode c++-mode objc-mode java-mode) :chars '(?\n ?\}))