0

My vscode extensions tmLanguage is not explicitly built for JavaScript, but I will use it as an example because it demonstrates the best use case. Take the following example:

 1  function {
 2     var p = 9;
 3 
 4     function do() {
 5       console.log(p);
 6     } 
 7
 8     var expr = function() {
 9        console.log(p);
10     }
11
12     var cons = new Function('\tconsole.log(p);');
13
14     var arrow = () => { console.log(p); }
15  }
16
17  function 
18  {
19     console.log('hello world');
20
21     return 'hello world';
22  }

My goal is to capture Line #1 as the beginning and line #15 as the end tokens and line #2-14 as the function-body token. And repeat respectively for lines #17-22. Note that my function starting line is not white-space specific and potentially be on a new line per users discretion.

I have tried many different ways, using \G anchor or otherwise and the following grammar example is the closest I've been. However, it stops after the first found closing braces }, or line #6 in my example above. I would like it to end capture at line #15

functions:
  patterns:
    - begin: (?:^|\s)(function)\s+
      beginCaptures: 
        '1' : { name: meta.tag.function-name  }
      end : (?<=(\}))
      endCaptures: 
        '1' : { name: entity.punctuation.definition.end }
      patterns:
        - begin: \{
          beginCaptures:
            '1' : { name: entity.punctuation.definition.start }
          end : \}
          patterns:
            - begin: \s*
              end : "[^\\}]*"
              name: meta.tag.function-body

My example is using yaml but anything you're comfortable using that works with vscode is fine


edit Based on the Gama11's feedback I was able to get it working. Essentially the most important part of the process is recursion. So basically I didn't change anything but add a recursive regex for finding {} pairs. Here is the working example:

patterns:
  - begin: (?:^|\s)(function)\s+
    beginCaptures: 
      '1' : { name: meta.tag.function-name  }
    end : (?<=\})
    patterns:
      - begin : \{
        beginCaptures: 
          '0' : { name: entity.punctuation.definition.start }
        end : \}
        endCaptures: 
          '0' : { name: entity.punctuation.definition.end }
        contentName: meta.tag.function-body
        patterns :
          - include : '#parens'
repository:
  parens: 
    - patterns:
      - begin :  \{
        end : \}
        patterns: 
          - include : '#parens'
soulshined
  • 9,612
  • 5
  • 44
  • 79
  • 1
    I think this could be considered a duplicate of https://stackoverflow.com/questions/56279964/how-to-use-as-the-comment-indicator-but-also-not-operator-in-language-synta/56280539#56280539? You need to solve pretty much the same issue here: applying a _recursive_ pattern between start and end to match the additional `{` / `}` tokens, to make sure `end` doesn't match too early. In my answer in the other question it's about `(` / `)`, but same idea. – Gama11 May 26 '19 at 15:26
  • great. thanks for the feedback @Gama11 that example assumes the `\(` starts on the same line as `eval`, whereas mine can be on the same line or the next. For brevity, the 'function-body' portion of my block will actually be an embedded language, and for my example, it's javascript, but can be others, so I would like to be able to identify the whole block where I can use an `include` statement conditionally based on the embedded languages syntax highlighting needs. If that's a good way of wanting to accomplish it? – soulshined May 26 '19 at 15:49
  • A simple workaround might be to only match `function` to `}` with `begin` / `end` and then match `{` separately within the patterns of that. – Gama11 May 26 '19 at 16:48
  • 1
    I thought that's what I was doing in my example :( but I did get it working based off your other example as long as it starts on the same line, so thanks for that @Gama11 . I will play around with it and see if I can get it going with braces potentially being on a new line. – soulshined May 26 '19 at 16:53
  • Ah, yeah. Tbh, I hadn't looked at the YAML in detail yet. – Gama11 May 26 '19 at 16:55
  • it's ok, to be even more fair, that disclaimer is kind of important to my particular language and I didn't mention that it's not white-space specific anywhere – soulshined May 26 '19 at 17:01
  • I updated my question to better support the whitespace caveat @Gama11 and provide an updated status. Would you mind reviewing for potential fallbacks of my working example? I would argue its not the same question as the potential duplicate you provided because that question isn't revolving around nested `eval()` statements, just a particular comment pattern. I think this is more SEO friendly specific to the situation because that question didn't show up when I searched for this issue. But i'll leave that up to you if you want to answer or not. Either way I sincerely appreciate you helping me. – soulshined May 26 '19 at 17:18
  • Not sure what purpose me adding an answer would serve, seems your question already contains the answer now, no? :) – Gama11 May 26 '19 at 19:26
  • Well, it's one way of doing it I guess, just what works for me, not sure if there is a 'better' alternative. Regardless, I didn't come to that conclusion without you, so you did answer it. Just want to extend StackOverflow courtesy for credit due, but no problem @Gama11 – soulshined May 26 '19 at 19:41

0 Answers0