5

最近刚开始将 yasnippet 用于 emacs,并且非常喜欢它的工作方式,但是我遇到了一个小麻烦,如果可能的话,我希望得到一些帮助来解决。

我特别喜欢的一个片段是“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-alist ( GNU doc ),我觉得我应该能够以某种方式使用它。但是我从来没有真正在 elisp 中进行过任何编程,而且我不确定如何实现这一点。任何帮助或建议将不胜感激!

4

2 回答 2

2

这是一个建议:

  1. 定义一个变量来保存当前的编码风格:

    (setq current-coding-style 'default)
    
  2. 定义一个命令以在默认样式和新项目中使用的样式之间切换,并将其绑定到您选择的键序列:

    (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
    
  3. 定义一个根据当前“活动”的编码样式放置左大括号的函数:

    (defun place-brace ()
      (if (eq current-coding-style 'default) " {" "\n{"))
    
  4. 将代码片段中的左大括号替换for为对该函数的调用(如此所述,可以通过将任意 Elisp 代码用反引号括起来将其嵌入到代码片段中):

    # -*- mode: snippet -*-
    # name: for
    # key: for
    # --
    for (${1:i = 0}; ${2:i < N}; ${3:i++})`(place-brace)`
        $0
    }
    

有了这个,您在编码样式(和相应的代码片段扩展)之间切换所需要做的就是 press C-c t

于 2014-09-20T21:06:13.470 回答
0

我最近也想知道如何以一种不那么侵入性和更通用的方式做到这一点,幸运的是,我在 yasnippet 项目上发现了一个关于此的问题: 将片段转换为您的大括号样式·问题 #728·joaotavora/yasnippet - github.com

简而言之,维护者建议使用yas-after-exit-snippet-hook它来实现它,这是我在它之后提出的:

;; 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 ")[ \t\r\n]*{" 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)))))

希望这可能会有所帮助。

于 2018-04-23T17:32:37.120 回答