C++11 mode or settings for emacs?

2019-01-30 06:48发布

问题:

I'm running Emacs 23.3.1 (Ubuntu, Oneiric package) and emacs doesn't appear to understand any of the new C++11 keywords, constexpr, thread_local, etc. Also it doesn't understand that '>>' is now permitted in template parameters, or the new 'enum class' syntax. Is there an updated or alternative module somewhere? Or failing that, some settings to make emacs more C++11 friendly in the mean time?

回答1:

I've checked trunk version, cc-mode hasn't been updated yet, and AFAIK there's no alternative. If you really want it, but don't want to get your hands dirty, you should pay someone to implement it for you...



回答2:

Well, I'm using 24.1. Some C++98 keywords are missing, and all new C++11 keywords. It does not even fontify number constants. It seems as if c++-mode hasn't been updated for a decade.

I'm using the following code for a long time now, and recently added C++11 keywords. Try putting it in your .emacs; it should fill some holes.

(require 'font-lock)

(defun --copy-face (new-face face)
  "Define NEW-FACE from existing FACE."
  (copy-face face new-face)
  (eval `(defvar ,new-face nil))
  (set new-face new-face))

(--copy-face 'font-lock-label-face  ; labels, case, public, private, proteced, namespace-tags
         'font-lock-keyword-face)
(--copy-face 'font-lock-doc-markup-face ; comment markups such as Javadoc-tags
         'font-lock-doc-face)
(--copy-face 'font-lock-doc-string-face ; comment markups
         'font-lock-comment-face)

(global-font-lock-mode t)
(setq font-lock-maximum-decoration t)


(add-hook 'c++-mode-hook
      '(lambda()
        (font-lock-add-keywords
         nil '(;; complete some fundamental keywords
           ("\\<\\(void\\|unsigned\\|signed\\|char\\|short\\|bool\\|int\\|long\\|float\\|double\\)\\>" . font-lock-keyword-face)
           ;; add the new C++11 keywords
           ("\\<\\(alignof\\|alignas\\|constexpr\\|decltype\\|noexcept\\|nullptr\\|static_assert\\|thread_local\\|override\\|final\\)\\>" . font-lock-keyword-face)
           ("\\<\\(char[0-9]+_t\\)\\>" . font-lock-keyword-face)
           ;; PREPROCESSOR_CONSTANT
           ("\\<[A-Z]+[A-Z_]+\\>" . font-lock-constant-face)
           ;; hexadecimal numbers
           ("\\<0[xX][0-9A-Fa-f]+\\>" . font-lock-constant-face)
           ;; integer/float/scientific numbers
           ("\\<[\\-+]*[0-9]*\\.?[0-9]+\\([ulUL]+\\|[eE][\\-+]?[0-9]+\\)?\\>" . font-lock-constant-face)
           ;; user-types (customize!)
           ("\\<[A-Za-z_]+[A-Za-z_0-9]*_\\(t\\|type\\|ptr\\)\\>" . font-lock-type-face)
           ("\\<\\(xstring\\|xchar\\)\\>" . font-lock-type-face)
           ))
        ) t)

Hope this helps.



回答3:

According to a request by Mike Weller here an updated version for C++11 strings literals (incl. user-defined literals).

(add-hook
 'c++-mode-hook
 '(lambda()
    ;; We could place some regexes into `c-mode-common-hook', but note that their evaluation order
    ;; matters.
    (font-lock-add-keywords
     nil '(;; complete some fundamental keywords
           ("\\<\\(void\\|unsigned\\|signed\\|char\\|short\\|bool\\|int\\|long\\|float\\|double\\)\\>" . font-lock-keyword-face)
           ;; namespace names and tags - these are rendered as constants by cc-mode
           ("\\<\\(\\w+::\\)" . font-lock-function-name-face)
           ;;  new C++11 keywords
           ("\\<\\(alignof\\|alignas\\|constexpr\\|decltype\\|noexcept\\|nullptr\\|static_assert\\|thread_local\\|override\\|final\\)\\>" . font-lock-keyword-face)
           ("\\<\\(char16_t\\|char32_t\\)\\>" . font-lock-keyword-face)
           ;; PREPROCESSOR_CONSTANT, PREPROCESSORCONSTANT
           ("\\<[A-Z]*_[A-Z_]+\\>" . font-lock-constant-face)
           ("\\<[A-Z]\\{3,\\}\\>"  . font-lock-constant-face)
           ;; hexadecimal numbers
           ("\\<0[xX][0-9A-Fa-f]+\\>" . font-lock-constant-face)
           ;; integer/float/scientific numbers
           ("\\<[\\-+]*[0-9]*\\.?[0-9]+\\([ulUL]+\\|[eE][\\-+]?[0-9]+\\)?\\>" . font-lock-constant-face)
           ;; c++11 string literals
           ;;       L"wide string"
           ;;       L"wide string with UNICODE codepoint: \u2018"
           ;;       u8"UTF-8 string", u"UTF-16 string", U"UTF-32 string"
           ("\\<\\([LuU8]+\\)\".*?\"" 1 font-lock-keyword-face)
           ;;       R"(user-defined literal)"
           ;;       R"( a "quot'd" string )"
           ;;       R"delimiter(The String Data" )delimiter"
           ;;       R"delimiter((a-z))delimiter" is equivalent to "(a-z)"
           ("\\(\\<[uU8]*R\"[^\\s-\\\\()]\\{0,16\\}(\\)" 1 font-lock-keyword-face t) ; start delimiter
           (   "\\<[uU8]*R\"[^\\s-\\\\()]\\{0,16\\}(\\(.*?\\))[^\\s-\\\\()]\\{0,16\\}\"" 1 font-lock-string-face t)  ; actual string
           (   "\\<[uU8]*R\"[^\\s-\\\\()]\\{0,16\\}(.*?\\()[^\\s-\\\\()]\\{0,16\\}\"\\)" 1 font-lock-keyword-face t) ; end delimiter

           ;; user-defined types (rather project-specific)
           ("\\<[A-Za-z_]+[A-Za-z_0-9]*_\\(type\\|ptr\\)\\>" . font-lock-type-face)
           ("\\<\\(xstring\\|xchar\\)\\>" . font-lock-type-face)
           ))
    ) t)

In the above implementation of user-defined strings literals, the delimiter tags are marked up separately as font-lock-keyword-face; another option would be font-lock-constant-face. This implementation is not as efficient as it could be; but it works and does not slow down Emacs. Note that the regexps for user-defined strings literals have not been "stolen" from somehere; so I hope they work. Any comments are welcome.

If you like to fontify the whole literal string as font-lock-string-face - including the delimiters - replace the three regexps by just one. Like this one:

    .
    .
("\\<\\([uU8]*R\"[^\\s-\\\\()]\\{0,16\\}(.*?)[^\\s-\\\\()]\\{0,16\\}\"\\)\\>" 1 font-lock-string-face t)

Have fun.



回答4:

Have a look at the package : "Modern C++" font-lock for Emacs. It is also available on Melpa.

Syntax highlighting support for "Modern C++" - until C++17 and Technical Specification. This package aims to provide a simple highlight of the C++ language without dependency.

It is recommended to use it in addition with the c++-mode major mode for extra highlighting (user defined types, functions, etc.) and indentation.

I am the maintainer of this minor mode. Any feedback is appreciated.



回答5:

Replacing Andreas' floating point regexp with this will improve hilighting of floats.

integer/float/scientific literals
("\\<[-+]?[0-9]*\\.?[0-9]+\\([uUlL]+\\|[eE][-+]?[0-9]+\\)?[fFlL]?\\>" . font-lock-constant-face)

Hope that helps someone.



回答6:

For me, the two most pressing pain points with font-locking of modern C++ code have been

  1. the fact that auto is highlighted as a keyword (and not a type) and thus the following identifier would normally not higlight as a variable declaration, and
  2. that highlighting simply goes crazy when presented with some code (for an example, try rtags' src/ClangIndexer.cpp) and then e.g fails to highlight top-level constructs such as function definitions.

After a bit of experimentation, I arrived at a solution that works well for me and addresses both points.

The first one is achieved by modifying lisp/progmodes/cc-langs.el (copying to one's load-path and then modifying also works) to remove "auto" from

(c-lang-defconst c-modifier-kwds
  "Keywords that can prefix normal declarations of identifiers

and add it to c++-font-lock-extra-types (e.g. via Customize).

For the second one, emptying c++-font-lock-extra-types (except for keeping "auto") helps.