-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathextension.js
More file actions
97 lines (89 loc) · 2.95 KB
/
Copy pathextension.js
File metadata and controls
97 lines (89 loc) · 2.95 KB
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
"use strict";
const vscode = require("vscode");
const cp = require("child_process");
const path = require("path");
function findRegions(text) {
const opener = /r(#+)"[ \t]*\/\*[ \t]*cpp[ \t]*\*\//g;
const regions = [];
let o;
while ((o = opener.exec(text)) !== null) {
const hashes = o[1];
const innerStart = o.index + o[0].length;
const close = '"' + hashes;
const innerEnd = text.indexOf(close, innerStart);
if (innerEnd === -1) continue;
const lineStart = text.lastIndexOf("\n", o.index) + 1;
const parentIndent = text.slice(lineStart, o.index).match(/^[ \t]*/)[0].length;
regions.push({ innerStart, innerEnd, parentIndent });
opener.lastIndex = innerEnd + close.length;
}
return regions;
}
function runClangFormat(input, cwd) {
const res = cp.spawnSync("clang-format", ["-style=file"], {
input,
cwd,
encoding: "utf8",
maxBuffer: 64 * 1024 * 1024,
});
if (res.error) throw new Error("could not run clang-format: " + res.error.message);
if (res.status !== 0) {
throw new Error("clang-format exited " + res.status + ": " + (res.stderr || res.stdout).trim());
}
return res.stdout;
}
function indent(s, pad) {
return s
.split("\n")
.map((l) => (l.trim() === "" ? "" : pad + l))
.join("\n");
}
function stripCommonIndent(s) {
let min = Infinity;
for (const l of s.split("\n")) {
if (l.trim() === "") continue;
min = Math.min(min, l.match(/^[ \t]*/)[0].length);
}
if (!isFinite(min) || min === 0) return s;
return s
.split("\n")
.map((l) => (l.trim() === "" ? l : l.slice(min)))
.join("\n");
}
function computeEdits(doc) {
const cwd = path.dirname(doc.uri.fsPath);
const text = doc.getText();
const edits = [];
for (const r of findRegions(text)) {
const inner = text.slice(r.innerStart, r.innerEnd);
const normalized = stripCommonIndent(inner.replace(/^\n+/, "").replace(/\s+$/, ""));
const body = runClangFormat(normalized, cwd).replace(/^\n+/, "").replace(/\s+$/, "");
const bodyPad = " ".repeat(r.parentIndent + 4);
const closerPad = " ".repeat(r.parentIndent);
const out = "\n" + indent(body, bodyPad) + "\n" + closerPad;
if (out === inner) continue;
const range = new vscode.Range(doc.positionAt(r.innerStart), doc.positionAt(r.innerEnd));
edits.push(vscode.TextEdit.replace(range, out));
}
return edits;
}
function activate(context) {
context.subscriptions.push(
vscode.workspace.onWillSaveTextDocument((e) => {
if (e.document.languageId !== "rust") return;
if (!vscode.workspace.getConfiguration("inlineCpp").get("formatOnSave")) return;
e.waitUntil(
(async () => {
try {
return computeEdits(e.document);
} catch (err) {
vscode.window.showErrorMessage("Inline C++: " + (err && err.message ? err.message : String(err)));
return [];
}
})()
);
})
);
}
function deactivate() {}
module.exports = { activate, deactivate };