From ac0d8c48f7a277d4a43448fe7dd4279383bc53f0 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Mon, 30 Jul 2018 21:58:49 +0300 Subject: JS plugin --- code/src/main.ts | 193 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 193 insertions(+) create mode 100644 code/src/main.ts (limited to 'code/src') diff --git a/code/src/main.ts b/code/src/main.ts new file mode 100644 index 000000000..dfb005c09 --- /dev/null +++ b/code/src/main.ts @@ -0,0 +1,193 @@ +'use strict' +import * as vscode from 'vscode' + +const backend = require("../../native") + +let docToSyntax; + +let uris = { + syntaxTree: vscode.Uri.parse('libsyntax-rust://syntaxtree') +} + + +export function activate(context: vscode.ExtensionContext) { + let textDocumentContentProvider = new TextDocumentContentProvider() + + let dispose = (disposable) => { + context.subscriptions.push(disposable); + } + + let registerCommand = (name, f) => { + dispose(vscode.commands.registerCommand(name, f)) + } + + docToSyntax = documentToFile(context.subscriptions, () => { + let emitter = textDocumentContentProvider.eventEmitter + emitter.fire(uris.syntaxTree) + let syntax = activeSyntax() + console.log(syntax.highlight()); + setHighlights(vscode.window.activeTextEditor, syntax.highlight()) + }) + + + dispose(vscode.workspace.registerTextDocumentContentProvider( + 'libsyntax-rust', + textDocumentContentProvider + )) + + registerCommand('libsyntax-rust.syntaxTree', () => openDoc(uris.syntaxTree)) +} + +export function deactivate() { } + +export class Syntax { + imp; + doc: vscode.TextDocument; + + constructor(imp, doc: vscode.TextDocument) { + this.imp = imp + this.doc = doc + } + + syntaxTree(): string { return this.imp.syntaxTree() } + highlight(): Array<[number, number, string]> { return this.imp.highlight() } +} + + +function activeDoc() { + return vscode.window.activeTextEditor.document +} + +function activeSyntax(): Syntax { + let doc = activeDoc() + if (doc == null) return null + return docToSyntax(doc) +} + +async function openDoc(uri: vscode.Uri) { + let document = await vscode.workspace.openTextDocument(uri) + return vscode.window.showTextDocument(document, vscode.ViewColumn.Two, true) +} + +function documentToFile(disposables: vscode.Disposable[], onChange) { + let docs = {} + function update(doc: vscode.TextDocument, file) { + let key = doc.uri.toString() + if (file == null) { + delete docs[key] + } else { + docs[key] = file + } + onChange(doc) + } + function get(doc: vscode.TextDocument) { + return docs[doc.uri.toString()] + } + + function isKnownDoc(doc: vscode.TextDocument) { + return doc.fileName.endsWith('.rs') + } + + function createFile(text: String) { + return new backend.RustFile(text) + } + + vscode.workspace.onDidChangeTextDocument((event: vscode.TextDocumentChangeEvent) => { + let doc = event.document + if (!isKnownDoc(event.document)) return + update(doc, null) + }, null, disposables) + + vscode.workspace.onDidOpenTextDocument((doc: vscode.TextDocument) => { + if (!isKnownDoc(doc)) return + update(doc, createFile(doc.getText())) + }, null, disposables) + + vscode.workspace.onDidCloseTextDocument((doc: vscode.TextDocument) => { + update(doc, null) + }, null, disposables) + + return (doc: vscode.TextDocument) => { + if (!isKnownDoc(doc)) return null + + if (!get(doc)) { + update(doc, createFile(doc.getText())) + } + let imp = get(doc) + return new Syntax(imp, doc) + } +} + +export class TextDocumentContentProvider implements vscode.TextDocumentContentProvider { + public eventEmitter = new vscode.EventEmitter() + public syntaxTree: string = "Not available" + + public provideTextDocumentContent(uri: vscode.Uri): vscode.ProviderResult { + let syntax = activeSyntax() + if (syntax == null) return + if (uri.toString() == uris.syntaxTree.toString()) { + return syntax.syntaxTree() + } + } + + get onDidChange(): vscode.Event { + return this.eventEmitter.event + } +} + +const decorations = (() => { + const decor = (obj) => vscode.window.createTextEditorDecorationType({ color: obj }) + return { + background: decor("#3F3F3F"), + error: vscode.window.createTextEditorDecorationType({ + borderColor: "red", + borderStyle: "none none dashed none", + }), + comment: decor("#7F9F7F"), + string: decor("#CC9393"), + keyword: decor("#F0DFAF"), + function: decor("#93E0E3"), + parameter: decor("#94BFF3"), + builtin: decor("#DD6718"), + text: decor("#DCDCCC"), + attribute: decor("#BFEBBF"), + literal: decor("#DFAF8F"), + } +})() + +function setHighlights( + editor: vscode.TextEditor, + highlihgs: Array<[number, number, string]> +) { + console.log("setHighlight"); + let byTag = {} + for (let tag in decorations) { + byTag[tag] = [] + } + + for (let [start, end, tag] of highlihgs) { + if (!byTag[tag]) { + console.log(`unknown tag ${tag}`) + continue + } + let range = toVsRange(editor.document, [start, end]) + byTag[tag].push(range) + } + + for (let tag in byTag) { + let dec = decorations[tag] + let ranges = byTag[tag] + editor.setDecorations(dec, ranges) + } +} + +export function toVsRange(doc: vscode.TextDocument, range: [number, number]): vscode.Range { + return new vscode.Range( + doc.positionAt(range[0]), + doc.positionAt(range[1]), + ) +} + +function fromVsRange(doc: vscode.TextDocument, range: vscode.Range): [number, number] { + return [doc.offsetAt(range.start), doc.offsetAt(range.end)] +} -- cgit v1.2.3