Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

VS Code snippet with multiple transforms

I am trying to make a snippet that will take clipboard contents (the text of a heading in a markdown document) and transform it into a link to that section. For example, if my clipboard contains: Some Heading - 20191107 then I want the following to be output:

[Some Heading - 20191107](filename.md#some-heading---20191107)

Here is my snippet VS Code for markdown so far:

    "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"
    }

This has the first transform, but what I cannot figure out is how to nest multiple transforms:

  • Replace all space with a hyphen.
  • Change all to lower case.
  • Remove any characters matching [^a-z0-9-]

Test Case

To clarify my test case for @Mark, in a markdown document in VS Code, I make a section heading such as:

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

I then copy the text 20191107 - @#$%^& This is a section - 20191107 and run the snippet you fixed up for me. What it outputs is:

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

Which is a valid link to the heading!

like image 968
Robert Mark Bram Avatar asked Nov 07 '19 01:11

Robert Mark Bram


People also ask

How do I create a multiline snippet in Vscode?

press ctrl + shift + P and type "Create snippet" on the command palette and press ENTER. snippet name, type snippet shortcut and then type snippet description. You are now good to go.

How does VS code change snippet?

To create or edit your own snippets, select User Snippets under File > Preferences (Code > Preferences on macOS), and then select the language (by language identifier) for which the snippets should appear, or the New Global Snippets file option if they should appear for all languages.

How are code snippets used in VS code?

You can insert this snippet by clicking Insert Snippet in the right-click menu (context menu) of the code window, then Visual C#, then type tryf , and then press Tab. Or, you can type tryf and press Tab twice.


1 Answers

Here is a snippet that I believe meets all requirements (I have simplified this from an earlier answer of mine).

"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"
}

I will explain this part:

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

The main idea here is to capture each group to be handled differently in its own group. A regex alternation will just capture one group for each match. See regex101 demo.

Then you can transform that group or ignore it without affecting any subsequent matches!

It is alternation of four capture groups:

  1. ([\\w-]+$) note the $ to indicate end of line, must be first capture group
  2. ([\\w-]+) same as group 1, but not at end of line
  3. ([-\\s]+) capture spaces and hyphens in a group
  4. ([^\\w]+) capture any characters other than A-Za-z0-9 in a group

Capture group 1 gets the last set of characters, like 12345 or asdasd.

Capture group 2 gets the same groups of characters as group 1 but not if they are at the end of the line. This is important because a - will be added if there is a capture group 2, but not if there is a capture group 1 (so no hyphen is added to the end).

Capture group 3 captures the spaces and hyphens. It will be ignored in the output.

Capture group 4 captures those non-A-Za-z0-9 characters and will be ignored.

Here is the output of the transform: ${1:/downcase}${2:/downcase}${2:+-} notice there is no mention of groups 3 or 4 - they are being discarded. But they must be matched otherwise they will pass through "un-transformed" and appear in the result - which we do not.

So lowercase groups 1 and 2, because of the alternation there will never be both in the same match.

${2:+-} if there is a group 2 add a - after it. The very last match of the entire CLIPBOARD will be a group 1 so for this last match no hyphen will be appended.

Because of the g flag the regex runs a few times, each time capturing only one of the 4 groups.


Input: Some Heading - 20191107
Output: [Some Heading - 20191107](fileName.ext#some-heading-20191107)

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


If you need more hyphens in the result, like:

[Some Heading - 20191107](filename.md#some-heading---20191107)

just take the hyphen out of the third capture group: ([\\s]+) to result in:

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

like image 175
Mark Avatar answered Sep 22 '22 12:09

Mark