Professional Syntax Highlighting and Developer Experience
This guide provides complete instructions for creating a professional VS Code extension for the ProXPL programming language, including syntax highlighting, snippets, and IntelliSense support.
- Prerequisites
- Initial Setup
- Project Structure
- Configuration
- Syntax Highlighting
- Code Snippets
- Language Configuration
- Testing
- Packaging & Publishing
- Advanced Features
Before you begin, ensure you have the following installed:
- Node.js (v14 or higher): Download
- npm (comes with Node.js)
- Visual Studio Code: Download
- Yeoman and VS Code Extension Generator:
npm install -g yo generator-code- vsce (VS Code Extension Manager):
npm install -g vsceUse the Yeoman generator to create the extension structure:
# Navigate to your extensions directory
cd ~/vscode-extensions # or your preferred location
# Run the generator
yo codeAnswer the prompts as follows:
? What type of extension do you want to create?
→ New Language Support
? What's the name of your language?
→ ProXPL
? What's the identifier of your language?
→ proxpl
? What's the name of your extension?
→ proxpl-language-support
? What's the description of your extension?
→ Syntax highlighting and language support for ProXPL
? What's your publisher name?
→ your-publisher-name
? Initialize a git repository?
→ Yes
This creates a directory structure:
proxpl-language-support/
├── .vscode/
│ └── launch.json
├── language-configuration.json
├── syntaxes/
│ └── proxpl.tmLanguage.json
├── package.json
├── README.md
└── CHANGELOG.md
proxpl-language-support/
├── .vscode/
│ └── launch.json # Debug configuration
├── syntaxes/
│ └── proxpl.tmLanguage.json # TextMate grammar
├── snippets/
│ └── proxpl.json # Code snippets
├── language-configuration.json # Language features
├── package.json # Extension manifest
├── README.md # Extension documentation
├── CHANGELOG.md # Version history
└── icon.png # Extension icon (128x128)
Update package.json with ProXPL-specific configuration:
{
"name": "proxpl-language-support",
"displayName": "ProXPL Language Support",
"description": "Syntax highlighting and language support for ProXPL",
"version": "1.0.0",
"publisher": "your-publisher-name",
"icon": "icon.png",
"repository": {
"type": "git",
"url": "https://github.com/ProgrammerKR/ProXPL"
},
"engines": {
"vscode": "^1.75.0"
},
"categories": [
"Programming Languages"
],
"keywords": [
"proxpl",
"prox",
"syntax",
"highlighting"
],
"contributes": {
"languages": [
{
"id": "proxpl",
"aliases": [
"ProXPL",
"prox"
],
"extensions": [
".prox"
],
"configuration": "./language-configuration.json",
"icon": {
"light": "./icon.png",
"dark": "./icon.png"
}
}
],
"grammars": [
{
"language": "proxpl",
"scopeName": "source.proxpl",
"path": "./syntaxes/proxpl.tmLanguage.json"
}
],
"snippets": [
{
"language": "proxpl",
"path": "./snippets/proxpl.json"
}
]
}
}Key Sections:
contributes.languages: Defines the language identifier, file extensions, and configurationcontributes.grammars: Links the TextMate grammar file for syntax highlightingcontributes.snippets: Provides code snippets for common patterns
Create syntaxes/proxpl.tmLanguage.json with comprehensive syntax highlighting:
{
"$schema": "https://raw.githubusercontent.com/martinring/tmlanguage/master/tmlanguage.json",
"name": "ProXPL",
"scopeName": "source.proxpl",
"patterns": [
{
"include": "#comments"
},
{
"include": "#keywords"
},
{
"include": "#types"
},
{
"include": "#strings"
},
{
"include": "#numbers"
},
{
"include": "#booleans"
},
{
"include": "#operators"
},
{
"include": "#functions"
},
{
"include": "#constants"
}
],
"repository": {
"comments": {
"patterns": [
{
"name": "comment.line.double-slash.proxpl",
"match": "//.*$"
},
{
"name": "comment.block.proxpl",
"begin": "/\\*",
"end": "\\*/"
}
]
},
"keywords": {
"patterns": [
{
"name": "keyword.control.proxpl",
"match": "\\b(if|else|while|for|switch|case|default|break|continue|return|try|catch|finally|throw|defer)\\b"
},
{
"name": "keyword.declaration.proxpl",
"match": "\\b(let|const|func|class|enum|struct|interface|abstract)\\b"
},
{
"name": "keyword.module.proxpl",
"match": "\\b(import|from|export|as|use)\\b"
},
{
"name": "keyword.other.proxpl",
"match": "\\b(this|super|static|public|private|protected|extends|implements|in|is|typeof|native|async|await)\\b"
}
]
},
"types": {
"patterns": [
{
"name": "storage.type.proxpl",
"match": "\\b(int|float|string|bool|void|null|list|dict|set|bytes|error)\\b"
}
]
},
"strings": {
"patterns": [
{
"name": "string.quoted.double.proxpl",
"begin": "\"",
"end": "\"",
"patterns": [
{
"name": "constant.character.escape.proxpl",
"match": "\\\\(n|t|r|\\\\|\"|'|x[0-9A-Fa-f]{2}|u[0-9A-Fa-f]{4})"
}
]
},
{
"name": "string.quoted.single.proxpl",
"begin": "'",
"end": "'",
"patterns": [
{
"name": "constant.character.escape.proxpl",
"match": "\\\\(n|t|r|\\\\|\"|'|x[0-9A-Fa-f]{2}|u[0-9A-Fa-f]{4})"
}
]
}
]
},
"numbers": {
"patterns": [
{
"name": "constant.numeric.hex.proxpl",
"match": "\\b0[xX][0-9A-Fa-f]+\\b"
},
{
"name": "constant.numeric.binary.proxpl",
"match": "\\b0[bB][01]+\\b"
},
{
"name": "constant.numeric.octal.proxpl",
"match": "\\b0[oO][0-7]+\\b"
},
{
"name": "constant.numeric.float.proxpl",
"match": "\\b[0-9]+\\.[0-9]+([eE][+-]?[0-9]+)?\\b"
},
{
"name": "constant.numeric.integer.proxpl",
"match": "\\b[0-9]+\\b"
}
]
},
"booleans": {
"patterns": [
{
"name": "constant.language.boolean.proxpl",
"match": "\\b(true|false)\\b"
},
{
"name": "constant.language.null.proxpl",
"match": "\\bnull\\b"
}
]
},
"operators": {
"patterns": [
{
"name": "keyword.operator.arithmetic.proxpl",
"match": "(\\+|\\-|\\*|\\/|%|\\*\\*)"
},
{
"name": "keyword.operator.comparison.proxpl",
"match": "(==|!=|<|>|<=|>=)"
},
{
"name": "keyword.operator.logical.proxpl",
"match": "(&&|\\|\\||!)"
},
{
"name": "keyword.operator.bitwise.proxpl",
"match": "(&|\\||\\^|~|<<|>>)"
},
{
"name": "keyword.operator.assignment.proxpl",
"match": "(=|\\+=|\\-=|\\*=|\\/=|%=|\\*\\*=|&=|\\|=|\\^=|<<=|>>=)"
},
{
"name": "keyword.operator.other.proxpl",
"match": "(\\?|:|\\?\\.|\\.\\.|\\+\\+|\\-\\-|\\?\\?)"
}
]
},
"functions": {
"patterns": [
{
"name": "entity.name.function.proxpl",
"match": "\\b([a-zA-Z_][a-zA-Z0-9_]*)\\s*(?=\\()"
},
{
"name": "support.function.builtin.proxpl",
"match": "\\b(print|input|read_file|write_file|append_file|abs|ceil|floor|round|max|min|pow|sqrt|log|sin|cos|tan|random|randint|len|upper|lower|trim|split|join|replace|push|pop|insert|remove|range|sort|reverse|keys|values|exit|env|platform|version|to_int|to_float|to_string|to_bool|type|assert|hash)\\b"
}
]
},
"constants": {
"patterns": [
{
"name": "constant.other.proxpl",
"match": "\\b[A-Z_][A-Z0-9_]*\\b"
}
]
}
}
}Grammar Breakdown:
comments: Single-line (//) and multi-line (/* */) commentskeywords: Control flow, declarations, modules, and other keywordstypes: Built-in types (int, float, string, bool, etc.)strings: Double and single-quoted strings with escape sequencesnumbers: Hex, binary, octal, float, and integer literalsbooleans: true, false, nulloperators: Arithmetic, comparison, logical, bitwise, assignmentfunctions: Function calls and built-in functionsconstants: ALL_CAPS constants
Create snippets/proxpl.json with common code patterns:
{
"Function Definition": {
"prefix": "func",
"body": [
"func ${1:functionName}(${2:params}) {",
"\t${3:// function body}",
"\treturn ${4:value};",
"}"
],
"description": "Create a function"
},
"If Statement": {
"prefix": "if",
"body": [
"if (${1:condition}) {",
"\t${2:// code}",
"}"
],
"description": "If statement"
},
"If-Else Statement": {
"prefix": "ifelse",
"body": [
"if (${1:condition}) {",
"\t${2:// if code}",
"} else {",
"\t${3:// else code}",
"}"
],
"description": "If-else statement"
},
"While Loop": {
"prefix": "while",
"body": [
"while (${1:condition}) {",
"\t${2:// code}",
"}"
],
"description": "While loop"
},
"For Loop": {
"prefix": "for",
"body": [
"for (let ${1:i} = ${2:0}; ${1:i} < ${3:10}; ${1:i} = ${1:i} + 1) {",
"\t${4:// code}",
"}"
],
"description": "For loop"
},
"Variable Declaration": {
"prefix": "let",
"body": "let ${1:varName} = ${2:value};",
"description": "Declare a variable"
},
"Constant Declaration": {
"prefix": "const",
"body": "const ${1:CONST_NAME} = ${2:value};",
"description": "Declare a constant"
},
"Print Statement": {
"prefix": "print",
"body": "print(${1:message});",
"description": "Print to console"
},
"Try-Catch": {
"prefix": "try",
"body": [
"try {",
"\t${1:// code}",
"} catch (${2:error}) {",
"\t${3:// error handling}",
"}"
],
"description": "Try-catch block"
},
"Main Function": {
"prefix": "main",
"body": [
"func main() {",
"\t${1:// main code}",
"}",
"",
"main();"
],
"description": "Main function entry point"
},
"Import Module": {
"prefix": "use",
"body": "use ${1:module};",
"description": "Import a module"
},
"List Declaration": {
"prefix": "list",
"body": "let ${1:listName} = [${2:items}];",
"description": "Declare a list"
},
"Dictionary Declaration": {
"prefix": "dict",
"body": "let ${1:dictName} = {${2:\"key\": \"value\"}};",
"description": "Declare a dictionary"
}
}Snippet Features:
- Tab stops:
${1:placeholder}allows tabbing through fields - Placeholders: Provide default values and hints
- Multi-line: Support for complex code structures
Create language-configuration.json for editor features:
{
"comments": {
"lineComment": "//",
"blockComment": ["/*", "*/"]
},
"brackets": [
["{", "}"],
["[", "]"],
["(", ")"]
],
"autoClosingPairs": [
{ "open": "{", "close": "}" },
{ "open": "[", "close": "]" },
{ "open": "(", "close": ")" },
{ "open": "\"", "close": "\"", "notIn": ["string"] },
{ "open": "'", "close": "'", "notIn": ["string", "comment"] }
],
"surroundingPairs": [
["{", "}"],
["[", "]"],
["(", ")"],
["\"", "\""],
["'", "'"]
],
"folding": {
"markers": {
"start": "^\\s*//\\s*#?region\\b",
"end": "^\\s*//\\s*#?endregion\\b"
}
},
"wordPattern": "(-?\\d*\\.\\d\\w*)|([^\\`\\~\\!\\@\\#\\%\\^\\&\\*\\(\\)\\-\\=\\+\\[\\{\\]\\}\\\\\\|\\;\\:\\'\\\"\\,\\.\\<\\>\\/\\?\\s]+)",
"indentationRules": {
"increaseIndentPattern": "^((?!\\/\\/).)*(\\{[^}\"'`]*|\\([^)\"'`]*|\\[[^\\]\"'`]*)$",
"decreaseIndentPattern": "^((?!.*?\\/\\*).*\\*/)?\\s*[\\)\\}\\]].*$"
}
}Features Enabled:
- Comment toggling: Ctrl+/ for line comments
- Bracket matching: Automatic bracket pairing
- Auto-closing: Automatic closing of brackets and quotes
- Code folding: Region-based code folding
- Smart indentation: Automatic indentation
-
Open Extension in VS Code:
cd proxpl-language-support code .
-
Launch Extension Development Host:
- Press
F5or click "Run > Start Debugging" - A new VS Code window opens with the extension loaded
- Press
-
Test the Extension:
- Create a new file:
test.prox - Write ProXPL code and verify:
- ✅ Syntax highlighting works
- ✅ Comments are colored correctly
- ✅ Keywords are highlighted
- ✅ Snippets autocomplete
- ✅ Brackets auto-close
- Create a new file:
-
Debug Issues:
- Check the Debug Console for errors
- Modify grammar files and reload (
Ctrl+Rin Extension Host)
Create test.prox with comprehensive syntax:
// ProXPL Test File
/* Multi-line comment
Testing all features */
use std.math;
const PI = 3.14159;
let count = 0;
func fibonacci(n: int): int {
if (n <= 1) return n;
return fibonacci(n - 1) + fibonacci(n - 2);
}
func main() {
let name = input("Enter name: ");
print("Hello, " + name + "!");
// Numbers
let hex = 0xFF;
let binary = 0b1010;
let float = 3.14e-2;
// Collections
let numbers = [1, 2, 3, 4, 5];
let person = {"name": "Alice", "age": 30};
// Control flow
for (let i = 0; i < 10; i = i + 1) {
if (i % 2 == 0) {
print("Even: " + to_string(i));
} else {
print("Odd: " + to_string(i));
}
}
// Try-catch
try {
let result = fibonacci(10);
print("Result: " + to_string(result));
} catch (error) {
print("Error: " + error);
}
}
main();-
Update README.md:
# ProXPL Language Support Syntax highlighting and language support for ProXPL. ## Features - Syntax highlighting - Code snippets - Auto-closing brackets - Comment toggling ## Installation Install from VS Code Marketplace or download .vsix
-
Update CHANGELOG.md:
# Change Log ## [1.0.0] - 2024-12-23 - Initial release - Syntax highlighting - Code snippets - Language configuration
-
Add Icon (optional):
- Create
icon.png(128x128 pixels) - Update
package.jsonicon path
- Create
# Install vsce if not already installed
npm install -g vsce
# Package the extension
vsce package
# Output: proxpl-language-support-1.0.0.vsix# Install locally
code --install-extension proxpl-language-support-1.0.0.vsix
# Verify installation
code --list-extensions | grep proxpl-
Create Publisher Account:
- Visit Visual Studio Marketplace
- Create a publisher ID
-
Get Personal Access Token:
- Go to Azure DevOps
- Create a PAT with "Marketplace (Manage)" scope
-
Login with vsce:
vsce login your-publisher-name # Enter your PAT when prompted -
Publish:
vsce publish # Or publish with version bump vsce publish patch # 1.0.0 -> 1.0.1 vsce publish minor # 1.0.0 -> 1.1.0 vsce publish major # 1.0.0 -> 2.0.0
-
Verify:
- Visit marketplace:
https://marketplace.visualstudio.com/items?itemName=your-publisher-name.proxpl-language-support
- Visit marketplace:
For advanced features like autocomplete, go-to-definition, and diagnostics, implement an LSP server:
Structure:
proxpl-language-support/
├── client/ # VS Code extension
└── server/ # LSP server
└── src/
└── server.ts
Resources:
Provide more accurate highlighting based on semantic analysis:
{
"contributes": {
"semanticTokenTypes": [
{ "id": "variable", "description": "Variables" },
{ "id": "function", "description": "Functions" }
]
}
}Add debugging capabilities:
{
"contributes": {
"debuggers": [
{
"type": "proxpl",
"label": "ProXPL Debug",
"program": "./out/debugAdapter.js"
}
]
}
}Integrate build tasks:
{
"contributes": {
"taskDefinitions": [
{
"type": "proxpl",
"required": ["task"],
"properties": {
"task": {
"type": "string",
"description": "The ProXPL task to execute"
}
}
}
]
}
}1. Syntax Highlighting Not Working
- Verify
scopeNameintmLanguage.jsonmatchespackage.json - Check regex patterns for syntax errors
- Reload Extension Host (
Ctrl+R)
2. Snippets Not Appearing
- Ensure
snippetspath inpackage.jsonis correct - Check JSON syntax in snippets file
- Verify language ID matches
3. Extension Not Loading
- Check
engines.vscodeversion compatibility - Review activation events in
package.json - Check Extension Host console for errors
4. Publishing Fails
- Verify publisher name is created
- Check PAT has correct permissions
- Ensure all required fields in
package.jsonare filled
- Version Control: Use Git and semantic versioning
- Testing: Test on multiple VS Code versions
- Documentation: Keep README.md updated
- Performance: Optimize regex patterns for speed
- Accessibility: Use semantic token types
- Updates: Regularly update dependencies
- ✅ Create basic syntax highlighting
- ✅ Add code snippets
- ✅ Test locally
- ✅ Package extension
- 🔄 Implement LSP server (advanced)
- 🔄 Add debugger support (advanced)
- 🔄 Publish to marketplace
ProXPL VS Code Extension - Professional Developer Experience