Setup for CodeMirror 5 with Angular 16

Hello,

I am new to CodeMirror and Lezer and I am trying to create a custom language parser for ABL (OpenEdge) syntax, with Lezer, and use it in the CodeMirror editor, for the highlighting feature.

Here is what I have until now:

  • in package.json:
"@ctrl/ngx-codemirror": "^7.0.0",
"codemirror": "^5.65.15",
"@types/codemirror": "^5.60.12",
"lezer-generator": "^0.13.4",
"@lezer/generator": "^1.1.1",
"@lezer/highlight": "^1.1.6",
  • openedge.grammar file:
@top Program { expression* }

@skip { space | LineComment }

expression {
  Identifier |
  String |
  Boolean |
  Application { "(" expression* ")" }
}

@tokens {
  Identifier { $[a-zA-Z_\-0-9]+ }

  String { '"' (!["\\] | "\\" _)* '"' }

  Boolean { "#t" | "#f" }

  LineComment { /\/\*\*(?!\/)/, '\\*/' }

  space { $[ \t\n\r]+ }

  "(" ")"
}

@detectDelim
  • the parser in openedge.ts file (this was generated using the command “npx @lezer/generator openedge.grammar -o openedge.js”):
import {LRParser} from "@lezer/lr"
export const parser = LRParser.deserialize({
  version: 14,
  states: "!WQYQPOOOhQPO'#CdOOQO'#Ci'#CiOOQO'#Ce'#CeQYQPOOOOQO,59O,59OOyQPO,59OOOQO-E6c-E6cOOQO1G.j1G.j",
  stateData: "![~O[OSPOS~ORQOSQOTQOVPO~ORQOSQOTQOUTOVPO~ORQOSQOTQOUWOVPO~O",
  goto: "u^PPPPPPPP_ePPPoXQOPSUQSOQUPTVSUXROPSU",
  nodeNames: "⚠ LineComment Program Identifier String Boolean ) ( Application",
  maxTerm: 13,
  nodeProps: [
    ["openedBy", 6,"("],
    ["closedBy", 7,")"]
  ],
  skippedNodes: [0,1],
  repeatNodeCount: 1,
  tokenData: "%c~R^XY}YZ}]^}pq}rs!`st#|xy$[yz$a}!O$f!Q![$f!]!^$z!c!}$f#R#S$f#T#o$f~!SS[~XY}YZ}]^}pq}~!cVOr!`rs!xs#O!`#O#P!}#P;'S!`;'S;=`#v<%lO!`~!}OS~~#QRO;'S!`;'S;=`#Z;=`O!`~#^WOr!`rs!xs#O!`#O#P!}#P;'S!`;'S;=`#v;=`<%l!`<%lO!`~#yP;=`<%l!`~$PQ#Y#Z$V#h#i$V~$[OT~~$aOV~~$fOU~~$kTR~}!O$f!Q![$f!c!}$f#R#S$f#T#o$f~%PSP~OY$zZ;'S$z;'S;=`%]<%lO$z~%`P;=`<%l$z",
  tokenizers: [0],
  topRules: {"Program":[0,2]},
  tokenPrec: 0
})
  • the openedge.language.ts file:
import { parser } from './openedge';
import { LRLanguage, LanguageSupport, indentNodeProp, foldNodeProp, foldInside, delimitedIndent } from '@codemirror/language';
import { styleTags, tags as t } from '@lezer/highlight';

export const OpenedgeLanguage = LRLanguage.define({
  parser: parser.configure({
    props: [
      indentNodeProp.add({
        Application: delimitedIndent({closing: ")", align: false})
      }),
      foldNodeProp.add({
        Application: foldInside
      }),
      styleTags({
        Identifier: t.variableName,
        Boolean: t.bool,
        String: t.string,
        LineComment: t.lineComment,
        "( )": t.paren
      })
    ]
  }),
  languageData: {
    commentTokens: {line: ";"},
    keywords: {
      tokens: 'RE::/(message|error)\\b/i', // "message" and "error" are the keywords that need to be highlighted for now 
      autocomplete: ['message', 'error'],
      caseInsensitive: true}
  },
})

export function Openedge() {
  return new LanguageSupport(OpenedgeLanguage)
}
  • the component that contains the CodeMirror editor:
import { LanguageSupport, language } from '@codemirror/language';
import { CodemirrorComponent } from '@ctrl/ngx-codemirror';
import { Openedge } from './openedge-grammar/openedge.language';
import { basicSetup } from "@codemirror/basic-setup";

@Component({
  selector: "abl-editor-codemirror",
  templateUrl: "./abl-editor-codemirror.component.html",
  styleUrls: ["./abl-editor-codemirror.component.css"]
})
export class AblEditorCodeMirrorComponent implements OnInit, AfterViewInit {
  private _openedge: LanguageSupport;
  public openedgeOptions: any;

  // ...
  ngOnInit(): void {
    this._openedge = Openedge();

    this.openedgeOptions = {
      extensions: [
        basicSetup,
        language.of(this._openedge.language)
      ],
      lineNumbers: true,
    }
  }
}

  • the component template containing the CodeMirror editor:
<ngx-codemirror
  #editor
  [options]="openedgeOptions"
  [autoFocus]="true"
></ngx-codemirror>

The editor is currently only highlighting comments (single/multiline) and strings.
Do I have a correct setup?
Where can I add the custom language keywords (e.g.“message”, “error”, “block-level”) to be highlighted?

Those would have to become part of your grammar (see this example), supposedly as part of grammar rules that recognize the constructs they are part of.