@duet3d/monacotokens 3.7.0-rc.3 → 3.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -13,6 +13,8 @@ function generateMonarchLanguage(fdmMode) {
13
13
  flowExprKeywords: ["if", "elif", "while"],
14
14
  // Flow-control keywords that stand alone - render in the same purple as flowExprKeywords
15
15
  flowNoArgKeywords: ["else", "break", "continue"],
16
+ // Standalone keywords that don't affect control flow - render as regular keywords (blue)
17
+ noArgKeywords: ["skip"],
16
18
  varKeywords: ["global", "var"],
17
19
  symbols: /[=><!~?:&|+\-*#\/\^%]+/,
18
20
  operators: ['*', '/', '+', '-', "==", "!=", '=', "<=", '<', ">=", ">>>", ">>", '>', '!', "&&", '&', "||", '|', '^', '?', ':'],
@@ -38,6 +40,7 @@ function generateMonarchLanguage(fdmMode) {
38
40
  "@keywords": { token: "keyword", next: "@lineExpression" },
39
41
  "@flowExprKeywords": { token: "keyword.flow", next: "@lineExpression" },
40
42
  "@flowNoArgKeywords": { token: "keyword.flow" },
43
+ "@noArgKeywords": { token: "keyword" },
41
44
  "@varKeywords": { token: "keyword", next: "varName" }
42
45
  }
43
46
  }],
package/dist/providers.js CHANGED
@@ -304,25 +304,24 @@ function isInsideStringLiteral(beforeCursor) {
304
304
  }
305
305
  return inString;
306
306
  }
307
- /** Walk `beforeCursor` and report whether the cursor sits past an unescaped `;` line comment marker. */
308
- function isInsideLineComment(beforeCursor) {
309
- let inString = false;
310
- for (let i = 0; i < beforeCursor.length; i++) {
311
- const ch = beforeCursor[i];
312
- if (inString) {
313
- if (ch === "\"") {
314
- inString = false;
315
- }
316
- continue;
317
- }
318
- if (ch === "\"") {
319
- inString = true;
320
- }
321
- else if (ch === ";") {
322
- return true;
307
+ /**
308
+ * Report whether the character at zero-based `offset` of a line is part of a comment, as classified by the
309
+ * language's own tokenizer - so `;` comments and the CNC-only `(...)` comments are both covered. Lines are
310
+ * tokenized in isolation, which is safe because every tokenizer state pops at end-of-line.
311
+ */
312
+ function isCommentAt(monacoInstance, model, lineNumber, offset) {
313
+ if (offset < 0) {
314
+ return false;
315
+ }
316
+ const tokens = monacoInstance.editor.tokenize(model.getLineContent(lineNumber), model.getLanguageId())[0] ?? [];
317
+ let type = "";
318
+ for (const token of tokens) {
319
+ if (token.offset > offset) {
320
+ break;
323
321
  }
322
+ type = token.type;
324
323
  }
325
- return false;
324
+ return type.startsWith("comment");
326
325
  }
327
326
  /**
328
327
  * Detect whether the cursor sits inside an RRF expression context:
@@ -385,7 +384,8 @@ const metaKeywords = [
385
384
  { keyword: "var", syntax: "var <name> = <expression>", description: "Declare a local variable" },
386
385
  { keyword: "global", syntax: "global <name> = <expression>", description: "Declare a global variable" },
387
386
  { keyword: "abort", syntax: "abort [<message>]", description: "Abort the running macro / queued moves with an optional message" },
388
- { keyword: "echo", syntax: "echo <expression>", description: "Print an expression to the response channel" }
387
+ { keyword: "echo", syntax: "echo <expression>", description: "Print an expression to the response channel" },
388
+ { keyword: "skip", syntax: "skip", description: "Do nothing" }
389
389
  ];
390
390
  /**
391
391
  * Find the closest G/M/T-code to the left of `column` on the given line.
@@ -810,6 +810,10 @@ export function registerProvidersFor(monacoInstance, languageId) {
810
810
  disposables.push(monacoInstance.languages.registerCompletionItemProvider(languageId, {
811
811
  triggerCharacters: ["G", "M", "T", "g", "m", "t", " ", "{", ".", "=", "!", "\""],
812
812
  provideCompletionItems: (model, position, context) => {
813
+ // Trigger characters bypass Monaco's quickSuggestions.comments gate, so check the token ourselves
814
+ if (isCommentAt(monacoInstance, model, position.lineNumber, position.column - 2)) {
815
+ return { suggestions: [] };
816
+ }
813
817
  const lineContent = model.getLineContent(position.lineNumber);
814
818
  const beforeCursor = lineContent.substring(0, position.column - 1);
815
819
  // A manual Ctrl+Space (Invoke) always shows the list; an auto-trigger (TriggerCharacter or
@@ -1036,10 +1040,10 @@ export function registerProvidersFor(monacoInstance, languageId) {
1036
1040
  if (isInsideStringLiteral(beforeCursor)) {
1037
1041
  return null;
1038
1042
  }
1039
- // Cursor past a `;` on the same line: we're inside a line comment (e.g. after bksp joins a line
1040
- // onto a previous commented line like "M106 P1 S255 ; note"). No signature help applies there,
1041
- // and without this guard Monaco would keep the previous parameter's tooltip floating over prose.
1042
- if (isInsideLineComment(beforeCursor)) {
1043
+ // Cursor inside a comment (e.g. after bksp joins a line onto a previous commented line like
1044
+ // "M106 P1 S255 ; note"). No signature help applies there, and without this guard Monaco would
1045
+ // keep the previous parameter's tooltip floating over prose.
1046
+ if (isCommentAt(monacoInstance, model, position.lineNumber, position.column - 2)) {
1043
1047
  return null;
1044
1048
  }
1045
1049
  // In an expression context the only meaningful signature help is the enclosing function call -
@@ -1231,6 +1235,10 @@ export function registerProvidersFor(monacoInstance, languageId) {
1231
1235
  provideHover: async (model, position) => {
1232
1236
  const lineContent = model.getLineContent(position.lineNumber);
1233
1237
  const word = model.getWordAtPosition(position);
1238
+ // Comment text may contain G/M-code letters that would otherwise match
1239
+ if (isCommentAt(monacoInstance, model, position.lineNumber, (word ? word.startColumn : position.column) - 1)) {
1240
+ return null;
1241
+ }
1234
1242
  if (!word) {
1235
1243
  // No identifier-shaped word under the cursor (e.g. cursor on `*` in `M586 C"*"`, on `?` etc.).
1236
1244
  // Try to resolve the cursor as a parameter value position via findParameterAtCursor; if it
@@ -1258,12 +1266,6 @@ export function registerProvidersFor(monacoInstance, languageId) {
1258
1266
  // prevents `"M104 done"` style false matches lives down at the wordIsCode branch
1259
1267
  const beforeWordForString = lineContent.substring(0, word.startColumn - 1);
1260
1268
  const insideString = isInsideStringLiteral(beforeWordForString);
1261
- // Suppress hover inside `;` line-comments - the tokeniser colours them as comments but the hover
1262
- // provider runs independently and would otherwise match G/M-code letters that appear in comment text
1263
- const semi = lineContent.indexOf(";");
1264
- if (semi >= 0 && word.startColumn - 1 >= semi) {
1265
- return null;
1266
- }
1267
1269
  // Determine up-front whether the word sits inside an expression context - used to route hover between
1268
1270
  // the gcode-parameter flavour (outside expressions) and the function/constant flavour (inside)
1269
1271
  const beforeWord = lineContent.substring(0, word.startColumn - 1);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@duet3d/monacotokens",
3
- "version": "3.7.0-rc.3",
3
+ "version": "3.7.0",
4
4
  "description": "TypeScript library that holds syntax highlighting files for the Monaco editor",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -26,17 +26,17 @@
26
26
  },
27
27
  "homepage": "https://github.com/Duet3D/MonacoTokens#readme",
28
28
  "peerDependencies": {
29
- "@duet3d/objectmodel": "~3.7.0-beta.2",
30
- "monaco-editor-core": "^0.56.0",
31
- "monaco-editor": "^0.56.0"
29
+ "@duet3d/objectmodel": "~3.7.0",
30
+ "monaco-editor-core": "^0.57.0",
31
+ "monaco-editor": "^0.57.0"
32
32
  },
33
33
  "peerDependenciesMeta": {
34
34
  "monaco-editor-core": { "optional": true },
35
35
  "monaco-editor": { "optional": true }
36
36
  },
37
37
  "devDependencies": {
38
- "@duet3d/objectmodel": "~3.7.0-beta.6",
39
- "monaco-editor-core": "^0.56.0",
38
+ "@duet3d/objectmodel": "~3.7.0",
39
+ "monaco-editor-core": "^0.57.0",
40
40
  "typescript": "^7.0.2"
41
41
  },
42
42
  "files": [