使用yasnippet进行框式注释

时间:2010-12-30 15:22:58

标签: emacs elisp code-snippets

我正在寻找一个yasnippet模板,允许我将许可证标头添加到Emacs中的脚本缓冲区。有点像this,但有点改进:

  1. 标题需要包含每用户数据,例如版权所有者的日期名称和电子邮件, 可以使用yasnippet中的embedded elisp expansion获得。
  2. 标题需要使用语法进行注释,具体取决于文件当前所处的编程模式。已经a gist of a snippet that does all that。基本上它相当于在代码段的末尾嵌入(comment-region (point-min) (point))
  3. 现在,我想将评论风格更改为方框。请参阅有关comment-style变量的emacs文档,或者,如果您想查看框式评论的内容,只需在活动区域​​上调用M-x comment-box:它会调用comment-region正确的选择。
  4. 这样做的第一种方法是通过修改上一个代码段的结尾来设置样式:

    (let ((comment-style 'box))
                (comment-region (point-min) (point)))
    

    不幸的是,缩进被搞砸了,我的盒子不是矩形。如果我从片段开始:

    Copyright (c) ${1:`(nth 5 (decode-time))`}
    All rights reserved.
    
    Redistribution and use in source and binary forms, with or
    without modification, are permitted`
          (let ((comment-style 'box))
                (comment-region (point-min) (point)))`
    

    该片段的扩展“打破了方块”(我正在使用ocaml注释语法调试此片段,而不是它应该重要):

    (**************************************************************)
    (* Copyright (c) 2010                                    *)
    (* All rights reserved.                                       *)
    (*                                                            *)
    (* Redistribution and use in source and binary forms, with or *)
    (* without modification, are permitted     *)
    (**************************************************************)
    
    • 起初我认为第二行是根据预扩展嵌入代码的大小缩进的,但在这种情况下,它应该使该行的最后*)过早地为25个空格,而不是4 。
    • 如果它基于嵌入点上的 no 文本缩进,则最终*)也应该到达的4个空格,而不是很快
    • 最后,我不明白最后一行发生了什么,其中没有嵌入式代码扩展:通常我从段落中获取方形注释框没有任何问题最后一行(使用comment-box)或此问题的第一个注释块中的elisp函数。

    我尝试在代码段扩展后发布评论,以避免任何副作用,将其添加到yas/after-exit-snippet-hook,将上面代码段的最后一个函数替换为:

    (add-hook 'yas/after-exit-snippet-hook
          (let ((comment-style 'box))
                (comment-region (point-min) (point))) nil t)
    

    但这没有帮助。即使它确实如此,它也会给我留下一个扩展钩子,它会评论所有我希望在该缓冲区中使用的片段,这是我当然不想要的。

    我还应该补充一点,我尝试通过添加

    yas/indent-line设置为fixed
    # expand-env: ((yas/indent-line 'fixed))
    

    在我的代码段的开头,但没有改变任何东西。关于如何获得矩形框的任何想法?


    编辑:我们有a very nice answer, along with a proposed fix,(荣誉和谢谢,Seiji!)但是仍有一个问题是如何使其适应人们希望重用某个字段的情况,比如说比如在{:1>中重用$1

    Copyright (c) ${1:`(nth 5 (decode-time))`}
    All rights reserved.
    
    Redistribution and use in $1, in source and binary forms
    `(let ((comment-style 'box))
            (comment-region (point-min) (point-at-eol 0)))`
    

    在这种情况下,模板引擎将为字段$1获取的(可变长度)值(即2011)复制到最后一行,模板扩展(缩进后),给出注释第2行字符太宽。在编写模板时,很难预测在此行应该删除 4 字符。也许字段重用正确的缩进太多,无法同时要求。有没有人看到这样做的方法呢?

3 个答案:

答案 0 :(得分:5)

将您的代码段更改为此代码会修复最后一行。

Copyright (c) ${1:`(nth 5 (decode-time))`}
All rights reserved.

Redistribution and use in source and binary forms, with or
without modification, are permitted
`(let ((comment-style 'box))(comment-region (point-min) (point-at-eol 0)))`

请注意,许可证(“允许”)和嵌入式emacs lisp代码之间存在换行符。

关于第二行,我将首先解释为什么会发生这种情况,然后提供(丑陋的)修复。将代码段插入文件后,将从缓冲区的开头到结尾依次评估嵌入的lisp块。在您的代码段中,这意味着(nth 5 (decode-time))在评估下一个块2011时已被(comment-region ...)替换。

因此,comment-region将第二行视为

Copyright (c) ${1:2011}

因此,comment-region为此字符串添加了足够的空格。然后,模板引擎将${1:2011}转换为2011,此转换将字符串缩短5个字符。这解释了第二行中*)过早出现5个字符。

解决这种情况的一种方法是在评估comment-region之后再放回5个空格 - 以下内容:

Copyright (c) ${1:`(nth 5 (decode-time))`} @
All rights reserved.

Redistribution and use in source and binary forms, with or
without modification, are permitted.
`(let ((comment-style 'box))(comment-region (point-min) (point-at-eol 0)))``
(replace-string "@" "      " nil (point-min) (point))`$0

答案 1 :(得分:1)

这可能会对您有所帮助:

# -*- mode: snippet -*-
# name: param
# key:  param
# --
m.parameter :${1:arg},${1:$(make-string (- 14 (string-width text)) ?\ 
                         )}:${2:type}$>

它使用带有函数的镜像来创建定位空白。所以,对你而言,这可能意味着这样的事情:

(* Copyright (c) ${1:2011}${1:$(make-string (- 72 (string-width text)) ?\ )} *)
(* ${2}${2:$(make-string (- 72 (string-width text)))}*)

另一种选择可能是使用yas/after-exit-snippet-hook,但似乎已弃用。 (哦,我的意思是自己过滤文本,你已经尝试过的评论区域更聪明。尝试缩进区域?)

答案 2 :(得分:0)

这对我有用:

# -*- mode: snippet -*-
# name: box comment block
# key: bbox
# expand-env: ((yas-after-exit-snippet-hook (lambda () (if (buffer-substring yas-snippet-beg yas-snippet-end) (comment-box yas-snippet-beg yas-snippet-end 1)))))
# --
Copyright (c) ${1:`(nth 5 (decode-time))`}
All rights reserved.

Redistribution and use in source and binary forms, with or
without modification, are permitted
$0

我在此问题中提到了信息Run function after specific snippet