2

I'm currently trying to write a user snippet that will take a variable of ${1} (For example JobsSummary) and convert it into Kebab case (jobs-summary).

"Example": {
    "prefix": "test",
    "body": [
      "${1}",
      "${1} -> ${1/(^.)+([A-Z])+/${1:/downcase}/}"
    ]
}

What is the proper way to convert a variable in a visual studio code user snippet from Pascal Case to Kebab Case?

JobsSummary -> jobs-summary

AnotherExampleOfSomething -> another-example-of-something

Naismith
  • 235
  • 2
  • 9

2 Answers2

7

Update as of vscode v1.69: A new command has been added :

Transform to Kebab Case
editor.action.transformToKebabcase

It is unbound by default, to make a keybinding in your keybindings.json:

{
  "key": "",        // whatever keybinding you want
  "command": "editor.action.transformToKebabcase"
}


Previous answer, before the new command mentioned above.

This works:

"Example": {
  "prefix": "psc",
  "body": [
    "${1}",
    "${1} -> ${1/([A-Z][a-z]*)([A-Z][a-z]*)?([A-Z][a-z]*)?([A-Z][a-z]*)?/${1:/downcase}${2:+-}${2:/downcase}${3:+-}${3:/downcase}${4:+-}${4:/downcase}/}"
  ],
  "description": "Convert from PascalCase to kebab-case"
},

Usually I am able to get these to work in a much shorter version - using the global modifier - and thus for any number of "words". But I was unable to do so in this case. The above is hard-coded for up to four "words", like PascalCaseThreeFour.

It works for one to four "words" but will not work for more but would be easy for you to modify for as many as you want. There is an obvious pattern to the transform to add more.

The ${3:+-} construct you see above means if there is a capture group 3, add a hyphen.

EDIT: the following simplification will handle any number of words in PascalCase:

"${1} -> ${1/([A-Z][a-z]+)/${1:/downcase}-/g}$0"

but will result in a trailing - like so:

PascalCaseThreeFourFive -> pascal-case-three-four-five- if you don't mind backspacing over the trailing dash -. Otherwise it would be easy to incorporate this snippet into a macro that then deleted that last dash.

Also, the change-case extension might work for you - it looks like it has a kebab-case command.


UPDATE:

See my answer here for a very powerful working example that handles many cases, including sequences of caps and many other odd cases:

"snake": {
  "prefix": "snake",
  "body": "${TM_SELECTED_TEXT/([A-Z]{2,})(?=[A-Z][a-z]+[0-9]*|$)|([A-Z]?[a-z]+[0-9]*|[A-Z]|[0-9]+)([- _])?/${1:/downcase}${2:/downcase}${2:+_}/gm}"
}, 
Mark
  • 143,421
  • 24
  • 428
  • 436
  • thank you, this does work pretty close to what I need. Is there a way to get this to work for unlimited capture groups? – Naismith Nov 08 '18 at 20:58
  • See my edit in the answer to handle any number of capture groups. – Mark Jun 23 '19 at 03:16
6

This works for any number of words in PascalCase and without a trailing dash:

"${TM_SELECTED_TEXT} -> ${TM_SELECTED_TEXT/(^[A-Z][a-z]*|[a-z])([A-Z])?/${1:/downcase}${2:+-}${2:/downcase}/g}"

This will produce something like this:

AnotherExampleOfSomething -> another-example-of-something

The only thing is, that it doesn't like sequences of caps, like acronyms (only the firs character will be downcased). However it potentially a case only for 2-letters abbreviations, since according to the rules the longer acronyms should be written using camel/Pascal case anyway (which works fine).

maxim
  • 616
  • 4
  • 7