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,150 @@
1
+ module CodeRay
2
+ module Scanners
3
+
4
+ class Delphi < Scanner
5
+
6
+ register_for :delphi
7
+ file_extension 'pas'
8
+
9
+ RESERVED_WORDS = [
10
+ 'and', 'array', 'as', 'at', 'asm', 'at', 'begin', 'case', 'class',
11
+ 'const', 'constructor', 'destructor', 'dispinterface', 'div', 'do',
12
+ 'downto', 'else', 'end', 'except', 'exports', 'file', 'finalization',
13
+ 'finally', 'for', 'function', 'goto', 'if', 'implementation', 'in',
14
+ 'inherited', 'initialization', 'inline', 'interface', 'is', 'label',
15
+ 'library', 'mod', 'nil', 'not', 'object', 'of', 'or', 'out', 'packed',
16
+ 'procedure', 'program', 'property', 'raise', 'record', 'repeat',
17
+ 'resourcestring', 'set', 'shl', 'shr', 'string', 'then', 'threadvar',
18
+ 'to', 'try', 'type', 'unit', 'until', 'uses', 'var', 'while', 'with',
19
+ 'xor', 'on'
20
+ ]
21
+
22
+ DIRECTIVES = [
23
+ 'absolute', 'abstract', 'assembler', 'at', 'automated', 'cdecl',
24
+ 'contains', 'deprecated', 'dispid', 'dynamic', 'export',
25
+ 'external', 'far', 'forward', 'implements', 'local',
26
+ 'near', 'nodefault', 'on', 'overload', 'override',
27
+ 'package', 'pascal', 'platform', 'private', 'protected', 'public',
28
+ 'published', 'read', 'readonly', 'register', 'reintroduce',
29
+ 'requires', 'resident', 'safecall', 'stdcall', 'stored', 'varargs',
30
+ 'virtual', 'write', 'writeonly'
31
+ ]
32
+
33
+ IDENT_KIND = CaseIgnoringWordList.new(:ident).
34
+ add(RESERVED_WORDS, :reserved).
35
+ add(DIRECTIVES, :directive)
36
+
37
+ NAME_FOLLOWS = CaseIgnoringWordList.new(false).
38
+ add(%w(procedure function .))
39
+
40
+ private
41
+ def scan_tokens tokens, options
42
+
43
+ state = :initial
44
+ last_token = ''
45
+
46
+ until eos?
47
+
48
+ kind = nil
49
+ match = nil
50
+
51
+ if state == :initial
52
+
53
+ if scan(/ \s+ /x)
54
+ tokens << [matched, :space]
55
+ next
56
+
57
+ elsif scan(%r! \{ \$ [^}]* \}? | \(\* \$ (?: .*? \*\) | .* ) !mx)
58
+ tokens << [matched, :preprocessor]
59
+ next
60
+
61
+ elsif scan(%r! // [^\n]* | \{ [^}]* \}? | \(\* (?: .*? \*\) | .* ) !mx)
62
+ tokens << [matched, :comment]
63
+ next
64
+
65
+ elsif match = scan(/ <[>=]? | >=? | :=? | [-+=*\/;,@\^|\(\)\[\]] | \.\. /x)
66
+ kind = :operator
67
+
68
+ elsif match = scan(/\./)
69
+ kind = :operator
70
+ if last_token == 'end'
71
+ tokens << [match, kind]
72
+ next
73
+ end
74
+
75
+ elsif match = scan(/ [A-Za-z_][A-Za-z_0-9]* /x)
76
+ kind = NAME_FOLLOWS[last_token] ? :ident : IDENT_KIND[match]
77
+
78
+ elsif match = scan(/ ' ( [^\n']|'' ) (?:'|$) /x)
79
+ tokens << [:open, :char]
80
+ tokens << ["'", :delimiter]
81
+ tokens << [self[1], :content]
82
+ tokens << ["'", :delimiter]
83
+ tokens << [:close, :char]
84
+ next
85
+
86
+ elsif match = scan(/ ' /x)
87
+ tokens << [:open, :string]
88
+ state = :string
89
+ kind = :delimiter
90
+
91
+ elsif scan(/ \# (?: \d+ | \$[0-9A-Fa-f]+ ) /x)
92
+ kind = :char
93
+
94
+ elsif scan(/ \$ [0-9A-Fa-f]+ /x)
95
+ kind = :hex
96
+
97
+ elsif scan(/ (?: \d+ ) (?![eE]|\.[^.]) /x)
98
+ kind = :integer
99
+
100
+ elsif scan(/ \d+ (?: \.\d+ (?: [eE][+-]? \d+ )? | [eE][+-]? \d+ ) /x)
101
+ kind = :float
102
+
103
+ else
104
+ kind = :error
105
+ getch
106
+
107
+ end
108
+
109
+ elsif state == :string
110
+ if scan(/[^\n']+/)
111
+ kind = :content
112
+ elsif scan(/''/)
113
+ kind = :char
114
+ elsif scan(/'/)
115
+ tokens << ["'", :delimiter]
116
+ tokens << [:close, :string]
117
+ state = :initial
118
+ next
119
+ elsif scan(/\n/)
120
+ tokens << [:close, :string]
121
+ kind = :error
122
+ state = :initial
123
+ else
124
+ raise "else case \' reached; %p not handled." % peek(1), tokens
125
+ end
126
+
127
+ else
128
+ raise 'else-case reached', tokens
129
+
130
+ end
131
+
132
+ match ||= matched
133
+ if $DEBUG and not kind
134
+ raise_inspect 'Error token %p in line %d' %
135
+ [[match, kind], line], tokens, state
136
+ end
137
+ raise_inspect 'Empty token', tokens unless match
138
+
139
+ last_token = match
140
+ tokens << [match, kind]
141
+
142
+ end
143
+
144
+ tokens
145
+ end
146
+
147
+ end
148
+
149
+ end
150
+ end
@@ -0,0 +1,105 @@
1
+ module CodeRay
2
+ module Scanners
3
+
4
+ class Diff < Scanner
5
+
6
+ register_for :diff
7
+ title 'diff output'
8
+
9
+ def scan_tokens tokens, options
10
+
11
+ line_kind = nil
12
+ state = :initial
13
+
14
+ until eos?
15
+ kind = match = nil
16
+
17
+ if match = scan(/\n/)
18
+ if line_kind
19
+ tokens << [:end_line, line_kind]
20
+ line_kind = nil
21
+ end
22
+ tokens << [match, :space]
23
+ next
24
+ end
25
+
26
+ case state
27
+
28
+ when :initial
29
+ if match = scan(/--- |\+\+\+ |=+|_+/)
30
+ tokens << [:begin_line, line_kind = :head]
31
+ tokens << [match, :head]
32
+ next unless match = scan(/.+/)
33
+ kind = :plain
34
+ elsif match = scan(/Index: |Property changes on: /)
35
+ tokens << [:begin_line, line_kind = :head]
36
+ tokens << [match, :head]
37
+ next unless match = scan(/.+/)
38
+ kind = :plain
39
+ elsif match = scan(/Added: /)
40
+ tokens << [:begin_line, line_kind = :head]
41
+ tokens << [match, :head]
42
+ next unless match = scan(/.+/)
43
+ kind = :plain
44
+ state = :added
45
+ elsif match = scan(/\\ /)
46
+ tokens << [:begin_line, line_kind = :change]
47
+ tokens << [match, :change]
48
+ next unless match = scan(/.+/)
49
+ kind = :plain
50
+ elsif scan(/(@@)((?>[^@\n]*))(@@)/)
51
+ tokens << [:begin_line, line_kind = :change]
52
+ tokens << [self[1], :change]
53
+ tokens << [self[2], :plain]
54
+ tokens << [self[3], :change]
55
+ next unless match = scan(/.+/)
56
+ kind = :plain
57
+ elsif match = scan(/\+/)
58
+ tokens << [:begin_line, line_kind = :insert]
59
+ tokens << [match, :insert]
60
+ next unless match = scan(/.+/)
61
+ kind = :plain
62
+ elsif match = scan(/-/)
63
+ tokens << [:begin_line, line_kind = :delete]
64
+ tokens << [match, :delete]
65
+ next unless match = scan(/.+/)
66
+ kind = :plain
67
+ elsif scan(/ .*/)
68
+ kind = :comment
69
+ elsif scan(/.+/)
70
+ tokens << [:begin_line, line_kind = :head]
71
+ kind = :plain
72
+ else
73
+ raise_inspect 'else case rached'
74
+ end
75
+
76
+ when :added
77
+ if match = scan(/ \+/)
78
+ tokens << [:begin_line, line_kind = :insert]
79
+ tokens << [match, :insert]
80
+ next unless match = scan(/.+/)
81
+ kind = :plain
82
+ else
83
+ state = :initial
84
+ next
85
+ end
86
+ end
87
+
88
+ match ||= matched
89
+ if $DEBUG and not kind
90
+ raise_inspect 'Error token %p in line %d' %
91
+ [[match, kind], line], tokens
92
+ end
93
+ raise_inspect 'Empty token', tokens unless match
94
+
95
+ tokens << [match, kind]
96
+ end
97
+
98
+ tokens << [:end_line, line_kind] if line_kind
99
+ tokens
100
+ end
101
+
102
+ end
103
+
104
+ end
105
+ end
@@ -0,0 +1,263 @@
1
+ module CodeRay
2
+ module Scanners
3
+
4
+ load :java
5
+
6
+ class Groovy < Java
7
+
8
+ include Streamable
9
+ register_for :groovy
10
+
11
+ # TODO: Check this!
12
+ GROOVY_KEYWORDS = %w[
13
+ as assert def in
14
+ ]
15
+ KEYWORDS_EXPECTING_VALUE = WordList.new.add %w[
16
+ case instanceof new return throw typeof while as assert in
17
+ ]
18
+ GROOVY_MAGIC_VARIABLES = %w[ it ]
19
+
20
+ IDENT_KIND = Java::IDENT_KIND.dup.
21
+ add(GROOVY_KEYWORDS, :keyword).
22
+ add(GROOVY_MAGIC_VARIABLES, :local_variable)
23
+
24
+ ESCAPE = / [bfnrtv$\n\\'"] | x[a-fA-F0-9]{1,2} | [0-7]{1,3} /x
25
+ UNICODE_ESCAPE = / u[a-fA-F0-9]{4} /x # no 4-byte unicode chars? U[a-fA-F0-9]{8}
26
+ REGEXP_ESCAPE = / [bfnrtv\n\\'"] | x[a-fA-F0-9]{1,2} | [0-7]{1,3} | \d | [bBdDsSwW\/] /x
27
+
28
+ # TODO: interpretation inside ', ", /
29
+ STRING_CONTENT_PATTERN = {
30
+ "'" => /(?>\\[^\\'\n]+|[^\\'\n]+)+/,
31
+ '"' => /[^\\$"\n]+/,
32
+ "'''" => /(?>[^\\']+|'(?!''))+/,
33
+ '"""' => /(?>[^\\$"]+|"(?!""))+/,
34
+ '/' => /[^\\$\/\n]+/,
35
+ }
36
+
37
+ def scan_tokens tokens, options
38
+
39
+ state = :initial
40
+ inline_block_stack = []
41
+ inline_block_paren_depth = nil
42
+ string_delimiter = nil
43
+ import_clause = class_name_follows = last_token = after_def = false
44
+ value_expected = true
45
+
46
+ until eos?
47
+
48
+ kind = nil
49
+ match = nil
50
+
51
+ case state
52
+
53
+ when :initial
54
+
55
+ if match = scan(/ \s+ | \\\n /x)
56
+ tokens << [match, :space]
57
+ if match.index ?\n
58
+ import_clause = after_def = false
59
+ value_expected = true unless value_expected
60
+ end
61
+ next
62
+
63
+ elsif scan(%r! // [^\n\\]* (?: \\. [^\n\\]* )* | /\* (?: .*? \*/ | .* ) !mx)
64
+ value_expected = true
65
+ after_def = false
66
+ kind = :comment
67
+
68
+ elsif bol? && scan(/ \#!.* /x)
69
+ kind = :doctype
70
+
71
+ elsif import_clause && scan(/ (?!as) #{IDENT} (?: \. #{IDENT} )* (?: \.\* )? /ox)
72
+ after_def = value_expected = false
73
+ kind = :include
74
+
75
+ elsif match = scan(/ #{IDENT} | \[\] /ox)
76
+ kind = IDENT_KIND[match]
77
+ value_expected = (kind == :keyword) && KEYWORDS_EXPECTING_VALUE[match]
78
+ if last_token == '.'
79
+ kind = :ident
80
+ elsif class_name_follows
81
+ kind = :class
82
+ class_name_follows = false
83
+ elsif after_def && check(/\s*[({]/)
84
+ kind = :method
85
+ after_def = false
86
+ elsif kind == :ident && last_token != '?' && check(/:/)
87
+ kind = :key
88
+ else
89
+ class_name_follows = true if match == 'class' || (import_clause && match == 'as')
90
+ import_clause = match == 'import'
91
+ after_def = true if match == 'def'
92
+ end
93
+
94
+ elsif scan(/;/)
95
+ import_clause = after_def = false
96
+ value_expected = true
97
+ kind = :operator
98
+
99
+ elsif scan(/\{/)
100
+ class_name_follows = after_def = false
101
+ value_expected = true
102
+ kind = :operator
103
+ if !inline_block_stack.empty?
104
+ inline_block_paren_depth += 1
105
+ end
106
+
107
+ # TODO: ~'...', ~"..." and ~/.../ style regexps
108
+ elsif match = scan(/ \.\.<? | \*?\.(?!\d)@? | \.& | \?:? | [,?:(\[] | -[->] | \+\+ |
109
+ && | \|\| | \*\*=? | ==?~ | <=?>? | [-+*%^~&|>=!]=? | <<<?=? | >>>?=? /x)
110
+ value_expected = true
111
+ value_expected = :regexp if match == '~'
112
+ after_def = false
113
+ kind = :operator
114
+
115
+ elsif match = scan(/ [)\]}] /x)
116
+ value_expected = after_def = false
117
+ if !inline_block_stack.empty? && match == '}'
118
+ inline_block_paren_depth -= 1
119
+ if inline_block_paren_depth == 0 # closing brace of inline block reached
120
+ tokens << [match, :inline_delimiter]
121
+ tokens << [:close, :inline]
122
+ state, string_delimiter, inline_block_paren_depth = inline_block_stack.pop
123
+ next
124
+ end
125
+ end
126
+
127
+ elsif check(/[\d.]/)
128
+ after_def = value_expected = false
129
+ if scan(/0[xX][0-9A-Fa-f]+/)
130
+ kind = :hex
131
+ elsif scan(/(?>0[0-7]+)(?![89.eEfF])/)
132
+ kind = :oct
133
+ elsif scan(/\d+[fFdD]|\d*\.\d+(?:[eE][+-]?\d+)?[fFdD]?|\d+[eE][+-]?\d+[fFdD]?/)
134
+ kind = :float
135
+ elsif scan(/\d+[lLgG]?/)
136
+ kind = :integer
137
+ end
138
+
139
+ elsif match = scan(/'''|"""/)
140
+ after_def = value_expected = false
141
+ state = :multiline_string
142
+ tokens << [:open, :string]
143
+ string_delimiter = match
144
+ kind = :delimiter
145
+
146
+ # TODO: record.'name'
147
+ elsif match = scan(/["']/)
148
+ after_def = value_expected = false
149
+ state = match == '/' ? :regexp : :string
150
+ tokens << [:open, state]
151
+ string_delimiter = match
152
+ kind = :delimiter
153
+
154
+ elsif value_expected && (match = scan(/\//))
155
+ after_def = value_expected = false
156
+ tokens << [:open, :regexp]
157
+ state = :regexp
158
+ string_delimiter = '/'
159
+ kind = :delimiter
160
+
161
+ elsif scan(/ @ #{IDENT} /ox)
162
+ after_def = value_expected = false
163
+ kind = :annotation
164
+
165
+ elsif scan(/\//)
166
+ after_def = false
167
+ value_expected = true
168
+ kind = :operator
169
+
170
+ else
171
+ getch
172
+ kind = :error
173
+
174
+ end
175
+
176
+ when :string, :regexp, :multiline_string
177
+ if scan(STRING_CONTENT_PATTERN[string_delimiter])
178
+ kind = :content
179
+
180
+ elsif match = scan(state == :multiline_string ? /'''|"""/ : /["'\/]/)
181
+ tokens << [match, :delimiter]
182
+ if state == :regexp
183
+ # TODO: regexp modifiers? s, m, x, i?
184
+ modifiers = scan(/[ix]+/)
185
+ tokens << [modifiers, :modifier] if modifiers && !modifiers.empty?
186
+ end
187
+ state = :string if state == :multiline_string
188
+ tokens << [:close, state]
189
+ string_delimiter = nil
190
+ after_def = value_expected = false
191
+ state = :initial
192
+ next
193
+
194
+ elsif (state == :string || state == :multiline_string) &&
195
+ (match = scan(/ \\ (?: #{ESCAPE} | #{UNICODE_ESCAPE} ) /mox))
196
+ if string_delimiter[0] == ?' && !(match == "\\\\" || match == "\\'")
197
+ kind = :content
198
+ else
199
+ kind = :char
200
+ end
201
+ elsif state == :regexp && scan(/ \\ (?: #{REGEXP_ESCAPE} | #{UNICODE_ESCAPE} ) /mox)
202
+ kind = :char
203
+
204
+ elsif match = scan(/ \$ #{IDENT} /mox)
205
+ tokens << [:open, :inline]
206
+ tokens << ['$', :inline_delimiter]
207
+ match = match[1..-1]
208
+ tokens << [match, IDENT_KIND[match]]
209
+ tokens << [:close, :inline]
210
+ next
211
+ elsif match = scan(/ \$ \{ /x)
212
+ tokens << [:open, :inline]
213
+ tokens << ['${', :inline_delimiter]
214
+ inline_block_stack << [state, string_delimiter, inline_block_paren_depth]
215
+ inline_block_paren_depth = 1
216
+ state = :initial
217
+ next
218
+
219
+ elsif scan(/ \$ /mx)
220
+ kind = :content
221
+
222
+ elsif scan(/ \\. /mx)
223
+ kind = :content
224
+
225
+ elsif scan(/ \\ | \n /x)
226
+ tokens << [:close, state]
227
+ kind = :error
228
+ after_def = value_expected = false
229
+ state = :initial
230
+
231
+ else
232
+ raise_inspect "else case \" reached; %p not handled." % peek(1), tokens
233
+ end
234
+
235
+ else
236
+ raise_inspect 'Unknown state', tokens
237
+
238
+ end
239
+
240
+ match ||= matched
241
+ if $DEBUG and not kind
242
+ raise_inspect 'Error token %p in line %d' %
243
+ [[match, kind], line], tokens
244
+ end
245
+ raise_inspect 'Empty token', tokens unless match
246
+
247
+ last_token = match unless [:space, :comment, :doctype].include? kind
248
+
249
+ tokens << [match, kind]
250
+
251
+ end
252
+
253
+ if [:multiline_string, :string, :regexp].include? state
254
+ tokens << [:close, state]
255
+ end
256
+
257
+ tokens
258
+ end
259
+
260
+ end
261
+
262
+ end
263
+ end