coderay 0.7.4.215 → 0.8.260

Sign up to get free protection for your applications and to get access to all the features.
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