Yasnippets能和输入法配合吗?

我有一个简单的snippet:

# -*- mode: snippet -*-
# name: equation in line
# key: 4
# --
\$$1\$$0

其中

  1. $是自动输入一个$符号
  2. $1表示展开这个snippet后光标的位置
  3. $0表示snippet结束后光标的位置

综合起来,这个snippet的作用是输入4+tab,自动就变成了$$, 且光标在两个$符号中间。

我用它在中文文章中写latex公式,因为我觉得输入$时要换英文输入法,输完后又要换中文输入法,这样来回换好麻烦。

上面的snippet体验已经好一些了,但是还有不足——就是光标进入两个$符号中间后输入法还是中文的。 有没有可能改进一下使得:

  1. 光标进入两个$符号中间后输入法自动变成英文(因为latex公式通常都是英文)
  2. tab将光标跳出$之外(结束公式输入)后,输入法恢复为使用snippet之前的状态

emacs上的输入法可以。chinese- pyim是可以自订输入法何时生效的。

参考: https://github.com/tumashu/chinese-pyim/blob/master/README.md#chinese-pyim-高级功能

只要写一个函数探针,令pyim在美元符号后面输入英文即可

YASnippet 可以执行 elisp,所以嵌入 elisp 代码就行。比如,如果用 fcitx.el 的话,先定义一个函数 foo 用于退出时激活输入法:

(defun foo ()
  (fcitx--activate)
  (remove-hook 'yas-after-exit-snippet-hook 'foo))

然后在进入 snippet 的时候先关闭输入法,同时把 foo 加到退出的 hook 上。Snippet 改成:

# -*- mode: snippet -*-
# name: equation in line
# key: 4
# --
`(progn (fcitx--deactivate) (add-hook 'yas-after-exit-snippet-hook 'foo) nil)`\$$1\$$0

思路大概如此。

1 个赞

试了一下,并没有成功,是不是因为我的snippet是 org-mode,不是eslip-mode? 你写在$前的那一段也出来了,并没有执行啊。

请问有没有在yasnippet中写lisp的参考资料可推荐的?

发现大侠顺道打了个广告:smiley:,不过这个广告我给满分!

有没有将chinese- pyim输入法独立于emacs的打算?

我只是按照我的记忆写的,我好久没用 YASnippet 了哈。思路大概那样应该不会有问题,而且那段代码应该会执行的啊。

嵌入 elisp 代码和 major-mode 应该没关系,官方手册: http://joaotavora.github.io/yasnippet/snippet-development.html#sec-3-2

你是不是误会了什么_(:зゝ∠)_我不是这个插件的作者啊

哦,我误会了。作者是呆神吧

可能是我函数foo的定义放错位置了,我放到自己layer的fun.el里。现在我把它放到.spacemacs.d/init.el里,确实可以执行了!不过好像还有点问题,未能完全实现我想要的功能。

  1. 如果我本来就处于英文输入法,tab结束snippet后,反而变成中文输入法了;
  2. 如果我本来处于中文输入法的状态,4+tab开始snippet,输入法并没有自动切换为英文输入法。

对于1.,我想是不是要在改变输入法之前,先用变量记住当前用的是什么输入法。只有当这个输入法是中文输入法时,才有切换?

我再学习一下

我用的就是fcitx! @cutejumper 这个snippet跟fcitx的功能很像啊:

进入evil的normal模式后自动切换为英文输入法,返回insert模式又自动还原为原来的输入法。

是的。可以参照 fcitx.el 里面的方法解决。

你可以使用 fcitx--defun-maybe 这个宏定义用于这个 snippet 的开启和关闭输入法的函数。具体地,假设你使用了以下代码:

(fcitx--defun-maybe "snippet")

你就可以使用 fcitx--snippet-maybe-activatefcitx--snippet-maybe-deactivate 来“智能”开启和关闭输入法了。

fcitx.el 中有好几个例子可以参考。

我在我的配置文件里定义了fcitx--snippet-maybe-activatefcitx--snippet-maybe-deactivatefoo

(fcitx--defun-maybe "snippet")

(defun foo ()
   (fcitx--snippet-maybe-activate)
   (remove-hook 'yas-after-exit-snippet-hook 'foo))

然后snippet这样写:

# -*- mode: snippet -*-
# name: equation in line
# key: 4
# --
`(progn (fcitx--snippet-maybe-deactivate) (add-hook 'yas-after-exit-snippet-hook 'foo) nil)`\$$1\$ $0

然而并没有成功!实在想不通,代码应该很清楚了呀。

是不是因为我使用C-c tab来展开snippet的时候,C-c就已经关闭了fcitx


即使退而求其次——在进入snippet时强制关闭输入法,都没有成功:

# -*- mode: snippet -*-
# name: equation in line
# key: 4
# --
`(fcitx--deactivate)`\$$1\$ $0

我觉得八成是C-c tab的问题,求大神指点。

我改变了一下snippet的快捷建:

(define-key yas-minor-mode-map (kbd "<f4>") 'yas-expand)

测试发现问题果然在C-c tab上。

推荐一下中州韵输入法 , 只有你想不到的,没有不能输入的东西,目前我见过的最强大的输入法,各种自定义,所有符号都可以输入

1 个赞

这是目前 fcitx.el 的一个局限。prefix-keys 是基于 timer 的,其他的功能基于 advice 和 hook,所以两者在某些情况下会有一些冲突。但是在 Emacs 目前的设计下,貌似没有好的办法解决。目前的话如果出现冲突,只能选其一。