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,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