在 Emacs 里如何实现类似 Intellij 的后缀模版展开?

在 Intellij 系的 IDE 里,这种 Live Template 很常见:

Kooha-03-20-2022-20-35-39

目前已知的是灵感来自 Intellij Rust 的 rust-analyzer 这种语言服务器也实现了这个功能,如:

Kooha-03-20-2022-20-43-40

我想问一下有没有 Emacs 的原生插件支持这样的模板展开方式?

才疏学浅,看不出来和yasnippet有什么不同QwQ……

哦有一个替换

我记得emacs自带有一个方式可以用elisp代码做展开的,可以实现这样的功能。稍等我找找

最明显的区别就是在模板展开时可以根据上下文自动填充模板的参数,并且删除展开前的代码

这里:

也是坛子里一个帖子提到的awa

用它写个宏大概就可以啦 :partying_face:

内嵌 S 表达式这个好像 yasnippet 也可以做到。如果没有现成的,我就自己研究一下了,看看能不能为 yasnippet 写个扩展用于方便地实现这种风格的模板展开

1 个赞

yasnippet 中可以加 elisp, 用 tree-sitter 去获取上文?

不过对我来说没必要,定位就够了,更喜欢手动挡

内嵌elisp的snippet,

能内嵌elisp就够了,自己想加什么功能都可以加.

2 个赞

好像不支持后缀展开, word.var 无法触发 yas 补全

不必拘泥于形式。

输入 some.match 展开,跟输入 match 展开再填入 some 的击键次数是一样的。

如果确实不爽后者,自己实现 some.match 也是可以的:

首先起用 companycompay-yasnippet

然后写 match 模板:

# -*- mode: snippet -*-
# name: match expression { ... }
# key: match
# --
match ${1:`(extract-match-object)`} {
      $0
}

extract-match-object 函数里实现 some.matchmatch some { 的转换。

3 个赞

emacs-company-yas


init.el

(require 'warnings)
(add-to-list 'warning-suppress-types '(yasnippet backquote-change))

(defun extract-match-object ()
  (let ((r "\\b\\.match\\b"))
    ;; Tests:
    ;; (cl-assert      (string-match r "some.match"))
    ;; (cl-assert (not (string-match r "some .match")))
    ;; (cl-assert (not (string-match r "some. match")))
    (save-excursion
      (when (re-search-backward r (point-at-bol) t)
        (let ((word (delete-and-extract-region
                     (car (bounds-of-thing-at-point 'symbol))
                     (point))))
          (delete-char 1)
          word)))))

match.snippet

# -*- mode: snippet -*-
# name: match expression { ... }
# key: match
# --
match ${1:`(extract-match-object)`} {
      $0
}
7 个赞

Intellij 里的有点像emmet那种补全方式,其实并不好用啊,有点反人类,非要记忆成它规定的那个样子。yasnippet 设置成自己习惯的snippet就可好了。@twlz0ne 已经给出了很好的例子。

其实 Intellij 这种后缀补全的方式能够获取上下文信息决定展开的模板内容,并且更加符合我们人脑的逻辑,即先确定操作的对象,再选择操作。

日常编程中记得越少越好,有几个常用的snippet就已经很好了,太多反而影响发挥。个人习惯不同吧

确实是这样的,因此 Intellij 的模板是以补全的形式展示的,并且可以根据 . 之前的对象,过滤当前语境不可用的模板,我个人很喜欢这种模板系统,因此想在 Emacs 里也实现一下。

支持你在emacs中实现一个更好用的snippet,也是造福大众 :+1:t2: