最近刚开始在emacs中使用yasnippet,我非常喜欢它的工作方式,但我遇到了一个小麻烦,如果可能的话,我希望得到一些帮助来解决。
我特别喜欢的一个片段是"for"-片段,即:
# -*- mode: snippet -*-
# name: for
# key: for
# --
for (${1:i = 0}; ${2:i < N}; ${3:i++}) {
$0
}
然而,我最近开始做一个项目,我们有一个不同的编码风格。简单地说,上面的代码片段将被更改为将起始大括号位置放为:
# -*- mode: snippet -*-
# name: for
# key: for
# --
for (${1:i = 0}; ${2:i < N}; ${3:i++})
{
$0
}
然而,我想在不同的项目之间轻松切换,从而在不同的编码风格之间切换,而不必手动更改片段或创建许多重复项。因此,我认为应该可以在代码片段中编写一些elisp代码,以自动适应当前活动的编码风格。
环顾一些Emacs/elisp文档,我发现了所谓的c-hanging-brace-list(GNU文档),我觉得我应该能够以某种方式使用它。然而,我从来没有真正在elisp中做过任何编程,我也不确定如何实现这一点。如有任何帮助或建议,我们将不胜感激!
这里有一个建议:
-
定义一个变量以保持当前编码样式:
(setq current-coding-style 'default)
-
定义一个命令,在默认样式和新项目中使用的样式之间切换,并将其绑定到您选择的关键序列:
(defun toggle-coding-style () (interactive) (if (eq current-coding-style 'default) (setq current-coding-style 'special) (setq current-coding-style 'default))) (global-set-key (kbd "C-c t") 'toggle-coding-style) ;; Replace C-c t ;; with another binding ;; if you like
-
定义一个函数,根据当前"活动"的编码样式放置左大括号:
(defun place-brace () (if (eq current-coding-style 'default) " {" "n{"))
-
用对该函数的调用替换
for
代码段中的大括号(如本文所述,可以通过将任意Elisp代码括在后引号中将其嵌入代码段中):# -*- mode: snippet -*- # name: for # key: for # -- for (${1:i = 0}; ${2:i < N}; ${3:i++})`(place-brace)` $0 }
有了这一点,您只需按C-ct即可在编码样式(和相应的代码段扩展)之间切换。
最近我还想知道如何以一种侵入性较小、更通用的方式来实现这一点,幸运的是,我在yasnippet项目上发现了一个关于这方面的问题:将片段转换为你的大括号风格·问题#728·joaotavora/yasnippet-github.com
总之,维护人员建议使用CCD_ 2来实现它,以下是我在它之后想到的:
;; https://en.wikipedia.org/wiki/Indentation_style
;; auto/allman/k&r
(setq my-yasnippet-brace-style 'auto)
;; see https://github.com/joaotavora/yasnippet/issues/728
(setq yas-after-exit-snippet-hook
#'(lambda ()
(let* ((begin yas-snippet-beg)
(end yas-snippet-end)
(snippet (buffer-substring-no-properties begin end))
(point (point))
rep
new-snippet)
(unless (eq 'auto my-yasnippet-brace-style)
(setq rep (case my-yasnippet-brace-style
('allman ")n{")
(('k&r t) ") {")))
(setq new-snippet (replace-regexp-in-string ")[ trn]*{" rep snippet))
(delete-region begin end)
(insert new-snippet)
;; XXX what's the proper way to retain point? save-excursion doesn't work.
(goto-char (+ point (- (length new-snippet) (length snippet))))
(indent-region begin end)))))
希望这能有所帮助。