v2 / cmd / tools / vdoc / highlight.v
166 lines · 161 sloc · 4.27 KB · 8e35f4d9848f7ad35d857a187dddbfd2eca5e19d
Raw
1module main
2
3import term
4import strings
5import v.scanner
6import v.ast
7import v.token
8import v.pref
9
10const highlight_builtin_types = ['bool', 'string', 'i8', 'i16', 'int', 'i64', 'i128', 'isize',
11 'byte', 'u8', 'u16', 'u32', 'u64', 'usize', 'u128', 'rune', 'f32', 'f64', 'byteptr', 'voidptr',
12 'any']
13
14fn color_highlight(code string, tb &ast.Table) string {
15 highlight_code := fn (tok token.Token, typ HighlightTokenTyp) string {
16 mut lit := ''
17 match typ {
18 .unone, .operator, .punctuation {
19 lit = tok.kind.str()
20 }
21 .string {
22 use_double_quote := tok.lit.contains("'") && !tok.lit.contains('"')
23 unescaped_val := tok.lit.replace('\\\\', '\x01').replace_each(["\\'", "'", '\\"',
24 '"'])
25 if use_double_quote {
26 s := unescaped_val.replace_each(['\x01', '\\\\', '"', '\\"'])
27 lit = term.yellow('"${s}"')
28 } else {
29 s := unescaped_val.replace_each(['\x01', '\\\\', "'", "\\'"])
30 lit = term.yellow("'${s}'")
31 }
32 }
33 .char {
34 lit = term.yellow('`${tok.lit}`')
35 }
36 .comment {
37 lit = if tok.lit != '' && tok.lit[0] == 1 {
38 term.gray('//${tok.lit[1..]}')
39 } else {
40 term.gray('//${tok.lit}')
41 }
42 }
43 .keyword {
44 lit = term.bright_blue(tok.lit)
45 }
46 .builtin, .symbol {
47 lit = term.green(tok.lit)
48 }
49 .function {
50 lit = term.cyan(tok.lit)
51 }
52 .number, .module_ {
53 lit = term.bright_blue(tok.lit)
54 }
55 .boolean {
56 lit = term.bright_magenta(tok.lit)
57 }
58 .none {
59 lit = term.red(tok.lit)
60 }
61 .prefix {
62 lit = term.magenta(tok.lit)
63 }
64 else {
65 lit = tok.lit
66 }
67 }
68
69 return lit
70 }
71 mut s := scanner.new_scanner(code, .parse_comments, &pref.Preferences{
72 is_fmt: true
73 })
74 mut prev_prev := token.Token{}
75 mut prev := token.Token{}
76 mut tok := s.scan()
77 mut next_tok := s.scan()
78 mut buf := strings.new_builder(200)
79 mut i := 0
80 for i < code.len {
81 if i == tok.pos {
82 mut tok_typ := HighlightTokenTyp.unone
83 match tok.kind {
84 .name {
85 if (tok.lit in highlight_builtin_types || tb.known_type(tok.lit))
86 && (next_tok.kind != .lpar || prev.kind !in [.key_fn, .rpar]) {
87 tok_typ = .builtin
88 } else if
89 (next_tok.kind in [.lcbr, .rpar, .eof, .name, .rcbr, .assign, .key_pub, .key_mut, .pipe, .comma, .comment, .lt, .lsbr]
90 && next_tok.lit !in highlight_builtin_types)
91 && (prev.kind in [.name, .amp, .lcbr, .rsbr, .key_type, .assign, .dot, .not, .question, .rpar, .key_struct, .key_enum, .pipe, .key_interface, .comment, .ellipsis, .comma]
92 && prev.lit !in highlight_builtin_types)
93 && ((tok.lit != '' && tok.lit[0].is_capital())
94 || prev_prev.lit in ['C', 'JS']) {
95 tok_typ = .symbol
96 } else if tok.lit[0].is_capital() && prev.kind == .lpar
97 && next_tok.kind == .comma {
98 tok_typ = .symbol
99 } else if next_tok.kind == .lpar
100 || (!(tok.lit != '' && tok.lit[0].is_capital())
101 && next_tok.kind in [.lt, .lsbr] && next_tok.pos == tok.pos + tok.lit.len) {
102 tok_typ = .function
103 } else if next_tok.kind == .dot {
104 if tok.lit in ['C', 'JS'] {
105 tok_typ = .prefix
106 } else {
107 if tok.lit != '' && tok.lit[0].is_capital() {
108 tok_typ = .symbol
109 } else {
110 tok_typ = .module_
111 }
112 }
113 } else if tok.lit in ['r', 'c'] && next_tok.kind == .string {
114 tok_typ = .prefix
115 } else {
116 tok_typ = .name
117 }
118 }
119 .comment {
120 tok_typ = .comment
121 }
122 .chartoken {
123 tok_typ = .char
124 }
125 .string {
126 tok_typ = .string
127 }
128 .number {
129 tok_typ = .number
130 }
131 .key_true, .key_false {
132 tok_typ = .boolean
133 }
134 .lpar, .lcbr, .rpar, .rcbr, .lsbr, .rsbr, .semicolon, .colon, .comma, .dot,
135 .dotdot, .ellipsis {
136 tok_typ = .punctuation
137 }
138 .key_none {
139 tok_typ = .none
140 }
141 else {
142 if token.is_key(tok.lit) || token.is_decl(tok.kind) {
143 tok_typ = .keyword
144 } else if tok.kind.is_assign() || tok.is_unary() || tok.kind.is_relational()
145 || tok.kind.is_infix() || tok.kind.is_postfix() {
146 tok_typ = .operator
147 }
148 }
149 }
150
151 buf.write_string(highlight_code(tok, tok_typ))
152 if prev_prev.kind == .eof || prev.kind == .eof || next_tok.kind == .eof {
153 break
154 }
155 prev_prev = prev
156 prev = tok
157 i = tok.pos + tok.len
158 tok = next_tok
159 next_tok = s.scan()
160 } else {
161 buf.write_u8(code[i])
162 i++
163 }
164 }
165 return buf.str()
166}
167