raldred-coderay 0.9.0 → 0.9.339

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (58) hide show
  1. data/lib/README +128 -0
  2. data/lib/coderay.rb +319 -0
  3. data/lib/coderay/duo.rb +85 -0
  4. data/lib/coderay/encoder.rb +187 -0
  5. data/lib/coderay/encoders/_map.rb +9 -0
  6. data/lib/coderay/encoders/count.rb +21 -0
  7. data/lib/coderay/encoders/debug.rb +49 -0
  8. data/lib/coderay/encoders/div.rb +20 -0
  9. data/lib/coderay/encoders/html.rb +306 -0
  10. data/lib/coderay/encoders/html/css.rb +70 -0
  11. data/lib/coderay/encoders/html/numerization.rb +133 -0
  12. data/lib/coderay/encoders/html/output.rb +206 -0
  13. data/lib/coderay/encoders/json.rb +19 -0
  14. data/lib/coderay/encoders/null.rb +26 -0
  15. data/lib/coderay/encoders/page.rb +21 -0
  16. data/lib/coderay/encoders/span.rb +20 -0
  17. data/lib/coderay/encoders/statistic.rb +77 -0
  18. data/lib/coderay/encoders/term.rb +114 -0
  19. data/lib/coderay/encoders/text.rb +32 -0
  20. data/lib/coderay/encoders/tokens.rb +44 -0
  21. data/lib/coderay/encoders/xml.rb +71 -0
  22. data/lib/coderay/encoders/yaml.rb +22 -0
  23. data/lib/coderay/for_redcloth.rb +73 -0
  24. data/lib/coderay/helpers/file_type.rb +226 -0
  25. data/lib/coderay/helpers/gzip_simple.rb +123 -0
  26. data/lib/coderay/helpers/plugin.rb +339 -0
  27. data/lib/coderay/helpers/word_list.rb +124 -0
  28. data/lib/coderay/scanner.rb +271 -0
  29. data/lib/coderay/scanners/_map.rb +21 -0
  30. data/lib/coderay/scanners/c.rb +166 -0
  31. data/lib/coderay/scanners/css.rb +202 -0
  32. data/lib/coderay/scanners/debug.rb +61 -0
  33. data/lib/coderay/scanners/delphi.rb +150 -0
  34. data/lib/coderay/scanners/diff.rb +104 -0
  35. data/lib/coderay/scanners/groovy.rb +271 -0
  36. data/lib/coderay/scanners/html.rb +175 -0
  37. data/lib/coderay/scanners/java.rb +173 -0
  38. data/lib/coderay/scanners/java/builtin_types.rb +419 -0
  39. data/lib/coderay/scanners/java_script.rb +195 -0
  40. data/lib/coderay/scanners/json.rb +107 -0
  41. data/lib/coderay/scanners/nitro_xhtml.rb +132 -0
  42. data/lib/coderay/scanners/php.rb +404 -0
  43. data/lib/coderay/scanners/plaintext.rb +18 -0
  44. data/lib/coderay/scanners/python.rb +232 -0
  45. data/lib/coderay/scanners/rhtml.rb +71 -0
  46. data/lib/coderay/scanners/ruby.rb +386 -0
  47. data/lib/coderay/scanners/ruby/patterns.rb +232 -0
  48. data/lib/coderay/scanners/scheme.rb +142 -0
  49. data/lib/coderay/scanners/sql.rb +162 -0
  50. data/lib/coderay/scanners/xml.rb +17 -0
  51. data/lib/coderay/scanners/yaml.rb +142 -0
  52. data/lib/coderay/style.rb +20 -0
  53. data/lib/coderay/styles/_map.rb +7 -0
  54. data/lib/coderay/styles/cycnus.rb +151 -0
  55. data/lib/coderay/styles/murphy.rb +132 -0
  56. data/lib/coderay/token_classes.rb +86 -0
  57. data/lib/coderay/tokens.rb +387 -0
  58. metadata +59 -1
@@ -0,0 +1,187 @@
1
+ require "stringio"
2
+
3
+ module CodeRay
4
+
5
+ # This module holds the Encoder class and its subclasses.
6
+ # For example, the HTML encoder is named CodeRay::Encoders::HTML
7
+ # can be found in coderay/encoders/html.
8
+ #
9
+ # Encoders also provides methods and constants for the register
10
+ # mechanism and the [] method that returns the Encoder class
11
+ # belonging to the given format.
12
+ module Encoders
13
+ extend PluginHost
14
+ plugin_path File.dirname(__FILE__), 'encoders'
15
+
16
+ # = Encoder
17
+ #
18
+ # The Encoder base class. Together with Scanner and
19
+ # Tokens, it forms the highlighting triad.
20
+ #
21
+ # Encoder instances take a Tokens object and do something with it.
22
+ #
23
+ # The most common Encoder is surely the HTML encoder
24
+ # (CodeRay::Encoders::HTML). It highlights the code in a colorful
25
+ # html page.
26
+ # If you want the highlighted code in a div or a span instead,
27
+ # use its subclasses Div and Span.
28
+ class Encoder
29
+ extend Plugin
30
+ plugin_host Encoders
31
+
32
+ attr_reader :token_stream
33
+
34
+ class << self
35
+
36
+ # Returns if the Encoder can be used in streaming mode.
37
+ def streamable?
38
+ is_a? Streamable
39
+ end
40
+
41
+ # If FILE_EXTENSION isn't defined, this method returns the
42
+ # downcase class name instead.
43
+ def const_missing sym
44
+ if sym == :FILE_EXTENSION
45
+ plugin_id
46
+ else
47
+ super
48
+ end
49
+ end
50
+
51
+ end
52
+
53
+ # Subclasses are to store their default options in this constant.
54
+ DEFAULT_OPTIONS = { :stream => false }
55
+
56
+ # The options you gave the Encoder at creating.
57
+ attr_accessor :options
58
+
59
+ # Creates a new Encoder.
60
+ # +options+ is saved and used for all encode operations, as long
61
+ # as you don't overwrite it there by passing additional options.
62
+ #
63
+ # Encoder objects provide three encode methods:
64
+ # - encode simply takes a +code+ string and a +lang+
65
+ # - encode_tokens expects a +tokens+ object instead
66
+ # - encode_stream is like encode, but uses streaming mode.
67
+ #
68
+ # Each method has an optional +options+ parameter. These are
69
+ # added to the options you passed at creation.
70
+ def initialize options = {}
71
+ @options = self.class::DEFAULT_OPTIONS.merge options
72
+ raise "I am only the basic Encoder class. I can't encode "\
73
+ "anything. :( Use my subclasses." if self.class == Encoder
74
+ end
75
+
76
+ # Encode a Tokens object.
77
+ def encode_tokens tokens, options = {}
78
+ options = @options.merge options
79
+ setup options
80
+ compile tokens, options
81
+ finish options
82
+ end
83
+
84
+ # Encode the given +code+ after tokenizing it using the Scanner
85
+ # for +lang+.
86
+ def encode code, lang, options = {}
87
+ options = @options.merge options
88
+ scanner_options = CodeRay.get_scanner_options(options)
89
+ tokens = CodeRay.scan code, lang, scanner_options
90
+ encode_tokens tokens, options
91
+ end
92
+
93
+ # You can use highlight instead of encode, if that seems
94
+ # more clear to you.
95
+ alias highlight encode
96
+
97
+ # Encode the given +code+ using the Scanner for +lang+ in
98
+ # streaming mode.
99
+ def encode_stream code, lang, options = {}
100
+ raise NotStreamableError, self unless kind_of? Streamable
101
+ options = @options.merge options
102
+ setup options
103
+ scanner_options = CodeRay.get_scanner_options options
104
+ @token_stream =
105
+ CodeRay.scan_stream code, lang, scanner_options, &self
106
+ finish options
107
+ end
108
+
109
+ # Behave like a proc. The token method is converted to a proc.
110
+ def to_proc
111
+ method(:token).to_proc
112
+ end
113
+
114
+ # Return the default file extension for outputs of this encoder.
115
+ def file_extension
116
+ self.class::FILE_EXTENSION
117
+ end
118
+
119
+ protected
120
+
121
+ # Called with merged options before encoding starts.
122
+ # Sets @out to an empty string.
123
+ #
124
+ # See the HTML Encoder for an example of option caching.
125
+ def setup options
126
+ @out = ''
127
+ end
128
+
129
+ # Called with +text+ and +kind+ of the currently scanned token.
130
+ # For simple scanners, it's enougth to implement this method.
131
+ #
132
+ # By default, it calls text_token or block_token, depending on
133
+ # whether +text+ is a String.
134
+ def token text, kind
135
+ out =
136
+ if text.is_a? ::String
137
+ text_token text, kind
138
+ elsif text.is_a? ::Symbol
139
+ block_token text, kind
140
+ else
141
+ raise 'Unknown token text type: %p' % text
142
+ end
143
+ @out << out if defined?(@out) && @out
144
+ end
145
+
146
+ def text_token text, kind
147
+ end
148
+
149
+ def block_token action, kind
150
+ case action
151
+ when :open
152
+ open_token kind
153
+ when :close
154
+ close_token kind
155
+ when :begin_line
156
+ begin_line kind
157
+ when :end_line
158
+ end_line kind
159
+ else
160
+ raise 'unknown block action: %p' % action
161
+ end
162
+ end
163
+
164
+ # Called with merged options after encoding starts.
165
+ # The return value is the result of encoding, typically @out.
166
+ def finish options
167
+ @out
168
+ end
169
+
170
+ # Do the encoding.
171
+ #
172
+ # The already created +tokens+ object must be used; it can be a
173
+ # TokenStream or a Tokens object.
174
+ if RUBY_VERSION >= '1.9'
175
+ def compile tokens, options
176
+ tokens.each { |text, kind| token text, kind } # FIXME for Ruby 1.9?
177
+ end
178
+ else
179
+ def compile tokens, options
180
+ tokens.each(&self)
181
+ end
182
+ end
183
+
184
+ end
185
+
186
+ end
187
+ end
@@ -0,0 +1,9 @@
1
+ module CodeRay
2
+ module Encoders
3
+
4
+ map :stats => :statistic,
5
+ :plain => :text,
6
+ :tex => :latex
7
+
8
+ end
9
+ end
@@ -0,0 +1,21 @@
1
+ module CodeRay
2
+ module Encoders
3
+
4
+ class Count < Encoder
5
+
6
+ include Streamable
7
+ register_for :count
8
+
9
+ protected
10
+
11
+ def setup options
12
+ @out = 0
13
+ end
14
+
15
+ def token text, kind
16
+ @out += 1
17
+ end
18
+ end
19
+
20
+ end
21
+ end
@@ -0,0 +1,49 @@
1
+ module CodeRay
2
+ module Encoders
3
+
4
+ # = Debug Encoder
5
+ #
6
+ # Fast encoder producing simple debug output.
7
+ #
8
+ # It is readable and diff-able and is used for testing.
9
+ #
10
+ # You cannot fully restore the tokens information from the
11
+ # output, because consecutive :space tokens are merged.
12
+ # Use Tokens#dump for caching purposes.
13
+ class Debug < Encoder
14
+
15
+ include Streamable
16
+ register_for :debug
17
+
18
+ FILE_EXTENSION = 'raydebug'
19
+
20
+ protected
21
+ def text_token text, kind
22
+ if kind == :space
23
+ text
24
+ else
25
+ text = text.gsub(/[)\\]/, '\\\\\0') # escape ) and \
26
+ "#{kind}(#{text})"
27
+ end
28
+ end
29
+
30
+ def open_token kind
31
+ "#{kind}<"
32
+ end
33
+
34
+ def close_token kind
35
+ ">"
36
+ end
37
+
38
+ def begin_line kind
39
+ "#{kind}["
40
+ end
41
+
42
+ def end_line kind
43
+ "]"
44
+ end
45
+
46
+ end
47
+
48
+ end
49
+ end
@@ -0,0 +1,20 @@
1
+ module CodeRay
2
+ module Encoders
3
+
4
+ load :html
5
+
6
+ class Div < HTML
7
+
8
+ FILE_EXTENSION = 'div.html'
9
+
10
+ register_for :div
11
+
12
+ DEFAULT_OPTIONS = HTML::DEFAULT_OPTIONS.merge({
13
+ :css => :style,
14
+ :wrap => :div,
15
+ })
16
+
17
+ end
18
+
19
+ end
20
+ end
@@ -0,0 +1,306 @@
1
+ require "set"
2
+
3
+ module CodeRay
4
+ module Encoders
5
+
6
+ # = HTML Encoder
7
+ #
8
+ # This is CodeRay's most important highlighter:
9
+ # It provides save, fast XHTML generation and CSS support.
10
+ #
11
+ # == Usage
12
+ #
13
+ # require 'coderay'
14
+ # puts CodeRay.scan('Some /code/', :ruby).html #-> a HTML page
15
+ # puts CodeRay.scan('Some /code/', :ruby).html(:wrap => :span)
16
+ # #-> <span class="CodeRay"><span class="co">Some</span> /code/</span>
17
+ # puts CodeRay.scan('Some /code/', :ruby).span #-> the same
18
+ #
19
+ # puts CodeRay.scan('Some code', :ruby).html(
20
+ # :wrap => nil,
21
+ # :line_numbers => :inline,
22
+ # :css => :style
23
+ # )
24
+ # #-> <span class="no">1</span> <span style="color:#036; font-weight:bold;">Some</span> code
25
+ #
26
+ # == Options
27
+ #
28
+ # === :tab_width
29
+ # Convert \t characters to +n+ spaces (a number.)
30
+ # Default: 8
31
+ #
32
+ # === :css
33
+ # How to include the styles; can be :class or :style.
34
+ #
35
+ # Default: :class
36
+ #
37
+ # === :wrap
38
+ # Wrap in :page, :div, :span or nil.
39
+ #
40
+ # You can also use Encoders::Div and Encoders::Span.
41
+ #
42
+ # Default: nil
43
+ #
44
+ # === :title
45
+ #
46
+ # The title of the HTML page (works only when :wrap is set to :page.)
47
+ #
48
+ # Default: 'CodeRay output'
49
+ #
50
+ # === :line_numbers
51
+ # Include line numbers in :table, :inline, :list or nil (no line numbers)
52
+ #
53
+ # Default: nil
54
+ #
55
+ # === :line_number_start
56
+ # Where to start with line number counting.
57
+ #
58
+ # Default: 1
59
+ #
60
+ # === :bold_every
61
+ # Make every +n+-th number appear bold.
62
+ #
63
+ # Default: 10
64
+ #
65
+ # === :highlight_lines
66
+ #
67
+ # Highlights certain line numbers now by using the :highlight_lines option.
68
+ # Can be any Enumerable, typically just an Array or Range, of numbers.
69
+ #
70
+ # Bolding is deactivated when :highlight_lines is set. It only makes sense
71
+ # in combination with :line_numbers.
72
+ #
73
+ # Default: nil
74
+ #
75
+ # === :hint
76
+ # Include some information into the output using the title attribute.
77
+ # Can be :info (show token type on mouse-over), :info_long (with full path)
78
+ # or :debug (via inspect).
79
+ #
80
+ # Default: false
81
+ class HTML < Encoder
82
+
83
+ include Streamable
84
+ register_for :html
85
+
86
+ FILE_EXTENSION = 'html'
87
+
88
+ DEFAULT_OPTIONS = {
89
+ :tab_width => 8,
90
+
91
+ :level => :xhtml,
92
+ :css => :class,
93
+
94
+ :style => :cycnus,
95
+ :wrap => nil,
96
+ :title => 'CodeRay output',
97
+
98
+ :line_numbers => nil,
99
+ :line_number_start => 1,
100
+ :bold_every => 10,
101
+ :highlight_lines => nil,
102
+
103
+ :hint => false,
104
+ }
105
+
106
+ helper :output, :css
107
+
108
+ attr_reader :css
109
+
110
+ protected
111
+
112
+ HTML_ESCAPE = { #:nodoc:
113
+ '&' => '&amp;',
114
+ '"' => '&quot;',
115
+ '>' => '&gt;',
116
+ '<' => '&lt;',
117
+ }
118
+
119
+ # This was to prevent illegal HTML.
120
+ # Strange chars should still be avoided in codes.
121
+ evil_chars = Array(0x00...0x20) - [?\n, ?\t, ?\s]
122
+ evil_chars.each { |i| HTML_ESCAPE[i.chr] = ' ' }
123
+ #ansi_chars = Array(0x7f..0xff)
124
+ #ansi_chars.each { |i| HTML_ESCAPE[i.chr] = '&#%d;' % i }
125
+ # \x9 (\t) and \xA (\n) not included
126
+ #HTML_ESCAPE_PATTERN = /[\t&"><\0-\x8\xB-\x1f\x7f-\xff]/
127
+ HTML_ESCAPE_PATTERN = /[\t"&><\0-\x8\xB-\x1f]/
128
+
129
+ TOKEN_KIND_TO_INFO = Hash.new { |h, kind|
130
+ h[kind] =
131
+ case kind
132
+ when :pre_constant
133
+ 'Predefined constant'
134
+ else
135
+ kind.to_s.gsub(/_/, ' ').gsub(/\b\w/) { $&.capitalize }
136
+ end
137
+ }
138
+
139
+ TRANSPARENT_TOKEN_KINDS = [
140
+ :delimiter, :modifier, :content, :escape, :inline_delimiter,
141
+ ].to_set
142
+
143
+ # Generate a hint about the given +classes+ in a +hint+ style.
144
+ #
145
+ # +hint+ may be :info, :info_long or :debug.
146
+ def self.token_path_to_hint hint, classes
147
+ title =
148
+ case hint
149
+ when :info
150
+ TOKEN_KIND_TO_INFO[classes.first]
151
+ when :info_long
152
+ classes.reverse.map { |kind| TOKEN_KIND_TO_INFO[kind] }.join('/')
153
+ when :debug
154
+ classes.inspect
155
+ end
156
+ title ? " title=\"#{title}\"" : ''
157
+ end
158
+
159
+ def setup options
160
+ super
161
+
162
+ @HTML_ESCAPE = HTML_ESCAPE.dup
163
+ @HTML_ESCAPE["\t"] = ' ' * options[:tab_width]
164
+
165
+ @opened = [nil]
166
+ @css = CSS.new options[:style]
167
+
168
+ hint = options[:hint]
169
+ if hint and not [:debug, :info, :info_long].include? hint
170
+ raise ArgumentError, "Unknown value %p for :hint; \
171
+ expected :info, :debug, false, or nil." % hint
172
+ end
173
+
174
+ case options[:css]
175
+
176
+ when :class
177
+ @css_style = Hash.new do |h, k|
178
+ c = CodeRay::Tokens::ClassOfKind[k.first]
179
+ if c == :NO_HIGHLIGHT and not hint
180
+ h[k.dup] = false
181
+ else
182
+ title = if hint
183
+ HTML.token_path_to_hint(hint, k[1..-1] << k.first)
184
+ else
185
+ ''
186
+ end
187
+ if c == :NO_HIGHLIGHT
188
+ h[k.dup] = '<span%s>' % [title]
189
+ else
190
+ h[k.dup] = '<span%s class="%s">' % [title, c]
191
+ end
192
+ end
193
+ end
194
+
195
+ when :style
196
+ @css_style = Hash.new do |h, k|
197
+ if k.is_a? ::Array
198
+ styles = k.dup
199
+ else
200
+ styles = [k]
201
+ end
202
+ type = styles.first
203
+ classes = styles.map { |c| Tokens::ClassOfKind[c] }
204
+ if classes.first == :NO_HIGHLIGHT and not hint
205
+ h[k] = false
206
+ else
207
+ styles.shift if TRANSPARENT_TOKEN_KINDS.include? styles.first
208
+ title = HTML.token_path_to_hint hint, styles
209
+ style = @css[*classes]
210
+ h[k] =
211
+ if style
212
+ '<span%s style="%s">' % [title, style]
213
+ else
214
+ false
215
+ end
216
+ end
217
+ end
218
+
219
+ else
220
+ raise ArgumentError, "Unknown value %p for :css." % options[:css]
221
+
222
+ end
223
+ end
224
+
225
+ def finish options
226
+ not_needed = @opened.shift
227
+ @out << '</span>' * @opened.size
228
+ unless @opened.empty?
229
+ warn '%d tokens still open: %p' % [@opened.size, @opened]
230
+ end
231
+
232
+ @out.extend Output
233
+ @out.css = @css
234
+ @out.numerize! options[:line_numbers], options
235
+ @out.wrap! options[:wrap]
236
+ @out.apply_title! options[:title]
237
+
238
+ super
239
+ end
240
+
241
+ def token text, type = :plain
242
+ case text
243
+
244
+ when nil
245
+ # raise 'Token with nil as text was given: %p' % [[text, type]]
246
+
247
+ when String
248
+ if text =~ /#{HTML_ESCAPE_PATTERN}/o
249
+ text = text.gsub(/#{HTML_ESCAPE_PATTERN}/o) { |m| @HTML_ESCAPE[m] }
250
+ end
251
+ @opened[0] = type
252
+ if text != "\n" && style = @css_style[@opened]
253
+ @out << style << text << '</span>'
254
+ else
255
+ @out << text
256
+ end
257
+
258
+
259
+ # token groups, eg. strings
260
+ when :open
261
+ @opened[0] = type
262
+ @out << (@css_style[@opened] || '<span>')
263
+ @opened << type
264
+ when :close
265
+ if @opened.empty?
266
+ # nothing to close
267
+ else
268
+ if $DEBUG and (@opened.size == 1 or @opened.last != type)
269
+ raise 'Malformed token stream: Trying to close a token (%p) \
270
+ that is not open. Open are: %p.' % [type, @opened[1..-1]]
271
+ end
272
+ @out << '</span>'
273
+ @opened.pop
274
+ end
275
+
276
+ # whole lines to be highlighted, eg. a deleted line in a diff
277
+ when :begin_line
278
+ @opened[0] = type
279
+ if style = @css_style[@opened]
280
+ @out << style.sub('<span', '<div')
281
+ else
282
+ @out << '<div>'
283
+ end
284
+ @opened << type
285
+ when :end_line
286
+ if @opened.empty?
287
+ # nothing to close
288
+ else
289
+ if $DEBUG and (@opened.size == 1 or @opened.last != type)
290
+ raise 'Malformed token stream: Trying to close a line (%p) \
291
+ that is not open. Open are: %p.' % [type, @opened[1..-1]]
292
+ end
293
+ @out << '</div>'
294
+ @opened.pop
295
+ end
296
+
297
+ else
298
+ raise 'unknown token kind: %p' % [text]
299
+
300
+ end
301
+ end
302
+
303
+ end
304
+
305
+ end
306
+ end