Emacs缩进C ++ 11 lambda函数(cc模式)

时间:2014-05-08 22:46:24

标签: c++ c++11 emacs indentation

默认的Emacs C ++模式(cc-mode)仍然无法识别许多C ++ 11功能。 一个恼人的问题是它对使用的lambda函数应用了太多的缩进 作为功​​能参数:

std::vector<int> ar(4);
std::generate_n(std::begin(ar), 4, [] {
        static int g_i;
        return g_i++;
    });
std::for_each(std::begin(ar), std::end(ar), [](int i) {
        std::cout << " " << i;
    });
bool b = std::is_sorted(std::begin(ar), std::end(ar), [&](int l, int r) {
        return l<r;
    });
std::cout << "   " << b << "\n";

理想情况下,人们更愿意:

std::vector<int> ar(4);
std::generate_n(std::begin(ar), 4, [] {
    static int g_i;
    return g_i++;
});
std::for_each(std::begin(ar), std::end(ar), [](int i) {
    std::cout << " " << i;
});
bool b = std::is_sorted(std::begin(ar), std::end(ar), [&](int l, int r) {
    return l<r;
});
std::cout << "   " << b << "\n";

对此有好的解决方案吗?

3 个答案:

答案 0 :(得分:15)

Emacs cc-mode indentation problem with C++0x enum class中的讨论修复了enum class 格式化问题。

这启发了以下建议功能。它检测到一个开放的C ++ lambda函数 在一个开放的参数列表中,取消一个级别的缩进以在问题中产生“理想”结果:

(defadvice c-lineup-arglist (around my activate)
  "Improve indentation of continued C++11 lambda function opened as argument."
  (setq ad-return-value
        (if (and (equal major-mode 'c++-mode)
                 (ignore-errors
                   (save-excursion
                     (goto-char (c-langelem-pos langelem))
                     ;; Detect "[...](" or "[...]{". preceded by "," or "(",
                     ;;   and with unclosed brace.
                     (looking-at ".*[(,][ \t]*\\[[^]]*\\][ \t]*[({][^}]*$"))))
            0                           ; no additional indent
          ad-do-it)))                   ; default behavior

答案 1 :(得分:6)

在Emacs26中,接受的答案对我不起作用了。我只是将'inlambda'设置为0。

  (c-offsets-alist . ((case-label . 0)
                      (inline-open . 0)
                      (substatement-open . 0)
                      (inlambda . 0) ; no extra indent for lambda
                      (block-open . 0) ; no space before {
                      (knr-argdecl-intro . -)))

答案 2 :(得分:4)

稍微修改Hugues的解决方案,将lambda函数识别为嵌套在另一个lambda函数中的参数,将lambda函数识别为类内初始化值:

(defun vr-c++-looking-at-lambda_as_param ()
  "Return t if text after point matches '[...](' or '[...]{'"
  (looking-at ".*[,(][ \t]*\\[[^]]*\\][ \t]*[({][^}]*?[ \t]*[({][^}]*?$"))

(defun vr-c++-looking-at-lambda_in_uniform_init ()
  "Return t if text after point matches '{[...](' or '{[...]{'"
  (looking-at ".*{[ \t]*\\[[^]]*\\][ \t]*[({][^}]*?[ \t]*[({][^}]*?$"))

(defun vr-c++-indentation-examine (langelem looking-at-p)
  (and (equal major-mode 'c++-mode)
       (ignore-errors
         (save-excursion
           (goto-char (c-langelem-pos langelem))
           (funcall looking-at-p)))))

(defun vr-c++-indentation-setup ()
  (require 'google-c-style)
  (google-set-c-style)

  (c-set-offset
   'block-close
   (lambda (langelem)
     (if (vr-c++-indentation-examine
          langelem
          #'vr-c++-looking-at-lambda_in_uniform_init)
         '-
       0)))

  (c-set-offset
   'statement-block-intro
   (lambda (langelem)
     (if (vr-c++-indentation-examine
          langelem
          #'vr-c++-looking-at-lambda_in_uniform_init)
         0
       '+)))

  (defadvice c-lineup-arglist (around my activate)
    "Improve indentation of continued C++11 lambda function opened as argument."
    (setq ad-return-value
          (if (vr-c++-indentation-examine
               langelem
               #'vr-c++-looking-at-lambda_as_param)
              0
            ad-do-it))))