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/util/code-formatter.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
// common configuration for mapping programming languages (lower case) to formatters
7
// this is used by webapp and the project
8
9
// ideally, this is the "syntax", but for historic reasons it's what is being called "parsed" and
10
// hence there there are additional entries for backwards compatibility with older projects.
11
// this shouldn't be necessary any more and could be removed.
12
export type Syntax =
13
| "r"
14
| "c"
15
| "c++"
16
| "clang"
17
| "latex"
18
| "go"
19
| "CSS"
20
| "html"
21
| "xml"
22
| "bibtex"
23
| "markdown"
24
| "Markdown"
25
| "Quarto"
26
| "knitr"
27
| "javascript" // backwards compatibility
28
| "json"
29
| "JSON"
30
| "latex"
31
| "yaml"
32
| "python"
33
| "python3"
34
| "zig"
35
| "py"
36
| "R"
37
| "RMarkdown"
38
| "TypeScript"
39
| "JavaScript"
40
// the ones below are to be eliminated (they're in "Tool")
41
| "prettier"
42
| "typescript"
43
| "css"
44
| "babel"
45
| "gofmt"
46
| "clang-format"
47
| "rust"
48
| "rustfmt" // deprecated, should be rust
49
| "tsx"
50
| "jsx"
51
| "yapf"
52
| "yapf3"
53
| "formatR"
54
| "latexindent"
55
| "bib-biber"
56
| "xml-tidy"
57
| "DOES_NOT_EXIST";
58
59
export type Parser = Syntax;
60
61
export type Tool =
62
| "r" // to be removed
63
| "yapf"
64
| "yapf3" // for python 3
65
| "python" // should be yapf
66
| "knitr"
67
| "formatR"
68
| "clang-format"
69
| "latex"
70
| "latexindent"
71
| "gofmt"
72
| "xml-tidy"
73
| "rustfmt"
74
| "bib-biber"
75
| "prettier" // always available
76
| "css" // via prettier
77
| "babel" // via prettier
78
| "typescript" // via prettier
79
| "json" // via prettier
80
| "yaml" // via prettier
81
| "markdown" // via prettier
82
| "html" // via prettier
83
| "zig"
84
| "DOES_NOT_EXIST"; // use this for testing;
85
86
// the file extensions where we want to have formatting support
87
export const file_extensions = [
88
"bib",
89
"c",
90
"c++",
91
"cc",
92
"cml" /* that's xml */,
93
"cpp",
94
"css",
95
"go",
96
"h",
97
"html",
98
"js",
99
"json",
100
"jsx",
101
"kml" /* geodata keyhole markup, also xml */,
102
"md",
103
"ptx",
104
"py",
105
"qmd",
106
"r",
107
"rmd",
108
"rs",
109
"tex",
110
"ts",
111
"tsx",
112
"xml",
113
"xsl",
114
"yaml",
115
"yml",
116
"zig",
117
] as const;
118
119
export const fileExtensionsSet = new Set(file_extensions);
120
121
// convert to type
122
export type Exts = (typeof file_extensions)[number];
123
124
// associating filename extensions with a specific type of syntax for a parser
125
type Ext2Syntax = { [s in Exts]: Parser };
126
export const ext2syntax: Readonly<Ext2Syntax> = {
127
js: "JavaScript",
128
jsx: "jsx",
129
md: "Markdown",
130
rmd: "RMarkdown",
131
qmd: "Quarto",
132
css: "CSS",
133
ts: "TypeScript",
134
tsx: "tsx",
135
json: "JSON",
136
yaml: "yaml",
137
yml: "yaml",
138
py: "python3",
139
tex: "latex",
140
html: "html",
141
r: "R",
142
rs: "rust",
143
go: "go",
144
c: "clang",
145
cc: "clang",
146
"c++": "clang",
147
cpp: "clang",
148
h: "clang",
149
xml: "xml",
150
cml: "xml",
151
kml: "xml",
152
xsl: "xml",
153
ptx: "xml",
154
zig: "zig",
155
bib: "bibtex", // via biber --tool
156
} as const;
157
158
export const ext2parser = ext2syntax;
159
160
// those syntaxes (parser) which aren't handled by "prettier" (the default),
161
// have these special tools (command-line interface)
162
// (several ones are added for backwards compatibility)
163
type SyntaxConfig = { [s in Parser]: Tool };
164
export const syntax2tool: Readonly<Partial<SyntaxConfig>> = {
165
"c++": "clang-format",
166
"clang-format": "clang-format",
167
babel: "prettier",
168
bibtex: "bib-biber",
169
c: "clang-format",
170
clang: "clang-format",
171
CSS: "css", // in prettier
172
go: "gofmt",
173
gofmt: "gofmt",
174
html: "html", // via prettier
175
JavaScript: "babel", // in prettier
176
json: "json", // in prettier
177
JSON: "json", // in prettier
178
jsx: "babel", // in prettier
179
latex: "latex", // should be "latexindent",
180
markdown: "markdown", // in prettier
181
Markdown: "markdown", // in prettier
182
py: "python", // should be yapf or whatever …
183
python: "python", // should be yapf or whatever …
184
python3: "python", // should be yapf or whatever …
185
Quarto: "markdown", // same as RMarkdown, at least for now
186
r: "formatR",
187
R: "formatR",
188
RMarkdown: "markdown", // same as markdown, at last for now!
189
rust: "rustfmt",
190
tsx: "typescript", // in prettier
191
typescript: "typescript", // in prettier
192
TypeScript: "typescript", // in prettier
193
xml: "xml-tidy",
194
yaml: "yaml", // in prettier
195
zig: "zig",
196
} as const;
197
198
export const parser2tool = syntax2tool;
199
200
// Map (a subset of) syntax (aka "parser") to a human-readable language
201
// in order to communicate what syntaxes can be formatted.
202
type Langs = { [s in Parser]?: string };
203
204
export const syntax2display: Readonly<Langs> = {
205
"bib-biber": "Bibtex",
206
"c++": "C++",
207
c: "C",
208
css: "CSS",
209
gofmt: "Go",
210
html: "HTML",
211
javascript: "JavaScript",
212
JavaScript: "JavaScript",
213
json: "JSON",
214
latex: "LaTeX",
215
markdown: "Markdown",
216
py: "Python",
217
r: "R Language",
218
rust: "Rust",
219
typescript: "TypeScript",
220
xml: "XML",
221
yaml: "YAML",
222
zig: "Zig",
223
} as const;
224
225
export const parser2display = syntax2display;
226
227
// pre-process mapping of each tool to human-readable language or text type
228
type Tool2Display = { [s in Tool]?: string[] };
229
230
const t2d: Tool2Display = {};
231
for (const parser of Object.keys(parser2tool)) {
232
const tool = parser2tool[parser];
233
if (t2d[tool] == null) t2d[tool] = [];
234
const lang = parser2display[parser];
235
if (lang != null) t2d[tool].push(lang);
236
}
237
238
for (const tool of Object.keys(t2d)) {
239
t2d[tool] = t2d[tool].sort();
240
}
241
242
export const tool2display: Readonly<Tool2Display> = Object.freeze(t2d);
243
244
export interface Config {
245
syntax: Syntax;
246
tabWidth?: number;
247
useTabs?: boolean;
248
}
249
250
export interface Options extends Omit<Config, "syntax"> {
251
parser: Syntax; // TODO refactor this to tool
252
tabWidth?: number;
253
}
254
255