liquidsoap-prettier 1.4.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/src/index.js ADDED
@@ -0,0 +1,739 @@
1
+ import prettierDoc from "prettier/doc";
2
+ import * as liquidsoap from "../dist/liquidsoap.cjs";
3
+
4
+ const {
5
+ builders: {
6
+ group,
7
+ trim,
8
+ indent,
9
+ dedent,
10
+ join,
11
+ hardline,
12
+ line,
13
+ litteralline,
14
+ softline,
15
+ ifBreak,
16
+ lineSuffix,
17
+ fill,
18
+ },
19
+ } = prettierDoc;
20
+
21
+ export const languages = [
22
+ {
23
+ name: "liquidsoap",
24
+ parsers: ["liquidsoap"],
25
+ extensions: [".liq"],
26
+ vscodeLanguageIds: ["liquidsoap"],
27
+ },
28
+ ];
29
+
30
+ export const parsers = {
31
+ liquidsoap: {
32
+ parse: liquidsoap.default.lang.parse,
33
+ astFormat: "liquidsoap",
34
+ locStart: () => 0,
35
+ locEnd: () => 0,
36
+ },
37
+ };
38
+
39
+ const printString = (str) => {
40
+ if (/(?<!\\)\n/.test(str)) return str;
41
+ if (!/\s/.test(str)) return str;
42
+
43
+ return fill(
44
+ str
45
+ .replace(/\\\n\s*/g, "")
46
+ .split(/(\s)/)
47
+ .map((s) =>
48
+ s === " " ? ifBreak(group([" ", "\\", hardline, " "]), " ") : s,
49
+ ),
50
+ );
51
+ };
52
+
53
+ const print = (path, options, print) => {
54
+ const node = path.getValue();
55
+
56
+ const printIfDef = (...ifdef) => [
57
+ group([trim, ...ifdef, hardline]),
58
+ group([print("then")]),
59
+ ...(node.else
60
+ ? [group([hardline, trim, "%else", hardline]), group([print("else")])]
61
+ : []),
62
+ group([hardline, trim, "%endif"]),
63
+ ];
64
+
65
+ const printPat = () => {
66
+ if (!node.cast) return print("pat");
67
+
68
+ return group([
69
+ "(",
70
+ group([indent([softline, print("pat")]), line, ":"]),
71
+ indent([line, print("cast")]),
72
+ softline,
73
+ ")",
74
+ ]);
75
+ };
76
+
77
+ const newLine = (pos1, pos2) => {
78
+ const posBefore = pos1?.[1]?.lnum;
79
+ const posAfter = pos2?.[0]?.lnum;
80
+ return posBefore && posAfter && posAfter - posBefore > 1 ? [hardline] : [];
81
+ };
82
+
83
+ const printEllipsis = (p) => {
84
+ node.ast_comments = node.value.ast_comments;
85
+ node.position = node.value.position;
86
+ delete node.value.ast_comments;
87
+ return group(["...", print(p)]);
88
+ };
89
+
90
+ const printComments = (node, content) => {
91
+ if (!node.ast_comments) return [node.position, content];
92
+
93
+ const beforeComments = node.ast_comments.before;
94
+ const afterComments = node.ast_comments.after;
95
+
96
+ delete node.ast_comments;
97
+
98
+ const [contentWithBeforeComments, beforePosition] = beforeComments
99
+ .reverse()
100
+ .reduce(
101
+ ([content, position], comment) => [
102
+ [
103
+ join(hardline, comment.value),
104
+ hardline,
105
+ ...(position === node.position
106
+ ? newLine(comment.position, position)
107
+ : [hardline]),
108
+ ...content,
109
+ ],
110
+ comment.position,
111
+ ],
112
+ [[content], node.position],
113
+ );
114
+
115
+ const [contentWithAfterComments, afterPosition] = afterComments.reduce(
116
+ ([content, position], comment) => [
117
+ [
118
+ ...content,
119
+ ...(position === node.position
120
+ ? [hardline, ...newLine(position, comment.position)]
121
+ : [hardline, hardline]),
122
+ lineSuffix(join(hardline, comment.value)),
123
+ ],
124
+ comment.position,
125
+ ],
126
+ [contentWithBeforeComments, node.position],
127
+ );
128
+
129
+ return [[beforePosition[0], afterPosition[1]], contentWithAfterComments];
130
+ };
131
+
132
+ const printSeq = (pos1, content1, pos2, content2) => {
133
+ return [content1, hardline, ...newLine(pos1, pos2), content2];
134
+ };
135
+
136
+ const printDef = (pos1, node1) =>
137
+ node.body.type === "eof"
138
+ ? node1
139
+ : printSeq(pos1, node1, node.body.position, print("body"));
140
+
141
+ const joinWithComments = (join, p) => {
142
+ const nodes = node[p].map((node) => {
143
+ if (node.type === "term") {
144
+ node.ast_comments = node.value.ast_comments;
145
+ node.position = node.value.position;
146
+ delete node.value.ast_comments;
147
+ }
148
+
149
+ const { ast_comments, position } = node;
150
+
151
+ delete node.ast_comments;
152
+
153
+ return { ast_comments, position };
154
+ });
155
+
156
+ const content = path.map(print, p);
157
+
158
+ return content.reduce(
159
+ ([position, result], c, idx) => {
160
+ const isLast = idx === content.length - 1;
161
+ const joinedContent = isLast ? c : [c, join];
162
+
163
+ if (!nodes[idx].position)
164
+ return [position, [result, joinedContent, ...(isLast ? [] : [line])]];
165
+
166
+ const [nextPosition, contentWithComments] = printComments(
167
+ nodes[idx],
168
+ joinedContent,
169
+ );
170
+
171
+ return [
172
+ [position[0], nextPosition[1]],
173
+ [
174
+ ...result,
175
+ ...newLine(position, nextPosition),
176
+ contentWithComments,
177
+ ...(isLast ? [] : [line]),
178
+ ],
179
+ ];
180
+ },
181
+ [node.position, []],
182
+ )[1];
183
+ };
184
+
185
+ const printOptTyp = (arg) => [
186
+ ...(node.typ ? ["(", softline] : []),
187
+ arg,
188
+ ...(node.typ ? [":", softline, print("typ"), softline, ")"] : []),
189
+ ];
190
+
191
+ const printLabel = () =>
192
+ node.label === ""
193
+ ? printOptTyp(node.as_variable)
194
+ : [
195
+ "~",
196
+ ...printOptTyp(
197
+ group([
198
+ node.label,
199
+ ...(node.as_variable ? ["=", node.as_variable] : []),
200
+ ]),
201
+ ),
202
+ ];
203
+
204
+ const printFunArg = () =>
205
+ group([...printLabel(), ...(node.default ? ["=", print("default")] : [])]);
206
+
207
+ const printAppArg = () => {
208
+ if (node.label)
209
+ return group([node.label, "=", indent([softline, print("value")])]);
210
+ return print("value");
211
+ };
212
+
213
+ const printTypeAnnotation = () => {
214
+ switch (node.subtype) {
215
+ case "named":
216
+ return node.value;
217
+ case "nullable":
218
+ return [print("value"), "?"];
219
+ case "fun_arg":
220
+ return [
221
+ ...(node.label ? ["~", node.label] : []),
222
+ print("value"),
223
+ ...(node.optional ? ["?"] : []),
224
+ ];
225
+ case "list":
226
+ return group(["[", indent([softline, print("value")]), softline, "]"]);
227
+ case "json_object":
228
+ return [
229
+ "[",
230
+ "(",
231
+ group([indent([softline, "string", "*", print("value")]), softline]),
232
+ ")",
233
+ "]",
234
+ " ",
235
+ "as",
236
+ " ",
237
+ "json.object",
238
+ ];
239
+ case "tuple":
240
+ return group([
241
+ "(",
242
+ indent(group([softline, join(["*"], path.map(print, "value"))])),
243
+ softline,
244
+ ")",
245
+ ]);
246
+ case "arrow":
247
+ return [
248
+ group([
249
+ "(",
250
+ indent([softline, joinWithComments([","], "args")]),
251
+ softline,
252
+ ")",
253
+ ]),
254
+ "->",
255
+ print("value"),
256
+ ];
257
+ case "method_annotation":
258
+ return [
259
+ ...(node.json_name
260
+ ? [JSON.stringify(node.json_name), " ", "as", " "]
261
+ : []),
262
+ node.name,
263
+ ...(node.optional ? ["?"] : []),
264
+ ":",
265
+ " ",
266
+ print("value"),
267
+ ];
268
+ case "record":
269
+ return group([
270
+ "{",
271
+ group([
272
+ indent([softline, joinWithComments([","], "value")]),
273
+ softline,
274
+ ]),
275
+ "}",
276
+ ]);
277
+ case "method":
278
+ return [
279
+ print("base"),
280
+ ".",
281
+ "{",
282
+ group([indent([line, joinWithComments([","], "value")]), line]),
283
+ "}",
284
+ ];
285
+ case "invoke":
286
+ return group([print("value"), indent([softline, ".", node.method])]);
287
+ case "source_annotation":
288
+ return node.value.length === 0
289
+ ? []
290
+ : group([
291
+ "(",
292
+ indent([
293
+ softline,
294
+ join(
295
+ [",", line],
296
+ [
297
+ ...path.map(print, "value"),
298
+ ...(node.extensible ? ["..."] : []),
299
+ ],
300
+ ),
301
+ ]),
302
+ softline,
303
+ ")",
304
+ ]);
305
+ case "source_track_annotation":
306
+ return [
307
+ node.name,
308
+ "=",
309
+ node.value,
310
+ ...(node.params.length === 0
311
+ ? []
312
+ : [
313
+ group([
314
+ "(",
315
+ indent([softline, joinWithComments([","], "params")]),
316
+ softline,
317
+ ")",
318
+ ]),
319
+ ]),
320
+ ];
321
+ case "source":
322
+ return [node.base, print("value")];
323
+ default:
324
+ throw `Uknown node: ${JSON.stringify(node, null, 2)}`;
325
+ }
326
+ };
327
+
328
+ const printValue = () => {
329
+ switch (node.type) {
330
+ case "while":
331
+ return group([
332
+ "while",
333
+ line,
334
+ print("condition"),
335
+ line,
336
+ "do",
337
+ line,
338
+ print("loop"),
339
+ line,
340
+ "end",
341
+ ]);
342
+ case "for":
343
+ return group([
344
+ "for",
345
+ " ",
346
+ group([node.variable, " ", "=", indent([line, print("from")]), line]),
347
+ "to",
348
+ indent([line, print("to")]),
349
+ line,
350
+ "do",
351
+ indent([line, print("loop")]),
352
+ line,
353
+ "end",
354
+ ]);
355
+ case "iterable_for":
356
+ return group([
357
+ "for",
358
+ line,
359
+ node.variable,
360
+ line,
361
+ "=",
362
+ line,
363
+ print("iterator"),
364
+ line,
365
+ "do",
366
+ print("do"),
367
+ indent([line, print("loop")]),
368
+ line,
369
+ "end",
370
+ ]);
371
+ case "open":
372
+ return ["open", " ", print("left"), hardline, print("right")];
373
+ case "if_def":
374
+ return printIfDef(
375
+ node.negative ? "%ifndef" : "%ifdef",
376
+ " ",
377
+ node.condition,
378
+ );
379
+ case "if_encoder":
380
+ return printIfDef(
381
+ node.negative ? "%ifnencoder" : "%ifencoder",
382
+ " ",
383
+ "%",
384
+ node.condition,
385
+ );
386
+ case "if_version":
387
+ return printIfDef("%ifversion", " ", node.opt, " ", node.version);
388
+ case "negative":
389
+ return group(["-", print("value")]);
390
+ case "append":
391
+ return group([print("left"), "::", print("right")]);
392
+ case "not":
393
+ return group(["not", " ", print("value")]);
394
+ case "var":
395
+ return node.value;
396
+ case "string":
397
+ return printString(node.value);
398
+ case "ground":
399
+ return node.value;
400
+ case "term":
401
+ return print("value");
402
+ case "ellipsis":
403
+ return printEllipsis("value");
404
+ case "argsof":
405
+ return group([
406
+ "%argsof",
407
+ "(",
408
+ group([
409
+ node.source,
410
+ ...(node.only.length !== 0 || node.except.length !== 0
411
+ ? [
412
+ indent([
413
+ "[",
414
+ softline,
415
+ join(
416
+ [",", softline],
417
+ [...node.only, ...node.except.map((s) => `!${s}`)],
418
+ ),
419
+ "]",
420
+ ]),
421
+ softline,
422
+ ]
423
+ : []),
424
+ ]),
425
+ ")",
426
+ ]);
427
+ case "get":
428
+ return group(["!", print("value")]);
429
+ case "ptuple":
430
+ case "tuple":
431
+ return group([
432
+ "(",
433
+ group([
434
+ indent([softline, joinWithComments([","], "value")]),
435
+ softline,
436
+ ]),
437
+ ")",
438
+ ]);
439
+ case "list":
440
+ return group([
441
+ "[",
442
+ indent(group([softline, joinWithComments([","], "value")])),
443
+ softline,
444
+ "]",
445
+ ]);
446
+ case "pmeth":
447
+ return group([
448
+ "{",
449
+ indent([softline, joinWithComments([","], "value")]),
450
+ softline,
451
+ "}",
452
+ ]);
453
+ case "pvar":
454
+ return group([indent(join([softline, "."], node.value))]);
455
+ case "plist":
456
+ return group([
457
+ "[",
458
+ indent([
459
+ softline,
460
+ join(
461
+ [",", line],
462
+ [
463
+ ...path.map(print, "left"),
464
+ ...(node.middle ? [group(["...", node.middle])] : []),
465
+ ...path.map(print, "right"),
466
+ ],
467
+ ),
468
+ ]),
469
+ softline,
470
+ "]",
471
+ ]);
472
+ case "invoke": {
473
+ const invoke_meth = [
474
+ ...(node.optional ? ["?"] : []),
475
+ ".",
476
+ print("meth"),
477
+ ];
478
+
479
+ return group([
480
+ print("invoked"),
481
+ ...(node.meth.type === "var" ? [indent(invoke_meth)] : invoke_meth),
482
+ ]);
483
+ }
484
+ case "type_annotation":
485
+ return printTypeAnnotation();
486
+ case "parenthesis":
487
+ return group(["(", indent([softline, print("value")]), softline, ")"]);
488
+ case "block":
489
+ return group(["begin", indent([line, print("value")]), line, "end"]);
490
+ case "cast":
491
+ return group([
492
+ "(",
493
+ group([indent([softline, print("left")]), line, ":"]),
494
+ indent([line, print("right")]),
495
+ softline,
496
+ ")",
497
+ ]);
498
+ case "fun":
499
+ return group([
500
+ "fun",
501
+ " ",
502
+ group([
503
+ "(",
504
+ indent([softline, joinWithComments([","], "arguments")]),
505
+ softline,
506
+ ")",
507
+ " ",
508
+ "->",
509
+ ]),
510
+ indent([line, print("body")]),
511
+ ]);
512
+ case "fun_arg":
513
+ return printFunArg();
514
+ case "app_arg":
515
+ return printAppArg();
516
+ case "app":
517
+ return group([
518
+ print("op"),
519
+ "(",
520
+ ...(node.args.length === 0
521
+ ? []
522
+ : [
523
+ indent([softline, group([joinWithComments([","], "args")])]),
524
+ softline,
525
+ ]),
526
+ ")",
527
+ ]);
528
+ case "eof":
529
+ return "";
530
+ case "seq":
531
+ if (node.right.type === "eof") return print("left");
532
+ return printSeq(
533
+ node.left.position,
534
+ print("left"),
535
+ node.right.position,
536
+ print("right"),
537
+ );
538
+ case "def":
539
+ return printDef(
540
+ ...printComments(
541
+ node,
542
+ group([
543
+ "def",
544
+ " ",
545
+ ...(node.decoration ? [print("decoration"), " "] : []),
546
+ printPat(),
547
+ ...(node.arglist
548
+ ? [
549
+ "(",
550
+ group([
551
+ indent([softline, joinWithComments([","], "arglist")]),
552
+ softline,
553
+ ]),
554
+ ")",
555
+ ]
556
+ : []),
557
+ " ",
558
+ "=",
559
+ group([indent([hardline, print("definition")]), hardline, "end"]),
560
+ ]),
561
+ ),
562
+ );
563
+ case "let":
564
+ return printDef(
565
+ ...printComments(
566
+ node,
567
+ group([
568
+ "let",
569
+ " ",
570
+ ...(node.decoration ? [print("decoration"), " "] : []),
571
+ printPat(),
572
+ " ",
573
+ "=",
574
+ group([indent([line, print("definition")])]),
575
+ ]),
576
+ ),
577
+ );
578
+ case "binding":
579
+ return printDef(
580
+ ...printComments(
581
+ node,
582
+ group([
583
+ printPat(),
584
+ " ",
585
+ "=",
586
+ group([indent([line, print("definition")])]),
587
+ ]),
588
+ ),
589
+ );
590
+ case "simple_fun":
591
+ return group(["{", indent([softline, print("value")]), softline, "}"]);
592
+ case "if":
593
+ return group([
594
+ "if",
595
+ indent([line, group(print("condition"))]),
596
+ line,
597
+ "then",
598
+ indent([line, print("then")]),
599
+ ...(node.elsif.length !== 0
600
+ ? [line, join(line, path.map(print, "elsif"))]
601
+ : []),
602
+ ...(node.else ? [line, "else", indent([line, print("else")])] : []),
603
+ line,
604
+ "end",
605
+ ]);
606
+ case "elsif":
607
+ return group([
608
+ "elsif",
609
+ indent([line, print("condition")]),
610
+ line,
611
+ "then",
612
+ indent([line, print("then")]),
613
+ ]);
614
+ case "inline_if":
615
+ return group([
616
+ print("condition"),
617
+ line,
618
+ "?",
619
+ group([indent([line, print("then")]), line]),
620
+ ":",
621
+ group([indent([line, print("else")]), line]),
622
+ ]);
623
+ case "infix":
624
+ return group([
625
+ print("left"),
626
+ " ",
627
+ node.op,
628
+ indent([line, print("right")]),
629
+ ]);
630
+ case "bool":
631
+ return group(
632
+ join(
633
+ [dedent(line), node.op, line],
634
+ path.map(
635
+ (v) => group([indent([softline, print(v)]), softline]),
636
+ "value",
637
+ ),
638
+ ),
639
+ );
640
+ case "string_interpolation":
641
+ return group(path.map(print, "value"));
642
+ case "interpolated_string":
643
+ return printString(node.value);
644
+ case "interpolated_term":
645
+ return group(["#{", indent([softline, print("value")]), softline, "}"]);
646
+ case "coalesce":
647
+ return group([
648
+ print("left"),
649
+ indent([line, "??", indent([line, print("right")])]),
650
+ ]);
651
+ case "assoc":
652
+ return group([
653
+ print("left"),
654
+ "[",
655
+ indent([softline, print("right")]),
656
+ softline,
657
+ "]",
658
+ ]);
659
+ case "include_lib":
660
+ return group([trim, "%include", " ", "<", node.value, ">"]);
661
+ case "include":
662
+ return group([trim, "%include", " ", '"', node.value, '"']);
663
+ case "include_extra":
664
+ return group([trim, "%include_extra", " ", '"', node.value, '"']);
665
+ case "time_interval":
666
+ return [print("left"), "-", print("right")];
667
+ case "time":
668
+ return [
669
+ ...(node.week ? ["" + node.week, "w"] : []),
670
+ ...(node.hours ? ["" + node.hours, "h"] : []),
671
+ ...(node.minutes ? ["" + node.minutes, "m"] : []),
672
+ ...(node.second ? ["" + node.seconds, "s"] : []),
673
+ ];
674
+ case "encoder":
675
+ return [
676
+ "%",
677
+ node.label,
678
+ ...(node.params.length === 0
679
+ ? []
680
+ : [
681
+ group([
682
+ "(",
683
+ indent([softline, joinWithComments([","], "params")]),
684
+ softline,
685
+ ")",
686
+ ]),
687
+ ]),
688
+ ];
689
+ case "regexp":
690
+ return group(["r/", node.name, "/", ...node.flags]);
691
+ case "methods":
692
+ return [
693
+ ...(node.base ? [print("base"), "."] : []),
694
+ group([
695
+ "{",
696
+ indent([softline, joinWithComments([","], "methods")]),
697
+ softline,
698
+ "}",
699
+ ]),
700
+ ];
701
+ case "method":
702
+ return group([node.name, "=", indent([softline, print("value")])]);
703
+ case "try":
704
+ return group([
705
+ "try",
706
+ indent(group([line, print("body")], { shouldBreak: true })),
707
+ line,
708
+ group([
709
+ "catch",
710
+ line,
711
+ node.variable,
712
+ ...(node.errors_list
713
+ ? [group([line, ":", line, print("errors_list")])]
714
+ : []),
715
+ line,
716
+ "do",
717
+ ]),
718
+ indent(group([line, print("handler")], { shouldBreak: true })),
719
+ line,
720
+ "end",
721
+ ]);
722
+ default:
723
+ throw `Uknown node: ${JSON.stringify(node, null, 2)}`;
724
+ }
725
+ };
726
+
727
+ return [
728
+ printComments(node, printValue())[1],
729
+ ...(path.stack.length == 1 ? ["\n"] : []),
730
+ ];
731
+ };
732
+
733
+ export const printers = {
734
+ liquidsoap: {
735
+ print,
736
+ },
737
+ };
738
+
739
+ export default { languages, parsers, printers };