-
-
Notifications
You must be signed in to change notification settings - Fork 1.6k
/
colorize.cr
87 lines (77 loc) · 2.42 KB
/
colorize.cr
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
require "colorize"
require "../syntax_highlighter"
# A syntax highlighter that renders Crystal source code with ANSI escape codes
# suitable for terminal highlighting.
#
# ```
# code = %(foo = bar("baz\#{PI + 1}") # comment)
# colorized = Crystal::SyntaxHighlighter::Colorize.highlight(code)
# colorized # => "foo \e[91m=\e[0m bar(\e[93m\"baz\#{\e[0;36mPI\e[0;93m \e[0;91m+\e[0;93m \e[0;35m1\e[0;93m}\"\e[0m) \e[90m# comment\e[0m"
# ```
class Crystal::SyntaxHighlighter::Colorize < Crystal::SyntaxHighlighter
# Highlights *code* and writes the result to *io*.
def self.highlight(io : IO, code : String)
new(io).highlight(code)
end
# Highlights *code* and returns the result.
def self.highlight(code : String)
String.build do |io|
highlight(io, code)
end
end
# Highlights *code* or returns unhighlighted *code* on error.
#
# Same as `.highlight(code : String)` except that any error is rescued and
# returns unhighlighted source code.
def self.highlight!(code : String)
highlight(code)
rescue
code
end
# Creates a new instance of a Colorize syntax highlighter.
#
# Appends highlighted output (when calling `#highlight`) to *io*.
def initialize(@io : IO, @colorize : ::Colorize::Object(String) = ::Colorize.with.toggle(true))
end
property colors : Hash(TokenType, ::Colorize::Color) = {
:comment => :dark_gray,
:number => :magenta,
:char => :light_yellow,
:symbol => :magenta,
:string => :light_yellow,
:interpolation => :light_yellow,
:const => :cyan,
:operator => :light_red,
:ident => :light_green,
:keyword => :light_red,
:primitive_literal => :magenta,
:self => :blue,
} of TokenType => ::Colorize::Color
def render(type : TokenType, value : String)
colorize(type, value)
end
def render_delimiter(&)
@colorize.fore(colors[TokenType::STRING]).surround(@io) do
yield
end
end
def render_interpolation(&)
colorize :INTERPOLATION, "\#{"
yield
colorize :INTERPOLATION, "}"
end
def render_string_array(&)
@colorize.fore(colors[TokenType::STRING]).surround(@io) do
yield
end
end
private def colorize(type : TokenType, token)
if color = colors[type]?
@colorize.fore(color).surround(@io) do
@io << token
end
else
@io << token
end
end
end