cairo_lang_parser/
colored_printer.rs1use cairo_lang_syntax::node::SyntaxNode;
2use cairo_lang_syntax::node::db::SyntaxGroup;
3use cairo_lang_syntax::node::green::GreenNodeDetails;
4use cairo_lang_syntax::node::kind::SyntaxKind;
5use colored::{ColoredString, Colorize};
6use smol_str::SmolStr;
7
8struct ColoredPrinter<'a> {
9 db: &'a dyn SyntaxGroup,
10 verbose: bool,
12 result: String,
13}
14impl ColoredPrinter<'_> {
15 fn print(&mut self, syntax_node: &SyntaxNode) {
16 let node = syntax_node.green_node(self.db);
17 match &node.details {
18 GreenNodeDetails::Token(text) => {
19 if self.verbose && node.kind == SyntaxKind::TokenMissing {
20 self.result.push_str(format!("{}", "<m>".red()).as_str());
21 } else {
22 self.result.push_str(set_color(text.clone(), node.kind).to_string().as_str());
23 }
24 }
25 GreenNodeDetails::Node { .. } => {
26 if self.verbose && is_missing_kind(node.kind) {
27 self.result.push_str(format!("{}", "<m>".red()).as_str());
28 } else if self.verbose && is_empty_kind(node.kind) {
29 self.result.push_str(format!("{}", "<e>".red()).as_str());
30 } else {
31 for child in self.db.get_children(syntax_node.clone()).iter() {
32 self.print(child);
33 }
34 }
35 }
36 }
37 }
38}
39
40fn is_missing_kind(kind: SyntaxKind) -> bool {
42 matches!(kind, SyntaxKind::ExprMissing | SyntaxKind::StatementMissing)
43}
44
45pub fn is_empty_kind(kind: SyntaxKind) -> bool {
47 matches!(
48 kind,
49 SyntaxKind::OptionStructArgExprEmpty
50 | SyntaxKind::OptionTypeClauseEmpty
51 | SyntaxKind::OptionReturnTypeClauseEmpty
52 | SyntaxKind::OptionTerminalSemicolonEmpty
53 | SyntaxKind::OptionTerminalColonColonEmpty
54 | SyntaxKind::OptionWrappedGenericParamListEmpty
55 )
56}
57
58fn set_color(text: SmolStr, kind: SyntaxKind) -> ColoredString {
59 match kind {
61 SyntaxKind::TokenIdentifier => text.truecolor(255, 255, 100), SyntaxKind::TokenPlus
63 | SyntaxKind::TokenMinus
64 | SyntaxKind::TokenMul
65 | SyntaxKind::TokenDiv
66 | SyntaxKind::TokenMod
67 | SyntaxKind::TokenDot => text.bright_magenta(),
68 SyntaxKind::TokenLiteralNumber
69 | SyntaxKind::TokenFalse
70 | SyntaxKind::TokenTrue
71 | SyntaxKind::TokenShortString
72 | SyntaxKind::TokenString => text.bright_cyan(),
73 SyntaxKind::TokenExtern
74 | SyntaxKind::TokenType
75 | SyntaxKind::TokenFunction
76 | SyntaxKind::TokenModule
77 | SyntaxKind::TokenEnum
78 | SyntaxKind::TokenStruct
79 | SyntaxKind::TokenTrait
80 | SyntaxKind::TokenImpl => text.bright_blue(),
81 SyntaxKind::TokenOf
82 | SyntaxKind::TokenLet
83 | SyntaxKind::TokenReturn
84 | SyntaxKind::TokenMatch
85 | SyntaxKind::TokenIf
86 | SyntaxKind::TokenElse
87 | SyntaxKind::TokenUse
88 | SyntaxKind::TokenImplicits
89 | SyntaxKind::TokenRef
90 | SyntaxKind::TokenMut
91 | SyntaxKind::TokenNoPanic => text.bright_blue(),
92 SyntaxKind::TokenArrow
93 | SyntaxKind::TokenMatchArrow
94 | SyntaxKind::TokenColon
95 | SyntaxKind::TokenColonColon
96 | SyntaxKind::TokenDotDot
97 | SyntaxKind::TokenSemicolon
98 | SyntaxKind::TokenAnd
99 | SyntaxKind::TokenAndAnd
100 | SyntaxKind::TokenOr
101 | SyntaxKind::TokenOrOr
102 | SyntaxKind::TokenXor
103 | SyntaxKind::TokenNot
104 | SyntaxKind::TokenQuestionMark
105 | SyntaxKind::TokenUnderscore
106 | SyntaxKind::TokenHash => text.truecolor(255, 180, 255), SyntaxKind::TokenEq
108 | SyntaxKind::TokenEqEq
109 | SyntaxKind::TokenGE
110 | SyntaxKind::TokenGT
111 | SyntaxKind::TokenLE
112 | SyntaxKind::TokenLT
113 | SyntaxKind::TokenNeq => {
114 text.truecolor(255, 165, 0) }
116 SyntaxKind::TokenLBrace
117 | SyntaxKind::TokenRBrace
118 | SyntaxKind::TokenLBrack
119 | SyntaxKind::TokenRBrack
120 | SyntaxKind::TokenLParen
121 | SyntaxKind::TokenRParen
122 | SyntaxKind::TokenComma => text.clear(),
123 SyntaxKind::TokenEndOfFile => text.clear(),
124 SyntaxKind::TokenBadCharacters => text.red(),
125 SyntaxKind::TokenMissing => text.clear(),
126 SyntaxKind::TokenSkipped => text.on_red(), SyntaxKind::TokenSingleLineComment
128 | SyntaxKind::TokenWhitespace
129 | SyntaxKind::TokenNewline
130 | SyntaxKind::TokenEmpty => text.clear(),
131 _ => panic!("Unexpected syntax kind: {kind:?}"),
133 }
134}
135
136pub fn print_colored(db: &dyn SyntaxGroup, syntax_root: &SyntaxNode, verbose: bool) -> String {
137 let mut printer = ColoredPrinter { db, verbose, result: "".to_string() };
138 printer.print(syntax_root);
139 printer.result
140}