diff options
Diffstat (limited to 'plugin')
| -rw-r--r-- | plugin/README.md | 2 | ||||
| -rw-r--r-- | plugin/ThirdPartyNotices.md | 6 | ||||
| -rw-r--r-- | plugin/examples/highlighting.cps | 10 | ||||
| -rw-r--r-- | plugin/syntaxes/cie-pseudocode.tmLanguage.json | 42 | ||||
| -rw-r--r-- | plugin/test/highlighting.test.js | 26 | ||||
| -rw-r--r-- | plugin/test/indentation.test.js | 10 |
6 files changed, 75 insertions, 21 deletions
diff --git a/plugin/README.md b/plugin/README.md index 48738dc..b0d6c01 100644 --- a/plugin/README.md +++ b/plugin/README.md @@ -20,7 +20,7 @@ Open a `.cps` file. The language mode should show **CIE Pseudocode**. ## Features -- C++ style syntax colors that follow your dark theme. +- C++ style syntax colors that follow your dark theme, including PP_DEFINE, PP_UNDEF, PP_IFDEF, PP_IFNDEF and PP_ENDIF. Preprocessor conditions do not add indentation. - Automatic Tab indentation and outdent for block keywords. - **Format Selection**: select code, then press **Cmd+K, Cmd+F** on macOS or **Ctrl+K, Ctrl+F** on Windows/Linux. Only indentation changes. - Colored `()` and `[]` pairs; unmatched brackets turn red. Quotes and comments are ignored. diff --git a/plugin/ThirdPartyNotices.md b/plugin/ThirdPartyNotices.md index e24f2c8..b195ffa 100644 --- a/plugin/ThirdPartyNotices.md +++ b/plugin/ThirdPartyNotices.md @@ -5,9 +5,9 @@ Microsoft VS Code’s built-in C++ extension. Exception keywords reuse its `keyword.control.try.cpp`, `keyword.control.catch.cpp` and `keyword.control.throw.cpp` scopes; ENDTRY uses the TRY scope. Selection, class, access, constant, template, operator and external-declaration highlighting also -reuse C++ scopes. OVERLOAD borrows a declaration modifier, #LIB borrows #pragma -and INCLUDE_OBJ borrows #include; ellipses use the C++ variadic scope. Literal -escapes reuse `constant.character.escape`; the adjacent C string suffix borrows +reuse C++ scopes. OVERLOAD borrows a declaration modifier, PP_* directives borrow +C++ preprocessor keyword and macro-name scopes, and INCLUDE_OBJ borrows #include; +ellipses use the C++ variadic scope. Literal escapes reuse `constant.character.escape`; the adjacent C string suffix borrows `keyword.other.suffix.literal.user-defined.string.cpp`. Custom types, template parameters and angle delimiters use the corresponding C++ type and template scopes; class-method receivers reuse `variable.language.this.cpp`. diff --git a/plugin/examples/highlighting.cps b/plugin/examples/highlighting.cps index 10d93d8..a7ec8c6 100644 --- a/plugin/examples/highlighting.cps +++ b/plugin/examples/highlighting.cps @@ -75,3 +75,13 @@ ENDCLASS DECLARE Count : Counter CALL Count.Add(Limit) OUTPUT Count.Get() + +// Preprocessor conditions do not add indentation. +PP_DEFINE Demo +PP_IFDEF Demo +OUTPUT "Enabled" +PP_IFNDEF OtherDemo +OUTPUT "Nested condition" +PP_ENDIF +PP_ENDIF +PP_UNDEF Demo diff --git a/plugin/syntaxes/cie-pseudocode.tmLanguage.json b/plugin/syntaxes/cie-pseudocode.tmLanguage.json index 16a4ac4..14ef33c 100644 --- a/plugin/syntaxes/cie-pseudocode.tmLanguage.json +++ b/plugin/syntaxes/cie-pseudocode.tmLanguage.json @@ -418,6 +418,9 @@ "include": "#strings" }, { + "include": "#preprocessor" + }, + { "include": "#class" }, { @@ -442,17 +445,6 @@ "include": "#return_type" }, { - "match": "^\\s*(#)(LIB)\\s*$", - "captures": { - "1": { - "name": "punctuation.definition.directive.cpp" - }, - "2": { - "name": "keyword.control.directive.pragma.cpp" - } - } - }, - { "match": "(?<!\\w)(?:CASE|ENDCASE)(?!\\w)", "name": "keyword.control.switch.cpp" }, @@ -599,6 +591,34 @@ "include": "#type_tokens" } ] + }, + "preprocessor": { + "begin": "^\\s*(?:(PP_DEFINE)|(PP_UNDEF)|(PP_IFDEF|PP_IFNDEF)|(PP_ENDIF))\\b", + "end": "$", + "beginCaptures": { + "1": { + "name": "keyword.control.directive.define.cpp" + }, + "2": { + "name": "keyword.control.directive.undef.cpp" + }, + "3": { + "name": "keyword.control.directive.conditional.cpp" + }, + "4": { + "name": "keyword.control.directive.conditional.cpp" + } + }, + "name": "meta.preprocessor.cie-pseudocode", + "patterns": [ + { + "include": "#line_comment" + }, + { + "match": "[A-Za-z_][A-Za-z0-9_]*", + "name": "entity.name.function.preprocessor.cpp" + } + ] } }, "injections": { diff --git a/plugin/test/highlighting.test.js b/plugin/test/highlighting.test.js index c8ee3f7..1edac7b 100644 --- a/plugin/test/highlighting.test.js +++ b/plugin/test/highlighting.test.js @@ -155,13 +155,27 @@ test('supported keywords reuse C++ scopes without matching identifiers or quoted } }); -test('library directives require their own line and ellipses use the C++ variadic scope', () => { - assert.ok(scopesAt('\t#LIB ', '#').includes('punctuation.definition.directive.cpp')); - assert.ok(scopesAt('\t#LIB ', 'LIB').includes('keyword.control.directive.pragma.cpp')); - for (const text of ['#lib', '#LIBRARY', '#LIB // comment', 'X #LIB', '// #LIB', 'OUTPUT "#LIB"']) { - assert.ok(!scopesAt(text, '#') - .includes('punctuation.definition.directive.cpp'), text); +test('preprocessor directives reuse C++ scopes and shield switch names from ordinary keywords', () => { + for (const [word, scope] of [ + ['PP_DEFINE', 'keyword.control.directive.define.cpp'], + ['PP_UNDEF', 'keyword.control.directive.undef.cpp'], + ['PP_IFDEF', 'keyword.control.directive.conditional.cpp'], + ['PP_IFNDEF', 'keyword.control.directive.conditional.cpp'], + ['PP_ENDIF', 'keyword.control.directive.conditional.cpp'] + ]) { + assert.ok(scopesAt(`\t${word} __LIB // comment`, word).includes(scope)); + for (const text of [word.toLowerCase(), `${word}Value`, `_${word}`, `X ${word}`, `// ${word}`, `OUTPUT "${word}"`]) { + assert.ok(!scopesAt(text, word.toLowerCase() === text ? text : word).includes(scope), text); + } } + for (const word of ['__LIB', 'FUNCTION', 'INTEGER']) { + assert.ok(scopesAt(`PP_DEFINE ${word}`, word).includes('entity.name.function.preprocessor.cpp')); + } + assert.ok(scopesAt('PP_IFDEF Flag // PP_ENDIF', 'PP_ENDIF').some(s => s.startsWith('comment.'))); + assert.ok(!scopesAt('#LIB', 'LIB').some(s => s.startsWith('keyword.control.directive.'))); +}); + +test('ellipses use the C++ variadic scope', () => { for (const text of ['TEMPLATE <Types...>', 'EXTERN "C" EXTERN_PROCEDURE print(C_INT, ...)', 'CALL print(Values...)']) { assert.ok(scopesAt(text, '...').includes('punctuation.vararg-ellipses.cpp'), text); } diff --git a/plugin/test/indentation.test.js b/plugin/test/indentation.test.js index 9140ed3..e71540f 100644 --- a/plugin/test/indentation.test.js +++ b/plugin/test/indentation.test.js @@ -82,3 +82,13 @@ test('escaped quotes keep block keywords inside literals masked', () => { 'THEN', String.raw`OUTPUT "escaped \" ENDIF //"`, 'ENDIF' ]), [0, 0, 1, 0]); }); + +test('preprocessor conditions preserve ordinary block depth without adding indentation', () => { + const lines = [ + 'PP_DEFINE Flag', 'PP_IFDEF Flag', 'PROCEDURE Demo()', 'PP_IFNDEF Other', + 'IF Ready THEN', 'OUTPUT 1', 'ENDIF', 'PP_ENDIF', 'PP_UNDEF Flag', + 'ENDPROCEDURE', 'PP_ENDIF' + ]; + assert.deepEqual(lineDepths(lines), [0, 0, 0, 1, 1, 2, 1, 1, 1, 0, 0]); + assert.deepEqual(indentationEdits(['PP_IFDEF Flag', 'OUTPUT 1', 'PP_ENDIF'], 0, 2), []); +}); |
