0
0
Fork 0
Codesys-MCP-SP21-plus/tests/tui/highlight.test.ts
Karstein Phobic Nyvold Kvistad 3da09f8aba tui(viewer): ST keyword/type/comment/string syntax highlighting
tokenize(line) splits a single line into typed tokens:
  keyword (cyan)   PROGRAM, FUNCTION_BLOCK, IF/THEN/ELSE/END_IF,
                   FOR/TO/DO, VAR/END_VAR, CASE/OF, AND/OR/XOR/NOT,
                   TRUE/FALSE, EXTENDS, IMPLEMENTS, etc.
  type    (magenta) BOOL, INT, DINT, REAL, LREAL, TIME, STRING,
                   ANY_*, ARRAY, POINTER, REFERENCE, etc.
  comment (gray)   (* ... *) inline and // line-to-end
  string  (yellow) 'single' and "double" quoted
  text    (none)   everything else

Identifier matching is case-sensitive uppercase only — matches
typical IEC 61131-3 convention and avoids false positives on lower-
case identifiers like if_x. Multi-line (* ... *) comments are not
joined across lines (out-of-scope for v0.2).
2026-04-29 08:22:09 +02:00

57 lines
1.9 KiB
TypeScript

import { describe, it, expect } from 'vitest';
import { tokenize, TokenKind } from '../../src/tui/browser/highlight';
function kinds(line: string): TokenKind[] {
return tokenize(line).map((t) => t.kind);
}
function texts(line: string): string[] {
return tokenize(line).map((t) => t.text);
}
describe('tokenize', () => {
it('returns a single text token for plain identifiers', () => {
expect(tokenize('foo bar baz')).toEqual([{ kind: 'text', text: 'foo bar baz' }]);
});
it('flags ST keywords (uppercase)', () => {
const ts = tokenize('PROGRAM PLC_PRG');
expect(ts.find((t) => t.text === 'PROGRAM')?.kind).toBe('keyword');
expect(ts.find((t) => t.text === 'PLC_PRG')?.kind).toBe('text');
});
it('flags END_VAR / END_IF compound keywords', () => {
const ts = tokenize('END_VAR END_IF END_FOR');
expect(ts.filter((t) => t.kind === 'keyword').map((t) => t.text)).toEqual([
'END_VAR',
'END_IF',
'END_FOR',
]);
});
it('flags IEC types', () => {
const ts = tokenize('counter : INT := 0;');
expect(ts.find((t) => t.text === 'INT')?.kind).toBe('type');
});
it('does not flag lowercase variants of keywords', () => {
const ts = tokenize('program plc_prg');
expect(ts.every((t) => t.kind !== 'keyword')).toBe(true);
});
it('captures (* ... *) comments inline', () => {
expect(kinds('x := 1; (* a comment *) y := 2;')).toContain('comment');
expect(texts('x := 1; (* a comment *) y := 2;')).toContain('(* a comment *)');
});
it('captures // line comments to end of line', () => {
const ts = tokenize('x := 1; // trailing');
expect(ts.at(-1)?.kind).toBe('comment');
expect(ts.at(-1)?.text).toBe('// trailing');
});
it("captures 'single-quoted' and \"double-quoted\" strings", () => {
expect(texts("s := 'hello';")).toContain("'hello'");
expect(texts('s := "hi";')).toContain('"hi"');
});
});