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"),
93 ThemeSlot::Strong => Some("st"),
94 ThemeSlot::Emphasis => Some("em"),
95 ThemeSlot::Link => Some("tu"),
96 ThemeSlot::Literal => Some("tl"),
97 ThemeSlot::Strikethrough => Some("tx"),
98 ThemeSlot::DiffAdd => Some("da"),
99 ThemeSlot::DiffDelete => Some("dd"),
100 ThemeSlot::Embedded => Some("eb"),
101 ThemeSlot::Error => Some("er"),
102 ThemeSlot::None => None,
103 }
104 }
105}
106
107pub fn capture_to_slot(capture: &str) -> ThemeSlot {
117 let capture = capture.strip_prefix('@').unwrap_or(capture);
119
120 match capture {
121 "keyword" | "keyword.conditional" | "keyword.coroutine" | "keyword.debug"
123 | "keyword.exception" | "keyword.function" | "keyword.import" | "keyword.operator"
124 | "keyword.repeat" | "keyword.return" | "keyword.type" | "keyword.modifier"
125 | "keyword.directive" | "keyword.storage" | "keyword.control"
126 | "keyword.control.conditional" | "keyword.control.repeat" | "keyword.control.import"
127 | "keyword.control.return" | "keyword.control.exception"
128 | "include" | "conditional" | "repeat" | "exception" | "storageclass" | "preproc"
130 | "define" | "structure" => ThemeSlot::Keyword,
131
132 "function" | "function.builtin" | "function.method" | "function.definition"
134 | "function.call" | "function.special" | "method" | "method.call" => ThemeSlot::Function,
135
136 "string" | "string.special" | "string.special.symbol" | "string.special.path"
138 | "string.special.url" | "string.escape" | "string.regexp" | "string.regex"
139 | "character" | "character.special" | "escape" => ThemeSlot::String,
140
141 "comment" | "comment.documentation" | "comment.line" | "comment.block"
143 | "comment.error" | "comment.warning" | "comment.note" | "comment.todo" => {
144 ThemeSlot::Comment
145 }
146
147 "type" | "type.builtin" | "type.qualifier" | "type.definition" | "type.enum"
149 | "type.enum.variant" | "type.parameter" => ThemeSlot::Type,
150
151 "variable" | "variable.builtin" | "variable.parameter" | "variable.member"
153 | "variable.other" | "variable.other.member" | "parameter" | "field" => {
154 ThemeSlot::Variable
155 }
156
157 "constant" | "constant.builtin" | "constant.builtin.boolean" | "boolean" => {
159 ThemeSlot::Constant
160 }
161
162 "number" | "constant.numeric" | "float" | "number.float" => ThemeSlot::Number,
164
165 "operator" => ThemeSlot::Operator,
167
168 "punctuation" | "punctuation.bracket" | "punctuation.delimiter" | "punctuation.special" => {
170 ThemeSlot::Punctuation
171 }
172
173 "property" | "property.builtin" => ThemeSlot::Property,
175
176 "attribute" | "attribute.builtin" => ThemeSlot::Attribute,
178
179 "tag" | "tag.delimiter" | "tag.error" | "tag.attribute" | "tag.builtin" => ThemeSlot::Tag,
181
182 "macro" | "function.macro" | "preproc.macro" => ThemeSlot::Macro,
184
185 "label" => ThemeSlot::Label,
187
188 "namespace" | "module" => ThemeSlot::Namespace,
190
191 "constructor" | "constructor.builtin" => ThemeSlot::Constructor,
193
194 "text.title" | "markup.heading" | "markup.heading.1" | "markup.heading.2"
196 | "markup.heading.3" | "markup.heading.4" | "markup.heading.5" | "markup.heading.6" => {
197 ThemeSlot::Title
198 }
199
200 "text.strong" | "markup.bold" => ThemeSlot::Strong,
202
203 "text.emphasis" | "markup.italic" => ThemeSlot::Emphasis,
205
206 "text.uri" | "text.reference" | "markup.link" | "markup.link.url" | "markup.link.text"
208 | "markup.link.label" => ThemeSlot::Link,
209
210 "text.literal" | "markup.raw" | "markup.raw.block" | "markup.raw.inline"
212 | "markup.inline" => ThemeSlot::Literal,
213
214 "text.strikethrough" | "markup.strikethrough" => ThemeSlot::Strikethrough,
216
217 "markup.list" | "markup.list.checked" | "markup.list.unchecked"
219 | "markup.list.numbered" | "markup.list.unnumbered" | "markup.quote" => {
220 ThemeSlot::Punctuation
221 }
222
223 "diff.addition" | "diff.plus" | "diff.delta" => ThemeSlot::DiffAdd,
225 "diff.deletion" | "diff.minus" => ThemeSlot::DiffDelete,
226
227 "embedded" => ThemeSlot::Embedded,
229
230 "error" => ThemeSlot::Error,
232
233 "none" | "nospell" | "spell" | "text" | "markup" => ThemeSlot::None,
235
236 other => {
238 if other.starts_with("keyword") {
239 ThemeSlot::Keyword
240 } else if other.starts_with("function") || other.starts_with("method") {
241 ThemeSlot::Function
242 } else if other.starts_with("string") || other.starts_with("character") {
243 ThemeSlot::String
244 } else if other.starts_with("comment") {
245 ThemeSlot::Comment
246 } else if other.starts_with("type") {
247 ThemeSlot::Type
248 } else if other.starts_with("variable") || other.starts_with("parameter") {
249 ThemeSlot::Variable
250 } else if other.starts_with("constant") {
251 ThemeSlot::Constant
252 } else if other.starts_with("punctuation") {
253 ThemeSlot::Punctuation
254 } else if other.starts_with("tag") {
255 ThemeSlot::Tag
256 } else if other.starts_with("markup.heading") || other.starts_with("text.title") {
257 ThemeSlot::Title
258 } else if other.starts_with("markup") || other.starts_with("text") {
259 ThemeSlot::None
261 } else {
262 ThemeSlot::None
264 }
265 }
266 }
267}
268
269pub struct HighlightDef {
274 pub name: &'static str,
276 pub tag: &'static str,
279 pub parent_tag: &'static str,
282 pub aliases: &'static [&'static str],
284}
285
286pub const HIGHLIGHTS: &[HighlightDef] = &[
289 HighlightDef {
291 name: "attribute",
292 tag: "at",
293 parent_tag: "",
294 aliases: &[],
295 },
296 HighlightDef {
297 name: "constant",
298 tag: "co",
299 parent_tag: "",
300 aliases: &[],
301 },
302 HighlightDef {
303 name: "constant.builtin",
304 tag: "cb",
305 parent_tag: "co",
306 aliases: &["constant.builtin.boolean"],
307 },
308 HighlightDef {
309 name: "constructor",
310 tag: "cr",
311 parent_tag: "",
312 aliases: &[],
313 },
314 HighlightDef {
315 name: "function.builtin",
316 tag: "fb",
317 parent_tag: "f",
318 aliases: &[],
319 },
320 HighlightDef {
321 name: "function",
322 tag: "f",
323 parent_tag: "",
324 aliases: &[],
325 },
326 HighlightDef {
327 name: "function.method",
328 tag: "fm",
329 parent_tag: "f",
330 aliases: &[],
331 },
332 HighlightDef {
333 name: "keyword",
334 tag: "k",
335 parent_tag: "",
336 aliases: &[],
337 },
338 HighlightDef {
339 name: "keyword.conditional",
340 tag: "kc",
341 parent_tag: "k",
342 aliases: &[],
343 },
344 HighlightDef {
345 name: "keyword.coroutine",
346 tag: "ko",
347 parent_tag: "k",
348 aliases: &[],
349 },
350 HighlightDef {
351 name: "keyword.debug",
352 tag: "kd",
353 parent_tag: "k",
354 aliases: &[],
355 },
356 HighlightDef {
357 name: "keyword.exception",
358 tag: "ke",
359 parent_tag: "k",
360 aliases: &[],
361 },
362 HighlightDef {
363 name: "keyword.function",
364 tag: "kf",
365 parent_tag: "k",
366 aliases: &[],
367 },
368 HighlightDef {
369 name: "keyword.import",
370 tag: "ki",
371 parent_tag: "k",
372 aliases: &[],
373 },
374 HighlightDef {
375 name: "keyword.operator",
376 tag: "kp",
377 parent_tag: "k",
378 aliases: &[],
379 },
380 HighlightDef {
381 name: "keyword.repeat",
382 tag: "kr",
383 parent_tag: "k",
384 aliases: &[],
385 },
386 HighlightDef {
387 name: "keyword.return",
388 tag: "kt",
389 parent_tag: "k",
390 aliases: &[],
391 },
392 HighlightDef {
393 name: "keyword.type",
394 tag: "ky",
395 parent_tag: "k",
396 aliases: &[],
397 },
398 HighlightDef {
399 name: "operator",
400 tag: "o",
401 parent_tag: "",
402 aliases: &[],
403 },
404 HighlightDef {
405 name: "property",
406 tag: "pr",
407 parent_tag: "",
408 aliases: &[],
409 },
410 HighlightDef {
411 name: "punctuation",
412 tag: "p",
413 parent_tag: "",
414 aliases: &[],
415 },
416 HighlightDef {
417 name: "punctuation.bracket",
418 tag: "pb",
419 parent_tag: "p",
420 aliases: &[],
421 },
422 HighlightDef {
423 name: "punctuation.delimiter",
424 tag: "pd",
425 parent_tag: "p",
426 aliases: &[],
427 },
428 HighlightDef {
429 name: "punctuation.special",
430 tag: "ps",
431 parent_tag: "p",
432 aliases: &[],
433 },
434 HighlightDef {
435 name: "string",
436 tag: "s",
437 parent_tag: "",
438 aliases: &[],
439 },
440 HighlightDef {
441 name: "string.special",
442 tag: "ss",
443 parent_tag: "s",
444 aliases: &["string.special.symbol", "string.special.path"],
445 },
446 HighlightDef {
447 name: "tag",
448 tag: "tg",
449 parent_tag: "",
450 aliases: &[],
451 },
452 HighlightDef {
453 name: "tag.delimiter",
454 tag: "td",
455 parent_tag: "tg",
456 aliases: &[],
457 },
458 HighlightDef {
459 name: "tag.error",
460 tag: "te",
461 parent_tag: "tg",
462 aliases: &[],
463 },
464 HighlightDef {
465 name: "type",
466 tag: "t",
467 parent_tag: "",
468 aliases: &[],
469 },
470 HighlightDef {
471 name: "type.builtin",
472 tag: "tb",
473 parent_tag: "t",
474 aliases: &[],
475 },
476 HighlightDef {
477 name: "type.qualifier",
478 tag: "tq",
479 parent_tag: "t",
480 aliases: &[],
481 },
482 HighlightDef {
483 name: "variable",
484 tag: "v",
485 parent_tag: "",
486 aliases: &[],
487 },
488 HighlightDef {
489 name: "variable.builtin",
490 tag: "vb",
491 parent_tag: "v",
492 aliases: &[],
493 },
494 HighlightDef {
495 name: "variable.parameter",
496 tag: "vp",
497 parent_tag: "v",
498 aliases: &["parameter"],
499 },
500 HighlightDef {
501 name: "comment",
502 tag: "c",
503 parent_tag: "",
504 aliases: &[],
505 },
506 HighlightDef {
507 name: "comment.documentation",
508 tag: "cd",
509 parent_tag: "c",
510 aliases: &[],
511 },
512 HighlightDef {
513 name: "macro",
514 tag: "m",
515 parent_tag: "",
516 aliases: &[],
517 },
518 HighlightDef {
519 name: "label",
520 tag: "l",
521 parent_tag: "",
522 aliases: &[],
523 },
524 HighlightDef {
525 name: "diff.addition",
526 tag: "da",
527 parent_tag: "",
528 aliases: &["diff.plus", "diff.delta"],
529 },
530 HighlightDef {
531 name: "diff.deletion",
532 tag: "dd",
533 parent_tag: "",
534 aliases: &["diff.minus"],
535 },
536 HighlightDef {
537 name: "number",
538 tag: "n",
539 parent_tag: "",
540 aliases: &["constant.numeric"],
541 },
542 HighlightDef {
543 name: "text.literal",
544 tag: "tl",
545 parent_tag: "",
546 aliases: &["markup.raw"],
547 },
548 HighlightDef {
549 name: "text.emphasis",
550 tag: "em",
551 parent_tag: "",
552 aliases: &["markup.italic"],
553 },
554 HighlightDef {
555 name: "text.strong",
556 tag: "st",
557 parent_tag: "",
558 aliases: &["markup.bold"],
559 },
560 HighlightDef {
561 name: "text.uri",
562 tag: "tu",
563 parent_tag: "",
564 aliases: &["markup.link.url"],
565 },
566 HighlightDef {
567 name: "text.reference",
568 tag: "tr",
569 parent_tag: "",
570 aliases: &["markup.link.text"],
571 },
572 HighlightDef {
573 name: "string.escape",
574 tag: "se",
575 parent_tag: "s",
576 aliases: &["escape"],
577 },
578 HighlightDef {
579 name: "text.title",
580 tag: "tt",
581 parent_tag: "",
582 aliases: &["markup.heading"],
583 },
584 HighlightDef {
585 name: "text.strikethrough",
586 tag: "tx",
587 parent_tag: "",
588 aliases: &["markup.strikethrough"],
589 },
590 HighlightDef {
591 name: "spell",
592 tag: "sp",
593 parent_tag: "",
594 aliases: &[],
595 },
596 HighlightDef {
597 name: "embedded",
598 tag: "eb",
599 parent_tag: "",
600 aliases: &[],
601 },
602 HighlightDef {
603 name: "error",
604 tag: "er",
605 parent_tag: "",
606 aliases: &[],
607 },
608 HighlightDef {
609 name: "namespace",
610 tag: "ns",
611 parent_tag: "",
612 aliases: &["module"],
613 },
614 HighlightDef {
616 name: "include",
617 tag: "in",
618 parent_tag: "k",
619 aliases: &[],
620 },
621 HighlightDef {
622 name: "storageclass",
623 tag: "sc",
624 parent_tag: "k",
625 aliases: &[],
626 },
627 HighlightDef {
628 name: "repeat",
629 tag: "rp",
630 parent_tag: "k",
631 aliases: &[],
632 },
633 HighlightDef {
634 name: "conditional",
635 tag: "cn",
636 parent_tag: "k",
637 aliases: &[],
638 },
639 HighlightDef {
640 name: "exception",
641 tag: "ex",
642 parent_tag: "k",
643 aliases: &[],
644 },
645 HighlightDef {
646 name: "preproc",
647 tag: "pp",
648 parent_tag: "k",
649 aliases: &[],
650 },
651 HighlightDef {
652 name: "none",
653 tag: "",
654 parent_tag: "",
655 aliases: &[],
656 }, HighlightDef {
658 name: "character",
659 tag: "ch",
660 parent_tag: "s",
661 aliases: &[],
662 },
663 HighlightDef {
664 name: "character.special",
665 tag: "cs",
666 parent_tag: "s",
667 aliases: &[],
668 },
669 HighlightDef {
670 name: "variable.member",
671 tag: "vm",
672 parent_tag: "v",
673 aliases: &[],
674 },
675 HighlightDef {
676 name: "function.definition",
677 tag: "fd",
678 parent_tag: "f",
679 aliases: &[],
680 },
681 HighlightDef {
682 name: "type.definition",
683 tag: "tf",
684 parent_tag: "t",
685 aliases: &[],
686 },
687 HighlightDef {
688 name: "function.call",
689 tag: "fc",
690 parent_tag: "f",
691 aliases: &[],
692 },
693 HighlightDef {
694 name: "keyword.modifier",
695 tag: "km",
696 parent_tag: "k",
697 aliases: &[],
698 },
699 HighlightDef {
700 name: "keyword.directive",
701 tag: "dr",
702 parent_tag: "k",
703 aliases: &[],
704 },
705 HighlightDef {
706 name: "string.regexp",
707 tag: "rx",
708 parent_tag: "s",
709 aliases: &["string.regex"],
710 },
711 HighlightDef {
712 name: "nospell",
713 tag: "",
714 parent_tag: "",
715 aliases: &[],
716 }, HighlightDef {
718 name: "float",
719 tag: "n",
720 parent_tag: "",
721 aliases: &[],
722 }, HighlightDef {
724 name: "boolean",
725 tag: "cb",
726 parent_tag: "",
727 aliases: &[],
728 }, ];
730
731pub const fn names() -> [&'static str; HIGHLIGHTS.len()] {
733 let mut names = [""; HIGHLIGHTS.len()];
734 let mut i = 0;
735 while i < HIGHLIGHTS.len() {
736 names[i] = HIGHLIGHTS[i].name;
737 i += 1;
738 }
739 names
740}
741
742pub const COUNT: usize = HIGHLIGHTS.len();
744
745#[inline]
748pub fn tag(index: usize) -> Option<&'static str> {
749 HIGHLIGHTS
750 .get(index)
751 .map(|h| h.tag)
752 .filter(|t| !t.is_empty())
753}
754
755#[inline]
757pub fn prefixed_tag(index: usize) -> Option<String> {
758 tag(index).map(|t| format!("a-{t}"))
759}
760
761#[inline]
763pub fn parent_tag(index: usize) -> Option<&'static str> {
764 HIGHLIGHTS
765 .get(index)
766 .map(|h| h.parent_tag)
767 .filter(|t| !t.is_empty())
768}
769
770pub fn css_inheritance_rules() -> String {
773 use std::collections::HashMap;
774 use std::fmt::Write;
775
776 let mut parent_children: HashMap<&str, Vec<&str>> = HashMap::new();
778 for def in HIGHLIGHTS {
779 if !def.parent_tag.is_empty() && !def.tag.is_empty() {
780 parent_children
781 .entry(def.parent_tag)
782 .or_default()
783 .push(def.tag);
784 }
785 }
786
787 let mut css = String::new();
788 for (_parent, children) in parent_children {
789 if children.is_empty() {
790 continue;
791 }
792 let selectors: Vec<String> = children.iter().map(|c| format!("a-{c}")).collect();
794 writeln!(css, "{} {{ color: inherit; }}", selectors.join(", ")).unwrap();
795 }
796 css
797}
798
799pub fn tag_for_capture(capture: &str) -> Option<&'static str> {
821 capture_to_slot(capture).tag()
822}
823
824pub const CAPTURE_NAMES: &[&str] = &[
830 "keyword",
832 "keyword.conditional",
833 "keyword.coroutine",
834 "keyword.debug",
835 "keyword.exception",
836 "keyword.function",
837 "keyword.import",
838 "keyword.operator",
839 "keyword.repeat",
840 "keyword.return",
841 "keyword.type",
842 "keyword.modifier",
843 "keyword.directive",
844 "keyword.storage",
845 "keyword.control",
846 "keyword.control.conditional",
847 "keyword.control.repeat",
848 "keyword.control.import",
849 "keyword.control.return",
850 "keyword.control.exception",
851 "include",
853 "conditional",
854 "repeat",
855 "exception",
856 "storageclass",
857 "preproc",
858 "define",
859 "structure",
860 "function",
862 "function.builtin",
863 "function.method",
864 "function.definition",
865 "function.call",
866 "function.macro",
867 "function.special",
868 "method",
869 "method.call",
870 "string",
872 "string.special",
873 "string.special.symbol",
874 "string.special.path",
875 "string.special.url",
876 "string.escape",
877 "string.regexp",
878 "string.regex",
879 "character",
880 "character.special",
881 "escape",
882 "comment",
884 "comment.documentation",
885 "comment.line",
886 "comment.block",
887 "comment.error",
888 "comment.warning",
889 "comment.note",
890 "comment.todo",
891 "type",
893 "type.builtin",
894 "type.qualifier",
895 "type.definition",
896 "type.enum",
897 "type.enum.variant",
898 "type.parameter",
899 "variable",
901 "variable.builtin",
902 "variable.parameter",
903 "variable.member",
904 "variable.other",
905 "variable.other.member",
906 "parameter",
907 "field",
908 "constant",
910 "constant.builtin",
911 "constant.builtin.boolean",
912 "constant.numeric",
913 "boolean",
914 "number",
916 "float",
917 "number.float",
918 "operator",
920 "punctuation",
922 "punctuation.bracket",
923 "punctuation.delimiter",
924 "punctuation.special",
925 "property",
927 "property.builtin",
928 "attribute",
930 "attribute.builtin",
931 "tag",
933 "tag.delimiter",
934 "tag.error",
935 "tag.attribute",
936 "tag.builtin",
937 "macro",
939 "label",
941 "namespace",
943 "module",
944 "constructor",
946 "constructor.builtin",
947 "text.title",
949 "markup.heading",
950 "markup.heading.1",
951 "markup.heading.2",
952 "markup.heading.3",
953 "markup.heading.4",
954 "markup.heading.5",
955 "markup.heading.6",
956 "text.strong",
958 "markup.bold",
959 "text.emphasis",
960 "markup.italic",
961 "text.uri",
963 "text.reference",
964 "markup.link",
965 "markup.link.url",
966 "markup.link.text",
967 "markup.link.label",
968 "text.literal",
970 "markup.raw",
971 "markup.raw.block",
972 "markup.raw.inline",
973 "markup.inline",
974 "text.strikethrough",
976 "markup.strikethrough",
977 "markup.list",
979 "markup.list.checked",
980 "markup.list.unchecked",
981 "markup.list.numbered",
982 "markup.list.unnumbered",
983 "markup.quote",
984 "text",
986 "markup",
987 "diff.addition",
989 "diff.plus",
990 "diff.delta",
991 "diff.deletion",
992 "diff.minus",
993 "embedded",
995 "error",
996 "none",
997 "nospell",
998 "spell",
999];
1000
1001#[cfg(test)]
1002mod tests {
1003 use super::*;
1004
1005 #[test]
1006 fn test_names_count() {
1007 assert_eq!(names().len(), COUNT);
1008 }
1009
1010 #[test]
1011 fn test_none_produces_no_tag() {
1012 let none_idx = HIGHLIGHTS.iter().position(|h| h.name == "none").unwrap();
1014 assert_eq!(tag(none_idx), None);
1015 }
1016
1017 #[test]
1018 fn test_keyword_tag() {
1019 let kw_idx = HIGHLIGHTS.iter().position(|h| h.name == "keyword").unwrap();
1020 assert_eq!(tag(kw_idx), Some("k"));
1021 assert_eq!(prefixed_tag(kw_idx), Some("a-k".to_string()));
1022 }
1023
1024 #[test]
1025 fn test_inheritance() {
1026 let kc_idx = HIGHLIGHTS
1027 .iter()
1028 .position(|h| h.name == "keyword.conditional")
1029 .unwrap();
1030 assert_eq!(parent_tag(kc_idx), Some("k"));
1031 }
1032
1033 #[test]
1034 fn test_capture_to_slot_keywords() {
1035 assert_eq!(capture_to_slot("keyword"), ThemeSlot::Keyword);
1037 assert_eq!(capture_to_slot("keyword.function"), ThemeSlot::Keyword);
1038 assert_eq!(capture_to_slot("keyword.import"), ThemeSlot::Keyword);
1039 assert_eq!(capture_to_slot("include"), ThemeSlot::Keyword);
1040 assert_eq!(capture_to_slot("conditional"), ThemeSlot::Keyword);
1041 assert_eq!(capture_to_slot("repeat"), ThemeSlot::Keyword);
1042 assert_eq!(capture_to_slot("storageclass"), ThemeSlot::Keyword);
1043 }
1044
1045 #[test]
1046 fn test_capture_to_slot_functions() {
1047 assert_eq!(capture_to_slot("function"), ThemeSlot::Function);
1048 assert_eq!(capture_to_slot("function.builtin"), ThemeSlot::Function);
1049 assert_eq!(capture_to_slot("function.method"), ThemeSlot::Function);
1050 assert_eq!(capture_to_slot("method"), ThemeSlot::Function);
1051 }
1052
1053 #[test]
1054 fn test_capture_to_slot_markup() {
1055 assert_eq!(capture_to_slot("markup.heading"), ThemeSlot::Title);
1056 assert_eq!(capture_to_slot("markup.heading.1"), ThemeSlot::Title);
1057 assert_eq!(capture_to_slot("text.title"), ThemeSlot::Title);
1058 assert_eq!(capture_to_slot("markup.bold"), ThemeSlot::Strong);
1059 assert_eq!(capture_to_slot("markup.italic"), ThemeSlot::Emphasis);
1060 }
1061
1062 #[test]
1063 fn test_capture_to_slot_none() {
1064 assert_eq!(capture_to_slot("none"), ThemeSlot::None);
1065 assert_eq!(capture_to_slot("spell"), ThemeSlot::None);
1066 assert_eq!(capture_to_slot("nospell"), ThemeSlot::None);
1067 }
1068
1069 #[test]
1070 fn test_tag_for_capture() {
1071 assert_eq!(tag_for_capture("keyword"), Some("k"));
1073 assert_eq!(tag_for_capture("keyword.function"), Some("k"));
1074 assert_eq!(tag_for_capture("include"), Some("k"));
1075 assert_eq!(tag_for_capture("conditional"), Some("k"));
1076
1077 assert_eq!(tag_for_capture("function"), Some("f"));
1079 assert_eq!(tag_for_capture("function.builtin"), Some("f"));
1080
1081 assert_eq!(tag_for_capture("comment"), Some("c"));
1083 assert_eq!(tag_for_capture("comment.documentation"), Some("c"));
1084
1085 assert_eq!(tag_for_capture("spell"), None);
1087 assert_eq!(tag_for_capture("none"), None);
1088 }
1089
1090 #[test]
1091 fn test_theme_slot_tag() {
1092 assert_eq!(ThemeSlot::Keyword.tag(), Some("k"));
1093 assert_eq!(ThemeSlot::Function.tag(), Some("f"));
1094 assert_eq!(ThemeSlot::String.tag(), Some("s"));
1095 assert_eq!(ThemeSlot::Comment.tag(), Some("c"));
1096 assert_eq!(ThemeSlot::None.tag(), None);
1097 }
1098
1099 #[test]
1100 fn test_capture_names_all_map_to_slot() {
1101 for name in CAPTURE_NAMES {
1103 let slot = capture_to_slot(name);
1104 let _ = slot.tag();
1106 }
1107 }
1108}