when 语句排除指定的文件夹和文件在上下文菜单中显示扩展命令

when statement to exclude specified folders and files from showing an extension command in a context menu

在我的 VS 代码扩展中,我有一些我希望在资源管理器视图中可用的命令,并希望它们的可用性基于所选择的内容。假设我在 VS Code 中打开一个文件夹,该文件夹包含以下内容:

/a
/a/1.txt
/a/2.txt

/b
/b/3.txt
/b/4.txt

/c
/c/5.txt
/c/6.txt

我希望在选择文件夹“c”或其中的任何内容时出现命令,而不是 a 或 b。

此外,我希望逻辑 exclude 特定文件夹(及其内容),而不是 include 特定文件夹(例如我想要逻辑是,“该命令可用于所有 除了 a 或 b”)

在我的扩展程序的 activate() 函数中,我有:

  vscode.commands.executeCommand(
    'setContext',
    'ext.list',
    [
      'a',
      'b'
    ]
  );

在我的 package.json 中,我有:

{
  "command": "samplecommand",
  "when": "resourceFilename in ext.list"
}

当我 运行 这样做时,我发现当我选择文件夹 a 或 b 时该命令可用,但当我选择其中的任何项目时(如 a/1.txt) .我尝试使用 a/*a/.*a/*.*,但我没有找到任何有效的方法。

那么,在使用“resourceFilename in”时,是否支持正则表达式?或者它只做精确的字符串匹配?选择文件夹或文件夹中的项目之一时,如何获得肯定匹配?

好的,接下来,无论如何我都想排除命令,当我尝试时:

{
  "command": "samplecommand",
  "when": "!(resourceFilename in ext.list)"
}

...或者:

{
  "command": "samplecommand",
  "when": "resourceFilename !in ext.list"
}

...a、b 或 c 均未显示该命令。是否可以测试列表中的文件名何时为 而不是 ?看起来这总是评估为 false。

所以,TL;DR,我想在资源管理器视图中过滤命令,然后不会针对特定文件夹和文件夹中的项目显示。这可能吗?

第一个问题:

你有

"contributes": {
   "menus": {
     "explorer/context": [
       {
         "command": "ext.samplecommand",
         "when": "resourceFilename in ext.list"
       }
     ]
   }
}

和一个'ext.list', [ 'a', 'b' ]

When I run this, I find that the command is available when I have folders a or b selected, but not when I have any of the items within it selected (like a/1.txt). I tried using a/*, a/.*, and a/*.* but I haven't found anything which works.

但是 resourceFilename 解析为类似于 a 的文件夹和 myFile.js 的文件。因此 "resourceFilename in ext.list" 对文件夹的工作方式与您预期的一样,因为 resourceFilename 解析为 ab(如果它们被选中)。但它对文件没有帮助,因为 resourceFilename 不解析为文件夹名称,而是解析为文件名。

要让菜单项显示两个文件夹及其包含的文件,您可以这样做:

"menus": {
  "explorer/context": [
    {
      "when": "resourceFilename in ext.list || !explorerResourceIsFolder && resourceDirname =~ /(\/|\\)(bundle|concat)$/",
      "command": "ext.samplecommand"
    }
  ]
}

其中 (bundle|concat) 表示 dirname 的您想要 包含的文件

这回答了您关于 when 子句支持正则表达式的问题。是的,参见 key-value when clause operator:

There is a key-value pair match operator for when clauses. The expression key =~ value treats the right-hand side as a regular expression to match against the left-hand side.

以上使用resourceDirname =~ /(\/|\\)(bundle|concat)$

这将检查 resourceDirnameending in \bundle or /bundle or \concat or /concat (在反斜杠或正斜杠之前有很多转义符)。


现在,要到达您的最终目的地 - 过滤菜单以显示特定文件夹和文件的命令。

我认为没有办法否定 resourceFilename in ext.list“运算符”。我似乎记得关于它的一个 github 问题,但我现在找不到它了。

但是还有另一种方法,因为我们可以使用上面在 when 子句中看到的正则表达式。但它必须有点棘手,因为我们正试图排除某些文件夹和文件。试试这个:

"menus": {
  "explorer/context": [
    {
      "when": "explorerResourceIsFolder && resourcePath =~ /.*?(?<!(\\|\\/)(bundle|concat))$/ || !explorerResourceIsFolder && resourceDirname =~ /.*?(?<!(\\|\\/)(bundle|concat))$/",
      "command": "ext.samplecommand"
    }
  ]
},

  • explorerResourceIsFolder && resourcePath =~ /.*?(?<!(\\|\\/)(bundle|concat))$

当所选资源是文件夹时,检查其resourcePath,这将是其以文件夹名称结尾的完整文件路径。

因此 resourcePath =~ /.*?(?<!(\\|\\/)(bundle|concat))$ 使用负后向匹配 而不是 以名称为 bundleconcat 的文件夹结尾的文件夹路径示例(您的 ab)。

  • !explorerResourceIsFolder && resourceDirname =~ /.*?(?<!(\\|\\/)(bundle|concat))$/

当所选资源是文件而非文件夹时,检查其resourceDirname,这将是其以文件夹名称结尾的完整文件路径。

所以像上面一样,它使用负后视来仅匹配具有 dirnames 而不是 bundleconcat.

的文件

所以总而言之,由于 resourceFilename in ext.list 类型的构造不能取反,因此您必须使用 key =~ value 类型的 when 子句,并确保将其与正确的资源进行比较姓名。并通过使用某种正则表达式否定环视来“否定”它。


要解决这个问题,Developer: Inspect Context Keys 命令是 无价的 。它允许您查看哪些上下文键可用于资源管理器文件夹和文件以及这些键的值。这就是我发现 resourcePath 最适合文件夹而 resourceDirname 最适合文件的方式 - 因为在这两种情况下,完整路径都以文件夹名称结尾。

参见 Inspect Context Keys utility documentation