据我所知,在emacs中,没有办法自定义结束'>'的缩进级别C ++中模板列表的字符。目前我的emacs缩进方案执行此操作:
template <
typename T1,
typename T2,
typename T3
>
class X;
我想要的是这样的:
template <
typename T1,
typename T2,
typename T3
>
class X;
将缩进变量template-args-cont设置为零将缩进'&gt;'正确的角色,但代价是取消模板参数列表的实际主体。
来自emacs大师的任何建议吗?
修改
我对以下黑客有所帮助:
(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
'+)))
然后在我的自定义主题中将template-args-cont设置为indent-templates,ala:
(c-add-style "my-style"
'("stroustrup"
;; ... Other stuff ...
(template-args-cont . indent-templates))))
但它仍然很漂亮。它大部分时间都可以工作,但有时emacs会因为模板列表是一个arglist而感到困惑,然后就会出现欢闹。
答案 0 :(得分: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 +))))
这可以处理我遇到的所有情况,即使模板嵌套了几层深层。
如何运作
对于缩进代码,如果提供了缩进函数列表,那么Emacs将按顺序尝试它们,如果当前正在执行的那个返回nil
,它将调用下一个。{1}。我所做的是在列表的开头添加一个新的缩进函数,用于检测该行上的第一个非空格字符是否为'&gt;',如果是,则将缩进设置为位置0(将对其进行排列)打开模板)。这还包括您具有模板模板参数的情况,如下所示:
template <
template <
typename T,
typename U,
typename... Args
> class... CS
>
因为它并不关心“&gt;”之后的内容。因此,缩进函数列表的工作原理如果'&gt;'不是第一个字符,函数返回nil
并调用通常的缩进函数。
答案 1 :(得分:1)
我认为部分您遇到的问题是,当您实例化模板时,emacs CC模式会使用相同的template-args-cont
结构查看它。所以,考虑到这一点,我扩展了你原来的想法,并试图让它符合我的喜好;我使代码冗长,希望每个人都能理解我的意图。 :)当你实例化时,这不应该导致问题,它似乎也适用于模板模板参数!试试这个,直到有更多Elisp技能的人可以提供更好的解决方案!
如果您遇到任何“打斗”(即交替或损坏的缩进),请尝试重新加载cpp文件 Cx Cv 输入并再次缩进。有时使用模板模板参数,emacs会将内部参数显示为arglist-cont-nonempty
,甚至可以使用template-args-const
来回切换,但重新加载始终会恢复状态。
要执行您想要的操作,请使用以下代码并添加到c-offsets-alist
条目中来尝试此操作:
(template-args-cont . brian-c-lineup-template-args)
并设置变量
(setq brian-c-lineup-template-closebracket t)
我实际上更喜欢稍微不同的对齐方式:
(setq brian-c-lineup-template-closebracket 'under)
(defvar brian-c-lineup-template-closebracket 'under
"Control the indentation of the closing template bracket, >.
Possible values and consequences:
'under : Align directly under (same column) the opening bracket.
t : Align at the beginning of the line (or current indentation level.
nil : Align at the same column of previous types (e.g. col of class T).")
(defun brian-c-lineup-template--closebracket-p ()
"Return t if the line contains only a template close bracket, >."
(save-excursion
(beginning-of-line)
;; Check if this line is empty except for the trailing bracket, >
(looking-at (rx (zero-or-more blank)
">"
(zero-or-more blank)))))
(defun brian-c-lineup-template--pos-to-col (pos)
(save-excursion
(goto-char pos)
(current-column)))
(defun brian-c-lineup-template--calc-open-bracket-pos (langelem)
"Calculate the position of a template declaration opening bracket via LANGELEM."
(save-excursion
(c-with-syntax-table c++-template-syntax-table
(goto-char (c-langelem-pos langelem))
(1- (re-search-forward "<" (point-max) 'move)))))
(defun brian-c-lineup-template--calc-indent-offset (ob-pos)
"Calculate the indentation offset for lining up types given the opening
bracket position, OB-POS."
(save-excursion
(c-with-syntax-table c++-template-syntax-table
;; Move past the opening bracket, and check for types (basically not space)
;; if types are on the same line, use their starting column for indentation.
(goto-char (1+ ob-pos))
(cond ((re-search-forward (rx
(or "class"
"typename"
(one-or-more (not blank))))
(c-point 'eol)
'move)
(goto-char (match-beginning 0))
(current-column))
(t
(back-to-indentation)
(+ c-basic-offset (current-column)))))))
(defun brian-c-lineup-template-args (langelem)
"Align template arguments and the closing bracket in a semi-custom manner."
(let* ((ob-pos (brian-c-lineup-template--calc-open-bracket-pos langelem))
(ob-col (brian-c-lineup-template--pos-to-col ob-pos))
(offset (brian-c-lineup-template--calc-indent-offset ob-pos)))
;; Optional check for a line consisting of only a closebracket and
;; line it up either at the start of indentation, or underneath the
;; column of the opening bracket
(cond ((and brian-c-lineup-template-closebracket
(brian-c-lineup-template--closebracket-p))
(cond ((eq brian-c-lineup-template-closebracket 'under)
(vector ob-col))
(t
0)))
(t
(vector offset)))))
答案 2 :(得分:0)