Chris@0
|
1 # encoders/term.rb
|
Chris@0
|
2 # By Rob Aldred (http://robaldred.co.uk)
|
Chris@0
|
3 # Based on idea by Nathan Weizenbaum (http://nex-3.com)
|
Chris@0
|
4 # MIT License (http://www.opensource.org/licenses/mit-license.php)
|
Chris@0
|
5 #
|
Chris@0
|
6 # A CodeRay encoder that outputs code highlighted for a color terminal.
|
Chris@0
|
7 # Check out http://robaldred.co.uk
|
Chris@0
|
8
|
Chris@0
|
9 module CodeRay
|
Chris@0
|
10 module Encoders
|
Chris@0
|
11 class Term < Encoder
|
Chris@0
|
12 register_for :term
|
Chris@0
|
13
|
Chris@0
|
14 TOKEN_COLORS = {
|
Chris@0
|
15 :annotation => '35',
|
Chris@0
|
16 :attribute_name => '33',
|
Chris@0
|
17 :attribute_name_fat => '33',
|
Chris@0
|
18 :attribute_value => '31',
|
Chris@0
|
19 :attribute_value_fat => '31',
|
Chris@0
|
20 :bin => '1;35',
|
Chris@0
|
21 :char => {:self => '36', :delimiter => '34'},
|
Chris@0
|
22 :class => '1;35',
|
Chris@0
|
23 :class_variable => '36',
|
Chris@0
|
24 :color => '32',
|
Chris@0
|
25 :comment => '37',
|
Chris@0
|
26 :complex => '34',
|
Chris@0
|
27 :constant => ['34', '4'],
|
Chris@0
|
28 :decoration => '35',
|
Chris@0
|
29 :definition => '1;32',
|
Chris@0
|
30 :directive => ['32', '4'],
|
Chris@0
|
31 :doc => '46',
|
Chris@0
|
32 :doctype => '1;30',
|
Chris@0
|
33 :doc_string => ['31', '4'],
|
Chris@0
|
34 :entity => '33',
|
Chris@0
|
35 :error => ['1;33', '41'],
|
Chris@0
|
36 :exception => '1;31',
|
Chris@0
|
37 :float => '1;35',
|
Chris@0
|
38 :function => '1;34',
|
Chris@0
|
39 :global_variable => '42',
|
Chris@0
|
40 :hex => '1;36',
|
Chris@0
|
41 :important => '1;31',
|
Chris@0
|
42 :include => '33',
|
Chris@0
|
43 :integer => '1;34',
|
Chris@0
|
44 :interpreted => '1;35',
|
Chris@0
|
45 :key => '35',
|
Chris@0
|
46 :label => '1;4',
|
Chris@0
|
47 :local_variable => '33',
|
Chris@0
|
48 :oct => '1;35',
|
Chris@0
|
49 :operator_name => '1;29',
|
Chris@0
|
50 :pre_constant => '1;36',
|
Chris@0
|
51 :pre_type => '1;30',
|
Chris@0
|
52 :predefined => ['4', '1;34'],
|
Chris@0
|
53 :preprocessor => '36',
|
Chris@0
|
54 :pseudo_class => '34',
|
Chris@0
|
55 :regexp => {
|
Chris@0
|
56 :content => '31',
|
Chris@0
|
57 :delimiter => '1;29',
|
Chris@0
|
58 :modifier => '35',
|
Chris@0
|
59 :function => '1;29'
|
Chris@0
|
60 },
|
Chris@0
|
61 :reserved => '1;31',
|
Chris@0
|
62 :shell => {
|
Chris@0
|
63 :self => '42',
|
Chris@0
|
64 :content => '1;29',
|
Chris@0
|
65 :delimiter => '37',
|
Chris@0
|
66 },
|
Chris@0
|
67 :string => {
|
Chris@0
|
68 :self => '32',
|
Chris@0
|
69 :modifier => '1;32',
|
Chris@0
|
70 :escape => '1;36',
|
Chris@0
|
71 :delimiter => '1;32',
|
Chris@0
|
72 },
|
Chris@0
|
73 :symbol => '1;32',
|
Chris@0
|
74 :tag => '34',
|
Chris@0
|
75 :tag_fat => '1;34',
|
Chris@0
|
76 :tag_special => ['34', '4'],
|
Chris@0
|
77 :type => '1;34',
|
Chris@0
|
78 :value => '36',
|
Chris@0
|
79 :variable => '34',
|
Chris@0
|
80 :insert => '42',
|
Chris@0
|
81 :delete => '41',
|
Chris@0
|
82 :change => '44',
|
Chris@0
|
83 :head => '45',
|
Chris@0
|
84 }
|
Chris@0
|
85 TOKEN_COLORS[:keyword] = TOKEN_COLORS[:reserved]
|
Chris@0
|
86 TOKEN_COLORS[:method] = TOKEN_COLORS[:function]
|
Chris@0
|
87 TOKEN_COLORS[:imaginary] = TOKEN_COLORS[:complex]
|
Chris@0
|
88 TOKEN_COLORS[:open] = TOKEN_COLORS[:close] = TOKEN_COLORS[:nesting_delimiter] = TOKEN_COLORS[:escape] = TOKEN_COLORS[:delimiter]
|
Chris@0
|
89
|
Chris@0
|
90 protected
|
Chris@0
|
91
|
Chris@0
|
92 def setup(options)
|
Chris@0
|
93 @out = ''
|
Chris@0
|
94 @opened = [nil]
|
Chris@0
|
95 @subcolors = nil
|
Chris@0
|
96 end
|
Chris@0
|
97
|
Chris@0
|
98 def finish(options)
|
Chris@0
|
99 super
|
Chris@0
|
100 end
|
Chris@0
|
101
|
Chris@0
|
102 def token text, type = :plain
|
Chris@0
|
103 case text
|
Chris@0
|
104
|
Chris@0
|
105 when nil
|
Chris@0
|
106 # raise 'Token with nil as text was given: %p' % [[text, type]]
|
Chris@0
|
107
|
Chris@0
|
108 when String
|
Chris@0
|
109
|
Chris@0
|
110 if color = (@subcolors || TOKEN_COLORS)[type]
|
Chris@0
|
111 color = color[:self] || return if Hash === color
|
Chris@0
|
112
|
Chris@0
|
113 @out << col(color) + text.gsub("\n", col(0) + "\n" + col(color)) + col(0)
|
Chris@0
|
114 @out << col(@subcolors[:self]) if @subcolors && @subcolors[:self]
|
Chris@0
|
115 else
|
Chris@0
|
116 @out << text
|
Chris@0
|
117 end
|
Chris@0
|
118
|
Chris@0
|
119 # token groups, eg. strings
|
Chris@0
|
120 when :open
|
Chris@0
|
121 @opened[0] = type
|
Chris@0
|
122 if color = TOKEN_COLORS[type]
|
Chris@0
|
123 if Hash === color
|
Chris@0
|
124 @subcolors = color
|
Chris@0
|
125 @out << col(color[:self]) if color[:self]
|
Chris@0
|
126 else
|
Chris@0
|
127 @subcolors = {}
|
Chris@0
|
128 @out << col(color)
|
Chris@0
|
129 end
|
Chris@0
|
130 end
|
Chris@0
|
131 @opened << type
|
Chris@0
|
132 when :close
|
Chris@0
|
133 if @opened.empty?
|
Chris@0
|
134 # nothing to close
|
Chris@0
|
135 else
|
Chris@0
|
136 @out << col(0) if (@subcolors || {})[:self]
|
Chris@0
|
137 @subcolors = nil
|
Chris@0
|
138 @opened.pop
|
Chris@0
|
139 end
|
Chris@0
|
140
|
Chris@0
|
141 # whole lines to be highlighted, eg. a added/modified/deleted lines in a diff
|
Chris@0
|
142 when :begin_line
|
Chris@0
|
143
|
Chris@0
|
144 when :end_line
|
Chris@0
|
145
|
Chris@0
|
146 else
|
Chris@0
|
147 raise 'unknown token kind: %p' % [text]
|
Chris@0
|
148 end
|
Chris@0
|
149 end
|
Chris@0
|
150
|
Chris@0
|
151 private
|
Chris@0
|
152
|
Chris@0
|
153 def col(color)
|
Chris@0
|
154 Array(color).map { |c| "\e[#{c}m" }.join
|
Chris@0
|
155 end
|
Chris@0
|
156 end
|
Chris@0
|
157 end
|
Chris@0
|
158 end |