Sublime Text 4 的 Snippet 必须严格满足四个条件才能生效:文件置于 Packages/User/ 下且命名规范(英文小写+连字符+.sublime-snippet)、XML 结构完整并用 CDATA 顶格包裹内容、scope 值精确匹配当前语法环境、$1/$2/$0 跳转位连续且 $0 唯一。

Sublime Text 4 的 Snippet 不是“写完就能用”,它对文件位置、XML 结构、scope 值和 CDATA 包裹方式极其敏感——错一个环节,就静默失效,不报错也不提示。
Snippet 文件必须放对位置且命名严格
Sublime Text 4 只加载 Packages/User/ 目录下的 .sublime-snippet 文件,其他路径(如项目根目录、桌面、Packages/MyPlugin/)全无效。Windows/macOS/Linux 路径不同,但统一用菜单打开最可靠:Preferences → Browse Packages… → 进入 User 文件夹。
- 文件名必须以英文小写 + 连字符 +
.sublime-snippet结尾,例如log-js.sublime-snippet;log.snippet、log.js、log-console.sublime-snippet.txt(Windows 隐藏扩展名常见坑)都会被忽略 - 中文命名(如
测试片段.sublime-snippet)在部分 ST4 版本中加载失败,强制用英文 - 保存后无需重启,但若之前存在同名 snippet,ST4 会按「最后修改时间」覆盖生效——改了新文件却触发旧内容?去
Packages/User/搜<tabTrigger>xxx</tabTrigger>找出并删掉冲突项
XML 结构缺一不可,CDATA 是硬性要求
<content> 里的代码必须用 <![CDATA[...]]> 包裹,否则 <、{、$ 等符号会被 XML 解析器截断或报错,导致插入内容不全或格式错乱。
- 最小可用结构必须含
<snippet>根节点、<content>、<tabTrigger>;<scope>和<description>可选,但漏掉前两者直接失效 - 别手动缩进
<![CDATA[内容:顶格写<![CDATA[console.log($1);$0]]>,否则插入时带多余空格或换行,破坏代码对齐 - 示例(存为
log-js.sublime-snippet):<snippet> <content><![CDATA[console.log($1);$0]]></content> <tabTrigger>log</tabTrigger> <scope>source.js</scope> </snippet>
scope 字段决定“能不能触发”,不是“想不想触发”
没写 <scope>,Snippet 只在纯文本(text.plain)下生效;写错 scope(比如把 source.js 写成 javascript),它就在 JS 文件里彻底隐身——ST4 不提示、不警告,只沉默跳过。
- Vue 单文件组件的
<script>块真实 scope 是source.vue meta.script.js,不是source.js;TSX 中 JSX 部分是source.tsx meta.jsx - 查当前准确 scope:按
Ctrl+Shift+P(Win/Linux)或Cmd+Shift+P(Mac)→ 输入Developer: Show Scope Name→ 光标所在位置的作用域会显示在状态栏,复制粘贴进<scope>字段即可 - 支持多 scope 并列,用逗号分隔,例如
<scope>source.js, source.ts</scope>;注意区分大小写,Source.Js无效
光标跳转位 $1、$2、$0 容易踩坑
$1 不是“随便写个数字就行”,编号必须连续,且 $0 必须且只能出现一次——漏掉 $0,光标卡在最后一处 $N 后无法退出;重复用 $1,两处会同步编辑,不是独立字段。
- 推荐用
${1:default}格式:第一个跳转位默认填default,可直接编辑或 Tab 跳过;$2后按 Tab 自动跳到第二处 - 多行结构(如函数模板)中,避免靠空格对齐跳转位——缩进会被原样插入。用
$1定位函数名,$2定位 body 入口,$0放在结尾分号后 - 错误写法:
<content><![CDATA[function $1() { $2 }]]></content>(缺 $0);正确写法:<content><![CDATA[function ${1:name}() { $2 }$0]]></content>
最常被忽略的是 scope 的精确匹配和 CDATA 的顶格书写——它们不像语法错误会报红,而是让 snippet “看起来存在,实际不存在”。调试时优先用 Developer: Show Scope Name 确认当前上下文,再比对 snippet 文件里的 <scope> 值,比反复重命名文件更省时间。

















