Search code examples
sublimetext3sublimetextsublime-text-plugin

Can I combine captures in Sublime Text syntax?


I'm writing the syntax for V which defines methods with a similar syntax to Go, where:

fn (o MyStruct) my_function(a int) {
  // ...
}

I might use something like (I will break it down into push, but just for brevity):

variables:
  ident: \b[A-Za-z_][A-Za-z_0-9]*\b

contexts:
  fn:
    - match: (fn)\s*\({{ident}}\s*({{ident}})\)\s*({{ident}})
      captures:
        1: keyword
        2: entity.name.type.v
        3: entity.name.function.v

But the problem is MyStruct and my_function are indexed separately, so methods of the same name (str() is a good example) will not be distinct to the indexer. Is there a way I can combine them into a single entity.name.function.v of value MyStruct.my_function?

I know I could treat the whole definition as the entity, but that's too verbose and won't work when split across multiple lines:

captures:
  0: entity.name.function.v

Solution

  • If you apply an unbroken/continuous scope to the text, you can target that in a .tmPreferences file (as opposed to the default entity.name scope) and index that, and make use of a "symbol index transformation" to remove the ) and spaces.

        - match: (fn)\s*\({{ident}}\s*(({{ident}})\)\s*({{ident}}))
          captures:
            1: keyword
            2: meta.indexed-unit.v
            3: entity.name.type.v
            4: entity.name.function.v
    

    Now the scope meta.indexed-unit.v would apply to the text MyStruct) my_function.

    A symbol index transformation is basically a regex replacement which applies to the indexed symbols:

    https://docs.sublimetext.io/reference/symbols.html#settings-subelements

    So your .tmPreferences file might look something like this:

    <?xml version="1.0" encoding="UTF-8"?>
    <!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
    <plist version="1.0">
    <dict>
      <key>scope</key>
      <string>source.v meta.indexed-unit.v</string>
      <key>settings</key>
      <dict>
        <key>showInIndexedSymbolList</key>
        <string>1</string>
        <key>symbolIndexTransformation</key>
        <string>
           s/\)\s*//;
        </string>
      </dict>
    </dict>
    </plist>