coderay-beta 0.9.1

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 (67) hide show
  1. data/FOLDERS +53 -0
  2. data/LICENSE +504 -0
  3. data/bin/coderay +82 -0
  4. data/bin/coderay_stylesheet +4 -0
  5. data/lib/README +129 -0
  6. data/lib/coderay.rb +320 -0
  7. data/lib/coderay/duo.rb +85 -0
  8. data/lib/coderay/encoder.rb +213 -0
  9. data/lib/coderay/encoders/_map.rb +11 -0
  10. data/lib/coderay/encoders/comment_filter.rb +43 -0
  11. data/lib/coderay/encoders/count.rb +21 -0
  12. data/lib/coderay/encoders/debug.rb +49 -0
  13. data/lib/coderay/encoders/div.rb +19 -0
  14. data/lib/coderay/encoders/filter.rb +75 -0
  15. data/lib/coderay/encoders/html.rb +305 -0
  16. data/lib/coderay/encoders/html/css.rb +70 -0
  17. data/lib/coderay/encoders/html/numerization.rb +133 -0
  18. data/lib/coderay/encoders/html/output.rb +206 -0
  19. data/lib/coderay/encoders/json.rb +69 -0
  20. data/lib/coderay/encoders/lines_of_code.rb +90 -0
  21. data/lib/coderay/encoders/null.rb +26 -0
  22. data/lib/coderay/encoders/page.rb +20 -0
  23. data/lib/coderay/encoders/span.rb +19 -0
  24. data/lib/coderay/encoders/statistic.rb +77 -0
  25. data/lib/coderay/encoders/term.rb +137 -0
  26. data/lib/coderay/encoders/text.rb +32 -0
  27. data/lib/coderay/encoders/token_class_filter.rb +84 -0
  28. data/lib/coderay/encoders/xml.rb +71 -0
  29. data/lib/coderay/encoders/yaml.rb +22 -0
  30. data/lib/coderay/for_redcloth.rb +85 -0
  31. data/lib/coderay/helpers/file_type.rb +240 -0
  32. data/lib/coderay/helpers/gzip_simple.rb +123 -0
  33. data/lib/coderay/helpers/plugin.rb +349 -0
  34. data/lib/coderay/helpers/word_list.rb +138 -0
  35. data/lib/coderay/scanner.rb +284 -0
  36. data/lib/coderay/scanners/_map.rb +23 -0
  37. data/lib/coderay/scanners/c.rb +203 -0
  38. data/lib/coderay/scanners/cpp.rb +228 -0
  39. data/lib/coderay/scanners/css.rb +210 -0
  40. data/lib/coderay/scanners/debug.rb +62 -0
  41. data/lib/coderay/scanners/delphi.rb +150 -0
  42. data/lib/coderay/scanners/diff.rb +105 -0
  43. data/lib/coderay/scanners/groovy.rb +263 -0
  44. data/lib/coderay/scanners/html.rb +182 -0
  45. data/lib/coderay/scanners/java.rb +176 -0
  46. data/lib/coderay/scanners/java/builtin_types.rb +419 -0
  47. data/lib/coderay/scanners/java_script.rb +224 -0
  48. data/lib/coderay/scanners/json.rb +112 -0
  49. data/lib/coderay/scanners/nitro_xhtml.rb +136 -0
  50. data/lib/coderay/scanners/php.rb +526 -0
  51. data/lib/coderay/scanners/plaintext.rb +21 -0
  52. data/lib/coderay/scanners/python.rb +285 -0
  53. data/lib/coderay/scanners/rhtml.rb +74 -0
  54. data/lib/coderay/scanners/ruby.rb +404 -0
  55. data/lib/coderay/scanners/ruby/patterns.rb +238 -0
  56. data/lib/coderay/scanners/scheme.rb +145 -0
  57. data/lib/coderay/scanners/sql.rb +162 -0
  58. data/lib/coderay/scanners/xml.rb +17 -0
  59. data/lib/coderay/scanners/yaml.rb +144 -0
  60. data/lib/coderay/style.rb +20 -0
  61. data/lib/coderay/styles/_map.rb +7 -0
  62. data/lib/coderay/styles/cycnus.rb +151 -0
  63. data/lib/coderay/styles/murphy.rb +132 -0
  64. data/lib/coderay/token_classes.rb +86 -0
  65. data/lib/coderay/tokens.rb +391 -0
  66. data/lib/term/ansicolor.rb +220 -0
  67. metadata +123 -0
@@ -0,0 +1,133 @@
1
+ module CodeRay
2
+ module Encoders
3
+
4
+ class HTML
5
+
6
+ module Output
7
+
8
+ def numerize *args
9
+ clone.numerize!(*args)
10
+ end
11
+
12
+ =begin NUMERIZABLE_WRAPPINGS = {
13
+ :table => [:div, :page, nil],
14
+ :inline => :all,
15
+ :list => [:div, :page, nil]
16
+ }
17
+ NUMERIZABLE_WRAPPINGS.default = :all
18
+ =end
19
+ def numerize! mode = :table, options = {}
20
+ return self unless mode
21
+
22
+ options = DEFAULT_OPTIONS.merge options
23
+
24
+ start = options[:line_number_start]
25
+ unless start.is_a? Integer
26
+ raise ArgumentError, "Invalid value %p for :line_number_start; Integer expected." % start
27
+ end
28
+
29
+ #allowed_wrappings = NUMERIZABLE_WRAPPINGS[mode]
30
+ #unless allowed_wrappings == :all or allowed_wrappings.include? options[:wrap]
31
+ # raise ArgumentError, "Can't numerize, :wrap must be in %p, but is %p" % [NUMERIZABLE_WRAPPINGS, options[:wrap]]
32
+ #end
33
+
34
+ bold_every = options[:bold_every]
35
+ highlight_lines = options[:highlight_lines]
36
+ bolding =
37
+ if bold_every == false && highlight_lines == nil
38
+ proc { |line| line.to_s }
39
+ elsif highlight_lines.is_a? Enumerable
40
+ highlight_lines = highlight_lines.to_set
41
+ proc do |line|
42
+ if highlight_lines.include? line
43
+ "<strong class=\"highlighted\">#{line}</strong>" # highlighted line numbers in bold
44
+ else
45
+ line.to_s
46
+ end
47
+ end
48
+ elsif bold_every.is_a? Integer
49
+ raise ArgumentError, ":bolding can't be 0." if bold_every == 0
50
+ proc do |line|
51
+ if line % bold_every == 0
52
+ "<strong>#{line}</strong>" # every bold_every-th number in bold
53
+ else
54
+ line.to_s
55
+ end
56
+ end
57
+ else
58
+ raise ArgumentError, 'Invalid value %p for :bolding; false or Integer expected.' % bold_every
59
+ end
60
+
61
+ case mode
62
+ when :inline
63
+ max_width = (start + line_count).to_s.size
64
+ line_number = start
65
+ gsub!(/^/) do
66
+ line_number_text = bolding.call line_number
67
+ indent = ' ' * (max_width - line_number.to_s.size) # TODO: Optimize (10^x)
68
+ res = "<span class=\"no\">#{indent}#{line_number_text}</span> "
69
+ line_number += 1
70
+ res
71
+ end
72
+
73
+ when :table
74
+ # This is really ugly.
75
+ # Because even monospace fonts seem to have different heights when bold,
76
+ # I make the newline bold, both in the code and the line numbers.
77
+ # FIXME Still not working perfect for Mr. Internet Exploder
78
+ line_numbers = (start ... start + line_count).to_a.map(&bolding).join("\n")
79
+ line_numbers << "\n" # also for Mr. MS Internet Exploder :-/
80
+ line_numbers.gsub!(/\n/) { "<tt>\n</tt>" }
81
+
82
+ line_numbers_table_tpl = TABLE.apply('LINE_NUMBERS', line_numbers)
83
+ gsub!(/<\/div>\n/) { '</div>' }
84
+ gsub!(/\n/) { "<tt>\n</tt>" }
85
+ wrap_in! line_numbers_table_tpl
86
+ @wrapped_in = :div
87
+
88
+ when :list
89
+ opened_tags = []
90
+ gsub!(/^.*$\n?/) do |line|
91
+ line.chomp!
92
+
93
+ open = opened_tags.join
94
+ line.scan(%r!<(/)?span[^>]*>?!) do |close,|
95
+ if close
96
+ opened_tags.pop
97
+ else
98
+ opened_tags << $&
99
+ end
100
+ end
101
+ close = '</span>' * opened_tags.size
102
+
103
+ "<li>#{open}#{line}#{close}</li>\n"
104
+ end
105
+ chomp!("\n")
106
+ wrap_in! LIST
107
+ @wrapped_in = :div
108
+
109
+ else
110
+ raise ArgumentError, 'Unknown value %p for mode: expected one of %p' %
111
+ [mode, [:table, :list, :inline]]
112
+ end
113
+
114
+ self
115
+ end
116
+
117
+ def line_count
118
+ line_count = count("\n")
119
+ position_of_last_newline = rindex(?\n)
120
+ if position_of_last_newline
121
+ after_last_newline = self[position_of_last_newline + 1 .. -1]
122
+ ends_with_newline = after_last_newline[/\A(?:<\/span>)*\z/]
123
+ line_count += 1 if not ends_with_newline
124
+ end
125
+ line_count
126
+ end
127
+
128
+ end
129
+
130
+ end
131
+
132
+ end
133
+ end
@@ -0,0 +1,206 @@
1
+ module CodeRay
2
+ module Encoders
3
+
4
+ class HTML
5
+
6
+ # This module is included in the output String from thew HTML Encoder.
7
+ #
8
+ # It provides methods like wrap, div, page etc.
9
+ #
10
+ # Remember to use #clone instead of #dup to keep the modules the object was
11
+ # extended with.
12
+ #
13
+ # TODO: more doc.
14
+ module Output
15
+
16
+ require 'coderay/encoders/html/numerization.rb'
17
+
18
+ attr_accessor :css
19
+
20
+ class << self
21
+
22
+ # This makes Output look like a class.
23
+ #
24
+ # Example:
25
+ #
26
+ # a = Output.new '<span class="co">Code</span>'
27
+ # a.wrap! :page
28
+ def new string, css = CSS.new, element = nil
29
+ output = string.clone.extend self
30
+ output.wrapped_in = element
31
+ output.css = css
32
+ output
33
+ end
34
+
35
+ # Raises an exception if an object that doesn't respond to to_str is extended by Output,
36
+ # to prevent users from misuse. Use Module#remove_method to disable.
37
+ def extended o
38
+ warn "The Output module is intended to extend instances of String, not #{o.class}." unless o.respond_to? :to_str
39
+ end
40
+
41
+ def make_stylesheet css, in_tag = false
42
+ sheet = css.stylesheet
43
+ sheet = <<-CSS if in_tag
44
+ <style type="text/css">
45
+ #{sheet}
46
+ </style>
47
+ CSS
48
+ sheet
49
+ end
50
+
51
+ def page_template_for_css css
52
+ sheet = make_stylesheet css
53
+ PAGE.apply 'CSS', sheet
54
+ end
55
+
56
+ # Define a new wrapper. This is meta programming.
57
+ def wrapper *wrappers
58
+ wrappers.each do |wrapper|
59
+ define_method wrapper do |*args|
60
+ wrap wrapper, *args
61
+ end
62
+ define_method "#{wrapper}!".to_sym do |*args|
63
+ wrap! wrapper, *args
64
+ end
65
+ end
66
+ end
67
+
68
+ end
69
+
70
+ wrapper :div, :span, :page
71
+
72
+ def wrapped_in? element
73
+ wrapped_in == element
74
+ end
75
+
76
+ def wrapped_in
77
+ @wrapped_in ||= nil
78
+ end
79
+ attr_writer :wrapped_in
80
+
81
+ def wrap_in template
82
+ clone.wrap_in! template
83
+ end
84
+
85
+ def wrap_in! template
86
+ Template.wrap! self, template, 'CONTENT'
87
+ self
88
+ end
89
+
90
+ def apply_title! title
91
+ self.sub!(/(<title>)(<\/title>)/) { $1 + title + $2 }
92
+ self
93
+ end
94
+
95
+ def wrap! element, *args
96
+ return self if not element or element == wrapped_in
97
+ case element
98
+ when :div
99
+ raise "Can't wrap %p in %p" % [wrapped_in, element] unless wrapped_in? nil
100
+ wrap_in! DIV
101
+ when :span
102
+ raise "Can't wrap %p in %p" % [wrapped_in, element] unless wrapped_in? nil
103
+ wrap_in! SPAN
104
+ when :page
105
+ wrap! :div if wrapped_in? nil
106
+ raise "Can't wrap %p in %p" % [wrapped_in, element] unless wrapped_in? :div
107
+ wrap_in! Output.page_template_for_css(@css)
108
+ if args.first.is_a?(Hash) && title = args.first[:title]
109
+ apply_title! title
110
+ end
111
+ self
112
+ when nil
113
+ return self
114
+ else
115
+ raise "Unknown value %p for :wrap" % element
116
+ end
117
+ @wrapped_in = element
118
+ self
119
+ end
120
+
121
+ def wrap *args
122
+ clone.wrap!(*args)
123
+ end
124
+
125
+ def stylesheet in_tag = false
126
+ Output.make_stylesheet @css, in_tag
127
+ end
128
+
129
+ class Template < String
130
+
131
+ def self.wrap! str, template, target
132
+ target = Regexp.new(Regexp.escape("<%#{target}%>"))
133
+ if template =~ target
134
+ str[0,0] = $`
135
+ str << $'
136
+ else
137
+ raise "Template target <%%%p%%> not found" % target
138
+ end
139
+ end
140
+
141
+ def apply target, replacement
142
+ target = Regexp.new(Regexp.escape("<%#{target}%>"))
143
+ if self =~ target
144
+ Template.new($` + replacement + $')
145
+ else
146
+ raise "Template target <%%%p%%> not found" % target
147
+ end
148
+ end
149
+
150
+ module Simple
151
+ def ` str #` <-- for stupid editors
152
+ Template.new str
153
+ end
154
+ end
155
+ end
156
+
157
+ extend Template::Simple
158
+
159
+ #-- don't include the templates in docu
160
+
161
+ SPAN = `<span class="CodeRay"><%CONTENT%></span>`
162
+
163
+ DIV = <<-`DIV`
164
+ <div class="CodeRay">
165
+ <div class="code"><pre><%CONTENT%></pre></div>
166
+ </div>
167
+ DIV
168
+
169
+ TABLE = <<-`TABLE`
170
+ <table class="CodeRay"><tr>
171
+ <td class="line_numbers" title="click to toggle" onclick="with (this.firstChild.style) { display = (display == '') ? 'none' : '' }"><pre><%LINE_NUMBERS%></pre></td>
172
+ <td class="code"><pre ondblclick="with (this.style) { overflow = (overflow == 'auto' || overflow == '') ? 'visible' : 'auto' }"><%CONTENT%></pre></td>
173
+ </tr></table>
174
+ TABLE
175
+ # title="double click to expand"
176
+
177
+ LIST = <<-`LIST`
178
+ <ol class="CodeRay">
179
+ <%CONTENT%>
180
+ </ol>
181
+ LIST
182
+
183
+ PAGE = <<-`PAGE`
184
+ <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
185
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
186
+ <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="de">
187
+ <head>
188
+ <meta http-equiv="content-type" content="text/html; charset=utf-8" />
189
+ <title></title>
190
+ <style type="text/css">
191
+ <%CSS%>
192
+ </style>
193
+ </head>
194
+ <body style="background-color: white;">
195
+
196
+ <%CONTENT%>
197
+ </body>
198
+ </html>
199
+ PAGE
200
+
201
+ end
202
+
203
+ end
204
+
205
+ end
206
+ end
@@ -0,0 +1,69 @@
1
+ ($:.unshift '../..'; require 'coderay') unless defined? CodeRay
2
+ module CodeRay
3
+ module Encoders
4
+
5
+ # = JSON Encoder
6
+ class JSON < Encoder
7
+
8
+ register_for :json
9
+ FILE_EXTENSION = 'json'
10
+
11
+ protected
12
+ def setup options
13
+ begin
14
+ require 'json'
15
+ rescue LoadError
16
+ require 'rubygems'
17
+ require 'json'
18
+ end
19
+ @out = []
20
+ end
21
+
22
+ def text_token text, kind
23
+ { :type => 'text', :text => text, :kind => kind }
24
+ end
25
+
26
+ def block_token action, kind
27
+ { :type => 'block', :action => action, :kind => kind }
28
+ end
29
+
30
+ def finish options
31
+ @out.to_json
32
+ end
33
+
34
+ end
35
+
36
+ end
37
+ end
38
+
39
+ if $0 == __FILE__
40
+ $VERBOSE = true
41
+ $: << File.join(File.dirname(__FILE__), '..')
42
+ eval DATA.read, nil, $0, __LINE__ + 4
43
+ end
44
+
45
+ __END__
46
+ require 'test/unit'
47
+ $:.delete '.'
48
+ require 'rubygems' if RUBY_VERSION < '1.9'
49
+
50
+ class JSONEncoderTest < Test::Unit::TestCase
51
+
52
+ def test_json_output
53
+ tokens = CodeRay.scan <<-RUBY, :ruby
54
+ puts "Hello world!"
55
+ RUBY
56
+ require 'json'
57
+ assert_equal [
58
+ {"type"=>"text", "text"=>"puts", "kind"=>"ident"},
59
+ {"type"=>"text", "text"=>" ", "kind"=>"space"},
60
+ {"type"=>"block", "action"=>"open", "kind"=>"string"},
61
+ {"type"=>"text", "text"=>"\"", "kind"=>"delimiter"},
62
+ {"type"=>"text", "text"=>"Hello world!", "kind"=>"content"},
63
+ {"type"=>"text", "text"=>"\"", "kind"=>"delimiter"},
64
+ {"type"=>"block", "action"=>"close", "kind"=>"string"},
65
+ {"type"=>"text", "text"=>"\n", "kind"=>"space"}
66
+ ], JSON.load(tokens.json)
67
+ end
68
+
69
+ end
@@ -0,0 +1,90 @@
1
+ ($:.unshift '../..'; require 'coderay') unless defined? CodeRay
2
+ module CodeRay
3
+ module Encoders
4
+
5
+ # Counts the LoC (Lines of Code). Returns an Integer >= 0.
6
+ #
7
+ # Alias: :loc
8
+ #
9
+ # Everything that is not comment, markup, doctype/shebang, or an empty line,
10
+ # is considered to be code.
11
+ #
12
+ # For example,
13
+ # * HTML files not containing JavaScript have 0 LoC
14
+ # * in a Java class without comments, LoC is the number of non-empty lines
15
+ #
16
+ # A Scanner class should define the token kinds that are not code in the
17
+ # KINDS_NOT_LOC constant, which defaults to [:comment, :doctype].
18
+ class LinesOfCode < Encoder
19
+
20
+ register_for :lines_of_code
21
+
22
+ NON_EMPTY_LINE = /^\s*\S.*$/
23
+
24
+ def compile tokens, options
25
+ if scanner = tokens.scanner
26
+ kinds_not_loc = scanner.class::KINDS_NOT_LOC
27
+ else
28
+ warn ArgumentError, 'Tokens have no scanner.' if $DEBUG
29
+ kinds_not_loc = CodeRay::Scanners::Scanner::KINDS_NOT_LOC
30
+ end
31
+ code = tokens.token_class_filter :exclude => kinds_not_loc
32
+ @loc = code.text.scan(NON_EMPTY_LINE).size
33
+ end
34
+
35
+ def finish options
36
+ @loc
37
+ end
38
+
39
+ end
40
+
41
+ end
42
+ end
43
+
44
+ if $0 == __FILE__
45
+ $VERBOSE = true
46
+ $: << File.join(File.dirname(__FILE__), '..')
47
+ eval DATA.read, nil, $0, __LINE__ + 4
48
+ end
49
+
50
+ __END__
51
+ require 'test/unit'
52
+
53
+ class LinesOfCodeTest < Test::Unit::TestCase
54
+
55
+ def test_creation
56
+ assert CodeRay::Encoders::LinesOfCode < CodeRay::Encoders::Encoder
57
+ filter = nil
58
+ assert_nothing_raised do
59
+ filter = CodeRay.encoder :loc
60
+ end
61
+ assert_kind_of CodeRay::Encoders::LinesOfCode, filter
62
+ assert_nothing_raised do
63
+ filter = CodeRay.encoder :lines_of_code
64
+ end
65
+ assert_kind_of CodeRay::Encoders::LinesOfCode, filter
66
+ end
67
+
68
+ def test_lines_of_code
69
+ tokens = CodeRay.scan <<-RUBY, :ruby
70
+ #!/usr/bin/env ruby
71
+
72
+ # a minimal Ruby program
73
+ puts "Hello world!"
74
+ RUBY
75
+ assert_equal 1, CodeRay::Encoders::LinesOfCode.new.encode_tokens(tokens)
76
+ assert_equal 1, tokens.lines_of_code
77
+ assert_equal 1, tokens.loc
78
+ end
79
+
80
+ def test_filtering_block_tokens
81
+ tokens = CodeRay::Tokens.new
82
+ tokens << ["Hello\n", :world]
83
+ tokens << ["Hello\n", :space]
84
+ tokens << ["Hello\n", :comment]
85
+ assert_equal 2, CodeRay::Encoders::LinesOfCode.new.encode_tokens(tokens)
86
+ assert_equal 2, tokens.lines_of_code
87
+ assert_equal 2, tokens.loc
88
+ end
89
+
90
+ end