Syntax highlighting, semantic coloring, and live diagnostics for G-Code (ISO 6983 / Siemens SINUMERIK 840D sl / 828D), tailored to Blohm grinding cycles and the Blohm variable naming conventions.
Supported file extensions: .gcode · .nc · .cnc · .gc · .ngc · .txt · .mpf · .spf
Features
Syntax highlighting
- G / M commands —
G0,G1,G41.1,M3,M30, … - Siemens 840D cycles & commands —
CYCLE832,POCKET3,TRANS,ROT,SCALE,MIRROR,MCALL,CALL,RET,STOPRE,MSG,SPOS,Pos/POSA, interrupt keywords (SETINT,PRIO,BLSYNC,LIFTFAST,CLRINT, …) and more. - R-parameters —
R1,R100, … - Blohm variables — identifiers ending in
_(e.g.MyVar_),$-system variables (e.g.$AA_IW,$TC_DP1), and plain mixed-case globals. - Comments —
;and'line comments (semicolons inside(...)and"..."are not treated as comments). - Function calls, DEF/DEFINE keywords, type keywords, labels, and the
%_N_…program header.
Semantic (depth-based) coloring
Nesting levels are colorized by depth (5 cycling levels) for:
IF/ELSE/ENDIFFOR/ENDFORandWHILE/ENDWHILE- Parentheses
( ) - Variable index brackets
[ ](e.g.$AN_CEC_STEP[N_LOOP1])
Diagnostics (error / warning squiggles)
| Severity | Rule |
|---|---|
| 🔴 Error | Undefined variable — used but never declared (locally or in a global DEF/GUD file) |
| 🔴 Error | Unclosed function call, [, or (; unexpected ) |
| 🔴 Error | Empty R-assignment (e.g. R11= with no value) |
| 🔴 Error | Assignment (=) used instead of == inside IF / WHILE / WHEN conditions |
| 🔴 Error | Standalone number not attached to an address/expression |
| 🔴 Error | DEF after the first G/M command |
| 🔴 Error | Unmatched / unexpected IF, ELSE, ENDIF, ENDFOR, ENDWHILE; unclosed loops at EOF |
| 🔴 Error | WHEN without DO; REPEAT without two valid labels |
| 🔴 Error | Commented-out program header / missing ;$PATH= / PROC name mismatch with header |
| 🔴 Error | Wrong number of indexes on a $TC_ tool-data variable (e.g. $TC_DP4[t,d] needs 2, $TC_TPC4[t] needs 1) |
| ⚠️ Warning | Unused variable — declared with DEF but never referenced |
| ⚠️ Warning | Undefined or wrong-direction GOTOF / GOTO / GOTOB label target |
| ⚠️ Warning | Missing DISPLOF on a PROC line |
Cross-file variable resolution
On workspace open, all DEF/GUD files (first line matching %_N_*_DEF) are pre-scanned so variables declared there — including commented-out DEF lines — are known globally and won't be flagged in other files. PROC parameter lists (including STRING[n]) are treated as local declarations. Matching is case-insensitive, and diagnostics refresh live when a DEF file is saved.
Hover documentation
Bilingual (DE/EN) hover tooltips sourced from the Siemens SINUMERIK 840D sl / 828D documentation for:
GandMcommands (including parameterized forms likeM31=10)Rparameters andOPTI1_[n]option bits$-variables (691+ BTSS parameters), with per-tool-type tables for$TC_*tool parameters- Path methods (
ASPLINE,CUT3DCC,SUPA, …) andTOFF/TOFFL/TOFFR
Go to Definition
F12 (or Ctrl+click / Go to Definition) navigates from a name to where it is declared:
| Name under the cursor | Jumps to |
|---|---|
Cycle call — SEL_STATION(…) |
The PROC SEL_STATION(…) line, in whichever workspace file defines it |
Jump-label target — GOTOF MARKE1, REPEAT START_ END_ |
The MARKE1: label definition (labels are file-local) |
Variable — AX4_, OPTI1_[3] |
Its DEF / DEFINE … AS / PROC parameter declaration — in this file, or in the DEF/GUD file that declares it globally |
The cursor lands on the declared name itself, so Peek Definition (Alt+F12) shows the declaration in context. Names with no declaration to jump to ($-system variables, R parameters, G/M commands) are left alone.
Editor integration
- Bracket-pair highlighting, auto-closing pairs, and surrounding pairs for
( ),[ ], and"…".
Extension settings
| Setting | Type | Default | Description |
|---|---|---|---|
blohmGCode.txtCheckPaths |
string[] |
["content/Zyklen"] |
Directories whose .txt files are checked (linted) as G-Code. |
Directories whose .txt files are checked (linted) as G-Code. Paths may be absolute or relative to a workspace folder — the default content/Zyklen resolves against the VS Code working directory (workspace root). When the list is empty, all .txt files are checked. Files with unambiguous G-Code extensions (.mpf, .spf, .nc, .gcode, .cnc, .gc, .ngc) are always checked regardless of this setting. This affects only the VS Code editor — the lint:gcode CLI is controlled solely by its own --dir argument.
// .vscode/settings.json
{
"blohmGCode.txtCheckPaths": ["content/Zyklen", "C:\\NC\\programs"]
}
CLI linter (CI / Azure DevOps)
A standalone command-line linter (out/cli.js) runs the same diagnostic checks in a pipeline:
npm run bundle:cli
node out/cli.js --dir <path> [--exclude "<glob>"]... [--fail-on-warnings]
- Scans a directory recursively for supported G-Code files.
- Resolves cross-file variables by pre-scanning DEF/GUD files first.
- Decodes UTF-16 LE (the SINUMERIK default), UTF-8, and UTF-8-with-BOM.
- In Azure DevOps (
TF_BUILD=True), emits each finding as an##vso[task.logissue]annotation and fails the stage on errors (or warnings with--fail-on-warnings).
Building & packaging
npm ci
npm run bundle # bundle client + server + CLI into out/
npm run release # produce a .vsix package
| Script | Purpose |
|---|---|
npm run bundle |
Bundle the extension client, language server, and CLI |
npm run compile / npm run watch |
TypeScript compile (one-shot / watch) |
npm run lint:gcode |
Build the CLI and lint the bundled ./examples |
npm run release |
Bundle and package a .vsix via vsce |