[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
emacs-29 1df2826639 1/4: Add c-or-c++-ts-mode (bug#59613)
From: |
Yuan Fu |
Subject: |
emacs-29 1df2826639 1/4: Add c-or-c++-ts-mode (bug#59613) |
Date: |
Sat, 7 Jan 2023 19:14:32 -0500 (EST) |
branch: emacs-29
commit 1df2826639c912396fac0af108301533dac71406
Author: Yuan Fu <casouri@gmail.com>
Commit: Yuan Fu <casouri@gmail.com>
Add c-or-c++-ts-mode (bug#59613)
* lisp/progmodes/c-ts-mode.el
(c-ts-mode--c-or-c++-regexp): New variable.
(c-or-c++-ts-mode): New mode.
* etc/NEWS: Mention c-or-c++-ts-mode.
---
etc/NEWS | 5 +++++
lisp/progmodes/c-ts-mode.el | 44 ++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 49 insertions(+)
diff --git a/etc/NEWS b/etc/NEWS
index 5901b2718e..c7cfead5fd 100644
--- a/etc/NEWS
+++ b/etc/NEWS
@@ -3210,6 +3210,11 @@ programs in the C language.
An optional major mode based on the tree-sitter library for editing
programs in the C++ language.
++++
+*** New major mode 'c-or-c++-ts-mode'.
+A function that automatically guesses the language of a header file,
+and enables either 'c-ts-mode' or 'c++-ts-mode' accordingly.
+
+++
*** New major mode 'java-ts-mode'.
An optional major mode based on the tree-sitter library for editing
diff --git a/lisp/progmodes/c-ts-mode.el b/lisp/progmodes/c-ts-mode.el
index 30a14ecdfa..b8c4313c0f 100644
--- a/lisp/progmodes/c-ts-mode.el
+++ b/lisp/progmodes/c-ts-mode.el
@@ -822,6 +822,50 @@ Set up:
(treesit-major-mode-setup))
+;; We could alternatively use parsers, but if this works well, I don't
+;; see the need to change. This is copied verbatim from cc-guess.el.
+(defconst c-ts-mode--c-or-c++-regexp
+ (eval-when-compile
+ (let ((id "[a-zA-Z_][a-zA-Z0-9_]*") (ws "[ \t]+") (ws-maybe "[ \t]*")
+ (headers '("string" "string_view" "iostream" "map" "unordered_map"
+ "set" "unordered_set" "vector" "tuple")))
+ (concat "^" ws-maybe "\\(?:"
+ "using" ws "\\(?:namespace" ws
+ "\\|" id "::"
+ "\\|" id ws-maybe "=\\)"
+ "\\|" "\\(?:inline" ws "\\)?namespace"
+ "\\(:?" ws "\\(?:" id "::\\)*" id "\\)?" ws-maybe "{"
+ "\\|" "class" ws id
+ "\\(?:" ws "final" "\\)?" ws-maybe "[:{;\n]"
+ "\\|" "struct" ws id "\\(?:" ws "final" ws-maybe "[:{\n]"
+ "\\|" ws-maybe ":\\)"
+ "\\|" "template" ws-maybe "<.*?>"
+ "\\|" "#include" ws-maybe "<" (regexp-opt headers) ">"
+ "\\)")))
+ "A regexp applied to C header files to check if they are really C++.")
+
+;;;###autoload
+(defun c-or-c++-ts-mode ()
+ "Analyze buffer and enable either C or C++ mode.
+
+Some people and projects use .h extension for C++ header files
+which is also the one used for C header files. This makes
+matching on file name insufficient for detecting major mode that
+should be used.
+
+This function attempts to use file contents to determine whether
+the code is C or C++ and based on that chooses whether to enable
+`c-ts-mode' or `c++-ts-mode'."
+ (interactive)
+ (if (save-excursion
+ (save-restriction
+ (save-match-data ; Why `save-match-data'?
+ (widen)
+ (goto-char (point-min))
+ (re-search-forward c-ts-mode--c-or-c++-regexp nil t))))
+ (c++-ts-mode)
+ (c-ts-mode)))
+
(provide 'c-ts-mode)
;;; c-ts-mode.el ends here