CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutSign UpSign In
sagemathinc

Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place.

GitHub Repository: sagemathinc/cocalc
Path: blob/master/src/packages/project/formatters/clang-format.ts
Views: 687
1
/*
2
* This file is part of CoCalc: Copyright © 2020 Sagemath, Inc.
3
* License: MS-RSL – see LICENSE.md for details
4
*/
5
6
import { callback } from "awaiting";
7
import { spawn } from "node:child_process";
8
import { readFile, unlink, writeFile } from "node:fs";
9
import { file as tmp_file } from "tmp";
10
11
import { Options } from "./index";
12
13
function close(proc, cb): void {
14
proc.on("close", (code) => cb(undefined, code));
15
}
16
17
// ref: https://clang.llvm.org/docs/ClangFormat.html
18
19
function run_clang_format(
20
input_path: string,
21
indent: number /*, logger: any*/
22
) {
23
const style = `-style={BasedOnStyle: google, IndentWidth: ${indent}}`;
24
// See https://github.com/sagemathinc/cocalc/issues/5419 for why we disable sort-includes!
25
const args = ["--sort-includes=0", "-i", style, input_path];
26
// logger.debug(`run_clang_format args: [${args}]`);
27
return spawn("clang-format", args);
28
}
29
30
export async function clang_format(
31
input: string,
32
ext: string,
33
options: Options,
34
logger: any
35
): Promise<string> {
36
// create input temp file
37
// we have to set the correct filename extension, because clang format uses it
38
const input_path: string = await callback(tmp_file, { postfix: `.${ext}` });
39
try {
40
// logger.debug(`clang_format tmp file: ${input_path}`);
41
await callback(writeFile, input_path, input);
42
43
// spawn the c formatter
44
let formatter;
45
const indent = options.tabWidth || 2;
46
47
switch (options.parser) {
48
case "clang-format":
49
formatter = run_clang_format(input_path, indent /*, logger*/);
50
break;
51
default:
52
throw Error(
53
`Unknown C/C++ code formatting utility '${options.parser}'`
54
);
55
}
56
// stdout/err capture
57
let stdout: string = "";
58
let stderr: string = "";
59
// read data as it is produced.
60
formatter.stdout.on("data", (data) => (stdout += data.toString()));
61
formatter.stderr.on("data", (data) => (stderr += data.toString()));
62
// wait for subprocess to close.
63
const code = await callback(close, formatter);
64
65
if (code >= 1) {
66
const err_msg = `C/C++ code formatting utility "${options.parser}" exited with code ${code}\nOutput:\n${stdout}\n${stderr}`;
67
logger.debug(`clang-format error: ${err_msg}`);
68
throw Error(err_msg);
69
}
70
71
// all fine, we read from the temp file
72
const output: Buffer = await callback(readFile, input_path);
73
74
const s: string = output.toString("utf-8");
75
// logger.debug(`clang_format output s ${s}`);
76
77
return s;
78
} finally {
79
unlink(input_path, () => {});
80
}
81
}
82
83