coderay-beta 0.9.1

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