forked from strikekat/whitespace-plus
-
Notifications
You must be signed in to change notification settings - Fork 0
/
extension.js
executable file
·178 lines (147 loc) · 5.5 KB
/
extension.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
var vscode = require('vscode');
var fs = require('fs');
var enabled = false;
var activeEditor;
var config;
var configPath = vscode.extensions.getExtension("davidhouchin.whitespace-plus").extensionPath + '/config.json';
var configUri = vscode.Uri.file(configPath);
var configWatcher = vscode.workspace.createFileSystemWatcher(configPath);
var modes = ["all", "trailing"];
var elements = [];
function activate(context) {
// Subscribe to change events from the config file
configWatcher.onDidChange(event => {
loadConfig(configPath);
});
// Initial configuration load
loadConfig(configPath);
// Are we set to go automatically?
if (config.autoStart) {enableUpdates();}
// Main toggle method
var disposable1 = vscode.commands.registerCommand('extension.toggleWhitespacePlus', function () {
// If already enabled, clean the decorations and then disable
if (enabled) {
cleanDecorations();
enabled = false;
return;
}
// Otherwise, let's go!
enableUpdates();
});
context.subscriptions.push(disposable1);
// Show a quick pick menu to change the display mode
var disposable2 = vscode.commands.registerCommand('extension.toggleWhitespacePlusMode', function () {
vscode.window.showQuickPick(modes).then(function(selection){
cleanDecorations();
setMode(selection);
if (enabled) {updateDecorations();}
});
});
context.subscriptions.push(disposable2);
// Open the config file
var disposable3 = vscode.commands.registerCommand('extension.configWhitespacePlus', function () {
vscode.workspace.openTextDocument(configUri).then( function(document) {vscode.window.showTextDocument(document)});
});
context.subscriptions.push(disposable3);
// Starts the decorator updating
function enableUpdates() {
// Start the update cycle
activeEditor = vscode.window.activeTextEditor;
if (activeEditor) {
enabled = true;
triggerUpdate();
}
// Also trigger an update on changing the editor
vscode.window.onDidChangeActiveTextEditor(editor => {
activeEditor = editor;
if (editor) {
triggerUpdate();
}
}, null, context.subscriptions);
// And when modifying the document
vscode.workspace.onDidChangeTextDocument(event => {
if (activeEditor && event.document === activeEditor.document) {
triggerUpdate();
}
}, null, context.subscriptions);
// Set timeout for updating decorations
var timeout = null;
function triggerUpdate() {
if (timeout) {
clearTimeout(timeout);
}
timeout = setTimeout(updateDecorations, config.refreshRate);
}
}
// Reads editor text, and updates decorators on page
function updateDecorations() {
if ((!activeEditor) || (!enabled)) {
return;
}
// Create decorators if they don't already exist
createDecorations();
var text = activeEditor.document.getText();
var decChars = [];
var match;
// For each element, find all patterns in the text and create decorators
elements.forEach(function(cur, idx) {
var regex = RegExp(cur.pattern, 'gm');
decChars[idx] = {
"chars": [],
"decorator": cur.decorator
};
while (match = regex.exec(text)) {
var startPos = activeEditor.document.positionAt(match.index);
var endPos = activeEditor.document.positionAt(match.index + match[0].length);
var range = {range: new vscode.Range(startPos, endPos)};
decChars[idx].chars.push(range);
}
});
// Apply decorators to the editor
decChars.forEach(function(cur) {
activeEditor.setDecorations(cur.decorator, cur.chars);
});
}
// Load config from config path then cleans and updates decorations
function loadConfig(filePath) {
config = JSON.parse(fs.readFileSync(filePath).toString());
cleanDecorations();
setMode(config.mode);
updateDecorations();
}
// First deletes elements, then checks mode for trailing element only, or all other elements
function setMode(mode) {
elements.length = 0;
if (mode == "trailing") {
config.elements.forEach(function(cur) {
if (cur.name == "trailing") {elements.push(cur)};
});
} else {
config.elements.forEach(function(cur) {
if (cur.enabled) {elements.push(cur)};
});
}
}
// Create decorators for the window
function createDecorations() {
elements.forEach(function(cur) {
if (cur.decorator == null) {
cur.decorator = vscode.window.createTextEditorDecorationType(cur.style);
}
});
}
// Clean decorators from the window
function cleanDecorations() {
elements.forEach(function(cur) {
if (cur.decorator != null) {
cur.decorator.dispose();
cur.decorator = null;
}
});
}
}
exports.activate = activate;
// this method is called when your extension is deactivated
function deactivate() {
}
exports.deactivate = deactivate;