wirb 1.0.3 → 2.0.0

Sign up to get free protection for your applications and to get access to all the features.
data/lib/wirb.rb CHANGED
@@ -1,135 +1,90 @@
1
- require File.dirname(__FILE__) + '/wirb/version'
2
- require File.dirname(__FILE__) + '/wirb/colorizer'
3
- require File.dirname(__FILE__) + '/wirb/tokenizer'
4
- require 'yaml'
5
-
6
- class << Wirb
7
- def running?() @running end
8
-
9
- @running = false
10
-
11
- # Start colorizing results, will hook into irb if IRB is defined
12
- def start
13
- require File.dirname(__FILE__) + '/wirb/irb' if defined?(IRB) && defined?(IRB::Irb) && !IRB::Irb.instance_methods.include?(:prompt_non_fancy)
14
- @running = true
15
- rescue LoadError
16
- warn "Couldn't activate Wirb"
17
- end
18
- alias activate start
19
- alias enable start
20
-
21
- # Stop colorizing
22
- def stop
23
- @running = false
24
- end
25
- alias deactivate stop
26
- alias disable stop
27
-
28
- # extend getter & setter for colorizer & schema
29
- def colorizer
30
- @colorizer ||= Wirb::Colorizer::Paint
31
- end
1
+ require_relative 'wirb/version'
2
+ require_relative 'wirb/tokenizer'
3
+ require_relative 'wirb/schema_builder'
4
+ require_relative 'wirb/inspector'
5
+ require_relative 'wirb/irb' if defined?(IRB)
32
6
 
33
- def colorizer=(col)
34
- @colorizer = col
35
- end
7
+ require 'yaml'
8
+ require 'paint'
9
+ require 'timeout'
36
10
 
37
- # Convenience method, permits simplified syntax like:
38
- # Wirb.load_colorizer :HighLine
39
- def load_colorizer(colorizer_name)
40
- # @colorizer = Wirb::Colorizer.const_get(colorizer_name, false)
41
- @colorizer = eval "Wirb::Colorizer::#{colorizer_name}"
42
- compatible_colorizer?(@colorizer)
43
- @colorizer
44
- end
45
11
 
46
- def schema
47
- @schema || load_schema
48
- end
12
+ module Wirb
13
+ class << self
14
+ def running?
15
+ defined?(IRB) && IRB.CurrentContext &&
16
+ IRB.CurrentContext.inspect_mode == :wirb
17
+ end
49
18
 
50
- def schema=(val)
51
- @schema = val
52
- end
19
+ def timeout
20
+ @timeout ||= 3
21
+ end
53
22
 
54
- # Loads a color schema from a yaml file
55
- # If first argument is a String: path to yaml file
56
- # If first argument is a Symbol: bundled schema
57
- def load_schema!(yaml_path = :classic_paint)
58
- if yaml_path.is_a? Symbol # bundled themes
59
- schema_name = yaml_path.to_s
60
- schema_yaml = YAML.load_file(File.join(Gem.datadir('wirb'), schema_name + '.yml'))
61
- else
62
- schema_name = File.basename(yaml_path).gsub(/\.yml$/, '')
63
- schema_yaml = YAML.load_file(yaml_path)
23
+ def schema
24
+ @schema ||= SchemaBuilder.load_schema_from_yaml
64
25
  end
65
26
 
66
- if schema_yaml.is_a?(Hash)
67
- @schema = Hash[ schema_yaml.map{ |k,v|
68
- [k.to_s.to_sym, Array( v )]
69
- } ]
70
- @schema[:name] = schema_name.to_sym
71
- @schema[:colorizer].map!(&:to_sym)
72
- else
73
- raise LoadError, "Could not load the Wirb schema at: #{yaml_path}"
27
+ def schema=(val)
28
+ @schema = val
74
29
  end
75
30
 
76
- @schema
77
- end
31
+ def load_schema(name)
32
+ @schema = SchemaBuilder.load_schema_from_yaml(name)
33
+ end
78
34
 
79
- # Loads a color schema from a yaml file and sets colorizer to first suggested one in schema
80
- def load_schema(yaml_path = :classic_paint)
81
- load_schema! yaml_path
82
- load_colorizer schema[:colorizer].first
83
- @schema
84
- end
35
+ def original_inspect_mode
36
+ @original_inspect_mode
37
+ end
85
38
 
86
- # Return the escape code for a given color
87
- def get_color(*keys)
88
- colorizer.color(*keys)
89
- end
90
- alias color get_color
91
-
92
- # Colorize a string
93
- def colorize_string(string, *colors)
94
- colorizer.run(string, *colors)
95
- end
39
+ def start
40
+ require_relative 'wirb/irb'
41
+ @original_inspect_mode =
42
+ IRB.conf[:INSPECT_MODE] ||
43
+ IRB.CurrentContext && IRB.CurrentContext.inspect_mode ||
44
+ true
45
+ IRB.conf[:INSPECT_MODE] = :wirb
46
+ IRB.CurrentContext.inspect_mode = :wirb if IRB.CurrentContext
47
+ true
48
+ end
49
+ alias activate start
50
+ alias enable start
51
+
52
+ def stop
53
+ if running?
54
+ IRB.conf[:INSPECT_MODE] = @original_inspect_mode
55
+ IRB.CurrentContext.inspect_mode = @original_inspect_mode if IRB.CurrentContext
56
+ true
57
+ end
58
+ end
59
+ alias deactivate stop
60
+ alias disable stop
96
61
 
97
- # Colorize a result string
98
- def colorize_result(string, custom_schema = schema)
99
- if @running
62
+ def colorize_result(string, _deprecated = nil)
100
63
  check = ''
101
- colorful = tokenize(string).map do |kind, token|
102
- check << token
103
- colorize_string token, *Array( custom_schema[kind] )
104
- end.join
64
+ colorful = ''
65
+ begin
66
+ Tokenizer.run(string).each{ |kind, token|
67
+ check << token
68
+ colorful << Paint[token, *Array( schema[kind] )]
69
+ }
70
+ rescue
71
+ p $!, $!.backtrace[0] if $VERBOSE
72
+ end
105
73
 
106
74
  # always display the correct inspect string!
107
75
  check == string ? colorful : string
108
- else
109
- string
110
76
  end
111
- end
112
- alias colorize_code colorize_result
113
- alias colorize_ruby colorize_result
114
-
115
- private
116
77
 
117
- def compatible_colorizer?(col)
118
- short_col = col.to_s.sub(/^.*::(.*?)$/, '\1').to_sym
119
- if !col
120
- warn "No colorizer selected!"
121
- false
122
- elsif !Array( @schema[:colorizer] ).include?(short_col)
123
- warn "Your current color schema does not support this colorizer:\n" +
124
- " #{ short_col }\n" +
125
- "The following colorizeres are supported with this schema (use Wirb.load_colorizer :Name):\n " +
126
- Array( @schema[:colorizer] ).join("\n ")
127
- false
128
- else
129
- true
78
+ def colorize_result_with_timeout(string)
79
+ if timeout.to_i == 0
80
+ colorize_result(string)
81
+ else
82
+ Timeout.timeout(timeout) do
83
+ colorize_result(string)
84
+ end
85
+ end
86
+ rescue Timeout::Error
87
+ string
130
88
  end
131
89
  end
132
-
133
90
  end
134
-
135
- # J-_-L
@@ -0,0 +1,10 @@
1
+ module Wirb
2
+ INSPECTOR = proc{ |value|
3
+ if defined?(value.inspect)
4
+ Wirb.colorize_result_with_timeout(value.inspect)
5
+ else
6
+ "(Object doesn't support #inspect)"
7
+ end
8
+ }
9
+ end
10
+
data/lib/wirb/irb.rb CHANGED
@@ -1,13 +1,4 @@
1
- require File.dirname(__FILE__) + '/../wirb' unless defined? Wirb
1
+ require_relative '../wirb' unless defined? Wirb
2
+ require 'irb'
2
3
 
3
- class IRB::Irb
4
- alias :output_value_without_wirb :output_value
5
-
6
- def output_value
7
- if @context.inspect?
8
- printf @context.return_format, ::Wirb.colorize_result( @context.last_value.inspect )
9
- else
10
- printf @context.return_format, @context.last_value
11
- end
12
- end
13
- end
4
+ IRB::Inspector.def_inspector(:wirb, &Wirb::INSPECTOR)
@@ -0,0 +1,44 @@
1
+ module Wirb
2
+ module SchemaBuilder
3
+ # Loads a color schema from a yaml file
4
+ # If first argument is a String: path to yaml file
5
+ # If first argument is a Symbol: bundled schema
6
+ def self.load_schema_from_yaml(yaml_path = :classic)
7
+ schema_name, schema_yaml = resolve_schema_yaml(yaml_path)
8
+ raise LoadError, "Could not load the Wirb schema at: #{yaml_path}" unless schema_yaml.is_a?(Hash)
9
+
10
+ schema = normalize_schema(schema_yaml)
11
+ schema[:name] = schema_name.to_sym
12
+ schema
13
+ end
14
+
15
+ def self.resolve_schema_yaml(yaml_path)
16
+ if yaml_path.is_a? Symbol # bundled themes
17
+ [yaml_path.to_s, YAML.load_file(File.join(Gem.datadir('wirb'), "#{yaml_path}.yml"))]
18
+ else
19
+ [File.basename(yaml_path).gsub(/\.yml$/, ''), YAML.load_file(yaml_path)]
20
+ end
21
+ end
22
+
23
+ def self.normalize_schema(schema_yaml)
24
+ normalized_schema = Hash[ schema_yaml.map{ |k,v| [k.to_s.to_sym, Array( v )] } ]
25
+ %w(
26
+ hash
27
+ array
28
+ set
29
+ symbol_string
30
+ string
31
+ regexp
32
+ rational
33
+ complex
34
+ object
35
+ ).each{ |what|
36
+ values = normalized_schema.delete(:"#{what}_delimiter")
37
+ normalized_schema[:"open_#{what}"] = values
38
+ normalized_schema[:"close_#{what}"] = values
39
+ }
40
+
41
+ normalized_schema
42
+ end
43
+ end
44
+ end
@@ -1,500 +1,474 @@
1
- class << Wirb
2
- # This is an extended version of the original wirble tokenizer.
3
- # Many people would say that 400 lines long case statements need refactoring, but
4
- # ...sometimes it is supposed to be this way!
5
- def tokenize(str)
6
- return [] if str.nil?
7
- raise ArgumentError, 'Tokenizer needs an inspect-string' unless str.is_a? String
8
- return enum_for(:tokenize, str) unless block_given?
9
-
10
- chars = str.split(//)
11
-
12
- @state, @token, i = [], '', 0
13
- @passed, snapshot = '', nil # exception handling
14
-
15
- # helpers
16
- pass_custom_state = lambda{ |kind, *options|
17
- yield kind, @token unless @token.empty?
18
- @passed << @token
19
- @state.pop if options.include?(:remove)
20
- @token = '' unless options.include?(:keep_token)
21
- @repeat = true if options.include?(:repeat)
22
- }
23
-
24
- pass_state = lambda{ |*options| pass_custom_state[ @state[-1], *options ] }
25
-
26
- pass = lambda{ |kind, string| @passed << string; yield kind, string }
27
-
28
- set_state = lambda{ |state, *options|
29
- @state[-1] = state
30
- @repeat = true if options.include? :repeat
31
- }
32
-
33
- get_state = lambda{ |state| @state[-1] == state }
34
-
35
- get_previous_state =
36
- lambda{ |state| @state[-2] == state }
37
-
38
- push_state = lambda{ |state, *options|
39
- @state << state
40
- @repeat = true if options.include? :repeat
41
- }
42
-
43
- pop_state = lambda{ |*options|
44
- @state.pop
45
- @repeat = true if options.include? :repeat
46
- }
47
-
48
- # action!
49
- while i <= chars.size
50
- @repeat = false
51
- llc, lc, c, nc = lc, c, chars[i], chars[i+1]
52
-
53
- # warn "char = #{c} state = #{@state*':'}"
54
-
55
- case @state[-1]
56
- when nil, :hash, :array, :enumerator, :set, :variable # default state
57
- case c
58
- when '"' then push_state[:string]
59
- when '/' then push_state[:regexp]
60
- when '#' then push_state[:object]
61
- when /[A-Z]/ then push_state[:class, :repeat]
62
- when /[a-z]/ then push_state[:keyword, :repeat]
63
- when /[0-9-]/ then push_state[:number, :repeat]
64
- when '.' then push_state[:range, :repeat]
65
- when /[~=]/ then push_state[:gem_requirement_condition, :repeat]
66
-
67
- when /\s/
68
- if get_state[:variable]
69
- pop_state[:repeat]
70
- else
71
- pass[:whitespace, c]
72
- end
1
+ module Wirb
2
+ module Tokenizer
3
+ def self.run(str)
4
+ return [] if str.nil?
5
+ raise ArgumentError, 'Tokenizer needs an inspect-string' unless str.is_a? String
6
+ return enum_for(:run, str) unless block_given?
7
+
8
+ chars = str.split('')
9
+
10
+ @state, @token, i = [], '', 0
11
+ @passed, snapshot = '', nil # exception handling
12
+
13
+ # helpers
14
+ pass_custom_state = lambda{ |kind, *options|
15
+ yield kind, @token unless @token.empty?
16
+ @passed << @token
17
+ @state.pop if options.include?(:remove)
18
+ @token = '' unless options.include?(:keep_token)
19
+ @repeat = true if options.include?(:repeat)
20
+ }
21
+
22
+ pass_state = lambda{ |*options|
23
+ pass_custom_state[ @state[-1], *options ]
24
+ }
25
+
26
+ pass = lambda{ |kind, string|
27
+ @passed << string
28
+ yield kind, string
29
+ }
30
+
31
+ set_state = lambda{ |state, *options|
32
+ @state[-1] = state
33
+ @repeat = true if options.include? :repeat
34
+ }
35
+
36
+ get_state = lambda{ |state| @state[-1] == state }
37
+
38
+ get_previous_state =
39
+ lambda{ |state| @state[-2] == state }
40
+
41
+ push_state = lambda{ |state, *options|
42
+ @state << state
43
+ @repeat = true if options.include? :repeat
44
+ }
45
+
46
+ pop_state = lambda{ |*options|
47
+ @state.pop
48
+ @repeat = true if options.include? :repeat
49
+ }
50
+
51
+ # action!
52
+ while i <= chars.size
53
+ @repeat = false
54
+ llc, lc, c, nc = lc, c, chars[i], chars[i+1]
55
+
56
+ # warn "char = #{c} state = #{@state*':'}"
57
+
58
+ case @state[-1]
59
+ when nil, :hash, :array, :enumerator, :set, :variable # default state
60
+ case c
61
+ when '"' then push_state[:string]
62
+ when '/' then push_state[:regexp]
63
+ when '#' then push_state[:object]
64
+ when /[A-Z]/ then push_state[:class, :repeat]
65
+ when /[a-z]/ then push_state[:word, :repeat]
66
+ when /[0-9-]/ then push_state[:number, :repeat]
67
+ when '.' then push_state[:range, :repeat]
68
+ when /\=/ then push_state[:equal, :repeat]
69
+
70
+ when /\s/
71
+ if get_state[:variable]
72
+ pop_state[:repeat]
73
+ else
74
+ pass[:whitespace, c]
75
+ end
73
76
 
74
- when ','
75
- if get_state[:variable]
76
- pop_state[:repeat]
77
- else
78
- pass[:comma, ',']
79
- @refers_seen[-1] = false if get_state[:hash]
80
- end
77
+ when ','
78
+ if get_state[:variable]
79
+ pop_state[:repeat]
80
+ else
81
+ pass[:comma, ',']
82
+ @refers_seen[-1] = false if get_state[:hash]
83
+ end
81
84
 
82
- when ':'
83
- if get_state[:enumerator]
84
- set_state[:object_description, :repeat]
85
- else
86
- push_state[:symbol]
87
- end
88
-
89
- when '>'
90
- if get_state[:variable]
85
+ when ':'
86
+ if get_state[:enumerator]
87
+ set_state[:object_description, :repeat]
88
+ else
89
+ push_state[:symbol]
90
+ end
91
+
92
+ when '>'
91
93
  pop_state[:repeat]
92
- elsif @token == '' && nc =~ /[= ]/
93
- push_state[:gem_requirement_condition, :repeat]
94
- end
95
- when '('
96
- peek = chars[i+1..-1].join
97
- if peek =~ /^-?(?:Infinity|NaN|[0-9.e]+)[+-](?:Infinity|NaN|[0-9.e]+)\*?i\)/
98
- push_state[:complex, :repeat]
99
- elsif nc =~ /[0-9-]/
100
- if @passed =~ /Complex$/ # cheat for old 1.8
94
+ when '('
95
+ peek = chars[i+1..-1].join
96
+ if peek =~ /^-?(?:Infinity|NaN|[0-9.e]+)[+-](?:Infinity|NaN|[0-9.e]+)\*?i\)/
101
97
  push_state[:complex, :repeat]
98
+ elsif nc =~ /[0-9-]/
99
+ if @passed =~ /Complex$/ # cheat for old 1.8
100
+ push_state[:complex, :repeat]
101
+ else
102
+ push_state[:rational, :repeat]
103
+ end
102
104
  else
103
- push_state[:rational, :repeat]
105
+ push_state[:object_description, :repeat]
106
+ open_brackets = 0
104
107
  end
105
- else
106
- push_state[:object_description, :repeat]
107
- open_brackets = 0
108
- end
109
-
110
- when '{'
111
- if get_state[:set]
112
- pass[:open_set, '{']; push_state[nil] # {{ means set-hash
113
- else
114
- pass[:open_hash, '{']; push_state[:hash]
115
- @refers_seen ||= []
116
- @refers_seen.push false
117
- end
118
108
 
119
- when '['
120
- pass[:open_array, '[']; push_state[:array]
121
-
122
- when ']'
123
- if get_state[:array]
124
- pass[:close_array, ']']
109
+ when '{'
110
+ if get_state[:set]
111
+ pass[:open_set, '{']; push_state[nil] # {{ means set-hash
112
+ else
113
+ pass[:open_hash, '{']; push_state[:hash]
114
+ @refers_seen ||= []
115
+ @refers_seen.push false
116
+ end
117
+
118
+ when '['
119
+ pass[:open_array, '[']; push_state[:array]
120
+
121
+ when ']'
122
+ if get_state[:array]
123
+ pass[:close_array, ']']
124
+ pop_state[]
125
+ pop_state[] if get_state[:enumerator]
126
+ end
127
+
128
+ when '}'
129
+ if get_state[:hash]
130
+ pass[:close_hash, '}']
131
+ @refers_seen.pop
132
+ elsif get_previous_state[:set]
133
+ pass[:close_set, '}']
134
+ pop_state[] # remove extra nil state
135
+ end
125
136
  pop_state[]
126
137
  pop_state[] if get_state[:enumerator]
127
- end
128
-
129
- when '}'
130
- if get_state[:hash]
131
- pass[:close_hash, '}']
132
- @refers_seen.pop
133
- elsif get_previous_state[:set]
134
- pass[:close_set, '}']
135
- pop_state[] # remove extra nil state
136
- end
137
- pop_state[]
138
- pop_state[] if get_state[:enumerator]
139
138
 
140
- when '<'
141
- if nc =~ /[= ]/
142
- push_state[:gem_requirement_condition, :repeat]
143
- else # MAYBE slightly refactoring
139
+ when '<'
144
140
  pass[:open_object, '<']
145
141
  push_state[:object]
146
142
  push_state[:object_class]
147
143
  open_brackets = 0
148
144
  end
149
145
 
150
- # else
151
- # warn "ignoring char #{c.inspect}" if @debug
152
- end
153
-
154
- when :class
155
- next set_state[:time, :repeat] if c == ' ' # Ruby 1.8 default timestamp
156
- case c
157
- when /[a-z0-9_]/i
158
- @token << c
159
- else
160
- if @token =~ /^(Infinity|NaN)$/
161
- set_state[:special_number, :repeat]
162
- elsif c ==':' && nc == ':'
163
- pass_state[]
164
- pass[:class_separator, '::']
165
- elsif !(c == ':' && lc == ':')
166
- pass_state[:remove, :repeat]
146
+ when :class
147
+ case c
148
+ when /[a-z0-9_]/i
149
+ @token << c
150
+ else
151
+ if @token =~ /^(Infinity|NaN)$/
152
+ set_state[:special_number, :repeat]
153
+ elsif c ==':' && nc == ':'
154
+ pass_state[]
155
+ pass[:class_separator, '::']
156
+ elsif !(c == ':' && lc == ':')
157
+ pass_state[:remove, :repeat]
158
+ end
167
159
  end
168
- end
169
160
 
170
- when :symbol
171
- case c
172
- when /"/
173
- if lc == '$' && llc == ':'
161
+ when :symbol
162
+ case c
163
+ when /"/
164
+ if lc == '$' && llc == ':'
165
+ @token << c
166
+ else
167
+ pass[:symbol_prefix, ':']
168
+ set_state[:symbol_string]
169
+ end
170
+ when /[^"., }\])=]/
174
171
  @token << c
175
172
  else
176
- pass[:symbol_prefix, ':']
177
- set_state[:symbol_string]
173
+ if c == ']' && lc == '['
174
+ @token << c
175
+ elsif c == '=' && nc != '>'
176
+ @token << c
177
+ elsif c =~ /[.,]/ && lc == '$' && llc == ':'
178
+ @token << c
179
+ else
180
+ pass[:symbol_prefix, ':']
181
+ pass_state[:remove, :repeat]
182
+ end
178
183
  end
179
- when /[^"., }\])=]/
180
- @token << c
181
- else
182
- if c == ']' && lc == '['
184
+
185
+ when :symbol_string
186
+ if c == '"' && ( !( @token =~ /\\+$/; $& ) || $&.size % 2 == 0 ) # see string
187
+ pass[:open_symbol_string, '"']
188
+ pass_state[:remove]
189
+ pass[:close_symbol_string, '"']
190
+ else
183
191
  @token << c
184
- elsif c == '=' && nc != '>'
192
+ end
193
+
194
+ when :string
195
+ if c == '"' && ( !( @token =~ /\\+$/; $& ) || $&.size % 2 == 0 ) # allow escaping of " and
196
+ pass[:open_string, '"'] # work around \\
197
+ pass_state[:remove]
198
+ pass[:close_string, '"']
199
+ else
185
200
  @token << c
186
- elsif c =~ /[.,]/ && lc == '$' && llc == ':'
201
+ end
202
+
203
+ when :regexp
204
+ if c == '/' && ( !( @token =~ /\\+$/; $& ) || $&.size % 2 == 0 ) # see string
205
+ pass[:open_regexp, '/']
206
+ pass_state[:remove]
207
+ pass[:close_regexp, '/']
208
+ push_state[:regexp_flags]
209
+ else
210
+ @token << c
211
+ end
212
+
213
+ when :regexp_flags
214
+ if c =~ /[a-z]/i #*%w[m i x o n e u s]
187
215
  @token << c
188
216
  else
189
- pass[:symbol_prefix, ':']
190
217
  pass_state[:remove, :repeat]
191
218
  end
192
- end
193
-
194
- when :symbol_string
195
- if c == '"' && ( !( @token =~ /\\+$/; $& ) || $&.size % 2 == 0 ) # see string
196
- pass[:open_symbol_string, '"']
197
- pass_state[:remove]
198
- pass[:close_symbol_string, '"']
199
- else
200
- @token << c
201
- end
202
-
203
- when :string
204
- if c == '"' && ( !( @token =~ /\\+$/; $& ) || $&.size % 2 == 0 ) # allow escaping of " and
205
- pass[:open_string, '"'] # work around \\
206
- pass_state[:remove]
207
- pass[:close_string, '"']
208
- else
209
- @token << c
210
- end
211
219
 
212
- when :regexp
213
- if c == '/' && ( !( @token =~ /\\+$/; $& ) || $&.size % 2 == 0 ) # see string
214
- pass[:open_regexp, '/']
215
- pass_state[:remove]
216
- pass[:close_regexp, '/']
217
- push_state[:regexp_flags]
218
- else
219
- @token << c
220
- end
221
-
222
- when :regexp_flags
223
- if c =~ /[a-z]/i #*%w[m i x o n e u s]
224
- @token << c
225
- else
226
- pass_state[:remove, :repeat]
227
- end
220
+ when :word
221
+ if c =~ /[a-z0-9_]/i
222
+ @token << c
223
+ pass_custom_state[@token.to_sym, :remove] if %w[nil false true].include?(@token)
224
+ else
225
+ pass_state[:remove, :repeat]
226
+ end
228
227
 
229
- when :keyword
230
- if c =~ /[a-z0-9_]/i
231
- @token << c
232
- pass_custom_state[@token.to_sym, :remove] if %w[nil false true].include?(@token)
233
- else
234
- pass_state[:remove, :repeat]
235
- end
228
+ when :number
229
+ if c == '-' && @token != '' && @token[-1] != 'e'
230
+ set_state[:time, :repeat]
231
+ elsif c =~ /[IN]/
232
+ set_state[:special_number, :repeat]
233
+ elsif c =~ /[0-9e.*i+-]/ && !(c == '.' && nc == '.')
234
+ @token << c
235
+ else
236
+ pass_state[:remove, :repeat]
237
+ end
236
238
 
237
- when :number
238
- if c == '-' && @token != '' && @token[-1] != 'e'
239
- set_state[:time, :repeat]
240
- elsif c =~ /[IN]/
241
- set_state[:special_number, :repeat]
242
- elsif c =~ /[0-9e.*i+-]/ && !(c == '.' && nc == '.')
243
- @token << c
244
- elsif c == '/' # ruby 1.8 mathn
245
- pass_state[]
246
- pass[:rational_separator, '/']
247
- else
248
- pass_state[:remove, :repeat]
249
- end
239
+ when :time # via regex, state needs to be triggered somewhere else
240
+ peek = chars[i..-1].join
241
+ if [
242
+ /^\d+-\d{2}-\d{2} \d{2}:\d{2}:\d{2} (?:[+-]\d{4}|[a-z]{3})/i, # 1.9 / UTC
243
+ ].any?{ |regex|
244
+ ( @token + peek ) =~ regex
245
+ } # found, adjust parsing-pointer:
246
+ i = i + $&.size - @token.size - 1
247
+ @token = $&
248
+ pass_state[:remove]
249
+ else
250
+ @token << c
251
+ pop_state[:remove]
252
+ end
250
253
 
251
- when :time # via regex, state needs to be triggered somewhere else
252
- peek = chars[i..-1].join
253
- if [
254
- /^\d+-\d{2}-\d{2} \d{2}:\d{2}:\d{2} (?:[+-]\d{4}|[a-z]{3})/i, # 1.9 / UTC
255
- /^[a-z]{3} [a-z]{3} \d{2} \d{2}:\d{2}:\d{2} (?:[+-]\d{4}|[a-z]{3}) \d{4}/i, # 1.8
256
- #/^\d+-\d{2}-\d{2}/, # simple date
257
- ].any?{ |regex|
258
- ( @token + peek ) =~ regex
259
- } # found, adjust parsing-pointer:
260
- i = i + $&.size - @token.size - 1
261
- @token = $&
262
- pass_state[:remove]
263
- else
264
- @token << c
265
- pop_state[:remove]
266
- end
254
+ when :special_number # like time, refactor if code is needed a third time
255
+ peek = chars[i..-1].join
256
+ if [
257
+ /^[-+]?Infinity/,
258
+ /^[-+]?NaN/,
259
+ ].any?{ |regex|
260
+ ( @token + peek ) =~ regex
261
+ } # found, adjust parsing-pointer:
262
+ i = i + $&.size - @token.size - 1
263
+ @token = $&
264
+ pass_state[]
265
+ set_state[:number]
266
+ else
267
+ # TODO verify...
268
+ @token << c
269
+ set_state[:number]
270
+ end
267
271
 
268
- when :special_number # like time, refactor if code is needed a third time
269
- peek = chars[i..-1].join
270
- if [
271
- /^[-+]?Infinity/,
272
- /^[-+]?NaN/,
273
- ].any?{ |regex|
274
- ( @token + peek ) =~ regex
275
- } # found, adjust parsing-pointer:
276
- i = i + $&.size - @token.size - 1
277
- @token = $&
278
- pass_state[]
279
- set_state[:number]
280
- else
281
- # TODO verify...
282
- @token << c
283
- set_state[:number]
284
- end
285
-
286
- when :range
287
- if c == '.'
288
- @token << c
289
- else
290
- pass_state[:remove, :repeat]
291
- end
272
+ when :range
273
+ if c == '.'
274
+ @token << c
275
+ else
276
+ pass_state[:remove, :repeat]
277
+ end
292
278
 
293
- when :rational
294
- case c
295
- when '('
296
- pass[:open_rational, '(']
297
- when /[0-9-]/
298
- push_state[:number, :repeat]
299
- when '/', ','
300
- pass[:rational_separator, c]
301
- when ' '
302
- pass[:whitespace, c]
303
- when ')'
304
- pass[:close_rational, ')']
305
- pop_state[]
306
- end
279
+ when :rational
280
+ case c
281
+ when '('
282
+ pass[:open_rational, '(']
283
+ when /[0-9-]/
284
+ push_state[:number, :repeat]
285
+ when '/', ','
286
+ pass[:rational_separator, c]
287
+ when ' '
288
+ pass[:whitespace, c]
289
+ when ')'
290
+ pass[:close_rational, ')']
291
+ pop_state[]
292
+ end
307
293
 
308
- when :complex
309
- case c
310
- when '('
311
- pass[:open_complex, '(']
312
- when /[0-9+-]/
313
- push_state[:number, :repeat]
314
- when ','
315
- pass[:number, c] # complex_separator
316
- when ' '
317
- pass[:whitespace, c]
318
- when ')'
319
- pass[:close_complex, ')']
320
- pop_state[]
321
- end
294
+ when :complex
295
+ case c
296
+ when '('
297
+ pass[:open_complex, '(']
298
+ when /[0-9+-]/
299
+ push_state[:number, :repeat]
300
+ when ','
301
+ pass[:number, c] # complex_separator
302
+ when ' '
303
+ pass[:whitespace, c]
304
+ when ')'
305
+ pass[:close_complex, ')']
306
+ pop_state[]
307
+ end
322
308
 
323
- when :object
324
- case c
325
- when '<'
326
- pass[:open_object, '#<']
327
- push_state[:object_class]
328
- open_brackets = 0
329
- when '>'
330
- pass[:close_object, '>']
331
- pop_state[]
332
- pop_state[] if get_state[:enumerator]
333
- end
309
+ when :object
310
+ case c
311
+ when '<'
312
+ pass[:open_object, '#<']
313
+ push_state[:object_class]
314
+ open_brackets = 0
315
+ when '>'
316
+ pass[:close_object, '>']
317
+ pop_state[]
318
+ pop_state[] if get_state[:enumerator]
319
+ end
334
320
 
335
- when :object_class
336
- case c
337
- when /[a-z0-9_]/i
338
- @token << c
339
- when '>'
340
- pass_state[:remove, :repeat]
341
- else
342
- if c == ':' && nc == ':'
343
- pass_state[]
344
- pass[:class_separator, '::']
345
- elsif !(c == ':' && lc == ':')
346
- pass_state[:keep_token]
347
- pass[:object_description_prefix, c]
348
-
349
- @token = @token.downcase
350
- if %w[set instructionsequence].include?(@token)
351
- set_state[@token.to_sym]
352
- else
353
- set_state[:object_description]
354
- if %w[enumerator].include?(@token) && RUBY_VERSION >= '1.9'
355
- push_state[@token.to_sym]
321
+ when :object_class
322
+ case c
323
+ when /[a-z0-9_]/i
324
+ @token << c
325
+ when '>'
326
+ pass_state[:remove, :repeat]
327
+ else
328
+ if c == ':' && nc == ':'
329
+ pass_state[]
330
+ pass[:class_separator, '::']
331
+ elsif c != ':' || lc != ':'
332
+ pass_state[:keep_token]
333
+ pass[:object_description_prefix, c]
334
+
335
+ @token = @token.downcase
336
+ if %w[set instructionsequence].include?(@token)
337
+ set_state[@token.to_sym]
338
+ else
339
+ set_state[:object_description]
340
+ if @token == "enumerator" && RUBY_ENGINE != "rbx"
341
+ push_state[:enumerator]
342
+ end
356
343
  end
344
+ @token = ''
357
345
  end
358
- @token = ''
359
346
  end
360
- end
361
347
 
362
- when :object_description
363
- case c
364
- when '>', nil
365
- if open_brackets == 0
366
- pass_state[:remove, :repeat]
367
- else
368
- open_brackets -= 1
348
+ when :object_description
349
+ case c
350
+ when '>', nil
351
+ if open_brackets == 0
352
+ pass_state[:remove, :repeat]
353
+ else
354
+ open_brackets -= 1
355
+ @token << c
356
+ end
357
+ when '#'
358
+ if nc == '<'
359
+ pass_state[]
360
+ push_state[:object]
361
+ else
362
+ @token << c
363
+ end
364
+ when '<'
365
+ open_brackets += 1
369
366
  @token << c
370
- end
371
- when '#'
372
- if nc == '<'
367
+ when '@'
368
+ if nc =~ /[a-z_]/i
369
+ pass_state[]
370
+ push_state[:object_variable]
371
+ else
372
+ @token << c
373
+ end
374
+ when '"'
373
375
  pass_state[]
374
- push_state[:object]
376
+ push_state[:string]
377
+ when /[0-9]/
378
+ if c == '0' && nc == 'x'
379
+ pass_state[:repeat]
380
+ push_state[:object_address]
381
+ else
382
+ # push_state[:number, :repeat]
383
+ @token << c
384
+ end
375
385
  else
376
386
  @token << c
377
387
  end
378
- when '<'
379
- open_brackets += 1
380
- @token << c
381
- when '@'
382
- if nc =~ /[a-z]/i
383
- pass_state[]
384
- push_state[:object_variable]
388
+
389
+ when :object_variable
390
+ if c =~ /[a-z0-9_]/i
391
+ @token << c
385
392
  else
393
+ pass[:object_variable_prefix, '@']
394
+ pass_state[:remove]
395
+ pass[:object_description, '=']
396
+ push_state[:variable]
397
+ end
398
+
399
+ when :object_address
400
+ if c =~ /[x0-9a-f]/
386
401
  @token << c
402
+ else
403
+ if c == '@'
404
+ pass_state[:remove]
405
+ push_state[:object_line]
406
+ pass[:object_line_prefix, '@']
407
+ else
408
+ pass_state[:remove, :repeat]
409
+ end
387
410
  end
388
- when '"'
389
- pass_state[]
390
- push_state[:string]
391
- when /[0-9]/
392
- if c == '0' && nc == 'x'
393
- pass_state[:repeat]
394
- push_state[:object_address]
411
+
412
+ when :object_line
413
+ if c == ':' && nc =~ /[0-9]/
414
+ @token << ':'
415
+ pass_state[:remove]
416
+ push_state[:object_line_number]
417
+ elsif c == '>' # e.g. RubyVM
418
+ pass_state[:remove, :repeat]
395
419
  else
396
- # push_state[:number, :repeat]
397
420
  @token << c
398
421
  end
399
- else
400
- @token << c
401
- end
402
422
 
403
- when :object_variable
404
- if c =~ /[a-z0-9_]/i
405
- @token << c
406
- else
407
- pass[:object_variable_prefix, '@']
408
- pass_state[:remove]
409
- pass[:object_description, '=']
410
- push_state[:variable]
411
- end
412
-
413
- when :object_address
414
- if c =~ /[x0-9a-f]/
415
- @token << c
416
- else
417
- if c == '@'
418
- pass_state[:remove]
419
- push_state[:object_line]
420
- pass[:object_line_prefix, '@']
423
+ when :object_line_number
424
+ if c =~ /[0-9]/
425
+ @token << c
421
426
  else
422
427
  pass_state[:remove, :repeat]
423
428
  end
424
- end
425
429
 
426
- when :object_line
427
- if c == ':' && nc =~ /[0-9]/
428
- @token << ':'
429
- pass_state[:remove]
430
- push_state[:object_line_number]
431
- elsif c == '>' # e.g. RubyVM
432
- pass_state[:remove, :repeat]
433
- else
434
- @token << c
435
- end
436
-
437
- when :object_line_number
438
- if c =~ /[0-9]/
439
- @token << c
440
- else
441
- pass_state[:remove, :repeat]
442
- end
443
-
444
- when :gem_requirement_condition
445
- if c == '>' && lc == '='
446
- @token = ''; pop_state[] # TODO in pass helper
447
- if get_state[:hash]
448
- if nc == '=' || @refers_seen[-1]
430
+ when :equal
431
+ if c == '>' && lc == '='
432
+ @token = ''; pop_state[] # TODO in pass helper
433
+ if get_state[:hash]
434
+ if nc == '=' || @refers_seen[-1]
435
+ pass[:symbol, '=>']
436
+ else
437
+ pass[:refers, '=>']
438
+ @refers_seen[-1] = true
439
+ end
440
+ else # MAYBE remove this <=> cheat
449
441
  pass[:symbol, '=>']
450
- else
451
- pass[:refers, '=>']
452
- @refers_seen[-1] = true
453
442
  end
454
- else # MAYBE remove this <=> cheat
455
- pass[:symbol, '=>']
443
+ elsif c =~ /\S/
444
+ @token << c
445
+ else
446
+ pass[:whitespace, c]
456
447
  end
457
- elsif c =~ /[^\s]/
458
- @token << c
459
- else
460
- pass_state[:remove]
461
- pass[:whitespace, c]
462
- push_state[:gem_requirement_version]
463
- end
464
448
 
465
- when :gem_requirement_version
466
- if c =~ /[0-9a-z.]/i
467
- @token << c
468
- else
469
- pass_state[:remove, :repeat]
470
- end
449
+ when :instructionsequence # RubyVM
450
+ if c =~ /[^@]/i
451
+ @token << c
452
+ else
453
+ pass[:object_line_prefix, @token + '@']
454
+ @token = ''
455
+ set_state[:object_line]
456
+ end
471
457
 
472
- when :instructionsequence # RubyVM
473
- if c =~ /[^@]/i
474
- @token << c
475
458
  else
476
- pass[:object_line_prefix, @token + '@']
477
- @token = ''
478
- set_state[:object_line]
459
+ raise "unknown state #{@state[-1]} #{@state.inspect}"
479
460
  end
480
461
 
481
-
482
- # else
483
- # raise "unknown state #{@state[-1]} #{@state.inspect}"
484
- end
462
+ # next round
463
+ if !@repeat
464
+ i += 1
465
+ elsif snapshot && Marshal.load(snapshot) == [@state, @token, llc, lc, c, nc] # loop protection
466
+ raise "This might be a WIRB bug, please open an issue at:\nhttps://github.com/janlelis/wirb/issues/new"
467
+ end
485
468
 
486
- # next round :)
487
- if !@repeat
488
- i += 1
489
- elsif snapshot && Marshal.load(snapshot) == [@state, @token, llc, lc, c, nc] # loop protection
490
- raise 'Wirb Bug :/'
469
+ snapshot = Marshal.dump([@state, @token, llc, lc, c, nc])
491
470
  end
492
-
493
- snapshot = Marshal.dump([@state, @token, llc, lc, c, nc])
494
471
  end
495
- rescue
496
- p$!, $!.backtrace[0] if $VERBOSE
497
- pass[:default, str.sub(@passed, '')]
498
472
  end
499
473
  end
500
474