To check out this repository please hg clone the following URL, or open the URL using EasyMercurial or your preferred Mercurial client.

Statistics Download as Zip
| Branch: | Tag: | Revision:

root / .svn / pristine / 89 / 896d2497486a7dfbefa5146aaa83a0fc9dd4aa0c.svn-base @ 1297:0a574315af3e

History | View | Annotate | Download (4.47 KB)

1
module CodeRay
2
  module Encoders
3
    
4
    # Outputs code highlighted for a color terminal.
5
    # 
6
    # Note: This encoder is in beta. It currently doesn't use the Styles.
7
    # 
8
    # Alias: +term+
9
    # 
10
    # == Authors & License
11
    # 
12
    # By Rob Aldred (http://robaldred.co.uk)
13
    # 
14
    # Based on idea by Nathan Weizenbaum (http://nex-3.com)
15
    # 
16
    # MIT License (http://www.opensource.org/licenses/mit-license.php)
17
    class Terminal < Encoder
18
      
19
      register_for :terminal
20
      
21
      TOKEN_COLORS = {
22
        :annotation => '35',
23
        :attribute_name => '33',
24
        :attribute_value => '31',
25
        :binary => '1;35',
26
        :char => {
27
          :self => '36', :delimiter => '34'
28
        },
29
        :class => '1;35',
30
        :class_variable => '36',
31
        :color => '32',
32
        :comment => '37',
33
        :complex => '34',
34
        :constant => ['34', '4'],
35
        :decoration => '35',
36
        :definition => '1;32',
37
        :directive => ['32', '4'],
38
        :doc => '46',
39
        :doctype => '1;30',
40
        :doc_string => ['31', '4'],
41
        :entity => '33',
42
        :error => ['1;33', '41'],
43
        :exception => '1;31',
44
        :float => '1;35',
45
        :function => '1;34',
46
        :global_variable => '42',
47
        :hex => '1;36',
48
        :include => '33',
49
        :integer => '1;34',
50
        :key => '35',
51
        :label => '1;15',
52
        :local_variable => '33',
53
        :octal => '1;35',
54
        :operator_name => '1;29',
55
        :predefined_constant => '1;36',
56
        :predefined_type => '1;30',
57
        :predefined => ['4', '1;34'],
58
        :preprocessor => '36',
59
        :pseudo_class => '34',
60
        :regexp => {
61
          :self => '31',
62
          :content => '31',
63
          :delimiter => '1;29',
64
          :modifier => '35',
65
          :function => '1;29'
66
        },
67
        :reserved => '1;31',
68
        :shell => {
69
          :self => '42',
70
          :content => '1;29',
71
          :delimiter => '37',
72
        },
73
        :string => {
74
          :self => '32',
75
          :modifier => '1;32',
76
          :escape => '1;36',
77
          :delimiter => '1;32',
78
        },
79
        :symbol => '1;32',
80
        :tag => '34',
81
        :type => '1;34',
82
        :value => '36',
83
        :variable => '34',
84
        
85
        :insert => '42',
86
        :delete => '41',
87
        :change => '44',
88
        :head => '45'
89
      }
90
      TOKEN_COLORS[:keyword] = TOKEN_COLORS[:reserved]
91
      TOKEN_COLORS[:method] = TOKEN_COLORS[:function]
92
      TOKEN_COLORS[:imaginary] = TOKEN_COLORS[:complex]
93
      TOKEN_COLORS[:begin_group] = TOKEN_COLORS[:end_group] =
94
        TOKEN_COLORS[:escape] = TOKEN_COLORS[:delimiter]
95
      
96
    protected
97
      
98
      def setup(options)
99
        super
100
        @opened = []
101
        @subcolors = nil
102
      end
103
      
104
    public
105
      
106
      def text_token text, kind
107
        if color = (@subcolors || TOKEN_COLORS)[kind]
108
          if Hash === color
109
            if color[:self]
110
              color = color[:self]
111
            else
112
              @out << text
113
              return
114
            end
115
          end
116
          
117
          @out << ansi_colorize(color)
118
          @out << text.gsub("\n", ansi_clear + "\n" + ansi_colorize(color))
119
          @out << ansi_clear
120
          @out << ansi_colorize(@subcolors[:self]) if @subcolors && @subcolors[:self]
121
        else
122
          @out << text
123
        end
124
      end
125
      
126
      def begin_group kind
127
        @opened << kind
128
        @out << open_token(kind)
129
      end
130
      alias begin_line begin_group
131
      
132
      def end_group kind
133
        if @opened.empty?
134
          # nothing to close
135
        else
136
          @opened.pop
137
          @out << ansi_clear
138
          @out << open_token(@opened.last)
139
        end
140
      end
141
      
142
      def end_line kind
143
        if @opened.empty?
144
          # nothing to close
145
        else
146
          @opened.pop
147
          # whole lines to be highlighted,
148
          # eg. added/modified/deleted lines in a diff
149
          @out << "\t" * 100 + ansi_clear
150
          @out << open_token(@opened.last)
151
        end
152
      end
153
      
154
    private
155
      
156
      def open_token kind
157
        if color = TOKEN_COLORS[kind]
158
          if Hash === color
159
            @subcolors = color
160
            ansi_colorize(color[:self]) if color[:self]
161
          else
162
            @subcolors = {}
163
            ansi_colorize(color)
164
          end
165
        else
166
          @subcolors = nil
167
          ''
168
        end
169
      end
170
      
171
      def ansi_colorize(color)
172
        Array(color).map { |c| "\e[#{c}m" }.join
173
      end
174
      def ansi_clear
175
        ansi_colorize(0)
176
      end
177
    end
178
  end
179
end