sourcify 0.1.2 → 0.2.0

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 (40) hide show
  1. data/.gitignore +1 -0
  2. data/HISTORY.txt +11 -0
  3. data/README.rdoc +52 -28
  4. data/VERSION +1 -1
  5. data/lib/sourcify.rb +13 -1
  6. data/lib/sourcify/proc.rb +7 -4
  7. data/lib/sourcify/proc/parser.rb +109 -40
  8. data/lib/sourcify/proc/scanner.rb +2140 -0
  9. data/lib/sourcify/proc/scanner.rl +285 -0
  10. data/lib/sourcify/proc/scanner/comment.rb +21 -0
  11. data/lib/sourcify/proc/scanner/counter.rb +44 -0
  12. data/lib/sourcify/proc/scanner/dstring.rb +58 -0
  13. data/lib/sourcify/proc/scanner/extensions.rb +135 -0
  14. data/lib/sourcify/proc/scanner/heredoc.rb +24 -0
  15. data/sourcify.gemspec +38 -9
  16. data/spec/dump_object_space_procs.rb +84 -0
  17. data/spec/proc/created_on_the_fly_proc_spec.rb +172 -0
  18. data/spec/proc/others_spec.rb +36 -0
  19. data/spec/proc/to_sexp_variables_spec.rb +6 -6
  20. data/spec/proc/to_source_from_do_end_block_w_nested_literal_keyword_spec.rb +2 -0
  21. data/spec/proc/to_source_from_multi_blocks_w_many_matches_spec.rb +105 -29
  22. data/spec/proc/to_source_from_multi_blocks_w_single_match_spec.rb +85 -17
  23. data/spec/proc_scanner/block_comment_spec.rb +59 -0
  24. data/spec/proc_scanner/double_colons_spec.rb +14 -0
  25. data/spec/proc_scanner/double_quote_str_w_interpolation_spec.rb +62 -0
  26. data/spec/proc_scanner/double_quote_str_wo_interpolation_spec.rb +75 -0
  27. data/spec/proc_scanner/heredoc_spec.rb +142 -0
  28. data/spec/proc_scanner/kw_do_alias1_spec.rb +87 -0
  29. data/spec/proc_scanner/kw_do_alias2_spec.rb +86 -0
  30. data/spec/proc_scanner/per_line_comment_spec.rb +34 -0
  31. data/spec/proc_scanner/single_quote_str_spec.rb +68 -0
  32. data/spec/proc_scanner/spec_helper.rb +33 -0
  33. data/spec/proc_scanner/to_proc_spec.rb +15 -0
  34. data/spec/spec_helper.rb +23 -0
  35. metadata +39 -10
  36. data/lib/sourcify/proc/counter.rb +0 -41
  37. data/lib/sourcify/proc/lexer.rb +0 -40
  38. data/lib/sourcify/proc/lexer18.rb +0 -237
  39. data/lib/sourcify/proc/lexer19.rb +0 -204
  40. data/spec/proc/misc_spec.rb +0 -16
@@ -0,0 +1,15 @@
1
+ require File.join(File.dirname(__FILE__), 'spec_helper')
2
+
3
+ describe "#to_proc" do
4
+
5
+ should 'handle &:xxx' do
6
+ process(" &:xxx ").should.include([:to_proc, '&:xxx'])
7
+ end
8
+
9
+ %w{&xxx :xxx}.each do |expr|
10
+ should "handle not #{expr}" do
11
+ process(" #{expr} ").map(&:first).should.not.include(:to_proc)
12
+ end
13
+ end
14
+
15
+ end
@@ -6,6 +6,18 @@ $LOAD_PATH.unshift(File.dirname(__FILE__))
6
6
  $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
7
7
  require 'sourcify'
8
8
 
9
+ ragel_dir = File.join(File.dirname(__FILE__), '..', 'lib', 'sourcify', 'proc')
10
+ ragel_file = File.join(ragel_dir, 'scanner.rl')
11
+ ruby_file = File.join(ragel_dir, 'scanner.rb')
12
+ File.delete(ruby_file) rescue nil
13
+ system("ragel -R #{ragel_file}")
14
+
15
+ begin
16
+ require File.join(ragel_dir, 'scanner.rb')
17
+ rescue LoadError
18
+ raise $!
19
+ end
20
+
9
21
  Bacon.summary_on_exit
10
22
 
11
23
  def watever(*args, &block)
@@ -39,3 +51,14 @@ def having_sexp(expected)
39
51
  end
40
52
  end
41
53
 
54
+ def capture(stdin_str = '')
55
+ begin
56
+ require 'stringio'
57
+ $o_stdin, $o_stdout, $o_stderr = $stdin, $stdout, $stderr
58
+ $stdin, $stdout, $stderr = StringIO.new(stdin_str), StringIO.new, StringIO.new
59
+ yield
60
+ {:stdout => $stdout.string, :stderr => $stderr.string}
61
+ ensure
62
+ $stdin, $stdout, $stderr = $o_stdin, $o_stdout, $o_stderr
63
+ end
64
+ end
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: sourcify
3
3
  version: !ruby/object:Gem::Version
4
- hash: 31
4
+ hash: 23
5
5
  prerelease: false
6
6
  segments:
7
7
  - 0
8
- - 1
9
8
  - 2
10
- version: 0.1.2
9
+ - 0
10
+ version: 0.2.0
11
11
  platform: ruby
12
12
  authors:
13
13
  - NgTzeYang
@@ -15,7 +15,7 @@ autorequire:
15
15
  bindir: bin
16
16
  cert_chain: []
17
17
 
18
- date: 2010-08-30 00:00:00 +08:00
18
+ date: 2010-09-11 00:00:00 +08:00
19
19
  default_executable:
20
20
  dependencies:
21
21
  - !ruby/object:Gem::Dependency
@@ -67,14 +67,19 @@ files:
67
67
  - VERSION
68
68
  - lib/sourcify.rb
69
69
  - lib/sourcify/proc.rb
70
- - lib/sourcify/proc/counter.rb
71
- - lib/sourcify/proc/lexer.rb
72
- - lib/sourcify/proc/lexer18.rb
73
- - lib/sourcify/proc/lexer19.rb
74
70
  - lib/sourcify/proc/parser.rb
71
+ - lib/sourcify/proc/scanner.rb
72
+ - lib/sourcify/proc/scanner.rl
73
+ - lib/sourcify/proc/scanner/comment.rb
74
+ - lib/sourcify/proc/scanner/counter.rb
75
+ - lib/sourcify/proc/scanner/dstring.rb
76
+ - lib/sourcify/proc/scanner/extensions.rb
77
+ - lib/sourcify/proc/scanner/heredoc.rb
75
78
  - sourcify.gemspec
79
+ - spec/dump_object_space_procs.rb
76
80
  - spec/proc/19x_extras.rb
77
- - spec/proc/misc_spec.rb
81
+ - spec/proc/created_on_the_fly_proc_spec.rb
82
+ - spec/proc/others_spec.rb
78
83
  - spec/proc/readme
79
84
  - spec/proc/to_sexp_variables_spec.rb
80
85
  - spec/proc/to_source_from_braced_block_w_nested_braced_block_spec.rb
@@ -99,6 +104,17 @@ files:
99
104
  - spec/proc/to_source_magic_file_var_spec.rb
100
105
  - spec/proc/to_source_magic_line_var_spec.rb
101
106
  - spec/proc/to_source_variables_spec.rb
107
+ - spec/proc_scanner/block_comment_spec.rb
108
+ - spec/proc_scanner/double_colons_spec.rb
109
+ - spec/proc_scanner/double_quote_str_w_interpolation_spec.rb
110
+ - spec/proc_scanner/double_quote_str_wo_interpolation_spec.rb
111
+ - spec/proc_scanner/heredoc_spec.rb
112
+ - spec/proc_scanner/kw_do_alias1_spec.rb
113
+ - spec/proc_scanner/kw_do_alias2_spec.rb
114
+ - spec/proc_scanner/per_line_comment_spec.rb
115
+ - spec/proc_scanner/single_quote_str_spec.rb
116
+ - spec/proc_scanner/spec_helper.rb
117
+ - spec/proc_scanner/to_proc_spec.rb
102
118
  - spec/spec_helper.rb
103
119
  has_rdoc: true
104
120
  homepage: http://github.com/ngty/sourcify
@@ -135,9 +151,21 @@ signing_key:
135
151
  specification_version: 3
136
152
  summary: Workarounds before ruby-core officially supports Proc#to_source (& friends)
137
153
  test_files:
154
+ - spec/proc_scanner/kw_do_alias1_spec.rb
155
+ - spec/proc_scanner/single_quote_str_spec.rb
156
+ - spec/proc_scanner/to_proc_spec.rb
157
+ - spec/proc_scanner/kw_do_alias2_spec.rb
158
+ - spec/proc_scanner/double_colons_spec.rb
159
+ - spec/proc_scanner/block_comment_spec.rb
160
+ - spec/proc_scanner/per_line_comment_spec.rb
161
+ - spec/proc_scanner/heredoc_spec.rb
162
+ - spec/proc_scanner/double_quote_str_w_interpolation_spec.rb
163
+ - spec/proc_scanner/spec_helper.rb
164
+ - spec/proc_scanner/double_quote_str_wo_interpolation_spec.rb
138
165
  - spec/proc/to_source_from_do_end_block_w_nested_until_spec.rb
139
166
  - spec/proc/to_source_from_do_end_block_w_nested_begin_spec.rb
140
167
  - spec/proc/to_source_from_braced_block_w_nested_hash_spec.rb
168
+ - spec/proc/created_on_the_fly_proc_spec.rb
141
169
  - spec/proc/to_source_from_braced_block_wo_nesting_complication_spec.rb
142
170
  - spec/proc/to_source_from_do_end_block_w_nested_while_spec.rb
143
171
  - spec/proc/to_source_from_multi_do_end_blocks_w_single_match_spec.rb
@@ -151,13 +179,14 @@ test_files:
151
179
  - spec/proc/to_source_magic_line_var_spec.rb
152
180
  - spec/proc/to_source_from_do_end_block_w_nested_literal_keyword_spec.rb
153
181
  - spec/proc/to_source_from_do_end_block_w_nested_unless_spec.rb
182
+ - spec/proc/others_spec.rb
154
183
  - spec/proc/19x_extras.rb
155
184
  - spec/proc/to_source_from_braced_block_w_nested_braced_block_spec.rb
156
185
  - spec/proc/to_source_from_do_end_block_wo_nesting_complication_spec.rb
157
186
  - spec/proc/to_source_variables_spec.rb
158
187
  - spec/proc/to_sexp_variables_spec.rb
159
188
  - spec/proc/to_source_magic_file_var_spec.rb
160
- - spec/proc/misc_spec.rb
161
189
  - spec/proc/to_source_from_do_end_block_w_nested_if_spec.rb
162
190
  - spec/proc/to_source_from_do_end_block_w_nested_for_spec.rb
191
+ - spec/dump_object_space_procs.rb
163
192
  - spec/spec_helper.rb
@@ -1,41 +0,0 @@
1
- module Sourcify
2
- module Proc
3
- class Counter #:nodoc:all
4
-
5
- attr_accessor :marker
6
-
7
- def initialize
8
- @marker, @counter = nil, {:start => 0, :end => 0}
9
- end
10
-
11
- def [](key)
12
- @counter[key]
13
- end
14
-
15
- def started?
16
- @counter.values != [0,0]
17
- end
18
-
19
- def telly?
20
- @counter[:start] == @counter[:end]
21
- end
22
-
23
- def decrement_start
24
- @counter[:start] -= 1
25
- self
26
- end
27
-
28
- def increment_start
29
- @counter[:start] += 1
30
- self
31
- end
32
-
33
- def increment_end
34
- @counter[:end] += 1
35
- self
36
- end
37
-
38
- end
39
- end
40
- end
41
-
@@ -1,40 +0,0 @@
1
- module Sourcify
2
- module Proc
3
- module Lexer #:nodoc:all
4
-
5
- class << self
6
- def new(*args)
7
- begin
8
- require 'sourcify/proc/lexer19'
9
- Lexer19.new(*args)
10
- rescue LoadError
11
- require 'sourcify/proc/lexer18'
12
- Lexer18.new(*args)
13
- end
14
- end
15
- end
16
-
17
- module Commons
18
-
19
- class EndOfBlock < Exception ; end
20
- class EndOfLine < Exception ; end
21
-
22
- def work
23
- begin
24
- @results ||= []
25
- @do_end_counter = Sourcify::Proc::Counter.new
26
- @braced_counter = Sourcify::Proc::Counter.new
27
- lex
28
- rescue EndOfBlock
29
- @results << @result.dup
30
- @is_multiline_block ? @results : retry
31
- rescue EndOfLine
32
- @results
33
- end
34
- end
35
-
36
- end
37
-
38
- end
39
- end
40
- end
@@ -1,237 +0,0 @@
1
- require 'irb/ruby-lex'
2
- require 'irb/ruby-token'
3
-
4
- module Sourcify
5
- module Proc
6
- class Lexer18 #:nodoc:all
7
-
8
- # NOTE: Implementation of this class has been heavily inspired by:
9
- # * the discussion @ http://www.justskins.com/forums/breaking-ruby-code-into-117453.html
10
- # * Florian Groß's solution for ruby quiz 'SerializableProc (#38)'
11
- # @ http://rubyquiz.com/quiz38.html
12
-
13
- include Lexer::Commons
14
-
15
- def initialize(io, file, line)
16
- @file, @line, @io, @pos = file, line, io, io.pos
17
- @lex = RubyLex.new
18
- @lex.set_input(@io)
19
- @lex.get_readed
20
- end
21
-
22
- def lex
23
- (@tokens = []).extend(Extensions)
24
- @magic_lines = []
25
-
26
- while @tk = @lex.token
27
- tkc = @tk.class.to_s.sub(/\ARubyToken::/, '').downcase.to_sym
28
- @tokens << [@tk.line_no, @tk.char_no, tkc]
29
- post_qstring if @qstring_data
30
- @lex.get_readed if tkc == :tknl
31
- next if @do_end_counter.started? && @tokens.curr.symbolized_keyword?
32
- send(:"on_#{tkc}") rescue NoMethodError
33
- end
34
- end
35
-
36
- def on_tknl
37
- raise EndOfLine unless @results.empty?
38
- end
39
-
40
- def on_tk__line__
41
- @magic_lines << [@tk.seek, @tk.line_no + @line]
42
- end
43
-
44
- def on_tkdstring
45
- @qstring_data = [@tk.seek, @tk.line_no + @line]
46
- end
47
-
48
- alias_method :on_tkstring, :on_tkdstring # heredoc
49
- alias_method :on_tkdregexp, :on_tkdstring # regexp
50
- alias_method :on_tkdxstring, :on_tkdstring # ` command
51
-
52
- def post_qstring
53
- seek, line = @qstring_data
54
- @magic_lines << [(seek .. @tk.seek), line]
55
- @qstring_data = nil
56
- end
57
-
58
- def on_tkdo
59
- if !@do_end_counter.started?
60
- @do_end_counter.marker = @tk.seek
61
- @do_end_counter.increment_start
62
- elsif @tokens.same_as_curr_line.keywords(:tkfor, :tkwhile, :tkuntil).empty?
63
- # It is possible for a 'for', 'while' or 'until' to have an attached 'do',
64
- # for such a case, we want to skip it
65
- @do_end_counter.increment_start
66
- end
67
- end
68
-
69
- def on_tkend
70
- if @do_end_counter.started? && @do_end_counter.increment_end.telly?
71
- @result = grab_result_and_reset_lex(@do_end_counter.marker, 3)
72
- @is_multiline_block = @tokens.multiline?
73
- raise EndOfBlock
74
- end
75
- end
76
-
77
- def on_tkclass
78
- # Pretty straightforward for these, each of them will consume an 'end' close it
79
- @do_end_counter.increment_start if @do_end_counter.started?
80
- end
81
-
82
- # These work the same as 'class', the exception is 'for', which can have an optional
83
- # 'do' attached:
84
- # * for a in [1,2] do ... end
85
- # * for a in [1,2] \n ... end
86
- %w{def module begin case for}.each{|kw| alias_method :"on_tk#{kw}", :on_tkclass }
87
-
88
- def on_tkwhile
89
- # This has optional trailing 'do', and can work as a modifier as well, eg:
90
- # * while true do ... end # => 'do' must be on the same line as 'while'
91
- # * while true \n ... end
92
- # * ... while true # => 'while' is pre-pended with non-spaces
93
- if @do_end_counter.started? && @tokens.start_of_line?
94
- @do_end_counter.increment_start
95
- end
96
- end
97
-
98
- # These work exactly the same as 'while'.
99
- %w{until if unless}.each{|kw| alias_method :"on_tk#{kw}", :on_tkwhile }
100
-
101
- def on_tklbrace
102
- unless @do_end_counter.started?
103
- @braced_counter.marker = @tk.seek unless @braced_counter.started?
104
- @braced_counter.increment_start
105
- end
106
- end
107
-
108
- def on_tkrbrace
109
- if @braced_counter.started? && @braced_counter.increment_end.telly?
110
- @result = grab_result_and_reset_lex(@braced_counter.marker, 1)
111
- @is_multiline_block = @tokens.multiline?
112
- raise EndOfBlock
113
- end
114
- end
115
-
116
- alias_method :on_tkflbrace, :on_tklbrace
117
- alias_method :on_tkfrbrace, :on_tkrbrace
118
-
119
- def on_tkassoc
120
- if @braced_counter.started? && @braced_counter[:start] == 1
121
- @braced_counter.decrement_start
122
- end
123
- end
124
-
125
- def on_tkgt
126
- on_tkassoc if @tokens[-2 .. -1].map(&:last) == [:tkassign, :tkgt]
127
- end
128
-
129
- def grab_result_and_reset_lex(marker, offset)
130
- @io.seek(@pos+marker)
131
- diff = @tk.seek - marker + offset
132
- result = replace_magic_lines(@io.read(diff), marker)
133
- @io.seek(@pos + diff)
134
- @lex.set_input(@io)
135
- @lex.get_readed
136
- result
137
- end
138
-
139
- def replace_magic_lines(result, marker, offset = 0)
140
- @magic_lines.inject(result) do |rs, (pos,val)|
141
- meth = :"replace_magic_line_by_#{pos.class.to_s.downcase}"
142
- n_rs = send(meth, rs, marker + offset, pos, val)
143
- offset = result.length - n_rs.length
144
- n_rs
145
- end
146
- end
147
-
148
- def replace_magic_line_by_fixnum(rs, offset, pos, val)
149
- m = rs.match(/^(.{#{pos - offset}})__LINE__(.*)$/m)
150
- m[1] + val.pred.to_s + m[2]
151
- end
152
-
153
- def replace_magic_line_by_range(rs, offset, pos, lineno)
154
- @io.seek(@pos + pos.begin)
155
- subject = @io.read(pos.end - pos.begin)
156
- return rs if %w{' %q %w}.any?{|q| subject.start_with?(q) }
157
- prepend, append = rs.match(/^(.*?)#{Regexp.quote(subject)}(.*)$/m)[1..2]
158
- middle = subject.split("\n").each_with_index do |line, i|
159
- line.gsub!(pattern = /(.*?\#\{)__LINE__(\})/) do |s|
160
- (m = s.match(pattern)[1..2])[0].end_with?('\\#{') ?
161
- s : m.insert(1, (lineno + i).pred.to_s).join
162
- end
163
- end.join("\n")
164
- prepend + middle + append
165
- end
166
-
167
- # Ease working with the hybrid token set collected from RubyLex
168
- module Extensions
169
-
170
- ROW, COL, TYP = 0, 1, 2
171
-
172
- def same_as_curr_line
173
- same_line(curr_line)
174
- end
175
-
176
- def multiline?
177
- self[0][ROW] != self[-1][ROW]
178
- end
179
-
180
- def curr_line
181
- curr[ROW]
182
- end
183
-
184
- def curr
185
- (self[-1]).respond_to?(:symbolized_keyword?) ? self[-1] : (
186
- preceding, current = self[-2 .. -1]
187
- (class << current ; self ; end).class_eval do
188
- define_method(:symbolized_keyword?) do
189
- preceding[TYP] == :tksymbeg && %w{
190
- class module def while until if unless for do begin case end
191
- }.include?(current[TYP].to_s.sub('tk',''))
192
- end
193
- end
194
- current
195
- )
196
- self[-1]
197
- end
198
-
199
- def same_line(line)
200
- (
201
- # ignore the current node
202
- self[0..-2].reverse.take_while do |e|
203
- if e[TYP] == :tsemi
204
- false
205
- elsif e[ROW] == line
206
- true
207
- elsif e[ROW] == line.pred && e[TYP] != :tknl
208
- line -= 1
209
- true
210
- end
211
- end.reverse
212
- ).extend(Extensions)
213
- end
214
-
215
- def keywords(*types)
216
- (
217
- types = [types].flatten
218
- select{|e| types.include?(e[TYP]) }
219
- ).extend(Extensions)
220
- end
221
-
222
- def non_spaces(*types)
223
- (
224
- types = [types].flatten
225
- reject{|e| types.empty? or types.include?(e[TYP]) }
226
- ).extend(Extensions)
227
- end
228
-
229
- def start_of_line?
230
- same_as_curr_line.non_spaces.empty?
231
- end
232
-
233
- end
234
-
235
- end
236
- end
237
- end