-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathextension.js
212 lines (165 loc) · 6.8 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
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
const vscode = require("vscode");
const sudo = require("sudo-prompt");
const path = require("path");
const tmp = require("tmp");
const fs = require("fs");
// Predefined to be used for errors and information.
const messages = {
enableSuccess: "Smooth Typing has been enabled. Please restart the window.",
disableSuccess: "Smooth Typing has been disabled. Please restart the window.",
reloadSuccess: "Smooth Typing has been reloaded. Please restart the window.",
enabledAlready: "Smooth Typing is already enabled.",
disabledAlready: "Smooth Typing is not enabled.",
enableFailed: "Failed to enable Smooth Typing.",
disableFailed: "Failed to disable Smooth Typing.",
reloadFailed: "Failed to reload Smooth Typing."
};
// Paths and directoies to VS Code itself.
const appDirectory = path.dirname(require.main.filename);
const cssPath = path.join(appDirectory, "/vs/workbench/workbench.main.css");
// Comments to indicate where the injected code begins and ends.
const beginComment = "/* Begin SmoothType */";
const endComment = "/* End SmoothType */";
// Template for the injected code. "{duration}" is replaced with the user preference.
const injectionTemplate =
"\n" + beginComment +
"\n.cursor { transition: all {duration}ms }" +
"\n" + endComment;
// Pattern to check if the code is injected.
const injectionPattern = new RegExp("\\s*" + escapeRegExp(beginComment) + "(?:.|\\s)*" + escapeRegExp(endComment));
// Export the activate function to be called whenever the extension is initialized.
exports.activate = activate;
// Subscribe all of the command functions to the corresponding contributions.
function activate(context) {
console.info("Application Directory: ", appDirectory);
console.info("Application Main CSS: ", cssPath);
context.subscriptions.push(vscode.commands.registerCommand("extension.enableAnimation", enableAnimation));
context.subscriptions.push(vscode.commands.registerCommand("extension.disableAnimation", disableAnimation));
context.subscriptions.push(vscode.commands.registerCommand("extension.reloadAnimation", reloadAnimation));
}
function enableAnimation() {
if (!checkInjection()) {
let config = vscode.workspace.getConfiguration("smoothtype");
injectCursorStyle(config.duration).then(() => {
if (config.autoReload) reloadWindow();
else reloadWindow(messages.enableSuccess);
}, (reason) => {
vscode.window.showWarningMessage(messages.enableFailed);
console.error(messages.enableFailed, "\n", reason);
});
} else {
vscode.window.showInformationMessage(messages.enabledAlready);
console.info(messages.enabledAlready);
}
}
function disableAnimation() {
if (checkInjection()) {
let config = vscode.workspace.getConfiguration("smoothtype");
removeCursorStyle().then(() => {
if (config.autoReload) reloadWindow();
else reloadWindow(messages.disableSuccess);
}, (reason) => {
vscode.window.showWarningMessage(messages.disableFailed);
console.error(messages.disableFailed, "\n", reason);
});
} else {
vscode.window.showInformationMessage(messages.disabledAlready);
console.info(messages.disabledAlready);
}
}
function reloadAnimation() {
let config = vscode.workspace.getConfiguration("smoothtype");
reloadCursorStyle(config.duration).then(() => {
if (config.autoReload) reloadWindow();
else reloadWindow(messages.reloadSuccess);
}, (reason) => {
vscode.window.showWarningMessage(messages.reloadFailed);
console.error(messages.reloadFailed, "\n", reason);
});
}
function injectCursorStyle(duration) {
console.info("Injecting cursor styles.");
return new Promise((resolve, reject) => {
fs.readFile(cssPath, "utf-8", (error, css) => {
if (error) reject(error);
else {
css += "\n" + injectionTemplate.replace("{duration}", duration);
writeFileAdmin(
cssPath, css, "utf-8", "Visual Studio Code"
).then(resolve, reject);
}
});
});
}
function removeCursorStyle() {
console.info("Removing cursor styles.");
return new Promise((resolve, reject) => {
fs.readFile(cssPath, "utf-8", (error, css) => {
if (error) reject(error);
else {
css = css.replace(injectionPattern, "");
writeFileAdmin(
cssPath, css, "utf-8", "Visual Studio Code"
).then(resolve, reject);
}
});
});
}
function reloadCursorStyle(duration) {
console.info("Reloading cursor styles.");
return new Promise((resolve, reject) => {
fs.readFile(cssPath, "utf-8", (error, css) => {
if (error) reject(error);
if (checkInjection())
css = css.replace(injectionPattern, "");
css += "\n" + injectionTemplate.replace("{duration}", duration);
writeFileAdmin(
cssPath, css, "utf-8", "Visual Studio Code"
).then(resolve, reject);
});
});
}
function checkInjection() {
console.info("Check if cursor styles are injected.");
let mainCSS = fs.readFileSync(cssPath, "utf-8");
let injected = injectionPattern.test(mainCSS);
console.info(injected ? "Cursor styles are present." : "Cursor styles are missing.");
return injected;
}
function writeFileAdmin(filePath, writeString, encoding = "utf-8", promptName = "File Writer") {
console.info("Writing file with administrator priveleges.");
return new Promise((resolve, reject) => {
tmp.file((error, tempFilePath) => {
if (error) reject(error);
else fs.writeFile(tempFilePath, writeString, encoding, (error) => {
if (error) reject(error);
else sudo.exec(
(process.platform === "win32" ? "copy " : "cp ") +
"\"" + tempFilePath + "\" \"" + filePath + "\"",
{ name: promptName },
(error) => {
if (error) reject(error);
else resolve(error);
}
);
});
});
});
}
function reloadWindow(message) {
if (message === undefined) {
console.info("Reloading window.");
vscode.commands.executeCommand("workbench.action.reloadWindow");
} else {
console.info("Requesting to reload window.");
vscode.window.showInformationMessage(message, {
title: "Reload Window"
}).then(clicked => {
if (clicked) reloadWindow();
});
}
}
// https://stackoverflow.com/a/6969486/2512078
function escapeRegExp(string) {
return string.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
}