skip to Main Content

I’m trying to write a Visual Studio Code snippet that converts Pascal case to lowercase with spaces. I’m almost there:

${1/([A-Z]*)([A-Z][a-z]+)/$1 ${2:/downcase} /g}

Group 1 matches acronyms and group 2 matches capitalized words.

So if the placeholder were MyUIDTest, the expected result would be my UID test. But currently I get my UID test (notice the spaces on either side).

How do I only add a space after group 1 if group 1 has a match? And how do I remove the space at the end of the line?

2

Answers


  1. According to the docs, ${1:+ } means "insert a space iff group 1 is captured":

    ${
      TM_SELECTED_TEXT
      /
        (?<=([A-Za-z])?)      # Lookbehind for and capture ($1) a preceding letter, if any,
        (?:                   # then match a "word" – either
          ([A-Z]+)(?![a-z])   # ($2) 1+ uppercase not followed by a lowercase
        |                     # or
          ([A-Z][a-z]+)       # ($3) an uppercase followed by 1+ lowercase.
        )                     #
      /                       # Replace each match with
        ${1:+u0020}          # a space, iff group 1 is captured,
        ${2:/upcase}          # the uppercase version of group 2
        ${3:/downcase}        # and the lowercase version of group 3.
      /g                      # for all matches found.
    }
    

    Since $2 and $3 are mutually exclusive, using them both always results in only one being actually inserted.

    Before After
    PascalCase pascal case
    MyUIDTest my UID test
    FoOBaR fo O ba R

    A more precise (and verbose) version would be (note that b needs to be escaped again when written in a JSON string: "\b"):

    ${
      TM_SELECTED_TEXT
      /
        (?<=                                    # Lookbehind for
          b                                    # a word boundary followed by
          ([A-Z]+(?![a-z])|[A-Z][a-z]+)*        # 0+ "words"
                                                # and capture the last word, if any.
        )
        (?:([A-Z]+)(?![a-z])|([A-Z][a-z]+))
      /
        ${1:+u0020}${2:/upcase}${3:/downcase}
      /g
    }
    

    I’m using TM_SELECTED_TEXT here, but you might want to change that depending on your needs.

    Login or Signup to reply.
  2. I think to remove the space at the end of the line,you can simply add a newline character at the end of the replacement pattern, and when you use the snippet with the placeholder "MyUIDTest", it should correctly produce "my UID test" without any extra spaces.

    ${1/(?:([A-Z]+)(?=[A-Z][a-z]))?([A-Z][a-z]+)/$1 ?${2:/downcase} :''/g}n
    

    also to add a space after group 1 only if it has a match, you can use a conditional statement in the replacement pattern

    ${1/(?:([A-Z]+)(?=[A-Z][a-z]))?([A-Z][a-z]+)/$1 ?${2:/downcase} :''/g}
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search