使用yasnippet进行框式注释

hui*_*ker 6 emacs elisp code-snippets

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

  1. 标题需要包括每用户数据,例如版权所有者的日期名称和电子邮件,可以通过yasnippet的嵌入式elisp扩展获得.
  2. 标题需要使用语法进行注释,具体取决于文件当前所处的编程模式.已经有一个片段的要点可以完成所有这些操作.基本上它等于嵌入(comment-region (point-min) (point))在你的代码片段的末尾.
  3. 现在,我想将注释样式更改为一个框.请参阅emacs文档以获取comment-style变量,或者,如果您想查看框样式注释的样子,只需调用M-x comment-box活动区域:它comment-region使用正确的选项进行调用.

第一种方法是通过将上一个代码段的末尾修改为:来设置样式:

(let ((comment-style 'box))
            (comment-region (point-min) (point)))
Run Code Online (Sandbox Code Playgroud)

不幸的是,压痕搞砸了,我的盒子不是矩形的.如果我从片段开始:

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)))`
Run Code Online (Sandbox Code Playgroud)

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

(**************************************************************)
(* Copyright (c) 2010                                    *)
(* All rights reserved.                                       *)
(*                                                            *)
(* Redistribution and use in source and binary forms, with or *)
(* without modification, are permitted     *)
(**************************************************************)
Run Code Online (Sandbox Code Playgroud)
  • 起初我认为第二行是根据预扩展嵌入代码的大小缩进的,但在这种情况下,它应该使该*)行的最后一个太快来25个空格,而不是4个.
  • 如果缩进基于文本存在于嵌入点,最终*)应该到达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)
Run Code Online (Sandbox Code Playgroud)

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

我还要补充一点,我试图设置yas/indent-linefixed,通过增加

# expand-env: ((yas/indent-line 'fixed))
Run Code Online (Sandbox Code Playgroud)

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


编辑:我们有一个非常好的答案,以及一个建议的修复,(荣誉和感谢,Seiji!)但问题仍然是如何使其适应人们希望重用一个字段的情况,比如重用$1in :

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)))`
Run Code Online (Sandbox Code Playgroud)

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

Sei*_*gai 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)))`
Run Code Online (Sandbox Code Playgroud)

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

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

结果,comment-region将第二行视为

Copyright (c) ${1:2011}
Run Code Online (Sandbox Code Playgroud)

因此,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
Run Code Online (Sandbox Code Playgroud)