From a318cf6e461d50769a0085fe3bb70933a7173efd Mon Sep 17 00:00:00 2001 From: Christoph Brandau Date: Wed, 8 Jan 2025 15:53:19 +0100 Subject: [PATCH] add Hover feature --- .prettierrc.json | 8 +++ client/src/common/handlers.ts | 100 ++++++++++++++++++++++++---------- client/src/extension.ts | 80 +++++++++++++++------------ package-lock.json | 25 +++++++-- package.json | 3 +- syntaxes/cdl.tmLanguage.json | 40 ++++++++++++++ tsconfig.json | 22 ++++---- vite.config.js | 28 +++++----- 8 files changed, 213 insertions(+), 93 deletions(-) create mode 100644 .prettierrc.json diff --git a/.prettierrc.json b/.prettierrc.json new file mode 100644 index 0000000..9b2313d --- /dev/null +++ b/.prettierrc.json @@ -0,0 +1,8 @@ +{ + "$schema": "https://json.schemastore.org/prettierrc", + "semi": false, + "tabWidth": 4, + "singleQuote": false, + "printWidth": 100, + "trailingComma": "none" +} \ No newline at end of file diff --git a/client/src/common/handlers.ts b/client/src/common/handlers.ts index 059c60e..691062a 100644 --- a/client/src/common/handlers.ts +++ b/client/src/common/handlers.ts @@ -1,36 +1,78 @@ -import * as vscode from "vscode"; +import * as vscode from "vscode" export function formatCdlFile(content: string): string { - let indentLevel = 0; - const formattedLines = []; - for (const line of content.split("\n")) { - const strippedLine = line.trim(); - if (strippedLine.endsWith("}")) { - indentLevel = Math.max(indentLevel - 1, 0); + let indentLevel = 0 + const formattedLines = [] + for (const line of content.split("\n")) { + const strippedLine = line.trim() + if (strippedLine.endsWith("}")) { + indentLevel = Math.max(indentLevel - 1, 0) + } + formattedLines.push(" ".repeat(indentLevel) + strippedLine) + if (strippedLine.endsWith("{")) { + indentLevel += 1 + } } - formattedLines.push(" ".repeat(indentLevel) + strippedLine); - if (strippedLine.endsWith("{")) { - indentLevel += 1; - } - } - return formattedLines.join("\n"); + return formattedLines.join("\n") } -export function completionHandler( - document: vscode.TextDocument, - position: vscode.Position -) { - const linePrefix = document - .lineAt(position) - .text.substr(0, position.character); - if (!linePrefix.endsWith("TYPE ")) { - return undefined; - } +export function completionHandler(document: vscode.TextDocument, position: vscode.Position) { + const linePrefix = document.lineAt(position).text.substring(0, position.character) + const categories = ["MILL", "LATHE", "DRILL"] - return [ - new vscode.CompletionItem("o", vscode.CompletionItemKind.Keyword), - new vscode.CompletionItem("b", vscode.CompletionItemKind.Keyword), - new vscode.CompletionItem("i", vscode.CompletionItemKind.Keyword), - new vscode.CompletionItem("d", vscode.CompletionItemKind.Keyword), - ]; + if (linePrefix.endsWith("TYPE ")) { + return [ + new vscode.CompletionItem("o", vscode.CompletionItemKind.TypeParameter), + new vscode.CompletionItem("b", vscode.CompletionItemKind.TypeParameter), + new vscode.CompletionItem("i", vscode.CompletionItemKind.TypeParameter), + new vscode.CompletionItem("d", vscode.CompletionItemKind.TypeParameter), + new vscode.CompletionItem("g", vscode.CompletionItemKind.TypeParameter), + new vscode.CompletionItem("s", vscode.CompletionItemKind.TypeParameter) + ] + } + + if (linePrefix.endsWith("CATEGORY ")) { + return categories.map( + (cat) => new vscode.CompletionItem(cat, vscode.CompletionItemKind.TypeParameter) + ) + } + + const categoryPrefix = linePrefix.match(/CATEGORY (.*) /) + if (categoryPrefix) { + const usedCategories = categoryPrefix[1].split(" ") + const remainingCategories = categories.filter((cat) => !usedCategories.includes(cat)) + return remainingCategories.map( + (cat) => new vscode.CompletionItem(cat, vscode.CompletionItemKind.TypeParameter) + ) + } + + return undefined +} + +export function hoverHandler(document: vscode.TextDocument, position: vscode.Position) { + const wordRange = document.getWordRangeAtPosition(position) + const word = document.getText(wordRange) + const text = document.getText() + const lines = text.split("\n") + + let hoverText: string | undefined + + for (const line of lines) { + const words = line.split(/\s+/) + const wordIndex = words.indexOf(word) + + if (wordIndex > 0) { + if (words[wordIndex - 1] === "EVENT") { + hoverText = `MOM_${word}` + } else if (words[wordIndex - 1] === "PARAM") { + hoverText = `mom_${word}` + } + break + } + } + + if (hoverText) { + return new vscode.Hover(hoverText) + } + return undefined } diff --git a/client/src/extension.ts b/client/src/extension.ts index 1f7b3a4..e093783 100644 --- a/client/src/extension.ts +++ b/client/src/extension.ts @@ -1,41 +1,53 @@ -import * as vscode from "vscode"; -import { formatCdlFile, completionHandler } from "./common/handlers"; +import * as vscode from "vscode" +import { formatCdlFile, completionHandler, hoverHandler } from "./common/handlers" export function activate(context: vscode.ExtensionContext) { - const disposable = vscode.languages.registerDocumentFormattingEditProvider( - { scheme: "file", language: "cdl" }, - { - provideDocumentFormattingEdits( - document: vscode.TextDocument - ): vscode.TextEdit[] { - const text = document.getText(); - const formattedText = formatCdlFile(text); - const fullRange = new vscode.Range( - document.positionAt(0), - document.positionAt(text.length) - ); - return [vscode.TextEdit.replace(fullRange, formattedText)]; - }, - } - ); + const formatProvider = vscode.languages.registerDocumentFormattingEditProvider( + { scheme: "file", language: "cdl" }, + { + provideDocumentFormattingEdits(document: vscode.TextDocument): vscode.TextEdit[] { + const text = document.getText() + const formattedText = formatCdlFile(text) + const fullRange = new vscode.Range( + document.positionAt(0), + document.positionAt(text.length) + ) + return [vscode.TextEdit.replace(fullRange, formattedText)] + } + } + ) - context.subscriptions.push(disposable); + context.subscriptions.push(formatProvider) - const completionProvider = vscode.languages.registerCompletionItemProvider( - { scheme: "file", language: "cdl" }, - { - provideCompletionItems( - document: vscode.TextDocument, - position: vscode.Position, - token: vscode.CancellationToken, - context: vscode.CompletionContext - ) { - return completionHandler(document, position); - }, - }, - " " // Trigger completion on space - ); - context.subscriptions.push(completionProvider); + const completionProvider = vscode.languages.registerCompletionItemProvider( + { scheme: "file", language: "cdl" }, + { + provideCompletionItems( + document: vscode.TextDocument, + position: vscode.Position, + token: vscode.CancellationToken, + context: vscode.CompletionContext + ) { + return completionHandler(document, position) + } + }, + " " // Trigger completion on space + ) + context.subscriptions.push(completionProvider) + + const hoverProvider = vscode.languages.registerHoverProvider( + { scheme: "file", language: "cdl" }, + { + provideHover( + document: vscode.TextDocument, + position: vscode.Position, + token: vscode.CancellationToken + ) { + return hoverHandler(document, position) + } + } + ) + context.subscriptions.push(hoverProvider) } export function deactivate() {} diff --git a/package-lock.json b/package-lock.json index 2eed91b..a9e0f0f 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,15 +1,16 @@ { - "name": "cdl", - "version": "0.0.1", + "name": "vscode-cdl-support", + "version": "0.1.0", "lockfileVersion": 3, "requires": true, "packages": { "": { - "name": "cdl", - "version": "0.0.1", + "name": "vscode-cdl-support", + "version": "0.1.0", "devDependencies": { "@types/vscode": "^1.96.0", "@vscode/vsce": "^3.2.1", + "prettier": "^3.4.2", "typescript": "^5.7.2", "vite": "^6.0.7" }, @@ -2766,6 +2767,22 @@ "node": ">=10" } }, + "node_modules/prettier": { + "version": "3.4.2", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.4.2.tgz", + "integrity": "sha512-e9MewbtFo+Fevyuxn/4rrcDAaq0IYxPGLvObpQjiZBMAzB9IGmzlnG9RZy3FFas+eBMu2vA0CszMeduow5dIuQ==", + "dev": true, + "license": "MIT", + "bin": { + "prettier": "bin/prettier.cjs" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/prettier/prettier?sponsor=1" + } + }, "node_modules/pump": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.2.tgz", diff --git a/package.json b/package.json index 55dc6b7..045b847 100644 --- a/package.json +++ b/package.json @@ -2,7 +2,7 @@ "name": "vscode-cdl-support", "displayName": "vscode-cdl-support", "description": "", - "version": "0.0.5", + "version": "0.1.0", "publisher": "Christoph", "repository": { "type": "git", @@ -50,6 +50,7 @@ "devDependencies": { "@types/vscode": "^1.96.0", "@vscode/vsce": "^3.2.1", + "prettier": "^3.4.2", "typescript": "^5.7.2", "vite": "^6.0.7" } diff --git a/syntaxes/cdl.tmLanguage.json b/syntaxes/cdl.tmLanguage.json index 46a0a60..91cecde 100644 --- a/syntaxes/cdl.tmLanguage.json +++ b/syntaxes/cdl.tmLanguage.json @@ -5,6 +5,9 @@ { "include": "#comment" }, + { + "include": "#function" + }, { "include": "#variables" }, @@ -14,6 +17,9 @@ { "include": "#keywords" }, + { + "include": "#numbers" + }, { "include": "#strings" } @@ -38,6 +44,27 @@ } ] }, + "numbers": { + "name": "constant.numeric", + "patterns": [ + { + "name": "constant.numeric", + "match": "\"\\d+\"" + }, + { + "name": "constant.numeric", + "match": "\"\\d+.\\d+\"" + }, + { + "name": "constant.numeric", + "match": "\\d+" + }, + { + "name": "constant.numeric", + "match": "\\d+.\\d+" + } + ] + }, "types": { "patterns": [ { @@ -82,6 +109,19 @@ } ] }, + "function": { + "patterns": [ + { + "name": "storage.type.function.cdl", + "match": "\\bEVENT\\s+([a-zA-Z_]\\w*)\\b", + "captures": { + "1": { + "name": "entity.name.function" + } + } + } + ] + }, "comment": { "patterns": [ { diff --git a/tsconfig.json b/tsconfig.json index 924b2b0..61ca316 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -1,13 +1,13 @@ { - "compilerOptions": { - "target": "es6", - "lib": ["es6"], - "module": "commonjs", - "outDir": "client/out", - "rootDir": "client", - "strict": true, - "esModuleInterop": true, - "skipLibCheck": true - }, - "exclude": ["node_modules", ".vscode-test"] + "compilerOptions": { + "target": "es2023", + "lib": ["es2023", "dom"], + "module": "commonjs", + "outDir": "client/out", + "rootDir": "client", + "strict": true, + "esModuleInterop": true, + "skipLibCheck": true + }, + "exclude": ["node_modules", ".vscode-test"] } diff --git a/vite.config.js b/vite.config.js index f159104..cbafb57 100644 --- a/vite.config.js +++ b/vite.config.js @@ -1,17 +1,17 @@ -import { defineConfig } from "vite"; +import { defineConfig } from "vite" export default defineConfig({ - build: { - lib: { - entry: "./client/src/extension.ts", - formats: ["cjs", "es"], - fileName: "extension", + build: { + lib: { + entry: "./client/src/extension.ts", + formats: ["cjs", "es"], + fileName: "extension" + }, + rollupOptions: { + external: ["vscode"] + }, + sourcemap: true, + outDir: "client/out/src" }, - rollupOptions: { - external: ["vscode"], - }, - sourcemap: true, - outDir: "client/out/src", - }, - plugins: [], -}); + plugins: [] +})