如何在不触发替换的情况下从键绑定中插入文字文本

How to Insert Literal Text from a Keybinding, without Triggering Substitutions

我是 VSCode 的新手,我经常需要制作键盘学习序列,这似乎与 VSCode IDE 无关。根据几个网站的建议,我获得了 marcos 的扩展,并一直在制作自定义键绑定作为解决方法。

这非常艰难,因为显然,唯一的命令主列表在“键盘快捷键”选项卡中,其次,几乎没有关于这数百个单独命令的文档。 (特别是,我无法找到每个命令接受的参数的 any 主列表)。

无论如何,我在制作我需要的自定义键绑定方面取得了一些成功,但是,我一直 运行 遇到的一个特殊问题是,我可以看到插入特定文字文本的唯一方法与 "type" 命令一起使用,但是,这显然确实 尝试键入每个字符 并让键盘样式等替换自动开火。我不需要也不想要这个,我需要能够停止它,或者找到其他一些(实用的)方法来插入我的文字文本而不需要 any 重新解释、替换或其他键绑定触发(或任何正在这样做的机构)。

这是我当前的键绑定命令集:

    "EditLitPropToGet": [
        {"command": "type", "args": {"text": "get "}},
        "cursorWordRight",
        "cursorRightSelect",
        {"command": "type", "args": {"text": "() { return "}},
        "cursorEnd",
        "cursorWordStartLeft",
        {"command": "type", "args": {"text": "; }"}},
        "cursorWordRight",
        "cursorWordRight",
        "cursorWordStartLeft"
    ]

这样做的目的是,当定位在这一行第一个单词的开头时:

referenceGravity: this.surfaceGravity * (this.radius**2),

然后把它变成这一行:

get referenceGravity() { this.surfaceGravity * (this.radius**2); },

在到达第二个 type 命令之前,它工作正常:

        {"command": "type", "args": {"text": "() { return "}},

在此运行之前,该行如下所示:

get referenceGravity: this.surfaceGravity * (this.radius**2),

选择了冒号字符。上面的 type 命令应该做的是:

get referenceGravity() { return  this.surfaceGravity * (this.radius**2),

但实际情况是这样的:

get referenceGravity() { return }) this.surfaceGravity * (this.radius**2),

显然,这是因为它将 type 文本视为键盘输入并触发了“()”和“{}”的样式闭包。

我怎样才能只插入文字文本?

需要说明的是,我不希望每次我想执行此操作时都必须定义自定义代码段,或者必须预加载粘贴缓冲区,我需要这些键绑定是独立的。

我也不想在开始时盲目地集体禁用所有扩展、样式等,如果这意味着我必须在最后盲目地启用它们。我愿意尝试 类似 的东西,但是如果我已经禁用了某些东西,它不应该再重新启用它,因为它不知道以前是什么 enabled/disabled .如果它只是 disabling/enabling 一个特定的设置,那很好,我可以接受根据需要进行更正。


为了更新这个,我接受了@Mark 的回答,因为它为这个特定案例提供了解决方案。但是,对于一般性问题:“How can I insert literal text?”,我相信我终于明白了人们所说的:您可以使用 insertSnippet 来插入文字文本,您只需要转义可能被视为 Textmate/RegEx 命令的内容(“$”和“`”与“\”)。所以这应该有效:

    "EditLitPropToGet": [
        {"command": "editor.action.insertSnippet", 
            "args": {"snippet": "get "}},
        "cursorWordRight",
        "cursorRightSelect",
        {"command": "editor.action.insertSnippet", 
            "args": {"snippet": "() { return "}},
        "cursorEnd",
        "cursorWordStartLeft",
        {"command": "editor.action.insertSnippet", 
            "args": {"snippet": "; }"}},
        "cursorWordRight",
        "cursorWordRight",
        "cursorWordStartLeft"
    ]

只是为了向您展示代码片段如何转换版本,此键绑定:

{
  "key": "ctrl+k ctrl+1",             // or whatever you want
  "command": "editor.action.insertSnippet",
    "args": {
      "snippet": "get ${TM_SELECTED_TEXT/^(\w*):(.*),$/() {/}; },"
  }
},

产生你想要的输出。您必须首先 select 该行,但这可以很容易地在宏内部自动执行(或者只需绑定 cursorLineEndSelect 命令。该宏将只有两个命令: cursorLineEndSelect 和插入上面的片段。


使用多命令的示例宏,我不知道 ctf0.macros 的语法看起来更强大:

 "multiCommand.commands": [

     {
      "command": "multiCommand.yourMacroNameHere",
      "interval": 2000,
      "sequence": [
        "cursorEnd",
        "cursorHomeSelect",
        {
          "command": "editor.action.insertSnippet",
          "args": {
            "snippet": "get ${TM_SELECTED_TEXT/^\s*(\w*):(.*),$/() {/}; },"
          }
        },
        "cursorDown"
      ]
    },

interval 在你的情况下是不必要的,只是在那里看它工作 - 它可以被注释掉。光标可以位于包含要转换的行的行上的任何位置。它不需要预先 selected,宏会为您完成。

为了以防万一,我会在进行这些更改后重新加载 vscode(通过命令面板)。

同样,该演示看起来很慢,但这只是为了演示使用 interval 选项的各个步骤。否则瞬发


如果您想使用宏,请使用 insertSnippet 命令代替那个 type 命令:

    // {"command": "type", "args": {"text": "() { return "}},
    {
      "command": "editor.action.insertSnippet",
      "args": {
        "snippet": "() { return }"
      }
    },

这似乎不会触发自动关闭大括号。片段确实需要转义比 type 命令更多的字符 - 但不是你的情况。