从clang格式样式中提取emacs c样式选项

问题描述 投票:4回答:2

一位同事为我提供了一个我们正在研究的C ++项目的clang格式样式文件。我安装了clang-format.el,以便能够从emacs格式化缓冲区。重新格式化按预期工作。但是,Emacs默认的c-mode缩进仍然完全不同。

我发现在编辑时破坏源代码格式并在以后恢复时非常令人不安。有没有办法读取clang格式文件并应用相应的cc模式选项?

c++ emacs formatting clang clang-format
2个回答
2
投票

我不知道是否有任何直接转换工具。但是,您可以尝试使用以下技巧:

  1. 将项目中相当数量的C ++文件连接成单个文件(例如cat *.cpp > single.cpp
  2. 将clang格式应用于single.cpp
  3. 在Emacs中打开single.cpp
  4. 使用CC模式的guess功能:M-x c-guess-no-install然后M-x c-guess-view

0
投票

我参加聚会有点晚了,但希望有人仍然觉得这个有用。我在下面发布了我的clang-format配置的相关部分,它提供了你想要的功能。

(use-package clang-format
  :after (s)
  :init
  (defun get-clang-format-option (config-str field is-num)
    "Retrieve a config option from a clang-format config.

CONFIG-STR is a string containing the entire clang-format config.
FIELD is specific option, e.g. `IndentWidth'.  IS-NUM is a
boolean that should be set to 1 if the option is numeric,
otherwise assumed alphabetic."
    (if is-num
        (let ((primary-match (s-match (concat "^" field ":[ \t]*[0-9]+") config-str)))
          (if primary-match
              (string-to-number (car (s-match "[0-9]+" (car primary-match))))
            0))
      (let ((primary-match (s-match (concat "^" field ":[ \t]*[A-Za-z]+") config-str)))
        (if primary-match
            (car (s-match "[A-Za-z]+$" (car primary-match)))
          ""))))
  :hook (c-mode-common . (lambda ()
                           (let* ((clang-format-config
                                   (shell-command-to-string "clang-format -dump-config"))
                                  (c-offset (get-clang-format-option clang-format-config "IndentWidth" t))
                                  (tabs-str (get-clang-format-option clang-format-config "UseTab" nil))
                                  (base-style
                                   (get-clang-format-option clang-format-config "BasedOnStyle" nil)))
                             (progn
                               (if (> c-offset 0)
                                   (setq-local c-basic-offset c-offset)
                                 (if (not (equal "" base-style))
                                     (cond ((or (equal "LLVM" base-style)
                                                (equal "Google" base-style)
                                                (equal "Chromium" base-style)
                                                (equal "Mozilla" base-style))
                                            (setq-local c-basic-offset 2))
                                           ((equal "WebKit" base-style)
                                            (setq-local c-basic-offset 4)))))
                               (if (not (equal "" tabs-str))
                                   (if (not (string-equal "Never" tabs-str))
                                       (setq-local indent-tabs-mode t)
                                     (setq-local indent-tabs-mode nil))
                                 (if (not (equal "" base-style))
                                     (cond ((or (equal "LLVM" base-style)
                                                (equal "Google" base-style)
                                                (equal "Chromium" base-style)
                                                (equal "Mozilla" base-style)
                                                (equal "WebKit" base-style))
                                            (setq-local indent-tabs-mode nil))))))))))

我用use-package。如果不这样做,则必须进行一些小的调整。另外,请注意我使用s.el进行字符串操作。

代码查找“IndentWidth”和“UseTab”。如果它找到“UseTab”并且未设置为“Never”,我将indent-tabs-mode设置为t。否则我把它设置为nil。 “IndentWidth”的值转到c-basic-offset。如果找不到这些字段,但找到“BasedOnStyle”,则根据该样式设置适当的值。我没有包含Microsoft样式,因为我的clang-format版本不会给我一个配置转储(可能是在更高版本中)。 “IndentWidth”和“UseTab”覆盖了“BasedOnStyle”的行为,符合clang-format的行为。最后,请注意c-basic-offsetindent-tabs-mode被设置为缓冲区局部变量,因此在处理具有不同配置的多个文件时,此设置可按预期工作。

© www.soinside.com 2019 - 2024. All rights reserved.