VSCode代码片段怎么设置触发时自动覆盖选中的文本?
在写React组件时想用代码片段替换选中的prop,选中一段文字后按tab触发snippet,但总是插入到选中内容前面而不是覆盖。试过把”prefix”改成带空格的形式,也调整过tabStops的位置,但还是不行。比如选中”oldName”后触发snippet,希望变成<${1:newName}>,结果却变成这样:
{
"trigger": "prop",
"body": ["${1:${SELECTED}}: ${2:type};"]
}
有没有办法让snippet自动替换选中的文本而不是追加?文档里只提到${TM_SELECTED_TEXT}但没解决位置问题…
$TM_SELECTED_TEXT和占位符默认值来实现覆盖行为。核心原理是这样的:当你在编辑器里选中了一段文本(比如 oldName),然后触发代码片段时,VSCode会把这段选中的内容作为
$TM_SELECTED_TEXT的值注入进去。而你可以在片段体里用${1:default}这种语法,其中 default 部分可以是一个变量,比如$TM_SELECTED_TEXT,这样它就会变成默认填充的内容,光标也会落在第一个 tab stop 上。所以你的目标是让 snippet 把选中的文本当成 prop 名来用,而不是插在前面。改法如下:
关键点解释:
-
${1:${TM_SELECTED_TEXT:newName}}这个结构表示这是一个 tab stop 第1位,里面的内容默认是$TM_SELECTED_TEXT,如果没选中任何东西,那就显示 newName 作为占位符。- 当你选中了 oldName 然后输入 prop 再按 Tab,VSCode 会把 oldName 填进这个位置,变成
oldName: string;,同时光标就在 oldName 这个位置上,你可以直接改。- 如果你没有选中任何文字就触发,那就会插入 newName 作为默认建议名。
需要注意的是,VSCode 的 snippet 不会自动“删除”选区再插入,而是靠这个变量机制把选中的内容“继承”下来。看起来像是覆盖,实际上是利用了选区内容作为默认值的特性。
还有一点容易被忽略:确保你在选中文本后触发 snippet 的方式是对的。比如你得先选中 oldName,然后键入 prefix(比如 prop),弹出补全后按 Tab 或 Enter。如果你是通过命令面板手动插入片段,
$TM_SELECTED_TEXT可能不会生效,因为上下文不一致。顺便吐槽一句,官方文档确实写得稀烂,这个功能藏得很深,连例子都没给几个。我也是翻 GitHub issues 才搞明白的。
补充一个实用变体,如果你想生成 JSX 属性格式:
选中 text 后触发 jprop,就会变成 text={'value'},光标停在引号里,效率拉满。
总结一下:别想什么“自动覆盖”,本质是用
$TM_SELECTED_TEXT做占位符默认值,配合 tab stop 实现视觉上的替换效果。这才是 VSCode 设计这个功能的本意。