9

I'm working on a grammar extension in VS Code, and I'm having difficulty with a look behind regex pattern. Given the following string, I want to only return cmp when it's preceded by the @fmt(

@fmt(cmp,foo)

The matching string I used in another editor was this:

(?<=[@|©](fmt)\()(\w+)

However, this is not working in VS Code, when I do a regex search it comes back with the error that it's not a valid expression. Playing around with it, the problem is the <= characters, which indicate the look behind.

Doing a search of the VS Code website doesn't return any kind of regex reference guide. Searching Stack Overflow came up with this question, which states that Visual Studio has a unique regex definitions. Unfortunately, the example given in that question doesn't work in VS Code.

Does anyone know how to do a look behind regex in VS Code? Or at least know where the regex documentation for VS Code is located?

I worry that it's not possible, since according to Stack Overflow reference look behinds aren't supported in JavaScript. There is another question that shows how to mimic look behinds in a JavaScript function, but I don't know if it's possible to extend a language in VS Code with user-defined functions. If anyone knows how to do that, and can point me in that direction, that would also be an acceptable workaround.

Community
  • 1
  • 1
thomasjbarrett
  • 105
  • 1
  • 7
  • Thomas, what are you doing? Please explain what you need to do with `@fmt(cmp,foo)`? What is the final result? Find & highlight? Then you do not need the lookbehind at all, nor capturing groups - `[@©]fmt\(\w+` will be enough. – Wiktor Stribiżew Oct 07 '16 at 11:15
  • It's for syntax highlighting, I want the **@fmt** to be one color (function), and the **cmp** to be another color (parameter). There are multiple possible strings following the @ symbols, this was just a simplified example. – thomasjbarrett Oct 07 '16 at 18:56
  • I do have the **@fmt** portion working using the string **([@|©|®]\w+)**. I was just stumped with having the parameter inside the parentheses as a different color, which as I stated in the question I have working in my Editpad Pro syntax coloring. – thomasjbarrett Oct 07 '16 at 18:58

3 Answers3

6

Update

Visual Studio Code v.1.31.0 and up have regex lookbehind support, see Wiktor's answer


Visual Studio code uses JavaScript's regular expressions as specified in ECMAScript 5, which doesn't support look behinds (https://github.com/Microsoft/vscode/issues/8635).

Here's a workaround you can try if you're doing find and replace (thanks cyborgx37):

Search Expression:

(lookbehind_expression_)text_to_replace

Replace Expression:

$1replacement_text

Given the input:

lookbehind_expression_text_to_replace

The output will be:

lookbehind_expression_replacement_text

Benoît P
  • 2,684
  • 9
  • 30
Adam
  • 6,140
  • 10
  • 41
  • 80
5

You can use infinite-width lookahead and lookbehind without any constraint now beginning with Visual Studio Code v.1.31.0 release.

See proof:

enter image description here

and another one (with (?<=@fmt\([^()]*)\w+ pattern, note the * in the lookbehind):

enter image description here

See the Github [VSCode 1.31] ES2018 RegExp lookbehind assertions are now supported #68004 issue:

As a result of moving to Electron 3.0, RegExp lookbehind assertions are now supported, since they’re supported since Chromium 62 and Node 8.10.0, and Electron 3.0 uses Chromium 66 and Node 10.2.0, so they’re now supported, but the release notes don’t mention that lookbehind assertions are now supported.

VS Code developers confirm that it is true that they "forgot to mention it in the release notes".

Wiktor Stribiżew
  • 484,719
  • 26
  • 302
  • 397
-2

Look ahead and look behind both work in VS Code. Download some of the existing language plugins and look at their rules, to learn how this must be formulated. Here's a part from my ANTLR grammar extension:

{
  "name": "meta.rule.parser.antlr",
  "begin": "[[:lower:]][[:alnum:]_]*(?=.*?:)",
  "beginCaptures": {
    "0": { "name": "entity.name.function.parser.antlr" }
  },
  "end": "(?<=;)",
  "patterns": [
    {
      "name": "variable.other",
      "match": "\\[.*?\\]"
    },
    {
      "name": "keyword.other.antlr",
      "match": "\\b(returns|locals)\\b"
    },
    {
      "name": "keyword.other.antlr",
      "match": "@\\w+"
    },
    {
      "name": "entity.other.rule.option",
      "match":" <.*?>"
    },
    {
      "name": "variable.other.antlr",
      "match": "\\w+\\s*="
    },
    {
      "name": "entity.name.tag.antlr",
      "match": "#.*"
    },

    { "include": "#comments" },
    { "include": "#strings" },
    { "include": "#lexer-rule-reference" },
    { "include": "#parser-rule-reference" },
    { "include": "#predicate" },
    { "include": "#action" },
    { "include": "#wildcard-regexp" },
    { "include": "#regexp-parts" },
    { "include": "#options-list" }

  ]
}

The end match uses a look behind pattern. Keep also in mind you can nest patterns, i.e. you can define begin/end for a bigger structure (e.g. an entire function) and then match parts of it with sub patterns (and assign the individual style). This why you often don't need look ahead/behind because you know you are in a certain block of code.

For your pattern above: is the (\w+) part supposed to be part of the lookbehind pattern? If so it should be before the last closing parenthesis.

Mike Lischke
  • 36,881
  • 12
  • 88
  • 141
  • 2
    I tried the `(?<=)` syntax, still getting an invalid regular expression / invalid group error. It seems like VS code doesn't support back references: https://github.com/Microsoft/vscode/issues/8635 – Adam Jul 31 '17 at 23:15
  • Your lookarounds are all lookaheads, not lookbehinds. – Ryszard Czech Sep 13 '19 at 15:43
  • `(?=` is a positive lookahead, while `(?<=` is a positive lookbehind. – Mike Lischke Sep 14 '19 at 07:24