C++模板和Emacs:自定义缩进

bst*_*our 44 c++ emacs

据我所知,在emacs中,没有办法在C++中自定义模板列表的结束'>'字符的缩进级别.目前我的emacs缩进方案执行此操作:

template <
    typename T1,
    typename T2,
    typename T3
    >
class X;
Run Code Online (Sandbox Code Playgroud)

我想要的是这样的:

template <
    typename T1,
    typename T2,
    typename T3
>
class X;
Run Code Online (Sandbox Code Playgroud)

将indent变量template-args-cont设置为零将正确缩进'>'字符,但代价是unindenting模板参数列表的实际主体.

来自emacs大师的任何建议吗?

编辑:

我有点使用以下hack:

(defun indent-templates (elem)
  (c-langelem-col elem t)
  (let ((current-line
         (buffer-substring-no-properties
          (point-at-bol) (point-at-eol))))
    (if (string-match-p "^\\s-*>" current-line)
        0
        '+)))
Run Code Online (Sandbox Code Playgroud)

然后在我的自定义主题中将template-args-cont设置为indent-templates,ala:

(c-add-style "my-style"
             '("stroustrup"
                ;; ... Other stuff ...
                (template-args-cont . indent-templates))))
Run Code Online (Sandbox Code Playgroud)

但它仍然很漂亮.它大部分时间都可以工作,但有时emacs会因为认为模板列表是arglist而感到困惑,然后就会出现欢闹.

m-r*_*aud 2

我发现的最佳解决方案是编写一个自定义(且相对简单)的缩进函数。

代码

(defun c++-template-args-cont (langelem)
"Control indentation of template parameters handling the special case of '>'.
Possible Values:
0   : The first non-ws character is '>'. Line it up under 'template'.
nil : Otherwise, return nil and run next lineup function."
  (save-excursion
    (beginning-of-line)
    (if (re-search-forward "^[\t ]*>" (line-end-position) t)
        0)))

(add-hook 'c++-mode-hook
          (lambda ()
            (c-set-offset 'template-args-cont
                          '(c++-template-args-cont c-lineup-template-args +))))
Run Code Online (Sandbox Code Playgroud)

这可以处理我遇到的所有情况,即使模板嵌套了几层深度。

怎么运行的

对于缩进代码,如果提供了缩进函数列表,那么 Emacs 将按顺序尝试它们,如果当前正在执行的函数返回nil,它将调用下一个。我所做的就是在列表的开头添加一个新的缩进函数,该函数检测该行上的第一个非空白字符是否为“>”,如果是,则将缩进设置为位置 0(这会将其对齐)与打开模板)。这也涵盖了具有模板-模板参数的情况,如下所示:

template <
  template <
    typename T,
    typename U,
    typename... Args
  > class... CS
>
Run Code Online (Sandbox Code Playgroud)

因为它不关心“>”后面的内容。因此,根据缩进函数列表的工作原理,如果“>”不是第一个字符,该函数将返回nil并调用通常的缩进函数。