1#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
28pub enum ThemeSlot {
29 Keyword,
30 Function,
31 String,
32 Comment,
33 Type,
34 Variable,
35 Constant,
36 Number,
37 Operator,
38 Punctuation,
39 Property,
40 Attribute,
41 Tag,
42 Macro,
43 Label,
44 Namespace,
45 Constructor,
46 Title,
48 Strong,
50 Emphasis,
52 Link,
54 Literal,
56 Strikethrough,
58 DiffAdd,
60 DiffDelete,
62 Embedded,
64 Error,
66 None,
68}
69
70impl ThemeSlot {
71 pub fn tag(self) -> Option<&'static str> {
74 match self {
75 ThemeSlot::Keyword => Some("k"),
76 ThemeSlot::Function => Some("f"),
77 ThemeSlot::String => Some("s"),
78 ThemeSlot::Comment => Some("c"),
79 ThemeSlot::Type => Some("t"),
80 ThemeSlot::Variable => Some("v"),
81 ThemeSlot::Constant => Some("co"),
82 ThemeSlot::Number => Some("n"),
83 ThemeSlot::Operator => Some("o"),
84 ThemeSlot::Punctuation => Some("p"),
85 ThemeSlot::Property => Some("pr"),
86 ThemeSlot::Attribute => Some("at"),
87 ThemeSlot::Tag => Some("tg"),
88 ThemeSlot::Macro => Some("m"),
89 ThemeSlot::Label => Some("l"),
90 ThemeSlot::Namespace => Some("ns"),
91 ThemeSlot::Constructor => Some("cr"),
92 ThemeSlot::Title => Some("tt"),
94 ThemeSlot::Strong => Some("st"),
96 ThemeSlot::Emphasis => Some("em"),
98 ThemeSlot::Link => Some("tu"),
100 ThemeSlot::Literal => Some("tl"),
102 ThemeSlot::Strikethrough => Some("tx"),
104 ThemeSlot::DiffAdd => Some("da"),
106 ThemeSlot::DiffDelete => Some("dd"),
108 ThemeSlot::Embedded => Some("eb"),
110 ThemeSlot::Error => Some("er"),
112 ThemeSlot::None => None,
114 }
115 }
116}
117
118pub fn slot_to_highlight_index(slot: ThemeSlot) -> Option<usize> {
123 match slot {
124 ThemeSlot::Keyword => HIGHLIGHTS.iter().position(|h| h.name == "keyword"),
125 ThemeSlot::Function => HIGHLIGHTS.iter().position(|h| h.name == "function"),
126 ThemeSlot::String => HIGHLIGHTS.iter().position(|h| h.name == "string"),
127 ThemeSlot::Comment => HIGHLIGHTS.iter().position(|h| h.name == "comment"),
128 ThemeSlot::Type => HIGHLIGHTS.iter().position(|h| h.name == "type"),
129 ThemeSlot::Variable => HIGHLIGHTS.iter().position(|h| h.name == "variable"),
130 ThemeSlot::Constant => HIGHLIGHTS.iter().position(|h| h.name == "constant"),
131 ThemeSlot::Number => HIGHLIGHTS.iter().position(|h| h.name == "number"),
132 ThemeSlot::Operator => HIGHLIGHTS.iter().position(|h| h.name == "operator"),
133 ThemeSlot::Punctuation => HIGHLIGHTS.iter().position(|h| h.name == "punctuation"),
134 ThemeSlot::Property => HIGHLIGHTS.iter().position(|h| h.name == "property"),
135 ThemeSlot::Attribute => HIGHLIGHTS.iter().position(|h| h.name == "attribute"),
136 ThemeSlot::Tag => HIGHLIGHTS.iter().position(|h| h.name == "tag"),
137 ThemeSlot::Macro => HIGHLIGHTS.iter().position(|h| h.name == "macro"),
138 ThemeSlot::Label => HIGHLIGHTS.iter().position(|h| h.name == "label"),
139 ThemeSlot::Namespace => HIGHLIGHTS.iter().position(|h| h.name == "namespace"),
140 ThemeSlot::Constructor => HIGHLIGHTS.iter().position(|h| h.name == "constructor"),
141 ThemeSlot::Title => HIGHLIGHTS
142 .iter()
143 .position(|h| h.name == "text.title" || h.name == "markup.heading"),
144 ThemeSlot::Strong => HIGHLIGHTS
145 .iter()
146 .position(|h| h.name == "text.strong" || h.name == "markup.bold"),
147 ThemeSlot::Emphasis => HIGHLIGHTS
148 .iter()
149 .position(|h| h.name == "text.emphasis" || h.name == "markup.italic"),
150 ThemeSlot::Link => HIGHLIGHTS
151 .iter()
152 .position(|h| h.name == "text.uri" || h.name == "text.reference"),
153 ThemeSlot::Literal => HIGHLIGHTS.iter().position(|h| h.name == "text.literal"),
154 ThemeSlot::Strikethrough => HIGHLIGHTS
155 .iter()
156 .position(|h| h.name == "text.strikethrough"),
157 ThemeSlot::DiffAdd => HIGHLIGHTS.iter().position(|h| h.name == "diff.addition"),
158 ThemeSlot::DiffDelete => HIGHLIGHTS.iter().position(|h| h.name == "diff.deletion"),
159 ThemeSlot::Embedded => HIGHLIGHTS.iter().position(|h| h.name == "embedded"),
160 ThemeSlot::Error => HIGHLIGHTS.iter().position(|h| h.name == "error"),
161 ThemeSlot::None => None,
162 }
163}
164
165pub fn capture_to_slot(capture: &str) -> ThemeSlot {
175 let capture = capture.strip_prefix('@').unwrap_or(capture);
177
178 match capture {
179 "keyword" | "keyword.conditional" | "keyword.coroutine" | "keyword.debug"
181 | "keyword.exception" | "keyword.function" | "keyword.import" | "keyword.operator"
182 | "keyword.repeat" | "keyword.return" | "keyword.type" | "keyword.modifier"
183 | "keyword.directive" | "keyword.storage" | "keyword.control"
184 | "keyword.control.conditional" | "keyword.control.repeat" | "keyword.control.import"
185 | "keyword.control.return" | "keyword.control.exception"
186 | "include" | "conditional" | "repeat" | "exception" | "storageclass" | "preproc"
188 | "define" | "structure" => ThemeSlot::Keyword,
189
190 "function" | "function.builtin" | "function.method" | "function.definition"
192 | "function.call" | "function.special" | "method" | "method.call" => ThemeSlot::Function,
193
194 "string" | "string.special" | "string.special.symbol" | "string.special.path"
196 | "string.special.url" | "string.escape" | "string.regexp" | "string.regex"
197 | "character" | "character.special" | "escape" => ThemeSlot::String,
198
199 "comment" | "comment.documentation" | "comment.line" | "comment.block"
201 | "comment.error" | "comment.warning" | "comment.note" | "comment.todo" => {
202 ThemeSlot::Comment
203 }
204
205 "type" | "type.builtin" | "type.qualifier" | "type.definition" | "type.enum"
207 | "type.enum.variant" | "type.parameter" => ThemeSlot::Type,
208
209 "variable" | "variable.builtin" | "variable.parameter" | "variable.member"
211 | "variable.other" | "variable.other.member" | "parameter" | "field" => {
212 ThemeSlot::Variable
213 }
214
215 "constant" | "constant.builtin" | "constant.builtin.boolean" | "boolean" => {
217 ThemeSlot::Constant
218 }
219
220 "number" | "constant.numeric" | "float" | "number.float" => ThemeSlot::Number,
222
223 "operator" => ThemeSlot::Operator,
225
226 "punctuation" | "punctuation.bracket" | "punctuation.delimiter" | "punctuation.special" => {
228 ThemeSlot::Punctuation
229 }
230
231 "property" | "property.builtin" => ThemeSlot::Property,
233
234 "attribute" | "attribute.builtin" => ThemeSlot::Attribute,
236
237 "tag" | "tag.delimiter" | "tag.error" | "tag.attribute" | "tag.builtin" => ThemeSlot::Tag,
239
240 "macro" | "function.macro" | "preproc.macro" => ThemeSlot::Macro,
242
243 "label" => ThemeSlot::Label,
245
246 "namespace" | "module" => ThemeSlot::Namespace,
248
249 "constructor" | "constructor.builtin" => ThemeSlot::Constructor,
251
252 "text.title" | "markup.heading" | "markup.heading.1" | "markup.heading.2"
254 | "markup.heading.3" | "markup.heading.4" | "markup.heading.5" | "markup.heading.6" => {
255 ThemeSlot::Title
256 }
257
258 "text.strong" | "markup.bold" => ThemeSlot::Strong,
260
261 "text.emphasis" | "markup.italic" => ThemeSlot::Emphasis,
263
264 "text.uri" | "text.reference" | "markup.link" | "markup.link.url" | "markup.link.text"
266 | "markup.link.label" => ThemeSlot::Link,
267
268 "text.literal" | "markup.raw" | "markup.raw.block" | "markup.raw.inline"
270 | "markup.inline" => ThemeSlot::Literal,
271
272 "text.strikethrough" | "markup.strikethrough" => ThemeSlot::Strikethrough,
274
275 "markup.list" | "markup.list.checked" | "markup.list.unchecked"
277 | "markup.list.numbered" | "markup.list.unnumbered" | "markup.quote" => {
278 ThemeSlot::Punctuation
279 }
280
281 "diff.addition" | "diff.plus" | "diff.delta" => ThemeSlot::DiffAdd,
283 "diff.deletion" | "diff.minus" => ThemeSlot::DiffDelete,
284
285 "embedded" => ThemeSlot::Embedded,
287
288 "error" => ThemeSlot::Error,
290
291 "none" | "nospell" | "spell" | "text" | "markup" => ThemeSlot::None,
293
294 other => {
296 if other.starts_with("keyword") {
297 ThemeSlot::Keyword
298 } else if other.starts_with("function") || other.starts_with("method") {
299 ThemeSlot::Function
300 } else if other.starts_with("string") || other.starts_with("character") {
301 ThemeSlot::String
302 } else if other.starts_with("comment") {
303 ThemeSlot::Comment
304 } else if other.starts_with("type") {
305 ThemeSlot::Type
306 } else if other.starts_with("variable") || other.starts_with("parameter") {
307 ThemeSlot::Variable
308 } else if other.starts_with("constant") {
309 ThemeSlot::Constant
310 } else if other.starts_with("punctuation") {
311 ThemeSlot::Punctuation
312 } else if other.starts_with("tag") {
313 ThemeSlot::Tag
314 } else if other.starts_with("markup.heading") || other.starts_with("text.title") {
315 ThemeSlot::Title
316 } else if other.starts_with("markup") || other.starts_with("text") {
317 ThemeSlot::None
319 } else {
320 ThemeSlot::None
322 }
323 }
324 }
325}
326
327pub struct HighlightDef {
332 pub name: &'static str,
334 pub tag: &'static str,
337 pub parent_tag: &'static str,
340 pub aliases: &'static [&'static str],
342}
343
344pub const HIGHLIGHTS: &[HighlightDef] = &[
347 HighlightDef {
349 name: "attribute",
350 tag: "at",
351 parent_tag: "",
352 aliases: &[],
353 },
354 HighlightDef {
355 name: "constant",
356 tag: "co",
357 parent_tag: "",
358 aliases: &[],
359 },
360 HighlightDef {
361 name: "constant.builtin",
362 tag: "cb",
363 parent_tag: "co",
364 aliases: &["constant.builtin.boolean"],
365 },
366 HighlightDef {
367 name: "constructor",
368 tag: "cr",
369 parent_tag: "",
370 aliases: &[],
371 },
372 HighlightDef {
373 name: "function.builtin",
374 tag: "fb",
375 parent_tag: "f",
376 aliases: &[],
377 },
378 HighlightDef {
379 name: "function",
380 tag: "f",
381 parent_tag: "",
382 aliases: &[],
383 },
384 HighlightDef {
385 name: "function.method",
386 tag: "fm",
387 parent_tag: "f",
388 aliases: &[],
389 },
390 HighlightDef {
391 name: "keyword",
392 tag: "k",
393 parent_tag: "",
394 aliases: &[],
395 },
396 HighlightDef {
397 name: "keyword.conditional",
398 tag: "kc",
399 parent_tag: "k",
400 aliases: &[],
401 },
402 HighlightDef {
403 name: "keyword.coroutine",
404 tag: "ko",
405 parent_tag: "k",
406 aliases: &[],
407 },
408 HighlightDef {
409 name: "keyword.debug",
410 tag: "kd",
411 parent_tag: "k",
412 aliases: &[],
413 },
414 HighlightDef {
415 name: "keyword.exception",
416 tag: "ke",
417 parent_tag: "k",
418 aliases: &[],
419 },
420 HighlightDef {
421 name: "keyword.function",
422 tag: "kf",
423 parent_tag: "k",
424 aliases: &[],
425 },
426 HighlightDef {
427 name: "keyword.import",
428 tag: "ki",
429 parent_tag: "k",
430 aliases: &[],
431 },
432 HighlightDef {
433 name: "keyword.operator",
434 tag: "kp",
435 parent_tag: "k",
436 aliases: &[],
437 },
438 HighlightDef {
439 name: "keyword.repeat",
440 tag: "kr",
441 parent_tag: "k",
442 aliases: &[],
443 },
444 HighlightDef {
445 name: "keyword.return",
446 tag: "kt",
447 parent_tag: "k",
448 aliases: &[],
449 },
450 HighlightDef {
451 name: "keyword.type",
452 tag: "ky",
453 parent_tag: "k",
454 aliases: &[],
455 },
456 HighlightDef {
457 name: "operator",
458 tag: "o",
459 parent_tag: "",
460 aliases: &[],
461 },
462 HighlightDef {
463 name: "property",
464 tag: "pr",
465 parent_tag: "",
466 aliases: &[],
467 },
468 HighlightDef {
469 name: "punctuation",
470 tag: "p",
471 parent_tag: "",
472 aliases: &[],
473 },
474 HighlightDef {
475 name: "punctuation.bracket",
476 tag: "pb",
477 parent_tag: "p",
478 aliases: &[],
479 },
480 HighlightDef {
481 name: "punctuation.delimiter",
482 tag: "pd",
483 parent_tag: "p",
484 aliases: &[],
485 },
486 HighlightDef {
487 name: "punctuation.special",
488 tag: "ps",
489 parent_tag: "p",
490 aliases: &[],
491 },
492 HighlightDef {
493 name: "string",
494 tag: "s",
495 parent_tag: "",
496 aliases: &[],
497 },
498 HighlightDef {
499 name: "string.special",
500 tag: "ss",
501 parent_tag: "s",
502 aliases: &["string.special.symbol", "string.special.path"],
503 },
504 HighlightDef {
505 name: "tag",
506 tag: "tg",
507 parent_tag: "",
508 aliases: &[],
509 },
510 HighlightDef {
511 name: "tag.delimiter",
512 tag: "td",
513 parent_tag: "tg",
514 aliases: &[],
515 },
516 HighlightDef {
517 name: "tag.error",
518 tag: "te",
519 parent_tag: "tg",
520 aliases: &[],
521 },
522 HighlightDef {
523 name: "type",
524 tag: "t",
525 parent_tag: "",
526 aliases: &[],
527 },
528 HighlightDef {
529 name: "type.builtin",
530 tag: "tb",
531 parent_tag: "t",
532 aliases: &[],
533 },
534 HighlightDef {
535 name: "type.qualifier",
536 tag: "tq",
537 parent_tag: "t",
538 aliases: &[],
539 },
540 HighlightDef {
541 name: "variable",
542 tag: "v",
543 parent_tag: "",
544 aliases: &[],
545 },
546 HighlightDef {
547 name: "variable.builtin",
548 tag: "vb",
549 parent_tag: "v",
550 aliases: &[],
551 },
552 HighlightDef {
553 name: "variable.parameter",
554 tag: "vp",
555 parent_tag: "v",
556 aliases: &["parameter"],
557 },
558 HighlightDef {
559 name: "comment",
560 tag: "c",
561 parent_tag: "",
562 aliases: &[],
563 },
564 HighlightDef {
565 name: "comment.documentation",
566 tag: "cd",
567 parent_tag: "c",
568 aliases: &[],
569 },
570 HighlightDef {
571 name: "macro",
572 tag: "m",
573 parent_tag: "",
574 aliases: &[],
575 },
576 HighlightDef {
577 name: "label",
578 tag: "l",
579 parent_tag: "",
580 aliases: &[],
581 },
582 HighlightDef {
583 name: "diff.addition",
584 tag: "da",
585 parent_tag: "",
586 aliases: &["diff.plus", "diff.delta"],
587 },
588 HighlightDef {
589 name: "diff.deletion",
590 tag: "dd",
591 parent_tag: "",
592 aliases: &["diff.minus"],
593 },
594 HighlightDef {
595 name: "number",
596 tag: "n",
597 parent_tag: "",
598 aliases: &["constant.numeric"],
599 },
600 HighlightDef {
601 name: "text.literal",
602 tag: "tl",
603 parent_tag: "",
604 aliases: &["markup.raw"],
605 },
606 HighlightDef {
607 name: "text.emphasis",
608 tag: "em",
609 parent_tag: "",
610 aliases: &["markup.italic"],
611 },
612 HighlightDef {
613 name: "text.strong",
614 tag: "st",
615 parent_tag: "",
616 aliases: &["markup.bold"],
617 },
618 HighlightDef {
619 name: "text.uri",
620 tag: "tu",
621 parent_tag: "",
622 aliases: &["markup.link.url"],
623 },
624 HighlightDef {
625 name: "text.reference",
626 tag: "tr",
627 parent_tag: "",
628 aliases: &["markup.link.text"],
629 },
630 HighlightDef {
631 name: "string.escape",
632 tag: "se",
633 parent_tag: "s",
634 aliases: &["escape"],
635 },
636 HighlightDef {
637 name: "text.title",
638 tag: "tt",
639 parent_tag: "",
640 aliases: &["markup.heading"],
641 },
642 HighlightDef {
643 name: "text.strikethrough",
644 tag: "tx",
645 parent_tag: "",
646 aliases: &["markup.strikethrough"],
647 },
648 HighlightDef {
649 name: "spell",
650 tag: "sp",
651 parent_tag: "",
652 aliases: &[],
653 },
654 HighlightDef {
655 name: "embedded",
656 tag: "eb",
657 parent_tag: "",
658 aliases: &[],
659 },
660 HighlightDef {
661 name: "error",
662 tag: "er",
663 parent_tag: "",
664 aliases: &[],
665 },
666 HighlightDef {
667 name: "namespace",
668 tag: "ns",
669 parent_tag: "",
670 aliases: &["module"],
671 },
672 HighlightDef {
674 name: "include",
675 tag: "in",
676 parent_tag: "k",
677 aliases: &[],
678 },
679 HighlightDef {
680 name: "storageclass",
681 tag: "sc",
682 parent_tag: "k",
683 aliases: &[],
684 },
685 HighlightDef {
686 name: "repeat",
687 tag: "rp",
688 parent_tag: "k",
689 aliases: &[],
690 },
691 HighlightDef {
692 name: "conditional",
693 tag: "cn",
694 parent_tag: "k",
695 aliases: &[],
696 },
697 HighlightDef {
698 name: "exception",
699 tag: "ex",
700 parent_tag: "k",
701 aliases: &[],
702 },
703 HighlightDef {
704 name: "preproc",
705 tag: "pp",
706 parent_tag: "k",
707 aliases: &[],
708 },
709 HighlightDef {
710 name: "none",
711 tag: "",
712 parent_tag: "",
713 aliases: &[],
714 }, HighlightDef {
716 name: "character",
717 tag: "ch",
718 parent_tag: "s",
719 aliases: &[],
720 },
721 HighlightDef {
722 name: "character.special",
723 tag: "cs",
724 parent_tag: "s",
725 aliases: &[],
726 },
727 HighlightDef {
728 name: "variable.member",
729 tag: "vm",
730 parent_tag: "v",
731 aliases: &[],
732 },
733 HighlightDef {
734 name: "function.definition",
735 tag: "fd",
736 parent_tag: "f",
737 aliases: &[],
738 },
739 HighlightDef {
740 name: "type.definition",
741 tag: "tf",
742 parent_tag: "t",
743 aliases: &[],
744 },
745 HighlightDef {
746 name: "function.call",
747 tag: "fc",
748 parent_tag: "f",
749 aliases: &[],
750 },
751 HighlightDef {
752 name: "keyword.modifier",
753 tag: "km",
754 parent_tag: "k",
755 aliases: &[],
756 },
757 HighlightDef {
758 name: "keyword.directive",
759 tag: "dr",
760 parent_tag: "k",
761 aliases: &[],
762 },
763 HighlightDef {
764 name: "string.regexp",
765 tag: "rx",
766 parent_tag: "s",
767 aliases: &["string.regex"],
768 },
769 HighlightDef {
770 name: "nospell",
771 tag: "",
772 parent_tag: "",
773 aliases: &[],
774 }, HighlightDef {
776 name: "float",
777 tag: "n",
778 parent_tag: "",
779 aliases: &[],
780 }, HighlightDef {
782 name: "boolean",
783 tag: "cb",
784 parent_tag: "",
785 aliases: &[],
786 }, ];
788
789pub const fn names() -> [&'static str; HIGHLIGHTS.len()] {
791 let mut names = [""; HIGHLIGHTS.len()];
792 let mut i = 0;
793 while i < HIGHLIGHTS.len() {
794 names[i] = HIGHLIGHTS[i].name;
795 i += 1;
796 }
797 names
798}
799
800pub const COUNT: usize = HIGHLIGHTS.len();
802
803#[inline]
806pub fn tag(index: usize) -> Option<&'static str> {
807 HIGHLIGHTS
808 .get(index)
809 .map(|h| h.tag)
810 .filter(|t| !t.is_empty())
811}
812
813#[inline]
815pub fn prefixed_tag(index: usize) -> Option<String> {
816 tag(index).map(|t| format!("a-{t}"))
817}
818
819#[inline]
821pub fn parent_tag(index: usize) -> Option<&'static str> {
822 HIGHLIGHTS
823 .get(index)
824 .map(|h| h.parent_tag)
825 .filter(|t| !t.is_empty())
826}
827
828pub fn css_inheritance_rules() -> String {
831 use std::collections::HashMap;
832 use std::fmt::Write;
833
834 let mut parent_children: HashMap<&str, Vec<&str>> = HashMap::new();
836 for def in HIGHLIGHTS {
837 if !def.parent_tag.is_empty() && !def.tag.is_empty() {
838 parent_children
839 .entry(def.parent_tag)
840 .or_default()
841 .push(def.tag);
842 }
843 }
844
845 let mut css = String::new();
846 for (_parent, children) in parent_children {
847 if children.is_empty() {
848 continue;
849 }
850 let selectors: Vec<String> = children.iter().map(|c| format!("a-{c}")).collect();
852 writeln!(css, "{} {{ color: inherit; }}", selectors.join(", ")).unwrap();
853 }
854 css
855}
856
857pub fn tag_for_capture(capture: &str) -> Option<&'static str> {
879 capture_to_slot(capture).tag()
880}
881
882pub const CAPTURE_NAMES: &[&str] = &[
888 "keyword",
890 "keyword.conditional",
891 "keyword.coroutine",
892 "keyword.debug",
893 "keyword.exception",
894 "keyword.function",
895 "keyword.import",
896 "keyword.operator",
897 "keyword.repeat",
898 "keyword.return",
899 "keyword.type",
900 "keyword.modifier",
901 "keyword.directive",
902 "keyword.storage",
903 "keyword.control",
904 "keyword.control.conditional",
905 "keyword.control.repeat",
906 "keyword.control.import",
907 "keyword.control.return",
908 "keyword.control.exception",
909 "include",
911 "conditional",
912 "repeat",
913 "exception",
914 "storageclass",
915 "preproc",
916 "define",
917 "structure",
918 "function",
920 "function.builtin",
921 "function.method",
922 "function.definition",
923 "function.call",
924 "function.macro",
925 "function.special",
926 "method",
927 "method.call",
928 "string",
930 "string.special",
931 "string.special.symbol",
932 "string.special.path",
933 "string.special.url",
934 "string.escape",
935 "string.regexp",
936 "string.regex",
937 "character",
938 "character.special",
939 "escape",
940 "comment",
942 "comment.documentation",
943 "comment.line",
944 "comment.block",
945 "comment.error",
946 "comment.warning",
947 "comment.note",
948 "comment.todo",
949 "type",
951 "type.builtin",
952 "type.qualifier",
953 "type.definition",
954 "type.enum",
955 "type.enum.variant",
956 "type.parameter",
957 "variable",
959 "variable.builtin",
960 "variable.parameter",
961 "variable.member",
962 "variable.other",
963 "variable.other.member",
964 "parameter",
965 "field",
966 "constant",
968 "constant.builtin",
969 "constant.builtin.boolean",
970 "constant.numeric",
971 "boolean",
972 "number",
974 "float",
975 "number.float",
976 "operator",
978 "punctuation",
980 "punctuation.bracket",
981 "punctuation.delimiter",
982 "punctuation.special",
983 "property",
985 "property.builtin",
986 "attribute",
988 "attribute.builtin",
989 "tag",
991 "tag.delimiter",
992 "tag.error",
993 "tag.attribute",
994 "tag.builtin",
995 "macro",
997 "label",
999 "namespace",
1001 "module",
1002 "constructor",
1004 "constructor.builtin",
1005 "text.title",
1007 "markup.heading",
1008 "markup.heading.1",
1009 "markup.heading.2",
1010 "markup.heading.3",
1011 "markup.heading.4",
1012 "markup.heading.5",
1013 "markup.heading.6",
1014 "text.strong",
1016 "markup.bold",
1017 "text.emphasis",
1018 "markup.italic",
1019 "text.uri",
1021 "text.reference",
1022 "markup.link",
1023 "markup.link.url",
1024 "markup.link.text",
1025 "markup.link.label",
1026 "text.literal",
1028 "markup.raw",
1029 "markup.raw.block",
1030 "markup.raw.inline",
1031 "markup.inline",
1032 "text.strikethrough",
1034 "markup.strikethrough",
1035 "markup.list",
1037 "markup.list.checked",
1038 "markup.list.unchecked",
1039 "markup.list.numbered",
1040 "markup.list.unnumbered",
1041 "markup.quote",
1042 "text",
1044 "markup",
1045 "diff.addition",
1047 "diff.plus",
1048 "diff.delta",
1049 "diff.deletion",
1050 "diff.minus",
1051 "embedded",
1053 "error",
1054 "none",
1055 "nospell",
1056 "spell",
1057];
1058
1059#[cfg(test)]
1060mod tests {
1061 use super::*;
1062
1063 #[test]
1064 fn test_names_count() {
1065 assert_eq!(names().len(), COUNT);
1066 }
1067
1068 #[test]
1069 fn test_none_produces_no_tag() {
1070 let none_idx = HIGHLIGHTS.iter().position(|h| h.name == "none").unwrap();
1072 assert_eq!(tag(none_idx), None);
1073 }
1074
1075 #[test]
1076 fn test_keyword_tag() {
1077 let kw_idx = HIGHLIGHTS.iter().position(|h| h.name == "keyword").unwrap();
1078 assert_eq!(tag(kw_idx), Some("k"));
1079 assert_eq!(prefixed_tag(kw_idx), Some("a-k".to_string()));
1080 }
1081
1082 #[test]
1083 fn test_inheritance() {
1084 let kc_idx = HIGHLIGHTS
1085 .iter()
1086 .position(|h| h.name == "keyword.conditional")
1087 .unwrap();
1088 assert_eq!(parent_tag(kc_idx), Some("k"));
1089 }
1090
1091 #[test]
1092 fn test_capture_to_slot_keywords() {
1093 assert_eq!(capture_to_slot("keyword"), ThemeSlot::Keyword);
1095 assert_eq!(capture_to_slot("keyword.function"), ThemeSlot::Keyword);
1096 assert_eq!(capture_to_slot("keyword.import"), ThemeSlot::Keyword);
1097 assert_eq!(capture_to_slot("include"), ThemeSlot::Keyword);
1098 assert_eq!(capture_to_slot("conditional"), ThemeSlot::Keyword);
1099 assert_eq!(capture_to_slot("repeat"), ThemeSlot::Keyword);
1100 assert_eq!(capture_to_slot("storageclass"), ThemeSlot::Keyword);
1101 }
1102
1103 #[test]
1104 fn test_capture_to_slot_functions() {
1105 assert_eq!(capture_to_slot("function"), ThemeSlot::Function);
1106 assert_eq!(capture_to_slot("function.builtin"), ThemeSlot::Function);
1107 assert_eq!(capture_to_slot("function.method"), ThemeSlot::Function);
1108 assert_eq!(capture_to_slot("method"), ThemeSlot::Function);
1109 }
1110
1111 #[test]
1112 fn test_capture_to_slot_markup() {
1113 assert_eq!(capture_to_slot("markup.heading"), ThemeSlot::Title);
1114 assert_eq!(capture_to_slot("markup.heading.1"), ThemeSlot::Title);
1115 assert_eq!(capture_to_slot("text.title"), ThemeSlot::Title);
1116 assert_eq!(capture_to_slot("markup.bold"), ThemeSlot::Strong);
1117 assert_eq!(capture_to_slot("markup.italic"), ThemeSlot::Emphasis);
1118 }
1119
1120 #[test]
1121 fn test_capture_to_slot_none() {
1122 assert_eq!(capture_to_slot("none"), ThemeSlot::None);
1123 assert_eq!(capture_to_slot("spell"), ThemeSlot::None);
1124 assert_eq!(capture_to_slot("nospell"), ThemeSlot::None);
1125 }
1126
1127 #[test]
1128 fn test_tag_for_capture() {
1129 assert_eq!(tag_for_capture("keyword"), Some("k"));
1131 assert_eq!(tag_for_capture("keyword.function"), Some("k"));
1132 assert_eq!(tag_for_capture("include"), Some("k"));
1133 assert_eq!(tag_for_capture("conditional"), Some("k"));
1134
1135 assert_eq!(tag_for_capture("function"), Some("f"));
1137 assert_eq!(tag_for_capture("function.builtin"), Some("f"));
1138
1139 assert_eq!(tag_for_capture("comment"), Some("c"));
1141 assert_eq!(tag_for_capture("comment.documentation"), Some("c"));
1142
1143 assert_eq!(tag_for_capture("spell"), None);
1145 assert_eq!(tag_for_capture("none"), None);
1146 }
1147
1148 #[test]
1149 fn test_theme_slot_tag() {
1150 assert_eq!(ThemeSlot::Keyword.tag(), Some("k"));
1151 assert_eq!(ThemeSlot::Function.tag(), Some("f"));
1152 assert_eq!(ThemeSlot::String.tag(), Some("s"));
1153 assert_eq!(ThemeSlot::Comment.tag(), Some("c"));
1154 assert_eq!(ThemeSlot::None.tag(), None);
1155 }
1156
1157 #[test]
1158 fn test_capture_names_all_map_to_slot() {
1159 for name in CAPTURE_NAMES {
1161 let slot = capture_to_slot(name);
1162 let _ = slot.tag();
1164 }
1165 }
1166}