[求助] 在C/C++ mode 下如何使得冒号(:)不影响缩进?

在Emacs 中写 C/C++ 代码,每次输入std: 的时候,当前行都会向左缩进,输入完第二个:的时候才会向右缩进。请问下怎么设置才能使得输入:的时候不缩进?

1 个赞

输入第一分号的时候,应该是被假定成函数的label来缩进了(加上默认开了electric-indent-mode,会自动缩进)

electric-indent-mode应该会比较不方便,不考虑这个,其他几个方案:

1、习惯这个行为,最简单的,我自己是不怎么在意这个行为的。

2、在c++-mode-map里面unbind掉分号的绑定

(with-eval-after-load 'cc-mode
  (define-key c++-mode-map
    ":" nil))

缺点:在部分情况下要自己手动缩进下,比如输入函数label、access specifier等的时候,可能还是比较容易忘的,你要是每次在保存的时候或者其他特定的时间点都会自动用formtter格式化代码倒还好。

为了解决这个缺点,可以选择像Visual Studio一样,在回车的时候,自动连前一行顺便一起格式化一下,在24.4以前的Emacs,cc-mode本来就会这么做,后面改了,具体原因你可以在cc-mode.el中搜索下electric-indent-inhibit,这里可以简单地搞个advice,完整的:

(with-eval-after-load 'cc-mode
  (define-key c++-mode-map
    ":" nil)
  (define-advice newline (:after (&rest _))
    ;; 顺便检查下electric-indent-mode,一般关了的用户不会想在回车的时候自动缩进前一行
    (when (and (derived-mode-p 'c++-mode) (bound-and-true-p electric-indent-mode))
      (save-excursion
        (previous-line)
        (c-indent-line)))))

evil-mode的用户如果想在按下o的时候也有这个行为,可以给evil-open-below也advice下:

(with-eval-after-load 'cc-mode
  (define-key c++-mode-map
    ":" nil)

  (defun my/cc-newline-and-indent-previous-line (&rest _)
    (when (and (derived-mode-p 'c++-mode) (bound-and-true-p electric-indent-mode))
      (save-excursion
        (previous-line)
        (c-indent-line))))

  (advice-add #'newline :after #'my/cc-newline-and-indent-previous-line)
  (advice-add #'evil-open-below :after #'my/cc-newline-and-indent-previous-line))

参考文章:[https://www.reddit.com/r/emacs/comments/fyl092/c_std_vs_electricindentmode/](C++ std:: V.S. electric-indent-mode)

4 个赞

多谢解答。用你的方法可以实现在std::的时候补全窗口不再跳来跳去了😄。

我也看了 cc-mode 的wiki,上面的提供的一个microsft的一个格式, 其中的 (innamespace . -) 不知道是不是处理这个问题的,但我设置了不生效。

 (c-add-style "microsoft"
              '("stroustrup"
                (c-offsets-alist
                 (innamespace . -)
                 (inline-open . 0)
                 (inher-cont . c-lineup-multi-inher)
                 (arglist-cont-nonempty . +)
                 (template-args-cont . +))))
 (setq c-default-style "microsoft")

innamespace 设置的是在namespace块中的缩进,符号-表示在当前正常缩进值的基础上减c-basic-offset的缩进值作为最终缩进值,这应该不是你想要的。

比如

namespace {
// 正常在这里,google style的缩进值是0,如果设置成-,那么计算出来的缩进值会是-2(假设c-basic-offset是2),然而这里都在最左侧了,缩进还是负值,没地方往左边缩了,就没用
}
1 个赞

还有一个办法是尝试 Ecb。大概八年前我用 Ecb 的时候没有出现类似的问题,多年未用,不能保证现在一定不会出类似问题。