From mboxrd@z Thu Jan 1 00:00:00 1970 Path: news.gmane.org!not-for-mail From: Michal Nazarewicz Newsgroups: gmane.emacs.bugs Subject: bug#23719: [PATCH] Automatically detect whether .h file is C or C++ Date: Tue, 7 Jun 2016 15:16:25 +0200 Message-ID: <1465305385-18615-1-git-send-email-mina86@mina86.com> NNTP-Posting-Host: plane.gmane.org X-Trace: ger.gmane.org 1465306173 11859 80.91.229.3 (7 Jun 2016 13:29:33 GMT) X-Complaints-To: usenet@ger.gmane.org NNTP-Posting-Date: Tue, 7 Jun 2016 13:29:33 +0000 (UTC) To: 23719@debbugs.gnu.org Original-X-From: bug-gnu-emacs-bounces+geb-bug-gnu-emacs=m.gmane.org@gnu.org Tue Jun 07 15:29:22 2016 Return-path: Envelope-to: geb-bug-gnu-emacs@m.gmane.org Original-Received: from lists.gnu.org ([208.118.235.17]) by plane.gmane.org with esmtp (Exim 4.69) (envelope-from ) id 1bAH4K-0006Oi-T3 for geb-bug-gnu-emacs@m.gmane.org; Tue, 07 Jun 2016 15:29:21 +0200 Original-Received: from localhost ([::1]:49746 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1bAH4K-0002uX-61 for geb-bug-gnu-emacs@m.gmane.org; Tue, 07 Jun 2016 09:29:20 -0400 Original-Received: from eggs.gnu.org ([2001:4830:134:3::10]:58769) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1bAGsW-0007k1-Gn for bug-gnu-emacs@gnu.org; Tue, 07 Jun 2016 09:17:09 -0400 Original-Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1bAGsQ-0007TK-8P for bug-gnu-emacs@gnu.org; Tue, 07 Jun 2016 09:17:08 -0400 Original-Received: from debbugs.gnu.org ([208.118.235.43]:45215) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1bAGsQ-0007TG-4G for bug-gnu-emacs@gnu.org; Tue, 07 Jun 2016 09:17:02 -0400 Original-Received: from Debian-debbugs by debbugs.gnu.org with local (Exim 4.84_2) (envelope-from ) id 1bAGsQ-0006Ke-0D for bug-gnu-emacs@gnu.org; Tue, 07 Jun 2016 09:17:02 -0400 X-Loop: help-debbugs@gnu.org Resent-From: Michal Nazarewicz Original-Sender: "Debbugs-submit" Resent-CC: bug-gnu-emacs@gnu.org Resent-Date: Tue, 07 Jun 2016 13:17:01 +0000 Resent-Message-ID: Resent-Sender: help-debbugs@gnu.org X-GNU-PR-Message: report 23719 X-GNU-PR-Package: emacs X-GNU-PR-Keywords: patch X-Debbugs-Original-To: bug-gnu-emacs@gnu.org Original-Received: via spool by submit@debbugs.gnu.org id=B.146530541324314 (code B ref -1); Tue, 07 Jun 2016 13:17:01 +0000 Original-Received: (at submit) by debbugs.gnu.org; 7 Jun 2016 13:16:53 +0000 Original-Received: from localhost ([127.0.0.1]:57552 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1bAGsG-0006K6-La for submit@debbugs.gnu.org; Tue, 07 Jun 2016 09:16:52 -0400 Original-Received: from eggs.gnu.org ([208.118.235.92]:39523) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1bAGsE-0006Jt-Aw for submit@debbugs.gnu.org; Tue, 07 Jun 2016 09:16:50 -0400 Original-Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1bAGs4-0007Qu-Oh for submit@debbugs.gnu.org; Tue, 07 Jun 2016 09:16:45 -0400 Original-Received: from lists.gnu.org ([2001:4830:134:3::11]:56313) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1bAGs4-0007Qj-LQ for submit@debbugs.gnu.org; Tue, 07 Jun 2016 09:16:40 -0400 Original-Received: from eggs.gnu.org ([2001:4830:134:3::10]:58709) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1bAGs0-0007IW-RM for bug-gnu-emacs@gnu.org; Tue, 07 Jun 2016 09:16:39 -0400 Original-Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1bAGry-0007Q3-5Q for bug-gnu-emacs@gnu.org; Tue, 07 Jun 2016 09:16:35 -0400 Original-Received: from mail-wm0-x22a.google.com ([2a00:1450:400c:c09::22a]:35579) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1bAGrx-0007Ps-7l for bug-gnu-emacs@gnu.org; Tue, 07 Jun 2016 09:16:34 -0400 Original-Received: by mail-wm0-x22a.google.com with SMTP id v199so19116704wmv.0 for ; Tue, 07 Jun 2016 06:16:33 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20120113; h=sender:from:to:subject:date:message-id; bh=Q64LBR8EWA9Nt/cYH0iOZh5jaEVq6cir/cEoT25YTVY=; b=OVOmRPXfpHZUXr/7YUzvT5gFkOeoYkXqHPKSSmg8l6UiGlQef9tmOhmi2GhYbWX54W 9jjaN1fYlsGdFbAkNAAVIFjthsootdxEbesfFVqfCKVAKt35XkLwyay8BOrnkb6rwDNu aXRyGiH9G0uaWg+UkJdCTOvtB7Po3fC9X6C/H4uHQ+v567kqatRqYvz3puDvVnr8mgPM Tx5z2VrTyfoXbFVJjZ8C+Q6oF0WiYa5k/NwQqUUJ4PjRvpi7k/35zzSSq0ZMCpD5LNrc /w8KftvqOhGQSH+s7aYDzso5KSRFJaqsQFw/rnBTFHzNoXAsqIIl4DjkfbvRVoMeqNpx 4lUw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:sender:from:to:subject:date:message-id; bh=Q64LBR8EWA9Nt/cYH0iOZh5jaEVq6cir/cEoT25YTVY=; b=b7e4EOphImsH1omaZvNPPAmKdycKZxvN37+ND1dBNlmF5XE1sGRckY7dSFpfcihQ8e xacx6b3XyaLnUfnuvNBShoFthkznxJB9nT9WHj5mnV2K79gESYuTGUad0T+k8FCz0rjG eiwqNo7Zfcir/2nJltGWvRtEOgUxPe7KjgsSKa62BllInsiy3QFHrkArPv1uPY679uaM 5VO817x23NkSPv+l5v3qo3/JArXrMpedBNQYctfCqRVfncmLz4a7MwmNlgUe6n8fB2+I XT5CayAMRU75Y9jTDErWwWnizAxssEKHcI/z244j8a4ufrOv2QANUem1zlo/5U7aDJ7b BxfQ== X-Gm-Message-State: ALyK8tKKGs4IVC2Pn5Vj8cWhVLql/ehR/yDTYww5RX6NjhNutzix/nAm+cGuVls9HnIJpC8R X-Received: by 10.194.205.105 with SMTP id lf9mr20335309wjc.25.1465305392144; Tue, 07 Jun 2016 06:16:32 -0700 (PDT) Original-Received: from mpn.zrh.corp.google.com ([172.16.113.135]) by smtp.gmail.com with ESMTPSA id b201sm19474946wmb.9.2016.06.07.06.16.29 for (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Tue, 07 Jun 2016 06:16:29 -0700 (PDT) Original-Received: by mpn.zrh.corp.google.com (Postfix, from userid 126942) id B514C1E35D2; Tue, 7 Jun 2016 15:16:28 +0200 (CEST) X-Mailer: git-send-email 2.8.0.rc3.226.g39d4020 X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.6.x X-BeenThere: debbugs-submit@debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] X-Received-From: 208.118.235.43 X-BeenThere: bug-gnu-emacs@gnu.org List-Id: "Bug reports for GNU Emacs, the Swiss army knife of text editors" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: bug-gnu-emacs-bounces+geb-bug-gnu-emacs=m.gmane.org@gnu.org Original-Sender: "bug-gnu-emacs" Xref: news.gmane.org gmane.emacs.bugs:119208 Archived-At: * lisp/progmodes/cc-mode.el (c-or-c++-mode): A new function which analyses contents of the buffer to determine whether it looks like C++ source code and based on that enables c-mode or c++-mode. (c-or-c++-mode--regexp): Regular expression which, when matches a buffer, signals file is C++. --- etc/NEWS | 7 +++++ lisp/progmodes/cc-mode.el | 39 +++++++++++++++++++++++-- test/lisp/progmodes/cc-mode.el | 65 ++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 109 insertions(+), 2 deletions(-) create mode 100644 test/lisp/progmodes/cc-mode.el diff --git a/etc/NEWS b/etc/NEWS index 23f6efc..8f4be56 100644 --- a/etc/NEWS +++ b/etc/NEWS @@ -373,6 +373,13 @@ string is computed dynamically based on 'url-privacy-level'. colorful faces to make it more obvious to the user what the state is. See the 'vc-faces' customization group. +** CC mode + +*** Opening a .h file will turn C or C++ mode depending on language used. +This is done with the help of 'c-or-c++-mode' function which analyses +contents of the buffer to determine whether it's a C or C++ source +file. + * New Modes and Packages in Emacs 25.2 diff --git a/lisp/progmodes/cc-mode.el b/lisp/progmodes/cc-mode.el index 9ab0480..f544dcb 100644 --- a/lisp/progmodes/cc-mode.el +++ b/lisp/progmodes/cc-mode.el @@ -1444,7 +1444,8 @@ c-mode-map ;;;###autoload (add-to-list 'auto-mode-alist '("\\.[ch]\\(pp\\|xx\\|\\+\\+\\)\\'" . c++-mode)) ;;;###autoload (add-to-list 'auto-mode-alist '("\\.\\(CC?\\|HH?\\)\\'" . c++-mode)) -;;;###autoload (add-to-list 'auto-mode-alist '("\\.[ch]\\'" . c-mode)) +;;;###autoload (add-to-list 'auto-mode-alist '("\\.c\\'" . c-mode)) +;;;###autoload (add-to-list 'auto-mode-alist '("\\.h\\'" . c-or-c++-mode)) ;; NB: The following two associate yacc and lex files to C Mode, which ;; is not really suitable for those formats. Anyway, afaik there's @@ -1485,6 +1486,40 @@ c-mode (cc-imenu-init cc-imenu-c-generic-expression) (c-run-mode-hooks 'c-mode-common-hook)) +(defconst c-or-c++-mode--regexp + (eval-when-compile + (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\\)>" + "\\)"))) + "A regexp applied to C header files to check if they are really C++.") + +;;;###autoload +(defun c-or-c++-mode () + "Analyse 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-mode' or `c++-mode'." + (if (save-excursion + (save-restriction + (save-match-data + (widen) + (goto-char (point-min)) + (re-search-forward c-or-c++-mode--regexp + (+ (point) c-guess-region-max) t)))) + (c++-mode) + (c-mode))) + ;; Support for C++ diff --git a/test/lisp/progmodes/cc-mode.el b/test/lisp/progmodes/cc-mode.el new file mode 100644 index 0000000..6cd9fa4 --- /dev/null +++ b/test/lisp/progmodes/cc-mode.el @@ -0,0 +1,65 @@ +;;; cc-mode-tests.el --- Test suite for cc-mode. -*- lexical-binning: t -*- + +;; Copyright (C) 2016 Free Software Foundation, Inc. + +;; Author: Michal Nazarewicz +;; Keywords: internal +;; Human-Keywords: internal + +;; This file is part of GNU Emacs. + +;; GNU Emacs 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. + +;; GNU Emacs 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 GNU Emacs. If not, see . + +;;; Code: + +(require 'ert) +(require 'ert-x) +(require 'cc-mode) + +(ert-deftest c-or-c++-mode () + "Test c-or-c++-mode language detection." + (cl-letf* ((mode nil) + (do-test (lambda (content expected) + (delete-region (point-min) (point-max)) + (insert content) + (setq mode nil) + (c-or-c++-mode) + (unless(eq expected mode) + (ert-fail + (format "expected %s but got %s when testing '%s'" + expected mode content))))) + ((symbol-function 'c-mode) (lambda () (setq mode 'c-mode))) + ((symbol-function 'c++-mode) (lambda () (setq mode 'c++-mode)))) + (with-temp-buffer + (mapc (lambda (content) + (funcall do-test content 'c++-mode) + (funcall do-test (concat "// " content) 'c-mode) + (funcall do-test (concat " * " content) 'c-mode)) + '("using \t namespace \t std;" + "using \t std::string;" + "namespace \t {" + "namespace \t foo \t {" + "class \t Blah_42 \t {" + "class \t Blah_42 \t \n" + "class \t _42_Blah:public Foo {" + "template \t < class T >" + "template< class T >" + "#include " + "#include" + "#include \t ")) + + (mapc (lambda (content) (funcall do-test content 'c-mode)) + '("struct \t Blah_42 \t {" + "struct template {" + "#include "))))) -- 2.8.0.rc3.226.g39d4020