coderay 1.1.0 → 1.1.3.rc1

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.
@@ -0,0 +1,27 @@
1
+ require 'strscan'
2
+
3
+ module CodeRay
4
+
5
+ autoload :WordList, coderay_path('helpers', 'word_list')
6
+
7
+ # = Scanners
8
+ #
9
+ # This module holds the Scanner class and its subclasses.
10
+ # For example, the Ruby scanner is named CodeRay::Scanners::Ruby
11
+ # can be found in coderay/scanners/ruby.
12
+ #
13
+ # Scanner also provides methods and constants for the register
14
+ # mechanism and the [] method that returns the Scanner class
15
+ # belonging to the given lang.
16
+ #
17
+ # See PluginHost.
18
+ module Scanners
19
+
20
+ extend PluginHost
21
+ plugin_path File.dirname(__FILE__), 'scanners'
22
+
23
+ autoload :Scanner, CodeRay.coderay_path('scanners', 'scanner')
24
+
25
+ end
26
+
27
+ end
@@ -37,7 +37,7 @@ module Scanners
37
37
  add(PREDEFINED_CONSTANTS, :predefined_constant) # :nodoc:
38
38
 
39
39
  ESCAPE = / [rbfntv\n\\'"] | x[a-fA-F0-9]{1,2} | [0-7]{1,3} /x # :nodoc:
40
- UNICODE_ESCAPE = / u[a-fA-F0-9]{4} | U[a-fA-F0-9]{8} /x # :nodoc:
40
+ UNICODE_ESCAPE = / u[a-fA-F0-9]{4} | U[a-fA-F0-9]{8} /x # :nodoc:
41
41
 
42
42
  protected
43
43
 
@@ -2,14 +2,14 @@ module CodeRay
2
2
  module Scanners
3
3
 
4
4
  # Scanner for C++.
5
- #
5
+ #
6
6
  # Aliases: +cplusplus+, c++
7
7
  class CPlusPlus < Scanner
8
8
 
9
9
  register_for :cpp
10
10
  file_extension 'cpp'
11
11
  title 'C++'
12
-
12
+
13
13
  #-- http://www.cppreference.com/wiki/keywords/start
14
14
  KEYWORDS = [
15
15
  'and', 'and_eq', 'asm', 'bitand', 'bitor', 'break',
@@ -17,28 +17,30 @@ module Scanners
17
17
  'continue', 'default', 'delete', 'do', 'dynamic_cast', 'else',
18
18
  'enum', 'export', 'for', 'goto', 'if', 'namespace', 'new',
19
19
  'not', 'not_eq', 'or', 'or_eq', 'reinterpret_cast', 'return',
20
- 'sizeof', 'static_cast', 'struct', 'switch', 'template',
21
- 'throw', 'try', 'typedef', 'typeid', 'typename', 'union',
20
+ 'sizeof', 'static_assert', 'static_cast', 'struct', 'switch',
21
+ 'template', 'throw', 'try', 'typedef', 'typeid', 'typename', 'union',
22
22
  'while', 'xor', 'xor_eq',
23
23
  ] # :nodoc:
24
-
24
+
25
25
  PREDEFINED_TYPES = [
26
- 'bool', 'char', 'double', 'float', 'int', 'long',
27
- 'short', 'signed', 'unsigned', 'wchar_t', 'string',
26
+ 'bool', 'char', 'char16_t', 'char32_t', 'double', 'float',
27
+ 'int', 'long', 'short', 'signed', 'unsigned',
28
+ 'wchar_t', 'string',
28
29
  ] # :nodoc:
29
30
  PREDEFINED_CONSTANTS = [
30
31
  'false', 'true',
31
- 'EOF', 'NULL',
32
+ 'EOF', 'NULL', 'nullptr'
32
33
  ] # :nodoc:
33
34
  PREDEFINED_VARIABLES = [
34
35
  'this',
35
36
  ] # :nodoc:
36
37
  DIRECTIVES = [
37
- 'auto', 'const', 'explicit', 'extern', 'friend', 'inline', 'mutable', 'operator',
38
- 'private', 'protected', 'public', 'register', 'static', 'using', 'virtual', 'void',
39
- 'volatile',
38
+ 'alignas', 'alignof', 'auto', 'const', 'constexpr', 'decltype', 'explicit',
39
+ 'extern', 'final', 'friend', 'inline', 'mutable', 'noexcept', 'operator',
40
+ 'override', 'private', 'protected', 'public', 'register', 'static',
41
+ 'thread_local', 'using', 'virtual', 'void', 'volatile',
40
42
  ] # :nodoc:
41
-
43
+
42
44
  IDENT_KIND = WordList.new(:ident).
43
45
  add(KEYWORDS, :keyword).
44
46
  add(PREDEFINED_TYPES, :predefined_type).
@@ -47,10 +49,10 @@ module Scanners
47
49
  add(PREDEFINED_CONSTANTS, :predefined_constant) # :nodoc:
48
50
 
49
51
  ESCAPE = / [rbfntv\n\\'"] | x[a-fA-F0-9]{1,2} | [0-7]{1,3} /x # :nodoc:
50
- UNICODE_ESCAPE = / u[a-fA-F0-9]{4} | U[a-fA-F0-9]{8} /x # :nodoc:
51
-
52
+ UNICODE_ESCAPE = / u[a-fA-F0-9]{4} | U[a-fA-F0-9]{8} /x # :nodoc:
53
+
52
54
  protected
53
-
55
+
54
56
  def scan_tokens encoder, options
55
57
 
56
58
  state = :initial
@@ -107,7 +109,7 @@ module Scanners
107
109
 
108
110
  elsif match = scan(/\$/)
109
111
  encoder.text_token match, :ident
110
-
112
+
111
113
  elsif match = scan(/L?"/)
112
114
  encoder.begin_group :string
113
115
  if match[0] == ?L
@@ -180,7 +182,7 @@ module Scanners
180
182
  state = :initial
181
183
 
182
184
  end
183
-
185
+
184
186
  when :class_name_expected
185
187
  if match = scan(/ [A-Za-z_][A-Za-z_0-9]* /x)
186
188
  encoder.text_token match, :class
@@ -194,7 +196,7 @@ module Scanners
194
196
  state = :initial
195
197
 
196
198
  end
197
-
199
+
198
200
  else
199
201
  raise_inspect 'Unknown state', encoder
200
202
 
@@ -100,7 +100,7 @@ module Scanners
100
100
  next
101
101
  elsif match = scan(/-/)
102
102
  deleted_lines_count += 1
103
- if options[:inline_diff] && deleted_lines_count == 1 && (changed_lines_count = 1 + check(/.*(?:\n\-.*)*/).count("\n")) && match?(/(?>.*(?:\n\-.*){#{changed_lines_count - 1}}(?:\n\+.*){#{changed_lines_count}})$(?!\n\+)/)
103
+ if options[:inline_diff] && deleted_lines_count == 1 && (changed_lines_count = 1 + check(/.*(?:\n\-.*)*/).count("\n")) && changed_lines_count <= 100_000 && match?(/(?>.*(?:\n\-.*){#{changed_lines_count - 1}}(?:\n\+.*){#{changed_lines_count}})$(?!\n\+)/)
104
104
  deleted_lines = Array.new(changed_lines_count) { |i| skip(/\n\-/) if i > 0; scan(/.*/) }
105
105
  inserted_lines = Array.new(changed_lines_count) { |i| skip(/\n\+/) ; scan(/.*/) }
106
106
 
@@ -109,7 +109,7 @@ module Scanners
109
109
  for deleted_line, inserted_line in deleted_lines.zip(inserted_lines)
110
110
  pre, deleted_part, inserted_part, post = diff deleted_line, inserted_line
111
111
  content_scanner_entry_state = content_scanner.state
112
- deleted_lines_tokenized << content_scanner.tokenize([pre, deleted_part, post], :tokens => Tokens.new)
112
+ deleted_lines_tokenized << content_scanner.tokenize([pre, deleted_part, post], :tokens => Tokens.new)
113
113
  content_scanner.state = content_scanner_entry_state || :initial
114
114
  inserted_lines_tokenized << content_scanner.tokenize([pre, inserted_part, post], :tokens => Tokens.new)
115
115
  end
@@ -212,7 +212,7 @@ module Scanners
212
212
  # does not precede the leftmost one from the left.
213
213
  j = -1
214
214
  j -= 1 while j >= j_min && a[j] == b[j]
215
- return a[0...i], a[i..j], b[i..j], (j < -1) ? a[j+1..-1] : ''
215
+ return a[0...i], a[i..j], b[i..j], (j < -1) ? a[j + 1..-1] : ''
216
216
  end
217
217
 
218
218
  end
@@ -22,8 +22,8 @@ module Scanners
22
22
  add(GROOVY_MAGIC_VARIABLES, :local_variable) # :nodoc:
23
23
 
24
24
  ESCAPE = / [bfnrtv$\n\\'"] | x[a-fA-F0-9]{1,2} | [0-7]{1,3} /x # :nodoc:
25
- UNICODE_ESCAPE = / u[a-fA-F0-9]{4} /x # :nodoc: 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 # :nodoc:
25
+ UNICODE_ESCAPE = / u[a-fA-F0-9]{4} /x # :nodoc: 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 # :nodoc:
27
27
 
28
28
  # TODO: interpretation inside ', ", /
29
29
  STRING_CONTENT_PATTERN = {
@@ -75,7 +75,7 @@ module Scanners
75
75
 
76
76
  tag = false
77
77
 
78
- if match = scan(/%[\w:]+\/?/)
78
+ if match = scan(/%[-\w:]+\/?/)
79
79
  encoder.text_token match, :tag
80
80
  # if match = scan(/( +)(.+)/)
81
81
  # encoder.text_token self[1], :space
@@ -20,7 +20,7 @@ module Scanners
20
20
  MAGIC_VARIABLES = %w[ this super ] # :nodoc:
21
21
  TYPES = %w[
22
22
  boolean byte char class double enum float int interface long
23
- short void
23
+ short void var
24
24
  ] << '[]' # :nodoc: because int[] should be highlighted as a type
25
25
  DIRECTIVES = %w[
26
26
  abstract extends final implements native private protected public
@@ -36,15 +36,15 @@ module Scanners
36
36
  add(BuiltinTypes::List, :predefined_type).
37
37
  add(BuiltinTypes::List.select { |builtin| builtin[/(Error|Exception)$/] }, :exception).
38
38
  add(DIRECTIVES, :directive) # :nodoc:
39
-
39
+
40
40
  ESCAPE = / [bfnrtv\n\\'"] | x[a-fA-F0-9]{1,2} | [0-7]{1,3} /x # :nodoc:
41
- UNICODE_ESCAPE = / u[a-fA-F0-9]{4} | U[a-fA-F0-9]{8} /x # :nodoc:
41
+ UNICODE_ESCAPE = / u[a-fA-F0-9]{4} | U[a-fA-F0-9]{8} /x # :nodoc:
42
42
  STRING_CONTENT_PATTERN = {
43
43
  "'" => /[^\\']+/,
44
44
  '"' => /[^\\"]+/,
45
45
  '/' => /[^\\\/]+/,
46
46
  } # :nodoc:
47
- IDENT = /[a-zA-Z_][A-Za-z_0-9]*/ # :nodoc:
47
+ IDENT = RUBY_VERSION < '1.9' ? /[a-zA-Z_][A-Za-z_0-9]*/ : Regexp.new('[[[:alpha:]]_][[[:alnum:]]_]*') # :nodoc:
48
48
 
49
49
  protected
50
50
 
@@ -40,8 +40,8 @@ module Scanners
40
40
  add(KEYWORDS, :keyword) # :nodoc:
41
41
 
42
42
  ESCAPE = / [bfnrtv\n\\'"] | x[a-fA-F0-9]{1,2} | [0-7]{1,3} /x # :nodoc:
43
- UNICODE_ESCAPE = / u[a-fA-F0-9]{4} | U[a-fA-F0-9]{8} /x # :nodoc:
44
- REGEXP_ESCAPE = / [bBdDsSwW] /x # :nodoc:
43
+ UNICODE_ESCAPE = / u[a-fA-F0-9]{4} | U[a-fA-F0-9]{8} /x # :nodoc:
44
+ REGEXP_ESCAPE = / [bBdDsSwW] /x # :nodoc:
45
45
  STRING_CONTENT_PATTERN = {
46
46
  "'" => /[^\\']+/,
47
47
  '"' => /[^\\"]+/,
@@ -100,7 +100,6 @@ module Scanners
100
100
  # TODO: scan over nested tags
101
101
  xml_scanner.tokenize match, :tokens => encoder
102
102
  value_expected = false
103
- next
104
103
 
105
104
  elsif match = scan(/ [-+*=<>?:;,!&^|(\[{~%]+ | \.(?!\d) /x)
106
105
  value_expected = true
@@ -76,7 +76,7 @@ module Scanners
76
76
  encoder.text_token(match, :comment)
77
77
 
78
78
  elsif match = scan(/\[=*\[/) # [[ long (possibly multiline) string ]]
79
- num_equals = match.count("=") # Number must match for comment end
79
+ num_equals = match.count("=") # Number must match for string end
80
80
  encoder.begin_group(:string)
81
81
  encoder.text_token(match, :delimiter)
82
82
  state = :long_string
@@ -63,7 +63,7 @@ module Scanners
63
63
 
64
64
  NAME = / [[:alpha:]_] \w* /x # :nodoc:
65
65
  ESCAPE = / [abfnrtv\n\\'"] | x[a-fA-F0-9]{1,2} | [0-7]{1,3} /x # :nodoc:
66
- UNICODE_ESCAPE = / u[a-fA-F0-9]{4} | U[a-fA-F0-9]{8} | N\{[-\w ]+\} /x # :nodoc:
66
+ UNICODE_ESCAPE = / u[a-fA-F0-9]{4} | U[a-fA-F0-9]{8} | N\{[-\w ]+\} /x # :nodoc:
67
67
 
68
68
  OPERATOR = /
69
69
  \.\.\. | # ellipsis
@@ -164,15 +164,19 @@ module Scanners
164
164
  end
165
165
 
166
166
  elsif match = scan(/ ' (?:(?>[^'\\]*) ')? | " (?:(?>[^"\\\#]*) ")? /mx)
167
- encoder.begin_group :string
168
167
  if match.size == 1
168
+ kind = check(self.class::StringState.simple_key_pattern(match)) ? :key : :string
169
+ encoder.begin_group kind
169
170
  encoder.text_token match, :delimiter
170
- state = self.class::StringState.new :string, match == '"', match # important for streaming
171
+ state = self.class::StringState.new kind, match == '"', match # important for streaming
171
172
  else
173
+ kind = value_expected == true && scan(/:/) ? :key : :string
174
+ encoder.begin_group kind
172
175
  encoder.text_token match[0,1], :delimiter
173
176
  encoder.text_token match[1..-2], :content if match.size > 2
174
177
  encoder.text_token match[-1,1], :delimiter
175
- encoder.end_group :string
178
+ encoder.end_group kind
179
+ encoder.text_token ':', :operator if kind == :key
176
180
  value_expected = false
177
181
  end
178
182
 
@@ -191,11 +195,14 @@ module Scanners
191
195
  encoder.text_token match, :error
192
196
  method_call_expected = false
193
197
  else
194
- encoder.text_token match, self[1] ? :float : :integer # TODO: send :hex/:octal/:binary
198
+ kind = self[1] ? :float : :integer # TODO: send :hex/:octal/:binary
199
+ match << 'r' if match !~ /e/i && scan(/r/)
200
+ match << 'i' if scan(/i/)
201
+ encoder.text_token match, kind
195
202
  end
196
203
  value_expected = false
197
204
 
198
- elsif match = scan(/ [-+!~^\/]=? | [:;] | [*|&]{1,2}=? | >>? /x)
205
+ elsif match = scan(/ [-+!~^\/]=? | [:;] | &\. | [*|&]{1,2}=? | >>? /x)
199
206
  value_expected = true
200
207
  encoder.text_token match, :operator
201
208
 
@@ -208,7 +215,7 @@ module Scanners
208
215
  encoder.end_group kind
209
216
  heredocs ||= [] # create heredocs if empty
210
217
  heredocs << self.class::StringState.new(kind, quote != "'", delim,
211
- self[1] == '-' ? :indented : :linestart)
218
+ self[1] ? :indented : :linestart)
212
219
  value_expected = false
213
220
 
214
221
  elsif value_expected && match = scan(/#{patterns::FANCY_STRING_START}/o)
@@ -60,7 +60,7 @@ module Scanners
60
60
 
61
61
  QUOTE_TO_TYPE = {
62
62
  '`' => :shell,
63
- '/'=> :regexp,
63
+ '/' => :regexp,
64
64
  }
65
65
  QUOTE_TO_TYPE.default = :string
66
66
 
@@ -114,7 +114,7 @@ module Scanners
114
114
  # NOTE: This is not completely correct, but
115
115
  # nobody needs heredoc delimiters ending with \n.
116
116
  HEREDOC_OPEN = /
117
- << (-)? # $1 = float
117
+ << ([-~])? # $1 = float
118
118
  (?:
119
119
  ( [A-Za-z_0-9]+ ) # $2 = delim
120
120
  |
@@ -37,6 +37,14 @@ module Scanners
37
37
  end
38
38
  end
39
39
 
40
+ def self.simple_key_pattern delim
41
+ if delim == "'"
42
+ / (?> (?: [^\\']+ | \\. )* ) ' : /mx
43
+ else
44
+ / (?> (?: [^\\"\#]+ | \\. | \#\$[\\"] | \#\{[^\{\}]+\} | \#(?!\{) )* ) " : /mx
45
+ end
46
+ end
47
+
40
48
  def initialize kind, interpreted, delim, heredoc = false
41
49
  if heredoc
42
50
  pattern = heredoc_pattern delim, interpreted, heredoc == :indented
@@ -1,25 +1,7 @@
1
1
  # encoding: utf-8
2
- require 'strscan'
3
2
 
4
3
  module CodeRay
5
-
6
- autoload :WordList, coderay_path('helpers', 'word_list')
7
-
8
- # = Scanners
9
- #
10
- # This module holds the Scanner class and its subclasses.
11
- # For example, the Ruby scanner is named CodeRay::Scanners::Ruby
12
- # can be found in coderay/scanners/ruby.
13
- #
14
- # Scanner also provides methods and constants for the register
15
- # mechanism and the [] method that returns the Scanner class
16
- # belonging to the given lang.
17
- #
18
- # See PluginHost.
19
4
  module Scanners
20
- extend PluginHost
21
- plugin_path File.dirname(__FILE__), 'scanners'
22
-
23
5
 
24
6
  # = Scanner
25
7
  #
@@ -29,7 +29,7 @@ module Scanners
29
29
  char varchar varchar2 enum binary text tinytext mediumtext
30
30
  longtext blob tinyblob mediumblob longblob timestamp
31
31
  date time datetime year double decimal float int
32
- integer tinyint mediumint bigint smallint unsigned bit
32
+ integer tinyint mediumint bigint smallint unsigned bit numeric
33
33
  bool boolean hex bin oct
34
34
  )
35
35
 
@@ -57,6 +57,12 @@ module Scanners
57
57
 
58
58
  STRING_PREFIXES = /[xnb]|_\w+/i
59
59
 
60
+ STRING_CONTENT_PATTERN = {
61
+ '"' => / (?: [^\\"] | "" )+ /x,
62
+ "'" => / (?: [^\\'] | '' )+ /x,
63
+ '`' => / (?: [^\\`] | `` )+ /x,
64
+ }
65
+
60
66
  def scan_tokens encoder, options
61
67
 
62
68
  state = :initial
@@ -90,7 +96,7 @@ module Scanners
90
96
  state = :string
91
97
  encoder.text_token match, :delimiter
92
98
 
93
- elsif match = scan(/ @? [A-Za-z_][A-Za-z_0-9]* /x)
99
+ elsif match = scan(/ @? [A-Za-z_][A-Za-z_0-9\$]* /x)
94
100
  encoder.text_token match, name_expected ? :ident : (match[0] == ?@ ? :variable : IDENT_KIND[match])
95
101
  name_expected = false
96
102
 
@@ -115,40 +121,26 @@ module Scanners
115
121
  end
116
122
 
117
123
  elsif state == :string
118
- if match = scan(/[^\\"'`]+/)
119
- string_content << match
120
- next
124
+ if match = scan(STRING_CONTENT_PATTERN[string_type])
125
+ encoder.text_token match, :content
121
126
  elsif match = scan(/["'`]/)
122
127
  if string_type == match
123
128
  if peek(1) == string_type # doubling means escape
124
- string_content << string_type << getch
125
- next
126
- end
127
- unless string_content.empty?
128
- encoder.text_token string_content, :content
129
- string_content = ''
129
+ encoder.text_token match + getch, :content
130
+ else
131
+ encoder.text_token match, :delimiter
132
+ encoder.end_group :string
133
+ state = :initial
134
+ string_type = nil
130
135
  end
131
- encoder.text_token match, :delimiter
132
- encoder.end_group :string
133
- state = :initial
134
- string_type = nil
135
136
  else
136
- string_content << match
137
+ encoder.text_token match, :content
137
138
  end
138
139
  elsif match = scan(/ \\ (?: #{ESCAPE} | #{UNICODE_ESCAPE} ) /mox)
139
- unless string_content.empty?
140
- encoder.text_token string_content, :content
141
- string_content = ''
142
- end
143
140
  encoder.text_token match, :char
144
141
  elsif match = scan(/ \\ . /mox)
145
- string_content << match
146
- next
142
+ encoder.text_token match, :content
147
143
  elsif match = scan(/ \\ | $ /x)
148
- unless string_content.empty?
149
- encoder.text_token string_content, :content
150
- string_content = ''
151
- end
152
144
  encoder.text_token match, :error unless match.empty?
153
145
  encoder.end_group :string
154
146
  state = :initial
@@ -0,0 +1,15 @@
1
+ module CodeRay
2
+
3
+ # This module holds the Style class and its subclasses.
4
+ #
5
+ # See Plugin.
6
+ module Styles
7
+
8
+ extend PluginHost
9
+ plugin_path File.dirname(__FILE__), 'styles'
10
+
11
+ autoload :Style, CodeRay.coderay_path('styles', 'style')
12
+
13
+ end
14
+
15
+ end