yasnippet 如何嵌套使用 snippet?

我想在一个 snippet 嵌套展开另一个 snippet. 我试过设置 yas-triggers-in-field 为 t, 起作用但行为并非我想要, 因为我得按好几次 tab, 而不是直接展开. 我试图用 embedding elisp code, 但遇到这个问题: 如何给 snippet name, 获取它的内容. 我试过 yas--lookup-snippet-1, 比如 (yas--lookup-snippet-1 "fold" 'org-mode), fold 是另一个 yasnippet 的 name, 问题在于它查找的结果不唯一. 或许是因为我使用了[[emacs 有没有这样的包: 保存常用 snippet 然后 consult 之类的搜索立即可以粘贴 - #5,来自 twlz0ne][emacs 有没有这样的包: 保存常用 snippet 然后 consult 之类的搜索立即可以粘贴 - Emacs-general - Emacs China]]这个链接中的函数.

所以有没有办法一次 tab 展开 snippet 呢? 我定义的 snippet 基本上不会用 placeholder.

举个例子: 这是某一个 snippet:

#include <stdio.h>
#include <cuda_runtime.h>

int main(int argc, char *argv[])
{
    int iDev = 0;
    cudaDeviceProp iProp;
    CHECK(cudaGetDeviceProperties(&iProp, iDev));

    printf("Device %d: %s\n", iDev, iProp.name);
    printf("  Number of multiprocessors:                     %d\n",
           iProp.multiProcessorCount);
    printf("  Warp size:                                     %d\n",
           iProp.warpSize);
    printf("  Maximum number of threads per block:           %d\n",
           iProp.maxThreadsPerBlock);
    printf("  Maximum number of threads per multiprocessor:  %d\n",
           iProp.maxThreadsPerMultiProcessor);
    printf("  Maximum number of blocks per multiprocessor:    %d\n",
           iProp.maxBlocksPerMultiProcessor);
    printf("  Total amount of constant memory:               %4.2f KB\n",
           iProp.totalConstMem / 1024.0);
    printf("  Total amount of shared memory per block:       %4.2f KB\n",
           iProp.sharedMemPerBlock / 1024.0);
    return EXIT_SUCCESS;
}

其中用到了 CHECK 宏定义, 不止这个 snippet 用到了 CHECK 宏, 还有若干 snippet 都用到了 CHECK 宏定义. 我现在是把 CHECK 宏定义直接贴在这里. 我希望我能单独把 CHECK 宏保存到一个 snippet, 然后其它 snippet 中引用这个 snippet. 这样 CHECK 的定义如果进行调整, 不需要改其它的 snippet. 就是想复用.

使用consult的话,我现在用方法是多弄几个snippet,按照你这种没有placeholder的情景,需要的snippet可能也不多

描述不清打回重写……你要说本来的问题,想展开一段什么样的代码,然后在里面的哪个slot插入/展开另一个什么样的代码

yas可以给某个slot预先设置选项的吧我记得。大概也许你只用一个snippet,然后把里面某个slot可能需要的选项都放进去就可以?

已更新问题描述, 加了个例子.

那其实就是在snippet里面复用一个string,那在你的配置里(或者在snippet目录新建个el文件load进来)写上(setq cpp-check-snippet "CHECK...")然后在snippet里面引用这个变量就好了。如果也需要单独使用这个CHECK的snippet的话就建个check的snippet,它的内容就是仅仅eval那个变量。

有个小问题是这样在snippet目录放了个el文件,是我我就忍了,你可以试着换成snipppet文件然后在别的snippet里面get文件内容再yas-expand-snippet

找到一种暂时可行的方法(保存到 这里):

(defun my/get-yasnippet-content-by-name(snippet-name &optional mode)
  (yas--template-content (yas--get-template-by-uuid (yas--table-get-create (or mode major-mode) ) snippet-name)))

(defun my/get-yasnippet-expansion-by-name(snippet-name &optional mode)
  (let ((mode (or mode major-mode)) start-point snippet-expansion)
    (save-excursion
      ;; (funcall mode)
      (unless yas-minor-mode (yas-minor-mode))
      (goto-char (point-max))
      (insert "\n")
      (setq start-point (point))
      (yas-expand-snippet (my/get-yasnippet-content-by-name snippet-name mode))
      (setq snippet-expansion (buffer-substring-no-properties start-point (point-max)))
      (delete-region start-point (point)))
      snippet-expansion
    ))

这样如果 mode 相同, 用起来就是:

`(my/get-yasnippet-expansion-by-name "CHECK_macro")`

如果 mode 不同, 就再指定 mode 参数:

`(my/get-yasnippet-expansion-by-name "CHECK_macro" 'cuda-mode)`

不过我这样是假定 template 的 uuid 和 name 一样了. 我不知道啥时候 uuid 和 name 不一样, 暂时还没遇到过. 欢迎大家补充 uuid 和 name 不一样的时候.