2011-10-20 41 views
44

据我所知在Emacs,有没有自定义关闭“>”在C模板列表的性格++的缩进级别的方式。目前我Emacs的压痕方案做到这一点:C++模板和Emacs:自定义缩进

template < 
    typename T1, 
    typename T2, 
    typename T3 
    > 
class X; 

我想是这样的:

template < 
    typename T1, 
    typename T2, 
    typename T3 
> 
class X; 

设置缩进可变模板ARGS-CONT为零将适当缩进“>”字符,但是以代替模板参数列表的实际主体为代价。

emacs guru的任何建议吗?

编辑:

我得到了它有些用下面的黑客工作:

(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 
     '+))) 

,然后设置模板ARGS-CONT缩进的模板在我的自定义主题,鼻翼:

(c-add-style "my-style" 
      '("stroustrup" 
       ;; ... Other stuff ... 
       (template-args-cont . indent-templates)))) 

但它仍然是相当马车。它大部分时间都在工作,但有时候emacs会认为模板列表是一个arglist,然后会出现闹剧,这会让人感到困惑。

+1

我不确定这是否可能,但如果是可以在此页面上找到信息:http://www.gnu.org/software/emacs/manual/html_mono/ccmode.html#Customizing-Indentation – rve

+0

其实,我认为如果你写自己的阵容功能也许是可能的。我之前评论的文件给出了更多关于这方面的信息。 – rve

+6

请注意,Emacs C++模式通常会周期性地对模板参数产生混淆,所以它可能实际上不会成为您代码的问题... [公平地说,实际上很难做到正确,因为它具有多种含义'<' and '>'在C + +(有时作为一个平衡的分隔符,有时作为一个操作符),除非你做了比c + +模式更多的实际解析...] – snogglethorpe

回答

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,它会调用下一个。我所做的是在列表开始处添加一个新的缩进函数,该函数检测行上的第一个非空白字符是否为'>',如果是,则将缩进设置为位置0(它将排列它与开放模板)。这也涵盖了如下模板模板参数的情况:

template < 
    template < 
    typename T, 
    typename U, 
    typename... Args 
    > class... CS 
> 

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

0

这是一种改变选项卡的不同方法,但使用像Yasnippet这样的片段系统(参见示例here)怎么样。

唯一的问题是,如果你重新格式化文档“M-X指数区域”(或部分),它可能会返回到其他标签规则。

1

评论

我想部分遇到的问题是,当你实例化模板,emacs的CC模式具有相同template-args-cont结构看待它。所以,考虑到这一点,我扩展了你的最初想法,并试图使其符合我的喜好;我使代码冗长,希望每个人都能理解我的意图。 :)这应该不会导致实例化时出现问题,并且它似乎也适用于模板模板参数!试试这个,直到有更多Elisp技能的人可以提供更好的解决方案!

如果您遇到任何 '战斗'(即交替或损坏压痕),尝试重新加载cpp文件C-XC-V输入并再次缩进。有时使用模板模板参数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))))) 
+0

哇,谢谢你。如果我有一段时间(在搬家的过程中),我会在周末尝试一下。 – bstamour