diff --git a/.github/workflows/vscode-extension.yml b/.github/workflows/vscode-extension.yml new file mode 100644 index 0000000..52f65ee --- /dev/null +++ b/.github/workflows/vscode-extension.yml @@ -0,0 +1,26 @@ +name: VS Code extension + +on: + push: + paths: + - "editors/vscode/**" + - ".github/workflows/vscode-extension.yml" + pull_request: + paths: + - "editors/vscode/**" + - ".github/workflows/vscode-extension.yml" + +jobs: + compile: + name: type-check + runs-on: ubuntu-latest + defaults: + run: + working-directory: editors/vscode + steps: + - uses: actions/checkout@v4 + - uses: actions/setup-node@v4 + with: + node-version: "20" + - run: npm install + - run: npm run compile diff --git a/editors/vscode/.gitignore b/editors/vscode/.gitignore new file mode 100644 index 0000000..b78270c --- /dev/null +++ b/editors/vscode/.gitignore @@ -0,0 +1,4 @@ +node_modules/ +out/ +*.vsix +package-lock.json diff --git a/editors/vscode/.vscodeignore b/editors/vscode/.vscodeignore new file mode 100644 index 0000000..7fceb02 --- /dev/null +++ b/editors/vscode/.vscodeignore @@ -0,0 +1,7 @@ +# Sources & build config (out/ is shipped, src/ is not). +.gitignore +tsconfig.json +src/** +**/*.map +# node_modules is intentionally NOT ignored: vsce ships production dependencies +# (vscode-languageclient) into the VSIX and prunes devDependencies itself. diff --git a/editors/vscode/README.md b/editors/vscode/README.md new file mode 100644 index 0000000..566a735 --- /dev/null +++ b/editors/vscode/README.md @@ -0,0 +1,33 @@ +# Hypercode — VS Code extension + +Language support for Hypercode `.hc` / `.hcs` files: **live diagnostics** from the +Hypercode language server (`hypercode lsp`), over the standard Language Server +Protocol. + +It is a thin client — all the language logic lives in the Swift +[`hypercode`](https://github.com/0al-spec/Hypercode) binary, so the same server +works in any LSP editor. + +## Requirements + +The `hypercode` CLI must be installed and support `hypercode lsp`: + +```bash +git clone https://github.com/0al-spec/Hypercode && cd Hypercode +swift build -c release # produces .build/release/hypercode +``` + +Put `hypercode` on your `PATH`, or set `hypercode.serverPath` to its absolute path. + +## Develop + +```bash +cd editors/vscode +npm install +npm run compile +# then press F5 in VS Code to launch the Extension Development Host +``` + +## Settings + +- `hypercode.serverPath` — path to the `hypercode` executable (default: `hypercode`). diff --git a/editors/vscode/language-configuration.json b/editors/vscode/language-configuration.json new file mode 100644 index 0000000..9505602 --- /dev/null +++ b/editors/vscode/language-configuration.json @@ -0,0 +1,8 @@ +{ + "autoClosingPairs": [ + { "open": "\"", "close": "\"" } + ], + "surroundingPairs": [ + ["\"", "\""] + ] +} diff --git a/editors/vscode/package.json b/editors/vscode/package.json new file mode 100644 index 0000000..d9251cc --- /dev/null +++ b/editors/vscode/package.json @@ -0,0 +1,52 @@ +{ + "name": "hypercode", + "displayName": "Hypercode", + "description": "Hypercode (.hc / .hcs) language support — live diagnostics via the Hypercode language server.", + "version": "0.1.0", + "publisher": "0al-spec", + "license": "MIT", + "repository": { "type": "git", "url": "https://github.com/0al-spec/Hypercode" }, + "engines": { "vscode": "^1.75.0" }, + "categories": ["Programming Languages", "Linters"], + "activationEvents": ["onLanguage:hypercode", "onLanguage:hypercode-hcs"], + "main": "./out/extension.js", + "contributes": { + "languages": [ + { + "id": "hypercode", + "aliases": ["Hypercode", "hc"], + "extensions": [".hc"], + "configuration": "./language-configuration.json" + }, + { + "id": "hypercode-hcs", + "aliases": ["Hypercode Cascade Sheet", "hcs"], + "extensions": [".hcs"], + "configuration": "./language-configuration.json" + } + ], + "configuration": { + "title": "Hypercode", + "properties": { + "hypercode.serverPath": { + "type": "string", + "default": "hypercode", + "description": "Path to the `hypercode` executable (it must support `hypercode lsp`). Defaults to `hypercode` on PATH." + } + } + } + }, + "scripts": { + "compile": "tsc -p ./", + "watch": "tsc -watch -p ./", + "vscode:prepublish": "npm run compile" + }, + "dependencies": { + "vscode-languageclient": "^9.0.1" + }, + "devDependencies": { + "@types/node": "^20.0.0", + "@types/vscode": "^1.75.0", + "typescript": "^5.4.0" + } +} diff --git a/editors/vscode/src/extension.ts b/editors/vscode/src/extension.ts new file mode 100644 index 0000000..b06c89c --- /dev/null +++ b/editors/vscode/src/extension.ts @@ -0,0 +1,40 @@ +import * as vscode from 'vscode'; +import { + LanguageClient, + LanguageClientOptions, + ServerOptions, + TransportKind, +} from 'vscode-languageclient/node'; + +let client: LanguageClient | undefined; + +export function activate(context: vscode.ExtensionContext): void { + const serverPath = vscode.workspace + .getConfiguration('hypercode') + .get('serverPath', 'hypercode'); + + // The Hypercode language server is `hypercode lsp` over stdio. + const server = { command: serverPath, args: ['lsp'], transport: TransportKind.stdio }; + const serverOptions: ServerOptions = { run: server, debug: server }; + + const clientOptions: LanguageClientOptions = { + documentSelector: [ + { scheme: 'file', language: 'hypercode' }, + { scheme: 'file', language: 'hypercode-hcs' }, + ], + }; + + client = new LanguageClient( + 'hypercode', + 'Hypercode Language Server', + serverOptions, + clientOptions, + ); + + void client.start(); + context.subscriptions.push({ dispose: () => { void client?.stop(); } }); +} + +export function deactivate(): Thenable | undefined { + return client?.stop(); +} diff --git a/editors/vscode/tsconfig.json b/editors/vscode/tsconfig.json new file mode 100644 index 0000000..68356ce --- /dev/null +++ b/editors/vscode/tsconfig.json @@ -0,0 +1,15 @@ +{ + "compilerOptions": { + "module": "Node16", + "moduleResolution": "Node16", + "target": "ES2022", + "lib": ["ES2022"], + "outDir": "out", + "rootDir": "src", + "strict": true, + "esModuleInterop": true, + "skipLibCheck": true, + "sourceMap": true + }, + "include": ["src"] +} diff --git a/workplan.md b/workplan.md index 010bc87..07fc62e 100644 --- a/workplan.md +++ b/workplan.md @@ -80,7 +80,7 @@ cascade sheets (`.hcs`). Companion to the [RFC](RFC/Hypercode.md) and the ## M7 — Diagnostics & LSP (VS Code) - [x] HC-100 Structured diagnostics: unified `Diagnostic` (severity, code, source range), LSP-shaped JSON + editor-parseable text, CLI `--diagnostics text|json` — `Sources/Hypercode/Diagnostics/` - [x] HC-101 Minimal Swift LSP server (`hypercode lsp`): JSON-RPC over stdio, `initialize`, document sync (didOpen/didChange/didSave/didClose), live `publishDiagnostics` — `Sources/HypercodeCLI/LSPServer.swift` + shared `diagnostics(for:text:)` in the library -- [ ] HC-102 Thin VS Code extension on `vscode-languageclient` that launches the server +- [x] HC-102 Thin VS Code extension on `vscode-languageclient` launching `hypercode lsp` — `editors/vscode/` (languages `.hc`/`.hcs`, `hypercode.serverPath` setting); compiled in CI (`.github/workflows/vscode-extension.yml`) - [ ] HC-103 Hover / go-to-definition (later, same server) *(Aim straight for LSP — the standard for VS Code & editor-agnostic. Hyperprompt's custom CLI+JSON-RPC was a documented MVP stopgap; see its ADR-001.)*