Regex for SublimeText Snippet

I’ve been stuck on this exalted fragment for some time.

I would like to display the correct package name when creating a new class using TM_FILEPATH and TM_FILENAME .

When printing the TM_FILEPATH variable TM_FILEPATH I get something like this:

/Users/caubry/d/[...]/src/com/[...]/folder/MyClass.as

I would like to convert this output, so I could get something like:

com.[...].folder

It includes:

  • Removing anything before /com/[...]/folder/MyClass.as ;
  • Removing TM_FILENAME with extension; in this example, MyClass.as ;
  • And finally, find all the slashes and replace them with dots.

So far this is what I have:

${1:${TM_FILEPATH/.+(?:src\/)(.+)\.\w+/\l$1/}}

and displays:

com/[...]/folder/MyClass

I understand how to replace splashes with dots, for example:

${1:${TM_FILEPATH/\//./g/}}

However, it is difficult for me to add this logic to the previous one, as well as remove TM_FILENAME at the end of the logic.

I'm really inexperienced with Regex, thanks in advance.

:]

EDIT: [...] indicates a variable number of folders.

+4
source share
1 answer

We can do this in one replacement with some trickery. What we will do, we put several different cases in our template and make another replacement for each of them. The trick for this is that the replacement string should not contain alphabetic characters, but consists solely of "backlinks". In this case, those groups that did not participate in the match (because they were part of another case) will simply be recorded as an empty line and will not facilitate replacement. Let's start.

First, we want to delete everything to the last src/ (to simulate the behavior of your fragment) - use a fuzzy quantifier if you want to delete everything to the first src/ ):

 ^.+/src/ 

We just want to give up on this, so there is no need to write anything or write anything.

Now we want to map subsequent folders to the last. We write the name of the folder, also match the final / , but write the name of the folder and . . But I did not say the literal text in the replacement string! In this way . must come from capture. Here comes the assumption that your file always has the extension. We can get the period from the file name using lookahead. We will also use this look to make sure there is another folder ahead:

 ^.+/src/|\G([^/]+)/(?=[^/]+/.*([.])) 

And we will replace this with $1$2 . Now, if the first alternative is caught, the groups $1 and $2 will be empty, and the leading bit will still be deleted. If the second choice catches, $1 will be the name of the folder, and $2 will be captured by the period. Sweet. \G is an anchor that ensures that all matches are adjacent to each other.

Finally, we compare the last folder and everything that follows it, and write only the folder name:

 ^.+/src/|\G([^/]+)/(?=[^/]+/.*([.]))|\G([^/]+)/[^/]+$ 

And now we will replace this with $1$2$3 for the final decision. Demo

A conceptually similar option would be:

 ^.+/src/|\G([^/]+)/(?:(?=[^/]+/.*([.]))|[^/]+$) 

replaced by $1$2 . I really only legalized the beginning of the second and third alternatives. Demo.

Finally, if Sublime uses Boost's extended format string syntax , you can actually conditionally get characters to replace (without spelling them magically) from the file extension):

 ^.+/src/|\G(/)?([^/]+)|\G/[^/]+$ 

Now we have the first alternative for everything up to src (which should be deleted), the third alternative for the last slash and file name (which should be deleted), and the middle alternative for all the folders you want to keep. This time I put a slash instead of optionally at the beginning. With conditional replacement we can write . there if and only if this slash was matched:

 (?1.:)$2 

Unfortunately, I cannot verify this right now, and I do not know an online tester that uses the Boost regex engine. But that should do the trick just fine.

+4
source

Source: https://habr.com/ru/post/1501370/


All Articles