diff options
Diffstat (limited to 'code/src')
-rw-r--r-- | code/src/main.ts | 193 |
1 files changed, 193 insertions, 0 deletions
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 @@ | |||
1 | 'use strict' | ||
2 | import * as vscode from 'vscode' | ||
3 | |||
4 | const backend = require("../../native") | ||
5 | |||
6 | let docToSyntax; | ||
7 | |||
8 | let uris = { | ||
9 | syntaxTree: vscode.Uri.parse('libsyntax-rust://syntaxtree') | ||
10 | } | ||
11 | |||
12 | |||
13 | export function activate(context: vscode.ExtensionContext) { | ||
14 | let textDocumentContentProvider = new TextDocumentContentProvider() | ||
15 | |||
16 | let dispose = (disposable) => { | ||
17 | context.subscriptions.push(disposable); | ||
18 | } | ||
19 | |||
20 | let registerCommand = (name, f) => { | ||
21 | dispose(vscode.commands.registerCommand(name, f)) | ||
22 | } | ||
23 | |||
24 | docToSyntax = documentToFile(context.subscriptions, () => { | ||
25 | let emitter = textDocumentContentProvider.eventEmitter | ||
26 | emitter.fire(uris.syntaxTree) | ||
27 | let syntax = activeSyntax() | ||
28 | console.log(syntax.highlight()); | ||
29 | setHighlights(vscode.window.activeTextEditor, syntax.highlight()) | ||
30 | }) | ||
31 | |||
32 | |||
33 | dispose(vscode.workspace.registerTextDocumentContentProvider( | ||
34 | 'libsyntax-rust', | ||
35 | textDocumentContentProvider | ||
36 | )) | ||
37 | |||
38 | registerCommand('libsyntax-rust.syntaxTree', () => openDoc(uris.syntaxTree)) | ||
39 | } | ||
40 | |||
41 | export function deactivate() { } | ||
42 | |||
43 | export class Syntax { | ||
44 | imp; | ||
45 | doc: vscode.TextDocument; | ||
46 | |||
47 | constructor(imp, doc: vscode.TextDocument) { | ||
48 | this.imp = imp | ||
49 | this.doc = doc | ||
50 | } | ||
51 | |||
52 | syntaxTree(): string { return this.imp.syntaxTree() } | ||
53 | highlight(): Array<[number, number, string]> { return this.imp.highlight() } | ||
54 | } | ||
55 | |||
56 | |||
57 | function activeDoc() { | ||
58 | return vscode.window.activeTextEditor.document | ||
59 | } | ||
60 | |||
61 | function activeSyntax(): Syntax { | ||
62 | let doc = activeDoc() | ||
63 | if (doc == null) return null | ||
64 | return docToSyntax(doc) | ||
65 | } | ||
66 | |||
67 | async function openDoc(uri: vscode.Uri) { | ||
68 | let document = await vscode.workspace.openTextDocument(uri) | ||
69 | return vscode.window.showTextDocument(document, vscode.ViewColumn.Two, true) | ||
70 | } | ||
71 | |||
72 | function documentToFile(disposables: vscode.Disposable[], onChange) { | ||
73 | let docs = {} | ||
74 | function update(doc: vscode.TextDocument, file) { | ||
75 | let key = doc.uri.toString() | ||
76 | if (file == null) { | ||
77 | delete docs[key] | ||
78 | } else { | ||
79 | docs[key] = file | ||
80 | } | ||
81 | onChange(doc) | ||
82 | } | ||
83 | function get(doc: vscode.TextDocument) { | ||
84 | return docs[doc.uri.toString()] | ||
85 | } | ||
86 | |||
87 | function isKnownDoc(doc: vscode.TextDocument) { | ||
88 | return doc.fileName.endsWith('.rs') | ||
89 | } | ||
90 | |||
91 | function createFile(text: String) { | ||
92 | return new backend.RustFile(text) | ||
93 | } | ||
94 | |||
95 | vscode.workspace.onDidChangeTextDocument((event: vscode.TextDocumentChangeEvent) => { | ||
96 | let doc = event.document | ||
97 | if (!isKnownDoc(event.document)) return | ||
98 | update(doc, null) | ||
99 | }, null, disposables) | ||
100 | |||
101 | vscode.workspace.onDidOpenTextDocument((doc: vscode.TextDocument) => { | ||
102 | if (!isKnownDoc(doc)) return | ||
103 | update(doc, createFile(doc.getText())) | ||
104 | }, null, disposables) | ||
105 | |||
106 | vscode.workspace.onDidCloseTextDocument((doc: vscode.TextDocument) => { | ||
107 | update(doc, null) | ||
108 | }, null, disposables) | ||
109 | |||
110 | return (doc: vscode.TextDocument) => { | ||
111 | if (!isKnownDoc(doc)) return null | ||
112 | |||
113 | if (!get(doc)) { | ||
114 | update(doc, createFile(doc.getText())) | ||
115 | } | ||
116 | let imp = get(doc) | ||
117 | return new Syntax(imp, doc) | ||
118 | } | ||
119 | } | ||
120 | |||
121 | export class TextDocumentContentProvider implements vscode.TextDocumentContentProvider { | ||
122 | public eventEmitter = new vscode.EventEmitter<vscode.Uri>() | ||
123 | public syntaxTree: string = "Not available" | ||
124 | |||
125 | public provideTextDocumentContent(uri: vscode.Uri): vscode.ProviderResult<string> { | ||
126 | let syntax = activeSyntax() | ||
127 | if (syntax == null) return | ||
128 | if (uri.toString() == uris.syntaxTree.toString()) { | ||
129 | return syntax.syntaxTree() | ||
130 | } | ||
131 | } | ||
132 | |||
133 | get onDidChange(): vscode.Event<vscode.Uri> { | ||
134 | return this.eventEmitter.event | ||
135 | } | ||
136 | } | ||
137 | |||
138 | const decorations = (() => { | ||
139 | const decor = (obj) => vscode.window.createTextEditorDecorationType({ color: obj }) | ||
140 | return { | ||
141 | background: decor("#3F3F3F"), | ||
142 | error: vscode.window.createTextEditorDecorationType({ | ||
143 | borderColor: "red", | ||
144 | borderStyle: "none none dashed none", | ||
145 | }), | ||
146 | comment: decor("#7F9F7F"), | ||
147 | string: decor("#CC9393"), | ||
148 | keyword: decor("#F0DFAF"), | ||
149 | function: decor("#93E0E3"), | ||
150 | parameter: decor("#94BFF3"), | ||
151 | builtin: decor("#DD6718"), | ||
152 | text: decor("#DCDCCC"), | ||
153 | attribute: decor("#BFEBBF"), | ||
154 | literal: decor("#DFAF8F"), | ||
155 | } | ||
156 | })() | ||
157 | |||
158 | function setHighlights( | ||
159 | editor: vscode.TextEditor, | ||
160 | highlihgs: Array<[number, number, string]> | ||
161 | ) { | ||
162 | console.log("setHighlight"); | ||
163 | let byTag = {} | ||
164 | for (let tag in decorations) { | ||
165 | byTag[tag] = [] | ||
166 | } | ||
167 | |||
168 | for (let [start, end, tag] of highlihgs) { | ||
169 | if (!byTag[tag]) { | ||
170 | console.log(`unknown tag ${tag}`) | ||
171 | continue | ||
172 | } | ||
173 | let range = toVsRange(editor.document, [start, end]) | ||
174 | byTag[tag].push(range) | ||
175 | } | ||
176 | |||
177 | for (let tag in byTag) { | ||
178 | let dec = decorations[tag] | ||
179 | let ranges = byTag[tag] | ||
180 | editor.setDecorations(dec, ranges) | ||
181 | } | ||
182 | } | ||
183 | |||
184 | export function toVsRange(doc: vscode.TextDocument, range: [number, number]): vscode.Range { | ||
185 | return new vscode.Range( | ||
186 | doc.positionAt(range[0]), | ||
187 | doc.positionAt(range[1]), | ||
188 | ) | ||
189 | } | ||
190 | |||
191 | function fromVsRange(doc: vscode.TextDocument, range: vscode.Range): [number, number] { | ||
192 | return [doc.offsetAt(range.start), doc.offsetAt(range.end)] | ||
193 | } | ||