6

In a Visual Studio Code Snippet I'm writing I want to convert a snake case string to camel case.

From the docs I know that the syntax is

'${' var '/' regex '/' (format | text)+ '/' options '}'

so I've come up with this :

${TM_FILENAME_BASE/([a-z])([a-z]*)_+([a-z])([a-z]*)_+/${1:/upcase}$2${3:/upcase}$4/}

This code however works only for strings with 2 elements (for exemple "carrot_cake") while I would like to process strings with arbitrary number of elements ("blueberry_pie_with_a_cup_of_coffee").

I guess that some kind of recursion is needed in 'regex' and 'format', but I have no idea of what to do.

How does one match arbitrary number of pattern occurrences?

Zoe
  • 27,060
  • 21
  • 118
  • 148
Darya
  • 89
  • 1
  • 3
  • Your not going to get an _arbitrary_ number of replacements. But, you could set up a regex to get say 20 or less. For example, this does 5 segments: `([a-z])([a-z]*)(?:_+([a-z])([a-z]*)(?:_+([a-z])([a-z]*)(?:_+([a-z])([a-z]*)(?:_+([a-z])([a-z]*))?)?)?)?` Adjust replacement as well. –  Jan 04 '18 at 23:27
  • Thanks for your answer! What does `?:...?` do? – Darya Jan 04 '18 at 23:47
  • `(?: anything )` is a non-capture group, it's known as a _cluster_ group. Adding a `?` after it makes it optional. –  Jan 05 '18 at 00:22

2 Answers2

18

UPDATE

vscode v1.75 is adding a Transform to Camel Case command, so rather than a snippet transformation you could select the result and trigger that command. Just FYI.


UPDATE

vscode v1.58 added a /camelcase transform. which makes your use case very easy now.

"${1/(.)(.*)/${1:/upcase}${2:/camelcase}/}"

to go from blueberry_pie_with_a_cup_of_coffee to BlueberryPieWithACupOfCoffee


"${1/(.*)/${1:/camelcase}/}" // just capture the whole thing

to go from blueberry_pie_with_a_cup_of_coffee to blueberryPieWithACupOfCoffee

vscode's implementation uses this regex: [a-zA-Z0-9] so anything other than those characters will be seen as separators - and the following "word" will be capitalized.



Previous answer::

To transform an arbitrary number of "_" separated words into CamelCase try:

EDIT: In October, 2018 (but not yet added to snippet grammar documentation as of February, 2020) vscode added the /pascalcase transform, see commit. I have modified the code below to use the /pascalcase transform. It only works for the some_file => SomeFile type of CamelCase though.

But it works with many characters as separators, these all work:

blueberry_pie_with_a_cup_of_coffee
blueberry-pie-with-a-cup-of-coffee
blueberry-pie-with_a-cup-of_coffee
blueberry-pie-with.a-cup-of.coffee
blueberry*pie-with.a*cup-of.coffee
blueberry*pie@with.a*cup1of.coffee
blueberry*pie@with.a*cup1of.coffee

"camelCase": {
    "prefix": "_cc",
    "body": [
            // "${TM_FILENAME_BASE/([a-z]*)_+([a-z]*)/${1:/capitalize}${2:/capitalize}/g}"

            "${TM_FILENAME_BASE/(.*)/${1:/pascalcase}/g}"
        ],
        "description": "Transform to camel case"
    },

carrot_cake.txt -> CarrotCake

blueberry_pie_with_a_cup_of_coffee.js -> BlueberryPieWithACupOfCoffee

[I assume CamelCase is the form you want, there are others, such as camelCase.]

For camelCase:

"${TM_FILENAME_BASE/([a-z]*)[-@_.*0-9]+([a-z]*)/$1${2:/capitalize}/g}"

put your desired list of separators in the [-@_.*0-9]+ part. The + quantifier allows you to use carrot--cake for example - multiple separators between words. Thanks to the other answer for using the [list the separators] part of the regex.

Note that the "g" flag at the end is doing most of that work for you in getting however many matches there are beyond the two explicitly captured.

I left the capture groups as ([a-z]*) as you had them. You may want to use ([A-Za-z0-9]*) for more flexibility.

Mark
  • 143,421
  • 24
  • 428
  • 436
  • Thank you! camelcase is not working it is putting comma between each word. example: submit-page.ts it is doing "submit,page" – Rupesh Kumar Tiwari Apr 24 '20 at 15:16
  • It isn't doing that for me and I tested it on your example `submit-page.ts`. There really is no way for it to be adding a `,` anywhere. You would have to post a new question with a gif showing it not working and your precise snippet - I think you have added a stray `,` somewhere it shouldn't be (like inside the quotes?). Same with the other answer - it isn't adding a `,` anywhere as well. – Mark Apr 24 '20 at 17:07
3

vs code snippet transform to camelCase:

"test": {
    "prefix": "test",
    "body": [
        "${1:${TM_FILENAME_BASE/^(.)([a-zA-Z0-9]*)([-_.])(.*)/${1:/downcase}${2}${4:/pascalcase}/}}"
    ]
}

wrapper is ${1:},

inner is ${TM_FILENAME_BASE/^(.)([a-zA-Z0-9]*)([-_.])(.*)/${1:/downcase}${2}${4:/pascalcase}/}

wrapper is ${}

inner is TM_FILENAME_BASE/^(.)([a-zA-Z0-9]*)([_\\W])(.*)/${1:/downcase}${2}${4:/pascalcase}/

string is TM_FILENAME_BASE

-------------------------------------------------------split

part 1 is /^(.)([a-zA-Z0-9]*)([-_.])(.*)

part 1.1 is ^(.)$1, first character

part 1.2 is ([a-zA-Z0-9]*)$2

part 1.3 is ([_\\W])$3, delimiter, ignore

part 1.4 is (.*)$4

-------------------------------------------------------replace

part 2 is /${1:/downcase}${2}${4:/pascalcase}/

part 2.1 ${1:/downcase} → lowercase

part 2.2 ${2} → normal

part 2.3 ${4:/pascalcase}


for-bar.service.js → fooBarService


Not strong enough, but enough.

山茶树和葡萄树
  • 2,050
  • 1
  • 18
  • 18