1use std::collections::HashMap;
2use std::sync::LazyLock;
3
4#[derive(Debug, Clone)]
5pub struct FormatEntry {
6 pub name: &'static str,
7 pub extensions: &'static [&'static str],
8 pub parent: Option<&'static str>,
9}
10
11pub static SUPPORTED_FORMATS: &[FormatEntry] = &[
13 FormatEntry {
14 name: "abap",
15 extensions: &[],
16 parent: None,
17 },
18 FormatEntry {
19 name: "actionscript",
20 extensions: &["as"],
21 parent: None,
22 },
23 FormatEntry {
24 name: "ada",
25 extensions: &["ada"],
26 parent: None,
27 },
28 FormatEntry {
29 name: "apacheconf",
30 extensions: &[],
31 parent: None,
32 },
33 FormatEntry {
34 name: "apl",
35 extensions: &["apl"],
36 parent: None,
37 },
38 FormatEntry {
39 name: "applescript",
40 extensions: &[],
41 parent: None,
42 },
43 FormatEntry {
44 name: "arduino",
45 extensions: &[],
46 parent: None,
47 },
48 FormatEntry {
49 name: "arff",
50 extensions: &[],
51 parent: None,
52 },
53 FormatEntry {
54 name: "asciidoc",
55 extensions: &[],
56 parent: None,
57 },
58 FormatEntry {
59 name: "asm6502",
60 extensions: &[],
61 parent: None,
62 },
63 FormatEntry {
64 name: "aspnet",
65 extensions: &["asp", "aspx"],
66 parent: None,
67 },
68 FormatEntry {
69 name: "autohotkey",
70 extensions: &[],
71 parent: None,
72 },
73 FormatEntry {
74 name: "autoit",
75 extensions: &[],
76 parent: None,
77 },
78 FormatEntry {
79 name: "bash",
80 extensions: &["sh", "ksh", "bash"],
81 parent: None,
82 },
83 FormatEntry {
84 name: "basic",
85 extensions: &["bas"],
86 parent: None,
87 },
88 FormatEntry {
89 name: "batch",
90 extensions: &[],
91 parent: None,
92 },
93 FormatEntry {
94 name: "bison",
95 extensions: &[],
96 parent: None,
97 },
98 FormatEntry {
99 name: "brainfuck",
100 extensions: &["b", "bf"],
101 parent: None,
102 },
103 FormatEntry {
104 name: "bro",
105 extensions: &[],
106 parent: None,
107 },
108 FormatEntry {
109 name: "c",
110 extensions: &["c", "z80"],
111 parent: None,
112 },
113 FormatEntry {
114 name: "c-header",
115 extensions: &["h"],
116 parent: None,
117 },
118 FormatEntry {
119 name: "clike",
120 extensions: &[],
121 parent: None,
122 },
123 FormatEntry {
124 name: "clojure",
125 extensions: &["cljs", "clj", "cljc", "cljx", "edn"],
126 parent: None,
127 },
128 FormatEntry {
129 name: "coffeescript",
130 extensions: &["coffee"],
131 parent: None,
132 },
133 FormatEntry {
134 name: "comments",
135 extensions: &[],
136 parent: None,
137 },
138 FormatEntry {
139 name: "cpp",
140 extensions: &["cpp", "c++", "cc", "cxx"],
141 parent: None,
142 },
143 FormatEntry {
144 name: "cpp-header",
145 extensions: &["hpp", "h++", "hh", "hxx"],
146 parent: None,
147 },
148 FormatEntry {
149 name: "crystal",
150 extensions: &["cr"],
151 parent: None,
152 },
153 FormatEntry {
154 name: "csharp",
155 extensions: &["cs"],
156 parent: None,
157 },
158 FormatEntry {
159 name: "csp",
160 extensions: &[],
161 parent: None,
162 },
163 FormatEntry {
164 name: "css-extras",
165 extensions: &[],
166 parent: None,
167 },
168 FormatEntry {
169 name: "css",
170 extensions: &["css", "gss"],
171 parent: None,
172 },
173 FormatEntry {
174 name: "d",
175 extensions: &["d"],
176 parent: None,
177 },
178 FormatEntry {
179 name: "dart",
180 extensions: &["dart"],
181 parent: None,
182 },
183 FormatEntry {
184 name: "diff",
185 extensions: &["diff", "patch"],
186 parent: None,
187 },
188 FormatEntry {
189 name: "django",
190 extensions: &[],
191 parent: None,
192 },
193 FormatEntry {
194 name: "docker",
195 extensions: &[],
196 parent: None,
197 },
198 FormatEntry {
199 name: "eiffel",
200 extensions: &["e"],
201 parent: None,
202 },
203 FormatEntry {
204 name: "elixir",
205 extensions: &[],
206 parent: None,
207 },
208 FormatEntry {
209 name: "elm",
210 extensions: &["elm"],
211 parent: None,
212 },
213 FormatEntry {
214 name: "erb",
215 extensions: &[],
216 parent: None,
217 },
218 FormatEntry {
219 name: "erlang",
220 extensions: &["erl", "erlang"],
221 parent: None,
222 },
223 FormatEntry {
224 name: "flow",
225 extensions: &[],
226 parent: None,
227 },
228 FormatEntry {
229 name: "fortran",
230 extensions: &["f", "for", "f77", "f90"],
231 parent: None,
232 },
233 FormatEntry {
234 name: "fsharp",
235 extensions: &["fs"],
236 parent: None,
237 },
238 FormatEntry {
239 name: "gdscript",
240 extensions: &["gd"],
241 parent: None,
242 },
243 FormatEntry {
244 name: "gedcom",
245 extensions: &[],
246 parent: None,
247 },
248 FormatEntry {
249 name: "gherkin",
250 extensions: &["feature"],
251 parent: None,
252 },
253 FormatEntry {
254 name: "git",
255 extensions: &[],
256 parent: None,
257 },
258 FormatEntry {
259 name: "glsl",
260 extensions: &[],
261 parent: None,
262 },
263 FormatEntry {
264 name: "go",
265 extensions: &["go"],
266 parent: None,
267 },
268 FormatEntry {
269 name: "graphql",
270 extensions: &["graphql"],
271 parent: None,
272 },
273 FormatEntry {
274 name: "groovy",
275 extensions: &["groovy", "gradle"],
276 parent: None,
277 },
278 FormatEntry {
279 name: "haml",
280 extensions: &["haml"],
281 parent: None,
282 },
283 FormatEntry {
284 name: "handlebars",
285 extensions: &["hb", "hbs", "handlebars"],
286 parent: None,
287 },
288 FormatEntry {
289 name: "haskell",
290 extensions: &["hs", "lhs"],
291 parent: None,
292 },
293 FormatEntry {
294 name: "haxe",
295 extensions: &["hx", "hxml"],
296 parent: None,
297 },
298 FormatEntry {
299 name: "hpkp",
300 extensions: &[],
301 parent: None,
302 },
303 FormatEntry {
304 name: "hsts",
305 extensions: &[],
306 parent: None,
307 },
308 FormatEntry {
309 name: "http",
310 extensions: &[],
311 parent: None,
312 },
313 FormatEntry {
314 name: "ichigojam",
315 extensions: &[],
316 parent: None,
317 },
318 FormatEntry {
319 name: "icon",
320 extensions: &[],
321 parent: None,
322 },
323 FormatEntry {
324 name: "inform7",
325 extensions: &[],
326 parent: None,
327 },
328 FormatEntry {
329 name: "ini",
330 extensions: &["ini"],
331 parent: None,
332 },
333 FormatEntry {
334 name: "io",
335 extensions: &[],
336 parent: None,
337 },
338 FormatEntry {
339 name: "j",
340 extensions: &[],
341 parent: None,
342 },
343 FormatEntry {
344 name: "java",
345 extensions: &["java"],
346 parent: None,
347 },
348 FormatEntry {
349 name: "javascript",
350 extensions: &["js", "es", "es6", "mjs", "cjs"],
351 parent: None,
352 },
353 FormatEntry {
354 name: "jolie",
355 extensions: &[],
356 parent: None,
357 },
358 FormatEntry {
359 name: "json",
360 extensions: &["json", "map", "jsonld"],
361 parent: None,
362 },
363 FormatEntry {
364 name: "jsx",
365 extensions: &["jsx"],
366 parent: None,
367 },
368 FormatEntry {
369 name: "julia",
370 extensions: &["jl"],
371 parent: None,
372 },
373 FormatEntry {
374 name: "keymap",
375 extensions: &[],
376 parent: None,
377 },
378 FormatEntry {
379 name: "kotlin",
380 extensions: &["kt", "kts"],
381 parent: None,
382 },
383 FormatEntry {
384 name: "latex",
385 extensions: &["tex"],
386 parent: None,
387 },
388 FormatEntry {
389 name: "less",
390 extensions: &["less"],
391 parent: None,
392 },
393 FormatEntry {
394 name: "liquid",
395 extensions: &[],
396 parent: None,
397 },
398 FormatEntry {
399 name: "lisp",
400 extensions: &["cl", "lisp", "el"],
401 parent: None,
402 },
403 FormatEntry {
404 name: "livescript",
405 extensions: &["ls"],
406 parent: None,
407 },
408 FormatEntry {
409 name: "lolcode",
410 extensions: &[],
411 parent: None,
412 },
413 FormatEntry {
414 name: "lua",
415 extensions: &["lua"],
416 parent: None,
417 },
418 FormatEntry {
419 name: "makefile",
420 extensions: &[],
421 parent: None,
422 },
423 FormatEntry {
424 name: "markdown",
425 extensions: &["md", "markdown", "mkd"],
426 parent: None,
427 },
428 FormatEntry {
429 name: "markup",
430 extensions: &["html", "htm", "xml", "xsl", "xslt", "svg", "ejs", "jsp"],
431 parent: None,
432 },
433 FormatEntry {
434 name: "matlab",
435 extensions: &[],
436 parent: None,
437 },
438 FormatEntry {
439 name: "mel",
440 extensions: &[],
441 parent: None,
442 },
443 FormatEntry {
444 name: "mizar",
445 extensions: &[],
446 parent: None,
447 },
448 FormatEntry {
449 name: "monkey",
450 extensions: &[],
451 parent: None,
452 },
453 FormatEntry {
454 name: "n4js",
455 extensions: &[],
456 parent: None,
457 },
458 FormatEntry {
459 name: "nasm",
460 extensions: &[],
461 parent: None,
462 },
463 FormatEntry {
464 name: "nginx",
465 extensions: &[],
466 parent: None,
467 },
468 FormatEntry {
469 name: "nim",
470 extensions: &[],
471 parent: None,
472 },
473 FormatEntry {
474 name: "nix",
475 extensions: &[],
476 parent: None,
477 },
478 FormatEntry {
479 name: "nsis",
480 extensions: &["nsh", "nsi"],
481 parent: None,
482 },
483 FormatEntry {
484 name: "objectivec",
485 extensions: &["m", "mm"],
486 parent: None,
487 },
488 FormatEntry {
489 name: "ocaml",
490 extensions: &["ocaml", "ml", "mli", "mll", "mly"],
491 parent: None,
492 },
493 FormatEntry {
494 name: "opencl",
495 extensions: &[],
496 parent: None,
497 },
498 FormatEntry {
499 name: "oz",
500 extensions: &["oz"],
501 parent: None,
502 },
503 FormatEntry {
504 name: "parigp",
505 extensions: &[],
506 parent: None,
507 },
508 FormatEntry {
509 name: "pascal",
510 extensions: &["pas", "p"],
511 parent: None,
512 },
513 FormatEntry {
514 name: "perl",
515 extensions: &["pl", "pm"],
516 parent: None,
517 },
518 FormatEntry {
519 name: "php",
520 extensions: &["php", "phtml"],
521 parent: None,
522 },
523 FormatEntry {
524 name: "plsql",
525 extensions: &["plsql"],
526 parent: None,
527 },
528 FormatEntry {
529 name: "powershell",
530 extensions: &["ps1", "psd1", "psm1"],
531 parent: None,
532 },
533 FormatEntry {
534 name: "processing",
535 extensions: &[],
536 parent: None,
537 },
538 FormatEntry {
539 name: "prolog",
540 extensions: &["pro"],
541 parent: None,
542 },
543 FormatEntry {
544 name: "properties",
545 extensions: &["properties"],
546 parent: None,
547 },
548 FormatEntry {
549 name: "protobuf",
550 extensions: &["proto"],
551 parent: None,
552 },
553 FormatEntry {
554 name: "pug",
555 extensions: &["pug", "jade"],
556 parent: None,
557 },
558 FormatEntry {
559 name: "puppet",
560 extensions: &["pp", "puppet"],
561 parent: None,
562 },
563 FormatEntry {
564 name: "pure",
565 extensions: &[],
566 parent: None,
567 },
568 FormatEntry {
569 name: "python",
570 extensions: &["py", "pyx", "pxd", "pxi"],
571 parent: None,
572 },
573 FormatEntry {
574 name: "q",
575 extensions: &["q"],
576 parent: None,
577 },
578 FormatEntry {
579 name: "qore",
580 extensions: &[],
581 parent: None,
582 },
583 FormatEntry {
584 name: "r",
585 extensions: &["r", "R"],
586 parent: None,
587 },
588 FormatEntry {
589 name: "reason",
590 extensions: &[],
591 parent: None,
592 },
593 FormatEntry {
594 name: "renpy",
595 extensions: &[],
596 parent: None,
597 },
598 FormatEntry {
599 name: "rest",
600 extensions: &[],
601 parent: None,
602 },
603 FormatEntry {
604 name: "rip",
605 extensions: &[],
606 parent: None,
607 },
608 FormatEntry {
609 name: "roboconf",
610 extensions: &[],
611 parent: None,
612 },
613 FormatEntry {
614 name: "ruby",
615 extensions: &["rb"],
616 parent: None,
617 },
618 FormatEntry {
619 name: "rust",
620 extensions: &["rs"],
621 parent: None,
622 },
623 FormatEntry {
624 name: "sas",
625 extensions: &["sas"],
626 parent: None,
627 },
628 FormatEntry {
629 name: "sass",
630 extensions: &["sass"],
631 parent: None,
632 },
633 FormatEntry {
634 name: "scala",
635 extensions: &["scala"],
636 parent: None,
637 },
638 FormatEntry {
639 name: "scheme",
640 extensions: &["scm", "ss"],
641 parent: None,
642 },
643 FormatEntry {
644 name: "scss",
645 extensions: &["scss"],
646 parent: None,
647 },
648 FormatEntry {
649 name: "svelte",
650 extensions: &["svelte"],
651 parent: None,
652 },
653 FormatEntry {
654 name: "smalltalk",
655 extensions: &["st"],
656 parent: None,
657 },
658 FormatEntry {
659 name: "smarty",
660 extensions: &["smarty", "tpl"],
661 parent: None,
662 },
663 FormatEntry {
664 name: "soy",
665 extensions: &["soy"],
666 parent: None,
667 },
668 FormatEntry {
669 name: "sql",
670 extensions: &["sql", "cql"],
671 parent: None,
672 },
673 FormatEntry {
674 name: "stylus",
675 extensions: &["styl", "stylus"],
676 parent: None,
677 },
678 FormatEntry {
679 name: "swift",
680 extensions: &["swift"],
681 parent: None,
682 },
683 FormatEntry {
684 name: "tap",
685 extensions: &["tap"],
686 parent: None,
687 },
688 FormatEntry {
689 name: "tcl",
690 extensions: &["tcl"],
691 parent: None,
692 },
693 FormatEntry {
694 name: "textile",
695 extensions: &["textile"],
696 parent: None,
697 },
698 FormatEntry {
699 name: "tsx",
700 extensions: &["tsx"],
701 parent: None,
702 },
703 FormatEntry {
704 name: "tt2",
705 extensions: &["tt2"],
706 parent: None,
707 },
708 FormatEntry {
709 name: "twig",
710 extensions: &["twig"],
711 parent: None,
712 },
713 FormatEntry {
714 name: "typescript",
715 extensions: &["ts", "mts", "cts"],
716 parent: None,
717 },
718 FormatEntry {
719 name: "txt",
720 extensions: &["txt"],
721 parent: None,
722 },
723 FormatEntry {
724 name: "vbnet",
725 extensions: &["vb"],
726 parent: None,
727 },
728 FormatEntry {
729 name: "velocity",
730 extensions: &["vtl"],
731 parent: None,
732 },
733 FormatEntry {
734 name: "verilog",
735 extensions: &["v"],
736 parent: None,
737 },
738 FormatEntry {
739 name: "vhdl",
740 extensions: &["vhd", "vhdl"],
741 parent: None,
742 },
743 FormatEntry {
744 name: "vim",
745 extensions: &[],
746 parent: None,
747 },
748 FormatEntry {
749 name: "visual-basic",
750 extensions: &[],
751 parent: None,
752 },
753 FormatEntry {
754 name: "astro",
755 extensions: &["astro"],
756 parent: None,
757 },
758 FormatEntry {
759 name: "vue",
760 extensions: &["vue"],
761 parent: None,
762 },
763 FormatEntry {
764 name: "wasm",
765 extensions: &[],
766 parent: None,
767 },
768 FormatEntry {
769 name: "wiki",
770 extensions: &[],
771 parent: None,
772 },
773 FormatEntry {
774 name: "xeora",
775 extensions: &[],
776 parent: None,
777 },
778 FormatEntry {
779 name: "xojo",
780 extensions: &[],
781 parent: None,
782 },
783 FormatEntry {
784 name: "xquery",
785 extensions: &["xy", "xquery"],
786 parent: None,
787 },
788 FormatEntry {
789 name: "yaml",
790 extensions: &["yaml", "yml"],
791 parent: None,
792 },
793 FormatEntry {
794 name: "abnf",
795 extensions: &[],
796 parent: None,
797 },
798 FormatEntry {
799 name: "agda",
800 extensions: &[],
801 parent: None,
802 },
803 FormatEntry {
804 name: "antlr4",
805 extensions: &["g4"],
806 parent: None,
807 },
808 FormatEntry {
809 name: "apex",
810 extensions: &["cls", "trigger", "apex"],
811 parent: None,
812 },
813 FormatEntry {
814 name: "aql",
815 extensions: &[],
816 parent: None,
817 },
818 FormatEntry {
819 name: "armasm",
820 extensions: &[],
821 parent: None,
822 },
823 FormatEntry {
824 name: "awk",
825 extensions: &["awk"],
826 parent: None,
827 },
828 FormatEntry {
829 name: "bicep",
830 extensions: &["bicep"],
831 parent: None,
832 },
833 FormatEntry {
834 name: "bnf",
835 extensions: &[],
836 parent: None,
837 },
838 FormatEntry {
839 name: "cfscript",
840 extensions: &["cfc"],
841 parent: None,
842 },
843 FormatEntry {
844 name: "cfml",
845 extensions: &["cfm"],
846 parent: None,
847 },
848 FormatEntry {
849 name: "cmake",
850 extensions: &["cmake"],
851 parent: None,
852 },
853 FormatEntry {
854 name: "cobol",
855 extensions: &[],
856 parent: None,
857 },
858 FormatEntry {
859 name: "csv",
860 extensions: &["csv"],
861 parent: None,
862 },
863 FormatEntry {
864 name: "cypher",
865 extensions: &[],
866 parent: None,
867 },
868 FormatEntry {
869 name: "dhall",
870 extensions: &[],
871 parent: None,
872 },
873 FormatEntry {
874 name: "dns-zone-file",
875 extensions: &[],
876 parent: None,
877 },
878 FormatEntry {
879 name: "dot",
880 extensions: &["dot", "gv"],
881 parent: None,
882 },
883 FormatEntry {
884 name: "ebnf",
885 extensions: &[],
886 parent: None,
887 },
888 FormatEntry {
889 name: "editorconfig",
890 extensions: &[],
891 parent: None,
892 },
893 FormatEntry {
894 name: "excel-formula",
895 extensions: &["xlsx", "xls"],
896 parent: None,
897 },
898 FormatEntry {
899 name: "factor",
900 extensions: &[],
901 parent: None,
902 },
903 FormatEntry {
904 name: "ftl",
905 extensions: &[],
906 parent: None,
907 },
908 FormatEntry {
909 name: "gcode",
910 extensions: &[],
911 parent: None,
912 },
913 FormatEntry {
914 name: "gettext",
915 extensions: &["po"],
916 parent: None,
917 },
918 FormatEntry {
919 name: "gml",
920 extensions: &[],
921 parent: None,
922 },
923 FormatEntry {
924 name: "go-module",
925 extensions: &[],
926 parent: None,
927 },
928 FormatEntry {
929 name: "hcl",
930 extensions: &["tf", "hcl"],
931 parent: None,
932 },
933 FormatEntry {
934 name: "hlsl",
935 extensions: &[],
936 parent: None,
937 },
938 FormatEntry {
939 name: "idris",
940 extensions: &["idr"],
941 parent: None,
942 },
943 FormatEntry {
944 name: "ignore",
945 extensions: &["gitignore"],
946 parent: None,
947 },
948 FormatEntry {
949 name: "jq",
950 extensions: &[],
951 parent: None,
952 },
953 FormatEntry {
954 name: "json5",
955 extensions: &["json5"],
956 parent: None,
957 },
958 FormatEntry {
959 name: "kusto",
960 extensions: &[],
961 parent: None,
962 },
963 FormatEntry {
964 name: "lilypond",
965 extensions: &["ly"],
966 parent: None,
967 },
968 FormatEntry {
969 name: "linker-script",
970 extensions: &["ld"],
971 parent: None,
972 },
973 FormatEntry {
974 name: "llvm",
975 extensions: &["ll"],
976 parent: None,
977 },
978 FormatEntry {
979 name: "log",
980 extensions: &["log"],
981 parent: None,
982 },
983 FormatEntry {
984 name: "mermaid",
985 extensions: &[],
986 parent: None,
987 },
988 FormatEntry {
989 name: "mongodb",
990 extensions: &[],
991 parent: None,
992 },
993 FormatEntry {
994 name: "n1ql",
995 extensions: &[],
996 parent: None,
997 },
998 FormatEntry {
999 name: "odin",
1000 extensions: &[],
1001 parent: None,
1002 },
1003 FormatEntry {
1004 name: "openqasm",
1005 extensions: &["qasm"],
1006 parent: None,
1007 },
1008 FormatEntry {
1009 name: "plant-uml",
1010 extensions: &["puml", "plantuml"],
1011 parent: None,
1012 },
1013 FormatEntry {
1014 name: "powerquery",
1015 extensions: &["pq"],
1016 parent: None,
1017 },
1018 FormatEntry {
1019 name: "promql",
1020 extensions: &[],
1021 parent: None,
1022 },
1023 FormatEntry {
1024 name: "purescript",
1025 extensions: &["purs"],
1026 parent: None,
1027 },
1028 FormatEntry {
1029 name: "qsharp",
1030 extensions: &["qs"],
1031 parent: None,
1032 },
1033 FormatEntry {
1034 name: "racket",
1035 extensions: &["rkt"],
1036 parent: None,
1037 },
1038 FormatEntry {
1039 name: "regex",
1040 extensions: &[],
1041 parent: None,
1042 },
1043 FormatEntry {
1044 name: "rego",
1045 extensions: &[],
1046 parent: None,
1047 },
1048 FormatEntry {
1049 name: "rescript",
1050 extensions: &["res"],
1051 parent: None,
1052 },
1053 FormatEntry {
1054 name: "robotframework",
1055 extensions: &["robot"],
1056 parent: None,
1057 },
1058 FormatEntry {
1059 name: "shell-session",
1060 extensions: &[],
1061 parent: None,
1062 },
1063 FormatEntry {
1064 name: "smali",
1065 extensions: &[],
1066 parent: None,
1067 },
1068 FormatEntry {
1069 name: "solidity",
1070 extensions: &["sol"],
1071 parent: None,
1072 },
1073 FormatEntry {
1074 name: "sparql",
1075 extensions: &["rq"],
1076 parent: None,
1077 },
1078 FormatEntry {
1079 name: "stata",
1080 extensions: &[],
1081 parent: None,
1082 },
1083 FormatEntry {
1084 name: "toml",
1085 extensions: &["toml"],
1086 parent: None,
1087 },
1088 FormatEntry {
1089 name: "turtle",
1090 extensions: &["ttl"],
1091 parent: None,
1092 },
1093 FormatEntry {
1094 name: "typoscript",
1095 extensions: &[],
1096 parent: None,
1097 },
1098 FormatEntry {
1099 name: "unrealscript",
1100 extensions: &["uc"],
1101 parent: None,
1102 },
1103 FormatEntry {
1104 name: "uri",
1105 extensions: &[],
1106 parent: None,
1107 },
1108 FormatEntry {
1109 name: "vala",
1110 extensions: &[],
1111 parent: None,
1112 },
1113 FormatEntry {
1114 name: "wgsl",
1115 extensions: &["wgsl"],
1116 parent: None,
1117 },
1118 FormatEntry {
1119 name: "wolfram",
1120 extensions: &["wl", "nb"],
1121 parent: None,
1122 },
1123 FormatEntry {
1124 name: "zig",
1125 extensions: &["zig"],
1126 parent: None,
1127 },
1128];
1129
1130static EXT_TO_FORMAT: LazyLock<HashMap<&'static str, &'static str>> = LazyLock::new(|| {
1131 let mut map = HashMap::new();
1132 for entry in SUPPORTED_FORMATS {
1133 for ext in entry.extensions {
1134 map.insert(*ext, entry.name);
1135 }
1136 }
1137 map
1138});
1139
1140pub fn get_format_by_extension(ext: &str) -> Option<&'static str> {
1142 EXT_TO_FORMAT.get(ext).copied()
1143}
1144
1145pub fn get_format_by_shebang(first_line: &str) -> Option<&'static str> {
1147 if first_line.contains("python3") || first_line.contains("python") {
1148 Some("python")
1149 } else if first_line.contains("node") || first_line.contains("nodejs") {
1150 Some("javascript")
1151 } else if first_line.contains("ruby") {
1152 Some("ruby")
1153 } else if first_line.contains("bash") || first_line.contains("/sh") {
1154 Some("bash")
1155 } else if first_line.contains("perl") {
1156 Some("perl")
1157 } else if first_line.contains("php") {
1158 Some("php")
1159 } else {
1160 None
1161 }
1162}
1163
1164pub fn list_formats() -> Vec<&'static str> {
1166 SUPPORTED_FORMATS.iter().map(|e| e.name).collect()
1167}
1168
1169static SYNONYMS: LazyLock<HashMap<&'static str, &'static str>> = LazyLock::new(|| {
1170 let mut map = HashMap::new();
1171 map.insert("node", "javascript");
1172 map.insert("shell", "bash");
1173 map.insert("zsh", "bash");
1174 map.insert("golang", "go");
1175 map
1176});
1177
1178pub fn resolve_format(hint: &str) -> Option<&'static str> {
1179 let normalized = hint.to_lowercase();
1180 if let Some(name) = SYNONYMS.get(normalized.as_str()) {
1181 return Some(*name);
1182 }
1183 if let Some(name) = get_format_by_extension(&normalized) {
1184 return Some(name);
1185 }
1186 SUPPORTED_FORMATS
1187 .iter()
1188 .find(|entry| entry.name == normalized)
1189 .map(|entry| entry.name)
1190}
1191
1192#[cfg(test)]
1193mod tests {
1194 use super::*;
1195
1196 #[test]
1197 fn js_extension_resolves() {
1198 assert_eq!(get_format_by_extension("js"), Some("javascript"));
1199 }
1200
1201 #[test]
1202 fn ts_extension_resolves() {
1203 assert_eq!(get_format_by_extension("ts"), Some("typescript"));
1204 }
1205
1206 #[test]
1207 fn unknown_extension_returns_none() {
1208 assert_eq!(get_format_by_extension("unknown_xyz_abc"), None);
1209 }
1210
1211 #[test]
1212 fn python_shebang_resolves() {
1213 assert_eq!(
1214 get_format_by_shebang("#!/usr/bin/env python3"),
1215 Some("python")
1216 );
1217 }
1218
1219 #[test]
1220 fn list_formats_has_at_least_100_entries() {
1221 assert!(list_formats().len() >= 100);
1222 }
1223
1224 #[test]
1225 fn supported_formats_has_223_entries() {
1226 assert_eq!(SUPPORTED_FORMATS.len(), 223);
1227 }
1228
1229 #[test]
1230 fn resolve_format_js_extension() {
1231 assert_eq!(resolve_format("js"), Some("javascript"));
1232 }
1233
1234 #[test]
1235 fn resolve_format_shell_synonym() {
1236 assert_eq!(resolve_format("shell"), Some("bash"));
1237 }
1238
1239 #[test]
1240 fn resolve_format_golang_synonym() {
1241 assert_eq!(resolve_format("golang"), Some("go"));
1242 }
1243
1244 #[test]
1245 fn resolve_format_unknown_returns_none() {
1246 assert_eq!(resolve_format("unknownxyz"), None);
1247 }
1248
1249 #[test]
1250 fn resolve_format_python_name() {
1251 assert_eq!(resolve_format("python"), Some("python"));
1252 }
1253
1254 #[test]
1255 fn empty_source_tokenize_returns_empty() {
1256 use crate::tokenizer::{Mode, tokenize};
1257 let result = std::panic::catch_unwind(|| tokenize("javascript", "", Mode::Mild));
1258 assert!(result.is_ok());
1259 }
1260}