coderay 0.4.3.48
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.
- data/LICENSE +340 -0
- data/README +103 -0
- data/demo/demo_count.rb +10 -0
- data/demo/demo_css.rb +4 -0
- data/demo/demo_div.rb +19 -0
- data/demo/demo_dump.rb +15 -0
- data/demo/demo_encoder.rb +39 -0
- data/demo/demo_global_vars.rb +13 -0
- data/demo/demo_global_vars2.rb +28 -0
- data/demo/demo_html.rb +394 -0
- data/demo/demo_html2.rb +11 -0
- data/demo/demo_load_encoder.rb +17 -0
- data/demo/demo_more.rb +204 -0
- data/demo/demo_scanner.rb +36 -0
- data/demo/demo_server.rb +92 -0
- data/demo/demo_simple.rb +10 -0
- data/demo/demo_stream.rb +25 -0
- data/demo/demo_stream2.rb +8 -0
- data/demo/demo_tokens.rb +3 -0
- data/lib/coderay.rb +284 -0
- data/lib/coderay/encoder.rb +151 -0
- data/lib/coderay/encoders/count.rb +21 -0
- data/lib/coderay/encoders/div.rb +16 -0
- data/lib/coderay/encoders/helpers/html_css.rb +155 -0
- data/lib/coderay/encoders/helpers/html_helper.rb +68 -0
- data/lib/coderay/encoders/helpers/html_output.rb +237 -0
- data/lib/coderay/encoders/html.rb +169 -0
- data/lib/coderay/encoders/null.rb +20 -0
- data/lib/coderay/encoders/span.rb +16 -0
- data/lib/coderay/encoders/statistic.rb +74 -0
- data/lib/coderay/encoders/text.rb +33 -0
- data/lib/coderay/encoders/tokens.rb +44 -0
- data/lib/coderay/encoders/yaml.rb +19 -0
- data/lib/coderay/helpers/filetype.rb +145 -0
- data/lib/coderay/helpers/gzip_simple.rb +123 -0
- data/lib/coderay/helpers/plugin.rb +286 -0
- data/lib/coderay/helpers/scanner_helper.rb +63 -0
- data/lib/coderay/scanner.rb +197 -0
- data/lib/coderay/scanners/c.rb +147 -0
- data/lib/coderay/scanners/delphi.rb +123 -0
- data/lib/coderay/scanners/helpers/ruby_helper.rb +212 -0
- data/lib/coderay/scanners/plaintext.rb +13 -0
- data/lib/coderay/scanners/ruby.rb +337 -0
- data/lib/coderay/tokens.rb +324 -0
- metadata +89 -0
@@ -0,0 +1,169 @@
|
|
1
|
+
module CodeRay
|
2
|
+
module Encoders
|
3
|
+
|
4
|
+
class HTML < Encoder
|
5
|
+
|
6
|
+
include Streamable
|
7
|
+
register_for :html
|
8
|
+
|
9
|
+
FILE_EXTENSION = 'html'
|
10
|
+
|
11
|
+
DEFAULT_OPTIONS = {
|
12
|
+
:tab_width => 8,
|
13
|
+
|
14
|
+
:level => :xhtml,
|
15
|
+
:css => :class,
|
16
|
+
|
17
|
+
:wrap => :page,
|
18
|
+
|
19
|
+
:line_numbers => nil,
|
20
|
+
:line_number_start => 1,
|
21
|
+
:bold_every => 10,
|
22
|
+
}
|
23
|
+
NUMERIZABLE_WRAPPINGS = [:div, :page]
|
24
|
+
|
25
|
+
require 'coderay/encoders/helpers/html_helper'
|
26
|
+
require 'coderay/encoders/helpers/html_output'
|
27
|
+
require 'coderay/encoders/helpers/html_css'
|
28
|
+
|
29
|
+
def initialize(*)
|
30
|
+
super
|
31
|
+
@last_options = nil
|
32
|
+
end
|
33
|
+
|
34
|
+
protected
|
35
|
+
|
36
|
+
HTML_ESCAPE = { #:nodoc:
|
37
|
+
'&' => '&',
|
38
|
+
'"' => '"',
|
39
|
+
'>' => '>',
|
40
|
+
'<' => '<',
|
41
|
+
}
|
42
|
+
|
43
|
+
# This is to prevent illegal HTML.
|
44
|
+
# Strange chars should still be avoided in codes.
|
45
|
+
evil_chars = Array(0x00...0x20) - [?n, ?t]
|
46
|
+
evil_chars.each { |i| HTML_ESCAPE[i.chr] = ' ' }
|
47
|
+
ansi_chars = Array(0x7f..0xff)
|
48
|
+
ansi_chars.each { |i| HTML_ESCAPE[i.chr] = '&#%d;' % i }
|
49
|
+
# \x9 (\t) and \xA (\n) not included
|
50
|
+
HTML_ESCAPE_PATTERN = /[&"><\0-\x8\xB-\x1f\x7f-\xff]/
|
51
|
+
|
52
|
+
def setup options
|
53
|
+
if options[:line_numbers] and not NUMERIZABLE_WRAPPINGS.include? options[:wrap]
|
54
|
+
warn ':line_numbers wanted, but :wrap is %p' % options[:wrap]
|
55
|
+
end
|
56
|
+
super
|
57
|
+
return if options == @last_options
|
58
|
+
@last_options = options
|
59
|
+
|
60
|
+
@HTML_ESCAPE = HTML_ESCAPE.dup
|
61
|
+
@HTML_ESCAPE["\t"] = ' ' * options[:tab_width]
|
62
|
+
|
63
|
+
@opened = [nil]
|
64
|
+
@css = CSS.new
|
65
|
+
|
66
|
+
case options[:css]
|
67
|
+
|
68
|
+
when :class
|
69
|
+
@css_style = Hash.new do |h, k|
|
70
|
+
if k.is_a? Array
|
71
|
+
type = k.first
|
72
|
+
else
|
73
|
+
type = k
|
74
|
+
end
|
75
|
+
c = ClassOfKind[type]
|
76
|
+
if c == :NO_HIGHLIGHT
|
77
|
+
h[k] = false
|
78
|
+
else
|
79
|
+
if options[:debug]
|
80
|
+
debug_info = ' title="%p"' % [ k ]
|
81
|
+
else
|
82
|
+
debug_info = ''
|
83
|
+
end
|
84
|
+
h[k] = '<span%s class="%s">' % [debug_info, c]
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
when :style
|
89
|
+
@css_style = Hash.new do |h, k|
|
90
|
+
if k.is_a? Array
|
91
|
+
styles = k.dup
|
92
|
+
else
|
93
|
+
styles = [k]
|
94
|
+
end
|
95
|
+
styles.map! { |c| ClassOfKind[c] }
|
96
|
+
if styles.first == :NO_HIGHLIGHT
|
97
|
+
h[k] = false
|
98
|
+
else
|
99
|
+
if options[:debug]
|
100
|
+
debug_info = ' title="%s"' % [ styles.inspect.gsub(/#{HTML_ESCAPE_PATTERN}/o) { |m| @HTML_ESCAPE[m] } ]
|
101
|
+
else
|
102
|
+
debug_info = ''
|
103
|
+
end
|
104
|
+
style = @css[*styles]
|
105
|
+
h[k] =
|
106
|
+
if style
|
107
|
+
'<span%s style="%s">' % [debug_info, style]
|
108
|
+
else
|
109
|
+
false
|
110
|
+
end
|
111
|
+
end
|
112
|
+
end
|
113
|
+
|
114
|
+
else
|
115
|
+
raise "Unknown value %p for :css." % options[:css]
|
116
|
+
|
117
|
+
end
|
118
|
+
end
|
119
|
+
|
120
|
+
def finish options
|
121
|
+
not_needed = @opened.shift
|
122
|
+
@out << '</span>' * @opened.size
|
123
|
+
|
124
|
+
@out.extend Output
|
125
|
+
@out.numerize! options[:line_numbers], options # if options[:line_numbers]
|
126
|
+
@out.wrap! options[:wrap] # if options[:wrap]
|
127
|
+
|
128
|
+
#require 'pp'
|
129
|
+
#pp @css_style, @css_style.size
|
130
|
+
|
131
|
+
super
|
132
|
+
end
|
133
|
+
|
134
|
+
def token text, type
|
135
|
+
if text.is_a? String
|
136
|
+
if text =~ /#{HTML_ESCAPE_PATTERN}/o
|
137
|
+
text = text.gsub(/#{HTML_ESCAPE_PATTERN}/o) { |m| @HTML_ESCAPE[m] }
|
138
|
+
end
|
139
|
+
@opened[0] = type
|
140
|
+
style = @css_style[@opened]
|
141
|
+
if style
|
142
|
+
@out << style << text << '</span>'
|
143
|
+
else
|
144
|
+
@out << text
|
145
|
+
end
|
146
|
+
else
|
147
|
+
case text
|
148
|
+
when :open
|
149
|
+
@opened[0] = type
|
150
|
+
@out << @css_style[@opened]
|
151
|
+
@opened << type
|
152
|
+
when :close
|
153
|
+
unless @opened.empty?
|
154
|
+
raise 'Not Token to be closed.' unless @opened.size > 1
|
155
|
+
@out << '</span>'
|
156
|
+
@opened.pop
|
157
|
+
end
|
158
|
+
when nil
|
159
|
+
raise 'Token with nil as text was given: %p' % [[text, type]]
|
160
|
+
else
|
161
|
+
raise 'unknown token kind: %p' % text
|
162
|
+
end
|
163
|
+
end
|
164
|
+
end
|
165
|
+
|
166
|
+
end
|
167
|
+
|
168
|
+
end
|
169
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
module CodeRay module Encoders
|
2
|
+
|
3
|
+
require 'coderay/encoders/html'
|
4
|
+
class Span < HTML
|
5
|
+
|
6
|
+
FILE_EXTENSION = 'span.html'
|
7
|
+
|
8
|
+
register_for :span
|
9
|
+
|
10
|
+
DEFAULT_OPTIONS = HTML::DEFAULT_OPTIONS.merge({
|
11
|
+
:css => :style,
|
12
|
+
:wrap => :span,
|
13
|
+
})
|
14
|
+
end
|
15
|
+
|
16
|
+
end end
|
@@ -0,0 +1,74 @@
|
|
1
|
+
module CodeRay module Encoders
|
2
|
+
|
3
|
+
# Makes a statistic for the given tokens.
|
4
|
+
class Statistic < Encoder
|
5
|
+
|
6
|
+
include Streamable
|
7
|
+
register_for :stats, :statistic
|
8
|
+
|
9
|
+
attr_reader :type_stats, :real_token_count
|
10
|
+
|
11
|
+
protected
|
12
|
+
|
13
|
+
TypeStats = Struct.new :count, :size
|
14
|
+
|
15
|
+
def setup options
|
16
|
+
@type_stats = Hash.new { |h, k| h[k] = TypeStats.new 0, 0 }
|
17
|
+
@real_token_count = 0
|
18
|
+
end
|
19
|
+
|
20
|
+
def generate tokens, options
|
21
|
+
@tokens = tokens
|
22
|
+
super
|
23
|
+
end
|
24
|
+
|
25
|
+
def token text, type
|
26
|
+
@type_stats['TOTAL'].count += 1
|
27
|
+
if text.is_a? String
|
28
|
+
@real_token_count += 1 unless type == :space
|
29
|
+
@type_stats[type].count += 1
|
30
|
+
@type_stats[type].size += text.size
|
31
|
+
@type_stats['TOTAL'].size += text.size
|
32
|
+
else
|
33
|
+
@content_type = type
|
34
|
+
@type_stats['open/close'].count += 1
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
STATS = <<-STATS
|
39
|
+
|
40
|
+
Code Statistics
|
41
|
+
|
42
|
+
Tokens %8d
|
43
|
+
Non-Whitespace %8d
|
44
|
+
Bytes Total %8d
|
45
|
+
|
46
|
+
Token Types (%d):
|
47
|
+
type count ratio size (average)
|
48
|
+
-------------------------------------------------------------
|
49
|
+
%s
|
50
|
+
STATS
|
51
|
+
# space 12007 33.81 % 1.7
|
52
|
+
TOKEN_TYPES_ROW = <<-TKR
|
53
|
+
%-20s %8d %6.2f %% %5.1f
|
54
|
+
TKR
|
55
|
+
|
56
|
+
def finish options
|
57
|
+
all = @type_stats['TOTAL']
|
58
|
+
all_count, all_size = all.count, all.size
|
59
|
+
@type_stats.each do |type, stat|
|
60
|
+
stat.size /= stat.count.to_f
|
61
|
+
end
|
62
|
+
types_stats = @type_stats.sort_by { |k, v| -v.count }.map do |k, v|
|
63
|
+
TOKEN_TYPES_ROW % [k, v.count, 100.0 * v.count / all_count, v.size]
|
64
|
+
end.join
|
65
|
+
STATS % [
|
66
|
+
all_count, @real_token_count, all_size,
|
67
|
+
@type_stats.delete_if { |k, v| k.is_a? String }.size,
|
68
|
+
types_stats
|
69
|
+
]
|
70
|
+
end
|
71
|
+
|
72
|
+
end
|
73
|
+
|
74
|
+
end end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
module CodeRay
|
2
|
+
module Encoders
|
3
|
+
|
4
|
+
class Text < Encoder
|
5
|
+
|
6
|
+
include Streamable
|
7
|
+
register_for :text
|
8
|
+
|
9
|
+
FILE_EXTENSION = 'txt'
|
10
|
+
|
11
|
+
DEFAULT_OPTIONS = {
|
12
|
+
:separator => ''
|
13
|
+
}
|
14
|
+
|
15
|
+
protected
|
16
|
+
def setup options
|
17
|
+
super
|
18
|
+
@sep = options[:separator]
|
19
|
+
end
|
20
|
+
|
21
|
+
def token text, kind
|
22
|
+
return unless text.respond_to? :to_str
|
23
|
+
@out << text + @sep
|
24
|
+
end
|
25
|
+
|
26
|
+
def finish options
|
27
|
+
@out.chomp @sep
|
28
|
+
end
|
29
|
+
|
30
|
+
end
|
31
|
+
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
module CodeRay
|
2
|
+
module Encoders
|
3
|
+
|
4
|
+
# The Tokens encoder converts the tokens to a simple
|
5
|
+
# readable format. It doesn't use colors and is mainly
|
6
|
+
# intended for console output.
|
7
|
+
#
|
8
|
+
# The tokens are converted with Tokens.write_token.
|
9
|
+
#
|
10
|
+
# The format is:
|
11
|
+
#
|
12
|
+
# <token-kind> \t <escaped token-text> \n
|
13
|
+
#
|
14
|
+
# Example:
|
15
|
+
#
|
16
|
+
# require 'coderay'
|
17
|
+
# puts CodeRay.scan("puts 3 + 4", :ruby).tokens
|
18
|
+
#
|
19
|
+
# prints:
|
20
|
+
#
|
21
|
+
# ident puts
|
22
|
+
# space
|
23
|
+
# integer 3
|
24
|
+
# space
|
25
|
+
# operator +
|
26
|
+
# space
|
27
|
+
# integer 4
|
28
|
+
#
|
29
|
+
class Tokens < Encoder
|
30
|
+
|
31
|
+
include Streamable
|
32
|
+
register_for :tokens
|
33
|
+
|
34
|
+
FILE_EXTENSION = 'tok'
|
35
|
+
|
36
|
+
protected
|
37
|
+
def token *args
|
38
|
+
@out << CodeRay::Tokens.write_token(*args)
|
39
|
+
end
|
40
|
+
|
41
|
+
end
|
42
|
+
|
43
|
+
end
|
44
|
+
end
|
@@ -0,0 +1,145 @@
|
|
1
|
+
# =FileType
|
2
|
+
#
|
3
|
+
# A simple filetype recognizer
|
4
|
+
#
|
5
|
+
# Author: murphy (mail to murphy cYcnus de)
|
6
|
+
#
|
7
|
+
# Version: 0.1 (2005.september.1)
|
8
|
+
#
|
9
|
+
# ==Documentation
|
10
|
+
#
|
11
|
+
# TODO
|
12
|
+
#
|
13
|
+
module FileType
|
14
|
+
|
15
|
+
UnknownFileType = Class.new Exception
|
16
|
+
|
17
|
+
class << self
|
18
|
+
|
19
|
+
def [] filename, read_shebang = false
|
20
|
+
name = File.basename filename
|
21
|
+
ext = File.extname name
|
22
|
+
ext.sub!(/^\./, '') # delete the leading dot
|
23
|
+
|
24
|
+
type =
|
25
|
+
TypeFromExt[ext] ||
|
26
|
+
TypeFromExt[ext.downcase] ||
|
27
|
+
TypeFromName[name] ||
|
28
|
+
TypeFromName[name.downcase]
|
29
|
+
type ||= shebang(filename) if read_shebang
|
30
|
+
|
31
|
+
type
|
32
|
+
end
|
33
|
+
|
34
|
+
def shebang filename
|
35
|
+
begin
|
36
|
+
File.open filename, 'r' do |f|
|
37
|
+
first_line = f.gets
|
38
|
+
first_line[TypeFromShebang]
|
39
|
+
end
|
40
|
+
rescue IOError
|
41
|
+
nil
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
# This works like Hash#fetch.
|
46
|
+
def fetch filename, default = nil, read_shebang = false
|
47
|
+
if default and block_given?
|
48
|
+
warn 'block supersedes default value argument'
|
49
|
+
end
|
50
|
+
|
51
|
+
unless type = self[filename, read_shebang]
|
52
|
+
return yield if block_given?
|
53
|
+
return default if default
|
54
|
+
raise UnknownFileType, 'Could not determine type of %p.' % filename
|
55
|
+
end
|
56
|
+
type
|
57
|
+
end
|
58
|
+
|
59
|
+
end
|
60
|
+
|
61
|
+
TypeFromExt = {
|
62
|
+
'rb' => :ruby,
|
63
|
+
'rbw' => :ruby,
|
64
|
+
'cpp' => :cpp,
|
65
|
+
'c' => :c,
|
66
|
+
'h' => :c,
|
67
|
+
'xml' => :xml,
|
68
|
+
'htm' => :html,
|
69
|
+
'html' => :html,
|
70
|
+
}
|
71
|
+
|
72
|
+
TypeFromShebang = /\b(?:ruby|perl|python|sh)\b/
|
73
|
+
|
74
|
+
TypeFromName = {
|
75
|
+
'Rakefile' => :ruby,
|
76
|
+
'Rantfile' => :ruby,
|
77
|
+
}
|
78
|
+
|
79
|
+
end
|
80
|
+
|
81
|
+
if $0 == __FILE__
|
82
|
+
$VERBOSE = true
|
83
|
+
eval DATA.read, nil, $0, __LINE__+4
|
84
|
+
end
|
85
|
+
|
86
|
+
__END__
|
87
|
+
|
88
|
+
require 'test/unit'
|
89
|
+
|
90
|
+
class TC_FileType < Test::Unit::TestCase
|
91
|
+
|
92
|
+
def test_fetch
|
93
|
+
assert_raise FileType::UnknownFileType do
|
94
|
+
FileType.fetch ''
|
95
|
+
end
|
96
|
+
|
97
|
+
assert_throws :not_found do
|
98
|
+
FileType.fetch '.' do
|
99
|
+
throw :not_found
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
103
|
+
assert_equal :default, FileType.fetch('c', :default)
|
104
|
+
|
105
|
+
stderr, fake_stderr = $stderr, Object.new
|
106
|
+
$err = ''
|
107
|
+
def fake_stderr.write x
|
108
|
+
$err << x
|
109
|
+
end
|
110
|
+
$stderr = fake_stderr
|
111
|
+
FileType.fetch('c', :default) { }
|
112
|
+
assert_equal "block supersedes default value argument\n", $err
|
113
|
+
$stderr = stderr
|
114
|
+
end
|
115
|
+
|
116
|
+
def test_ruby
|
117
|
+
assert_equal :ruby, FileType['test.rb']
|
118
|
+
assert_equal :ruby, FileType['C:\\Program Files\\x\\y\\c\\test.rbw']
|
119
|
+
assert_equal :ruby, FileType['/usr/bin/something/Rakefile']
|
120
|
+
assert_equal :ruby, FileType['~/myapp/gem/Rantfile']
|
121
|
+
assert_not_equal :ruby, FileType['test_rb']
|
122
|
+
assert_not_equal :ruby, FileType['Makefile']
|
123
|
+
assert_not_equal :ruby, FileType['set.rb/set']
|
124
|
+
assert_not_equal :ruby, FileType['~/projects/blabla/rb']
|
125
|
+
end
|
126
|
+
|
127
|
+
def test_c
|
128
|
+
assert_equal :c, FileType['test.c']
|
129
|
+
assert_equal :c, FileType['C:\\Program Files\\x\\y\\c\\test.h']
|
130
|
+
assert_not_equal :c, FileType['test_c']
|
131
|
+
assert_not_equal :c, FileType['Makefile']
|
132
|
+
assert_not_equal :c, FileType['set.h/set']
|
133
|
+
assert_not_equal :c, FileType['~/projects/blabla/c']
|
134
|
+
end
|
135
|
+
|
136
|
+
def test_shebang
|
137
|
+
dir = './test'
|
138
|
+
if File.directory? dir
|
139
|
+
Dir.chdir dir do
|
140
|
+
assert_equal :c, FileType['test.c']
|
141
|
+
end
|
142
|
+
end
|
143
|
+
end
|
144
|
+
|
145
|
+
end
|