VS Code多重转换代码片段

7
我正在尝试制作一个片段,它将获取剪贴板内容(即markdown文档中标题的文本),并将其转换为指向该部分的链接。例如,如果我的剪贴板包含:Some Heading - 20191107,则我希望输出以下内容:
[Some Heading - 20191107](filename.md#some-heading---20191107)

这是我目前为止用于markdownVS Code代码片段:

    "link to this section": {
        "prefix": "isection",
        "body": [
            "[${1:${CLIPBOARD}}](${TM_FILENAME}#${CLIPBOARD/ /-/g})"
        ],
        "description": "Insert link to section whose heading text is in the clipboard"
    }

这里有第一个转换,但我无法弄清如何嵌套多个转换:

  • 将所有空格替换为连字符。
  • 将所有字符转换为小写。
  • 删除任何与[^a-z0-9-]匹配的字符。

测试用例

为了澄清我的测试用例给@Mark,在VS Code中的一个markdown文档中,我创建了一个标题部分,例如:

# 20191107 - @#$%^& This is a section - 20191107

我随后复制了文本20191107 - @#$%^& This is a section - 20191107,并运行了你为我修正过的代码片段。其输出结果是:

[20191107 - @#$%^& This is a section - 20191107](tips.tech.git.md#20191107----this-is-a-section---20191107)

哪个是指向标题的有效链接!


在您的测试用例中,您希望输出看起来是什么样子?我使用了您原始问题中的“Some Heading - 20191107”来设计正则表达式,但似乎您实际上是从“# 20191107 - @#$%^& This is a section - 20191107”开始的? - Mark
那只是一个例子,以便我测试它对具有非字母数字字符的标题所做的操作。顺便说一句,它完美地工作 - 正是我试图自己创建的东西。最重要的部分是它创建链接部分的方式 - 在圆括号内。如果您不介意对正则表达式进行一些解释,那将不胜感激! - Robert Mark Bram
1个回答

12

下面是我认为符合所有要求的代码片段(我从之前的回答中简化了它)。

"link to this section": {
  "prefix": "isection",
  "body": [

    "[${1:${CLIPBOARD}}](${TM_FILENAME}#${CLIPBOARD/([\\w-]+$)|([\\w-]+)|([-\\s]+)|([^\\w]+)/${1:/downcase}${2:/downcase}${2:+-}/gm})"

  ],
  "description": "Insert link to section whose heading text is in the clipboard"
}

我将解释这一部分: ${CLIPBOARD/([\\w-]+$)|([\\w-]+)|([-\\s]+)|([^\\w]+)/${1:/downcase}${2:/downcase}${2:+-}/gm} 这里的主要思想是捕获每个组以便在自己的组中进行不同的处理。正则表达式的交替只会为每个匹配捕获一个组。请参见regex101 demo
然后,您可以转换该组或忽略它,而不影响任何后续匹配!
它是四个捕获组的交替:
  1. ([\\w-]+$) 注意使用$表示行尾,必须是第一个捕获组
  2. ([\\w-]+) 与组1相同,但不在行尾
  3. ([-\\s]+) 捕获空格和连字符
  4. ([^\\w]+) 捕获除A-Za-z0-9之外的任何字符

捕获组1 获取最后一组字符,比如 12345 或者 asdasd

捕获组2 获取与组1相同的字符组,但不包括行尾。这很重要,因为如果有捕获组2,则会添加一个-,但如果有捕获组1,则不会添加连字符(因此不会在末尾添加连字符)。

捕获组3 捕获空格和连字符。它将在输出中被忽略。

捕获组4 捕获那些非A-Za-z0-9的字符,并将其忽略。

这是转换的输出:${1:/downcase}${2:/downcase}${2:+-} 请注意,没有提到第3或第4组 - 它们被丢弃了。但必须匹配它们,否则它们将通过“未转换”并出现在结果中 - 这是我们不想看到的。

因此,对组1和组2进行小写处理,由于交替使用,永远不会同时匹配这两个组。

如果有第二组,则在其后添加“-”。整个 CLIPBOARD 的最后一个匹配项将是第一组,因此不会附加连字符。由于使用了“g”标志,正则表达式会运行几次,每次仅捕获其中的一个 4 组。

输入:Some Heading - 20191107
输出:[Some Heading - 20191107](fileName.ext#some-heading-20191107)

输入:20191107 - @#$%^& This is a section - 20191107
输出:[20191107 - @#$%^& This is a section - 20191107](test-bed-snippets.code-snippets#20191107-this-is-a-section-20191107)


如果您需要更多连字符的结果,例如:

[某个标题-20191107](filename.md#some-heading---20191107)

只需将第三个捕获组中的连字符去掉:([\\s]+),结果为:

[20191107-@#$%^& This is a section-20191107](test-bed-snippets.code-snippets#20191107---this-is-a-section---20191107)


感谢您的回复,@Mark。针对您的问题,文本可以包含任何字符。Markdown标题创建锚点标签的规则是:1)用连字符替换所有空格,2)将所有字母小写,删除每个非字母数字字符(或连字符)。 - Robert Mark Bram
不太确定我是否理解您的测试用例。 20191107 - @#$%^& 这是一个部分 - 20191107 整个东西都是一个测试用例吗?并且该转换在该测试用例上按照您的要求工作? - Mark
Robert和@RomainVincent,我终于解释了我的答案(并简化了转换过程)。如果您理解有问题,请告诉我。 - Mark
谢谢您添加解释,这非常好。我想我不明白,为什么第一组必须先出现?否则可能永远无法匹配? - Romain Vincent
@Romain 如果 ([\\w-]+$) 不是第一个匹配的序列,比如 OP 示例中的 20191107,那么它将被 ([\\w-]+) 匹配。我们需要将它们分成不同的组,这样我们才能使用 ${2:+-} 仅将连字符添加到不在末尾的组中。 - Mark
显示剩余4条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接