【问题标题】:box-style comments with yasnippet带有 yasnippet 的框式注释
【发布时间】:2011-06-01 14:48:47
【问题描述】:

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

  1. 标题需要包含每个用户的数据,例如版权所有者的日期名称和电子邮件, 可以使用来自 yasn-p 的embedded elisp expansion 获得。
  2. 需要根据文件当前所处的编程模式使用语法注释标题。已经有a gist of a snippet that does all that。基本上它相当于在你的 sn-p 末尾嵌入(comment-region (point-min) (point))
  3. 现在,我想将评论样式更改为方框。请参阅 comment-style 变量的 emacs 文档,或者,如果您想查看框式注释的外观,只需在活动区域​​上调用 M-x comment-box:它使用正确的选项调用 comment-region

第一种方法是通过修改前一个 sn-p 的结尾来设置样式:

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

不幸的是,压痕搞砸了,我的盒子不是矩形。如果我从sn-p开始:

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)))`

那个sn-p的扩展“打破了盒子”(我正在用ocaml注释语法调试这个sn-p,这并不重要):

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

我尝试在 sn-p 扩展之后进行注释,以避免任何副作用,将其添加到 yas/after-exit-snippet-hook,将上面 sn-p 的最后一个函数替换为:

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

但这并没有帮助。即使是这样,它也会给我留下一个扩展钩子,它会注释 all 我想在该缓冲区中使用的 sn-ps,这是我当然不想要的。

我还应该补充一点,我尝试通过添加将yas/indent-line 设置为fixed

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

在我的 sn-p 开头,但这并没有改变任何东西。关于如何获得矩形框的任何想法?


编辑:我们有 a very nice answer, along with a proposed fix,(感谢 Seiji !),但仍然存在一个问题,即如何使其适应想要重用字段的情况,比如重用$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 个字符。也许字段重用正确的缩进太多了,不能同时要求。不过,有没有人看到一种方法来做到这一点?

【问题讨论】:

    标签: emacs elisp code-snippets


    【解决方案1】:

    这对我有用:

    # -*- 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

    【讨论】:

      【解决方案2】:

      将您的 sn-p 更改为这个可以修复最后一行。

      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 代码之间有一个换行符。

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

      因此,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
      

      【讨论】:

      • 感谢point-at-eol 的建议,它彻底解决了最后一行的问题。 很好的解释,谢谢。您的修复工作有效,但是将其推广到一行中的许多字段(您必须手动计算每个模板的样板)是很痛苦的,并且不可能扩展到 $1 其他地方的字段的 reuse模板(您必须在其中 删除 与创建的嵌入式 lisp 的评估一样多的空格)。我会等一会儿,如果没有人提出解决方案,我会“接受”你的回答。
      • 我同意我对第二行的解决方案不是最理想的。如果yas/after-exit-snipeet-hook 可以处理我们看到的文本,那就太好了。但是,该钩子似乎适用于底层文本(例如${1:...})。顺便说一句,如果你在# expand-env中设置了钩子,钩子只会影响sn-p而不影响其他sn-ps ---通过添加# expand-env: ((yas/after-exit-snippet-hook (list (let ((comment-style 'box))(comment-region (point-min) (point-max) nil)))))
      【解决方案3】:

      这可能对你有些用处:

      # -*- 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,但这似乎已被弃用。 (哦,我的意思是自己过滤文本,你已经尝试过的评论区域更聪明。试试缩进区域?)

      【讨论】:

      • 这很聪明,但不幸的是,正如Seiji's answer中解释的那样,模板引擎会在执行块之后替换字段,这意味着@插入的空格987654325@ 是 5 个字符的两倍短(${1:}${1:})。 (感谢钩子的建议,但我已经在原始问题中提到了我不成功的尝试)
      猜你喜欢
      • 2017-10-17
      • 1970-01-01
      • 1970-01-01
      • 2019-09-16
      • 2016-07-19
      • 2012-12-06
      • 2019-12-08
      • 2011-03-24
      • 1970-01-01
      相关资源
      最近更新 更多