diff options
author | 2021-03-25 10:38:17 -0500 | |
---|---|---|
committer | 2021-03-25 10:38:17 -0500 | |
commit | 18e7cc5af903543ac6f46780bfea67c13c6517df (patch) | |
tree | f61100a6adf3d4641cab89a23ac071268ed911e2 /vscode/packages/client/src | |
parent | 30cccdf7154b6470e876464da9e412af10894dd5 (diff) | |
download | astro-18e7cc5af903543ac6f46780bfea67c13c6517df.tar.gz astro-18e7cc5af903543ac6f46780bfea67c13c6517df.tar.zst astro-18e7cc5af903543ac6f46780bfea67c13c6517df.zip |
Scaffold language server (#25)
* wip: scaffold astro extension
* wip: scaffold astro extension
* WIP: vscode extension
* fix: autoCloseBefore
* chore: update package.json
* fix: use tsx instead of plain ts
* chore: remove dist files
* chore: remove comments
* chore: cleanup package build process, switch build to esbuild
* refactor: use shared esbuild config
Co-authored-by: Nate Moore <nate@skypack.dev>
Diffstat (limited to 'vscode/packages/client/src')
-rw-r--r-- | vscode/packages/client/src/features/defaultSettings.ts | 30 | ||||
-rw-r--r-- | vscode/packages/client/src/index.ts | 79 |
2 files changed, 109 insertions, 0 deletions
diff --git a/vscode/packages/client/src/features/defaultSettings.ts b/vscode/packages/client/src/features/defaultSettings.ts new file mode 100644 index 000000000..ec3de70a1 --- /dev/null +++ b/vscode/packages/client/src/features/defaultSettings.ts @@ -0,0 +1,30 @@ +import * as vscode from 'vscode'; + +export async function activate() { + onConfigUpdated(); + + vscode.workspace.onDidChangeConfiguration(onConfigUpdated); + + function onConfigUpdated() { + const astro = vscode.extensions.getExtension('skypack.astro'); + if (!astro) { + return; + } + const emmet = vscode.extensions.getExtension('vscode.emmet'); + if (!emmet) { + return; + } + + const emmetIncludeLanguages = getEmmetIncludeLanguages(); + if (emmetIncludeLanguages && emmetIncludeLanguages['astro']) { + return; + } + setEmmetIncludeLanguages({ ...emmetIncludeLanguages, astro: 'html' }); + } + function getEmmetIncludeLanguages() { + return vscode.workspace.getConfiguration('emmet').get<Record<string, string>>('includeLanguages'); + } + function setEmmetIncludeLanguages(value: Record<string, string>) { + return vscode.workspace.getConfiguration('emmet').set('includeLanguages', value); + } +} diff --git a/vscode/packages/client/src/index.ts b/vscode/packages/client/src/index.ts new file mode 100644 index 000000000..c7233892b --- /dev/null +++ b/vscode/packages/client/src/index.ts @@ -0,0 +1,79 @@ +import * as path from 'path'; +import * as vscode from 'vscode'; +import * as lsp from 'vscode-languageclient/node'; + +import * as defaultSettings from './features/defaultSettings.js'; + +let docClient: lsp.LanguageClient; + +export async function activate(context: vscode.ExtensionContext) { + docClient = createLanguageService(context, 'doc', 'astro', 'Astro', 6040); + + defaultSettings.activate(); + + await docClient.onReady(); + startEmbeddedLanguageServices(); +} + +function createLanguageService(context: vscode.ExtensionContext, mode: 'doc', id: string, name: string, port: number) { + const serverModule = context.asAbsolutePath(path.join('dist', 'server.js')); + const debugOptions = { execArgv: ['--nolazy', '--inspect=' + port] }; + const serverOptions: lsp.ServerOptions = { + run: { module: serverModule, transport: lsp.TransportKind.ipc }, + debug: { + module: serverModule, + transport: lsp.TransportKind.ipc, + options: debugOptions, + }, + }; + const serverInitOptions: any = { + mode: mode, + appRoot: vscode.env.appRoot, + language: vscode.env.language, + }; + const clientOptions: lsp.LanguageClientOptions = { + documentSelector: [{ scheme: 'file', language: 'astro' }], + initializationOptions: serverInitOptions, + }; + const client = new lsp.LanguageClient(id, name, serverOptions, clientOptions); + context.subscriptions.push(client.start()); + + return client; +} + +async function startEmbeddedLanguageServices() { + const ts = vscode.extensions.getExtension('vscode.typescript-language-features'); + const css = vscode.extensions.getExtension('vscode.css-language-features'); + const html = vscode.extensions.getExtension('vscode.html-language-features'); + + if (ts && !ts.isActive) { + await ts.activate(); + } + if (css && !css.isActive) { + await css.activate(); + } + if (html && !html.isActive) { + await html.activate(); + } + + /* from html-language-features */ + const EMPTY_ELEMENTS: string[] = ['area', 'base', 'br', 'col', 'embed', 'hr', 'img', 'input', 'keygen', 'link', 'menuitem', 'meta', 'param', 'source', 'track', 'wbr']; + vscode.languages.setLanguageConfiguration('astro', { + indentationRules: { + increaseIndentPattern: /<(?!\?|(?:area|base|br|col|frame|hr|html|img|input|link|meta|param)\b|[^>]*\/>)([-_\.A-Za-z0-9]+)(?=\s|>)\b[^>]*>(?!.*<\/\1>)|<!--(?!.*-->)|\{[^}"']*$/, + decreaseIndentPattern: /^\s*(<\/(?!html)[-_\.A-Za-z0-9]+\b[^>]*>|-->|\})/, + }, + wordPattern: /(-?\d*\.\d\w*)|([^\`\~\!\@\$\^\&\*\(\)\=\+\[\{\]\}\\\|\;\:\'\"\,\.\<\>\/\s]+)/g, + onEnterRules: [ + { + beforeText: new RegExp(`<(?!(?:${EMPTY_ELEMENTS.join('|')}))([_:\\w][_:\\w-.\\d]*)([^/>]*(?!/)>)[^<]*$`, 'i'), + afterText: /^<\/([_:\w][_:\w-.\d]*)\s*>/i, + action: { indentAction: vscode.IndentAction.IndentOutdent }, + }, + { + beforeText: new RegExp(`<(?!(?:${EMPTY_ELEMENTS.join('|')}))(\\w[\\w\\d]*)([^/>]*(?!/)>)[^<]*$`, 'i'), + action: { indentAction: vscode.IndentAction.Indent }, + }, + ], + }); +} |