Sublime Text snippet to insert PSR-0 namespace

2019-05-26 16:07发布

问题:

I'm trying to make a Sublime Text-snippet that inserts a PHP boilerplate class, in the lines of:

<?php

namespace Namespace\Subnamespace;

class TestClass
{
    public function __construct()
    {
        //code...
    }
}

When using PHP-FIG standards(or similar), both the namespace and classname can be obtained from the path of the file. The file in the example above would be placed in /Users/Projects/Whatever/src/Namespace/Subnamespace/TestClass.php.

This is what I have so far:

<snippet>
    <content><![CDATA[
<?php
namespace ${1:Namespace};

class ${TM_FILENAME/(.*)[.](.*)/$1/g}
{
    public function __construct()
    {
        ${0://code...}
    }
}
]]></content>
    <tabTrigger>phpclass</tabTrigger>
    <scope>text.html</scope>
</snippet>

I've already figured out how to get the classname - but getting the namespace has proven to be much more difficult. I'm far from an expert in regexes - and this one requires:

  1. Getting everything after src/
  2. ...and before the last /
  3. Flipping all the remaining slashes to backslashes.

/Users/Projects/Whatever/src/Namespace/Subnamespace/TestClass.php becomes Namespace\Subnamespace.

This is the most relevant thread I've found on the subject, but it is way over my head, and I couldn't even get it working.

Can anyone help me with this?

回答1:

Here is a namespace substitution that works at more than 2 levels in ST-3:

namespace ${1:${TM_FILEPATH/(?:.*src\/)|(\/)?([^\/]+)(?=\/)|(?:\/[^\/]+\.php$)/(?1:\\$^N:$^N)/g}};

file: /path/to/project/src/sub1/sub2/sub3/sub4/class.php

output: namespace sub1\sub2\sub3\sub4;



回答2:

I did manage to get it working, but it is sadly limited to a specified number of namespace-levels. Since my current project always has 2 levels (Project\Namespace) it works well for now. But it is not the optimal solution.

Here is the regex:

(?:^.*src\/|\G)(.*?)\/(.*?)\/(?:.*php|\G)
  1. Non capturing selection of everything up to src/
  2. Select everything to next /. ("Namespace")
  3. Do step 2 again. ("Subnamespace")
  4. Non capturing selection of the filename

Then I do a replace with $1\\$2, which puts the captures from step 2 and 3 with a backslash between.

The full snippet-ready version is:

${TM_FILEPATH/(?:^.*src\/|\G)(.*?)\/(.*?)\/(?:.*php|\G)/$1\\$2/g}

This will output Namespace\Subnamespace.

It works for now, but I would very much like to see a version that works for any number of namespace levels.