coderay 0.7.4.215 → 0.8.260

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 (47) hide show
  1. data/LICENSE +421 -257
  2. data/README +24 -13
  3. data/bin/coderay +9 -4
  4. data/lib/coderay.rb +19 -17
  5. data/lib/coderay/duo.rb +67 -9
  6. data/lib/coderay/encoder.rb +18 -9
  7. data/lib/coderay/encoders/_map.rb +2 -1
  8. data/lib/coderay/encoders/debug.rb +14 -11
  9. data/lib/coderay/encoders/html.rb +44 -17
  10. data/lib/coderay/encoders/html/css.rb +13 -8
  11. data/lib/coderay/encoders/html/numerization.rb +8 -6
  12. data/lib/coderay/encoders/html/output.rb +3 -1
  13. data/lib/coderay/encoders/statistic.rb +2 -6
  14. data/lib/coderay/encoders/text.rb +2 -3
  15. data/lib/coderay/encoders/tokens.rb +3 -3
  16. data/lib/coderay/encoders/xml.rb +1 -2
  17. data/lib/coderay/for_redcloth.rb +72 -0
  18. data/lib/coderay/helpers/file_type.rb +38 -9
  19. data/lib/coderay/helpers/gzip_simple.rb +1 -0
  20. data/lib/coderay/helpers/plugin.rb +15 -8
  21. data/lib/coderay/helpers/word_list.rb +4 -0
  22. data/lib/coderay/scanner.rb +30 -13
  23. data/lib/coderay/scanners/_map.rb +1 -1
  24. data/lib/coderay/scanners/c.rb +3 -1
  25. data/lib/coderay/scanners/css.rb +181 -0
  26. data/lib/coderay/scanners/debug.rb +1 -0
  27. data/lib/coderay/scanners/delphi.rb +1 -0
  28. data/lib/coderay/scanners/diff.rb +104 -0
  29. data/lib/coderay/scanners/java.rb +179 -0
  30. data/lib/coderay/scanners/java/builtin_types.rb +419 -0
  31. data/lib/coderay/scanners/java_script.rb +187 -0
  32. data/lib/coderay/scanners/json.rb +106 -0
  33. data/lib/coderay/scanners/nitro_xhtml.rb +5 -4
  34. data/lib/coderay/scanners/plaintext.rb +2 -0
  35. data/lib/coderay/scanners/rhtml.rb +2 -2
  36. data/lib/coderay/scanners/ruby.rb +64 -50
  37. data/lib/coderay/scanners/ruby/patterns.rb +15 -19
  38. data/lib/coderay/scanners/scheme.rb +142 -0
  39. data/lib/coderay/scanners/sql.Keith.rb +143 -0
  40. data/lib/coderay/scanners/sql.rb +154 -0
  41. data/lib/coderay/scanners/xml.rb +1 -0
  42. data/lib/coderay/styles/cycnus.rb +30 -9
  43. data/lib/coderay/styles/murphy.rb +15 -2
  44. data/lib/coderay/{encoders/html/classes.rb → token_classes.rb} +14 -9
  45. data/lib/coderay/tokens.rb +33 -14
  46. data/lib/term/ansicolor.rb +220 -0
  47. metadata +62 -44
@@ -34,9 +34,12 @@ module Encoders
34
34
  private
35
35
 
36
36
  CSS_CLASS_PATTERN = /
37
- ( (?: # $1 = classes
38
- \s* \. [-\w]+
39
- )+ )
37
+ ( # $1 = selectors
38
+ (?:
39
+ (?: \s* \. [-\w]+ )+
40
+ \s* ,?
41
+ )+
42
+ )
40
43
  \s* \{ \s*
41
44
  ( [^\}]+ )? # $2 = style
42
45
  \s* \} \s*
@@ -44,12 +47,14 @@ module Encoders
44
47
  ( . ) # $3 = error
45
48
  /mx
46
49
  def parse stylesheet
47
- stylesheet.scan CSS_CLASS_PATTERN do |classes, style, error|
50
+ stylesheet.scan CSS_CLASS_PATTERN do |selectors, style, error|
48
51
  raise "CSS parse error: '#{error.inspect}' not recognized" if error
49
- styles = classes.scan(/[-\w]+/)
50
- cl = styles.pop
51
- @classes[cl] ||= Hash.new
52
- @classes[cl][styles] = style.to_s.strip
52
+ for selector in selectors.split(',')
53
+ classes = selector.scan(/[-\w]+/)
54
+ cl = classes.pop
55
+ @classes[cl] ||= Hash.new
56
+ @classes[cl][classes] = style.to_s.strip.delete(' ').chomp(';')
57
+ end
53
58
  end
54
59
  end
55
60
 
@@ -51,12 +51,12 @@ module Encoders
51
51
  case mode
52
52
  when :inline
53
53
  max_width = (start + line_count).to_s.size
54
- line = start
54
+ line_number = start
55
55
  gsub!(/^/) do
56
- line_number = bolding.call line
57
- indent = ' ' * (max_width - line.to_s.size)
58
- res = "<span class=\"no\">#{indent}#{line_number}</span> "
59
- line += 1
56
+ line_number_text = bolding.call line_number
57
+ indent = ' ' * (max_width - line_number.to_s.size) # TODO: Optimize (10^x)
58
+ res = "<span class=\"no\">#{indent}#{line_number_text}</span> "
59
+ line_number += 1
60
60
  res
61
61
  end
62
62
 
@@ -71,6 +71,7 @@ module Encoders
71
71
  line_numbers.gsub!(/\n/) { "<tt>\n</tt>" }
72
72
 
73
73
  line_numbers_table_tpl = TABLE.apply('LINE_NUMBERS', line_numbers)
74
+ gsub!(/<\/div>\n/) { '</div>' }
74
75
  gsub!(/\n/) { "<tt>\n</tt>" }
75
76
  wrap_in! line_numbers_table_tpl
76
77
  @wrapped_in = :div
@@ -90,8 +91,9 @@ module Encoders
90
91
  end
91
92
  close = '</span>' * opened_tags.size
92
93
 
93
- "<li>#{open}#{line}#{close}</li>"
94
+ "<li>#{open}#{line}#{close}</li>\n"
94
95
  end
96
+ chomp!("\n")
95
97
  wrap_in! LIST
96
98
  @wrapped_in = :div
97
99
 
@@ -166,7 +166,9 @@ module Encoders
166
166
  # title="double click to expand"
167
167
 
168
168
  LIST = <<-`LIST`
169
- <ol class="CodeRay"><%CONTENT%></ol>
169
+ <ol class="CodeRay">
170
+ <%CONTENT%>
171
+ </ol>
170
172
  LIST
171
173
 
172
174
  PAGE = <<-`PAGE`
@@ -28,17 +28,13 @@ module Encoders
28
28
  @type_stats[kind].count += 1
29
29
  @type_stats[kind].size += text.size
30
30
  @type_stats['TOTAL'].size += text.size
31
+ @type_stats['TOTAL'].count += 1
31
32
  end
32
33
 
33
34
  # TODO Hierarchy handling
34
35
  def block_token action, kind
35
- #@content_type = kind
36
- @type_stats['open/close'].count += 1
37
- end
38
-
39
- def token text, kind
40
- super
41
36
  @type_stats['TOTAL'].count += 1
37
+ @type_stats['open/close'].count += 1
42
38
  end
43
39
 
44
40
  STATS = <<-STATS
@@ -14,13 +14,12 @@ module Encoders
14
14
 
15
15
  protected
16
16
  def setup options
17
- super
17
+ @out = ''
18
18
  @sep = options[:separator]
19
19
  end
20
20
 
21
21
  def token text, kind
22
- return unless text.respond_to? :to_str
23
- @out << text + @sep
22
+ @out << text + @sep if text.is_a? ::String
24
23
  end
25
24
 
26
25
  def finish options
@@ -33,9 +33,9 @@ module Encoders
33
33
 
34
34
  FILE_EXTENSION = 'tok'
35
35
 
36
- protected
37
- def token *args
38
- @out << CodeRay::Tokens.write_token(*args)
36
+ protected
37
+ def token text, kind
38
+ @out << CodeRay::Tokens.write_token(text, kind)
39
39
  end
40
40
 
41
41
  end
@@ -22,7 +22,6 @@ module Encoders
22
22
  protected
23
23
 
24
24
  def setup options
25
- @out = ''
26
25
  @doc = REXML::Document.new
27
26
  @doc << REXML::XMLDecl.new
28
27
  @tab_width = options[:tab_width]
@@ -33,7 +32,7 @@ module Encoders
33
32
  @doc.write @out, options[:pretty], options[:transitive], true
34
33
  @out
35
34
  end
36
-
35
+
37
36
  def text_token text, kind
38
37
  if kind == :space
39
38
  token = @node
@@ -0,0 +1,72 @@
1
+ module CodeRay # :nodoc:
2
+
3
+ # A little hack to enable CodeRay highlighting in RedCloth.
4
+ #
5
+ # Usage:
6
+ # require 'coderay'
7
+ # require 'coderay/for_redcloth'
8
+ # RedCloth.new('@[ruby]puts "Hello, World!"@').to_html
9
+ #
10
+ # Make sure you have RedCloth 4.0.3 activated, for example by calling
11
+ # require 'rubygems'
12
+ # before RedCloth is loaded and before calling CodeRay.for_redcloth.
13
+ module ForRedCloth
14
+
15
+ def self.install
16
+ gem 'RedCloth', '>= 4.0.3' rescue nil
17
+ require 'redcloth'
18
+ raise 'CodeRay.for_redcloth needs RedCloth 4.0.3 or later.' unless RedCloth::VERSION.to_s >= '4.0.3'
19
+ RedCloth::TextileDoc.send :include, ForRedCloth::TextileDoc
20
+ RedCloth::Formatters::HTML.module_eval do
21
+ def unescape(html)
22
+ replacements = {
23
+ '&amp;' => '&',
24
+ '&quot;' => '"',
25
+ '&gt;' => '>',
26
+ '&lt;' => '<',
27
+ }
28
+ html.gsub(/&(?:amp|quot|[gl]t);/) { |entity| replacements[entity] }
29
+ end
30
+ undef_method :code, :bc_open, :bc_close, :escape_pre
31
+ def code(opts) # :nodoc:
32
+ opts[:block] = true
33
+ if opts[:lang] && !filter_coderay
34
+ require 'coderay'
35
+ @in_bc ||= nil
36
+ format = @in_bc ? :div : :span
37
+ highlighted_code = CodeRay.encode opts[:text], opts[:lang], format, :stream => true
38
+ highlighted_code.sub!(/\A<(span|div)/) { |m| m + pba(@in_bc || opts) }
39
+ highlighted_code = unescape(highlighted_code) unless @in_bc
40
+ highlighted_code
41
+ else
42
+ "<code#{pba(opts)}>#{opts[:text]}</code>"
43
+ end
44
+ end
45
+ def bc_open(opts) # :nodoc:
46
+ opts[:block] = true
47
+ @in_bc = opts
48
+ opts[:lang] ? '' : "<pre#{pba(opts)}>"
49
+ end
50
+ def bc_close(opts) # :nodoc:
51
+ @in_bc = nil
52
+ opts[:lang] ? '' : "</pre>\n"
53
+ end
54
+ def escape_pre(text)
55
+ if @in_bc ||= nil
56
+ text
57
+ else
58
+ html_esc(text, :html_escape_preformatted)
59
+ end
60
+ end
61
+ end
62
+ end
63
+
64
+ module TextileDoc # :nodoc:
65
+ attr_accessor :filter_coderay
66
+ end
67
+
68
+ end
69
+
70
+ end
71
+
72
+ CodeRay::ForRedCloth.install
@@ -1,3 +1,6 @@
1
+ #!/usr/bin/env ruby
2
+ module CodeRay
3
+
1
4
  # = FileType
2
5
  #
3
6
  # A simple filetype recognizer.
@@ -31,12 +34,12 @@ module FileType
31
34
  # That means you can get filetypes from files that don't exist.
32
35
  def [] filename, read_shebang = false
33
36
  name = File.basename filename
34
- ext = File.extname name
35
- ext.sub!(/^\./, '') # delete the leading dot
37
+ ext = File.extname(name).sub(/^\./, '') # from last dot, delete the leading dot
38
+ ext2 = filename[/\.(.*)/, 1] # from first dot
36
39
 
37
40
  type =
38
- TypeFromExt[ext] ||
39
41
  TypeFromExt[ext.downcase] ||
42
+ (TypeFromExt[ext2.downcase] if ext2) ||
40
43
  TypeFromName[name] ||
41
44
  TypeFromName[name.downcase]
42
45
  type ||= shebang(filename) if read_shebang
@@ -47,8 +50,11 @@ module FileType
47
50
  def shebang filename
48
51
  begin
49
52
  File.open filename, 'r' do |f|
50
- first_line = f.gets
51
- first_line[TypeFromShebang]
53
+ if first_line = f.gets
54
+ if type = first_line[TypeFromShebang]
55
+ type.to_sym
56
+ end
57
+ end
52
58
  end
53
59
  rescue IOError
54
60
  nil
@@ -78,15 +84,20 @@ module FileType
78
84
  'rb' => :ruby,
79
85
  'rbw' => :ruby,
80
86
  'rake' => :ruby,
87
+ 'mab' => :ruby,
81
88
  'cpp' => :c,
82
89
  'c' => :c,
83
90
  'h' => :c,
91
+ 'js' => :java_script,
84
92
  'xml' => :xml,
85
93
  'htm' => :html,
86
94
  'html' => :html,
87
95
  'xhtml' => :xhtml,
88
96
  'raydebug' => :debug,
89
97
  'rhtml' => :rhtml,
98
+ 'html.erb' => :rhtml,
99
+ 'ss' => :scheme,
100
+ 'sch' => :scheme,
90
101
  'yaml' => :yaml,
91
102
  'yml' => :yaml,
92
103
  }
@@ -100,17 +111,20 @@ module FileType
100
111
 
101
112
  end
102
113
 
114
+ end
115
+
103
116
  if $0 == __FILE__
104
117
  $VERBOSE = true
105
- eval DATA.read, nil, $0, __LINE__+4
118
+ eval DATA.read, nil, $0, __LINE__ + 4
106
119
  end
107
120
 
108
121
  __END__
109
-
110
122
  require 'test/unit'
111
123
 
112
124
  class TC_FileType < Test::Unit::TestCase
113
-
125
+
126
+ include CodeRay
127
+
114
128
  def test_fetch
115
129
  assert_raise FileType::UnknownFileType do
116
130
  FileType.fetch ''
@@ -161,6 +175,7 @@ class TC_FileType < Test::Unit::TestCase
161
175
  assert_equal :xhtml, FileType['test.xhtml']
162
176
  assert_equal :xhtml, FileType['test.html.xhtml']
163
177
  assert_equal :rhtml, FileType['_form.rhtml']
178
+ assert_equal :rhtml, FileType['_form.html.erb']
164
179
  end
165
180
 
166
181
  def test_yaml
@@ -170,7 +185,7 @@ class TC_FileType < Test::Unit::TestCase
170
185
  assert_not_equal :yaml, FileType['YAML']
171
186
  end
172
187
 
173
- def test_shebang
188
+ def test_no_shebang
174
189
  dir = './test'
175
190
  if File.directory? dir
176
191
  Dir.chdir dir do
@@ -178,5 +193,19 @@ class TC_FileType < Test::Unit::TestCase
178
193
  end
179
194
  end
180
195
  end
196
+
197
+ def test_shebang_empty_file
198
+ require 'tmpdir'
199
+ tmpfile = File.join(Dir.tmpdir, 'bla')
200
+ File.open(tmpfile, 'w') { } # touch
201
+ assert_equal nil, FileType[tmpfile]
202
+ end
203
+
204
+ def test_shebang
205
+ require 'tmpdir'
206
+ tmpfile = File.join(Dir.tmpdir, 'bla')
207
+ File.open(tmpfile, 'w') { |f| f.puts '#!/usr/bin/env ruby' }
208
+ assert_equal :ruby, FileType[tmpfile, true]
209
+ end
181
210
 
182
211
  end
@@ -46,6 +46,7 @@ module GZip
46
46
  end
47
47
  end
48
48
 
49
+
49
50
  # String extensions to use the GZip module.
50
51
  #
51
52
  # The methods gzip and gunzip provide an even more simple
@@ -1,6 +1,8 @@
1
+ module CodeRay
2
+
1
3
  # = PluginHost
2
4
  #
3
- # $Id: plugin.rb 188 2006-10-17 11:18:01Z murphy $
5
+ # $Id: plugin.rb 255 2008-09-21 16:25:44Z murphy $
4
6
  #
5
7
  # A simple subclass plugin system.
6
8
  #
@@ -20,7 +22,7 @@
20
22
  #
21
23
  # Generators[:fancy] #-> FancyGenerator
22
24
  # # or
23
- # require_plugin 'Generators/fancy'
25
+ # CodeRay.require_plugin 'Generators/fancy'
24
26
  module PluginHost
25
27
 
26
28
  # Raised if Encoders::[] fails because:
@@ -133,9 +135,13 @@ module PluginHost
133
135
  # map :navy => :dark_blue
134
136
  # default :gray
135
137
  # end
136
- def default id
137
- id = validate_id id
138
- plugin_hash[nil] = id
138
+ def default id = nil
139
+ if id
140
+ id = validate_id id
141
+ plugin_hash[nil] = id
142
+ else
143
+ plugin_hash[nil]
144
+ end
139
145
  end
140
146
 
141
147
  # Every plugin must register itself for one or more
@@ -310,17 +316,18 @@ module Plugin
310
316
 
311
317
  end
312
318
 
313
-
314
319
  # Convenience method for plugin loading.
315
320
  # The syntax used is:
316
321
  #
317
- # require_plugin '<Host ID>/<Plugin ID>'
322
+ # CodeRay.require_plugin '<Host ID>/<Plugin ID>'
318
323
  #
319
324
  # Returns the loaded plugin.
320
- def require_plugin path
325
+ def self.require_plugin path
321
326
  host_id, plugin_id = path.split '/', 2
322
327
  host = PluginHost.host_by_id(host_id)
323
328
  raise PluginHost::HostNotFound,
324
329
  "No host for #{host_id.inspect} found." unless host
325
330
  host.load plugin_id
326
331
  end
332
+
333
+ end
@@ -1,3 +1,5 @@
1
+ module CodeRay
2
+
1
3
  # = WordList
2
4
  #
3
5
  # <b>A Hash subclass designed for mapping word lists to token types.</b>
@@ -117,3 +119,5 @@ class CaseIgnoringWordList < WordList
117
119
  end
118
120
 
119
121
  end
122
+
123
+ end
@@ -4,7 +4,7 @@ module CodeRay
4
4
 
5
5
  # = Scanners
6
6
  #
7
- # $Id: scanner.rb 174 2006-10-15 09:08:50Z murphy $
7
+ # $Id: scanner.rb 253 2008-09-16 22:07:44Z murphy $
8
8
  #
9
9
  # This module holds the Scanner class and its subclasses.
10
10
  # For example, the Ruby scanner is named CodeRay::Scanners::Ruby
@@ -66,7 +66,17 @@ module CodeRay
66
66
  end
67
67
 
68
68
  def normify code
69
- code = code.to_s.to_unix
69
+ code = code.to_s
70
+ code.force_encoding 'binary' if code.respond_to? :force_encoding
71
+ code.to_unix
72
+ end
73
+
74
+ def file_extension extension = nil
75
+ if extension
76
+ @file_extension = extension.to_s
77
+ else
78
+ @file_extension ||= plugin_id.to_s
79
+ end
70
80
  end
71
81
 
72
82
  end
@@ -117,9 +127,6 @@ module CodeRay
117
127
  setup
118
128
  end
119
129
 
120
- # More mnemonic accessor name for the input string.
121
- alias code string
122
-
123
130
  def reset
124
131
  super
125
132
  reset_instance
@@ -131,6 +138,10 @@ module CodeRay
131
138
  reset_instance
132
139
  end
133
140
 
141
+ # More mnemonic accessor name for the input string.
142
+ alias code string
143
+ alias code= string=
144
+
134
145
  # Scans the code and returns all tokens in a Tokens object.
135
146
  def tokenize new_string=nil, options = {}
136
147
  options = @options.merge(options)
@@ -148,6 +159,11 @@ module CodeRay
148
159
  def tokens
149
160
  @cached_tokens ||= tokenize
150
161
  end
162
+
163
+ # Whether the scanner is in streaming mode.
164
+ def streaming?
165
+ !!@options[:stream]
166
+ end
151
167
 
152
168
  # Traverses the tokens.
153
169
  def each &block
@@ -195,7 +211,7 @@ module CodeRay
195
211
  raise ScanError, <<-EOE % [
196
212
 
197
213
 
198
- ***ERROR in %s: %s
214
+ ***ERROR in %s: %s (after %d tokens)
199
215
 
200
216
  tokens:
201
217
  %s
@@ -211,13 +227,14 @@ surrounding code:
211
227
  ***ERROR***
212
228
 
213
229
  EOE
214
- File.basename(caller[0]),
215
- msg,
216
- tokens.last(10).map { |t| t.inspect }.join("\n"),
217
- line, pos,
218
- matched, state, bol?, eos?,
219
- string[pos-ambit,ambit],
220
- string[pos,ambit],
230
+ File.basename(caller[0]),
231
+ msg,
232
+ tokens.size,
233
+ tokens.last(10).map { |t| t.inspect }.join("\n"),
234
+ line, pos,
235
+ matched, state, bol?, eos?,
236
+ string[pos-ambit,ambit],
237
+ string[pos,ambit],
221
238
  ]
222
239
  end
223
240