ruby_list_comprehension 0.2.4 → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (3) hide show
  1. checksums.yaml +4 -4
  2. data/lib/ruby_list_comprehension.rb +64 -72
  3. metadata +7 -7
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: da0d475e01e660a109eff36d8f0f4f8ca3e105757bf6577bfdce20c7440177b5
4
- data.tar.gz: e36bcd2fa8ba9e34fce4f78efb9f4853e7fff9469573dc1da1eb3fc447e17d4b
3
+ metadata.gz: 95831203a1a00b6e900cb5fa9ec453fdf798ac177eeed2b7ca5fd7f5ea152afd
4
+ data.tar.gz: 3672b3b9fc66ee631e34f9535868093aaf2a88294edfbc0fba20249f8bd97374
5
5
  SHA512:
6
- metadata.gz: 0116246f99df3cb5f403963e4743fcc34c88d9767434c9505454078b29c8a0814f84ec7ca21a22ffc309b433a4dd5f7c1944a1b695049196f09253072f379d1f
7
- data.tar.gz: 905a24fdd92c58f87e4cf7e0539f0b711e7689564e825a1a84168609a1a320b9e9856ad5544fb5c2e25cbdfbfe721fb3186c34334ac031d4905c28ce20bab149
6
+ metadata.gz: a9becdd8385020e8cfc668c80313847e33f4440474619cf6c2abb7ac40a9f63b347213904dde0f158b8ae37d6c6c08726e2830a03624e9b8560674e8ef3bae5d
7
+ data.tar.gz: 9fba4623572daf749efefa775b1456918dee7afd1a6b857e5d5c6c4771550afa27571fddf6baca5510bd7769a814f495f3f89ff87532f52ac2f48dd60126afe2
@@ -2,14 +2,17 @@
2
2
  require 'readline'
3
3
  require 'singleton'
4
4
  require 'set'
5
+
5
6
  module RubyListComprehension
6
7
  FM_REGEX = /for(?<parameter>.*)(?=in)in(?<iterable>.*)(?=do)do(?<mappable>.*)(?=if)if(?<filterable>.+)end/.freeze
7
8
  F_REGEX = /for(?<parameter>.*)(?=in)in(?<iterable>.*)(.+)do(.+)(?=if)if(?<filterable>.*)end/.freeze
8
9
  M_REGEX = /(?=for)for(?<parameter>.*)(?=in)in(?<iterable>.*)(?=do)do(?<mappable>.*)(?=end)end/.freeze
9
10
  I_REGEX = /for(?<parameter>.*)(?=in)in(?<iterable>.*)(?=do)do(?<identity>.+)(?=end)end/.freeze
10
11
 
12
+ private
13
+
11
14
  def fetch_capture(data, name)
12
- data[name.to_sym] if data.names.include?(name.to_s)
15
+ data[name.to_sym] if data.names.include?(name.to_s) && !data.nil?
13
16
  end
14
17
 
15
18
  def op_type(str)
@@ -19,42 +22,40 @@ module RubyListComprehension
19
22
  match_identity = str.match(I_REGEX)
20
23
  parameter = fetch_capture(match_identity, :parameter)
21
24
  mappable = fetch_capture(match_map, :mappable)
22
- if match_filter_map.nil? && match_filter.nil?
23
- if parameter.strip == mappable.strip || /\A\s*\Z/ === mappable
24
- return :identity
25
- else
26
- return :map
27
- end
28
- end
29
25
  map_condition = mappable.split('if')[0]
30
- if fetch_capture(match_map, :mappable).include?('if') && !(parameter.strip == map_condition.strip || /\A\s*\Z/ === mappable)
31
- return :filter_map
26
+
27
+ if match_filter_map.nil? && match_filter.nil? && (parameter.strip == mappable.strip || /\A\s*\Z/ === mappable)
28
+ return :identity
29
+ elsif match_filter_map.nil? && match_filter.nil?
30
+ return :map
31
+ end
32
+
33
+ if fetch_capture(match_map, :mappable).include?('if') &&
34
+ !(parameter.strip == map_condition.strip || /\A\s*\Z/ === mappable)
35
+ :filter_map
32
36
  else
33
37
  if match_identity[:parameter].strip == match_filter[:filterable].strip
34
38
  return :identity
35
39
  end
36
- return :filter
40
+ :filter
37
41
  end
38
42
  end
39
43
 
40
44
  def denest_builder(nested_list)
41
- nested_list
42
- nested_list
43
- len = 0
44
- nested_list
45
- fin = nested_list.split('[').delete_if{|x| x == ""}
46
- fin = fin.map{|str|str[0..-1] + " end"}
47
- fin = fin.join.split('],')
48
- fin = fin.join.split(' end')
49
- fin.map{|x|"#{x} end"}
45
+ nested_list.split('[')
46
+ .delete_if{|x| x == ""}
47
+ .map{|str|str[0..-1] + " end"}
48
+ .join.split('],')
49
+ .join.split(' end')
50
+ .map{|x|"#{x} end"}
50
51
  end
51
52
 
52
53
  def denest_flattener(nested_list)
53
- nested_list
54
- len = nested_list.index('for')
55
- nested_list_array = nested_list.split(" end").join
56
- nested_list_array.split(' end')
57
- nested_list_array = nested_list_array.split('for')[1..-1].map!{|x|"for#{x} end"}
54
+ nested_list.split(" end")
55
+ .join
56
+ .split(' end')
57
+ .split('for')[1..-1]
58
+ .map!{|x|"for#{x} end"}
58
59
  end
59
60
 
60
61
  def create_protocol(denested_array, operator_array)
@@ -82,7 +83,6 @@ module RubyListComprehension
82
83
  i = 0
83
84
  until op_array.empty?
84
85
  current_data = match_data_array[i]
85
- current_op = op_array[0]
86
86
  $iterable_string = fetch_capture(current_data, 'iterable')
87
87
  $mappable = fetch_capture(current_data, 'mappable')
88
88
  $parameter = fetch_capture(current_data, 'parameter')
@@ -97,64 +97,63 @@ module RubyListComprehension
97
97
  if !@nested
98
98
  return *$iterable
99
99
  elsif i.zero? && !@flattener
100
- $process_str += "(#$iterable).map"
100
+ $process_str += "(#{$iterable}).map"
101
101
  elsif i.zero? && @flattener
102
- $process_str += "(#$iterable).flat_map"
102
+ $process_str += "(#{$iterable}).flat_map"
103
103
  elsif !i.zero? && i != start_index
104
- $process_str += "{(#$iterable).map"
104
+ $process_str += "{(#{$iterable}).map"
105
105
  elsif i == start_index
106
- $process_str += "{(#$iterable_string).map(&:itself)"
106
+ $process_str += "{(#{$iterable_string}).map(&:itself)"
107
107
  $process_str += '}' * (start_index)
108
108
  elsif nested && i.zero? && !flatten
109
- $process_str += "(#$iterable).map"
109
+ $process_str += "(#{$iterable}).map"
110
110
  elsif i != 0 && nested
111
- $process_str += "(#$iterable_string).map"
111
+ $process_str += "(#{$iterable_string}).map"
112
112
  end
113
113
  when :map
114
114
  if i == 0
115
115
  $mappable = $parameter if /\A\s*\Z/ === $mappable
116
- $process_str += "(#$iterable).map{|(#$parameter)|(#$mappable)}"
116
+ $process_str += "(#{$iterable}).map{|#{$parameter}|(#{$mappable})}"
117
117
  elsif i == 0 && flatten
118
118
  $mappable = $parameter if /\A\s*\Z/ === $mappable
119
- $process_str += "(#$iterable).flat_map{|(#$parameter)|(#$mappable)"
119
+ $process_str += "(#{$iterable}).flat_map{|#{$parameter}|(#{$mappable})"
120
120
  elsif i == 0 && !flatten
121
121
  $mappable = $parameter if /\A\s*\Z/ === $mappable
122
- $process_str += "(#$iterable).map{|(#$parameter)|(#$mappable)"
122
+ $process_str += "(#{$iterable}).map{|#{$parameter}|(#{$mappable})"
123
123
  elsif i == start_index
124
124
  $mappable = $parameter if /\A\s*\Z/ === $mappable
125
- $process_str += "{(#$iterable).map{|(#$parameter)|(#$mappable)"
125
+ $process_str += "{(#{$iterable}).map{|#{$parameter}|(#{$mappable})"
126
126
  $process_str += '}' * (start_index+1)
127
127
  elsif i != start_index
128
- $process_str += "{(#$iterable_string).map{|(#$parameter)|(#$mappable)"
128
+ $process_str += "{(#{$iterable_string}).map{|#{$parameter}|(#{$mappable})"
129
129
  end
130
130
  when :filter
131
131
  if op_array.empty?
132
- $process_str += "(#$iterable).filter{|(#$parameter)|(#$filterable)}"
132
+ $process_str += "(#{$iterable}).filter{|#{$parameter}|(#{$filterable})}"
133
133
  end
134
134
  when :filter_map
135
135
  if op_array.empty? && RUBY_VERSION >= '2.7.0'
136
- $process_str += "(#$iterable).filter_map{|(#$parameter)|(#$mappable) if (#$filterable)}"
136
+ $process_str += "(#{$iterable}).filter_map{|#{$parameter}|(#{$mappable}) if (#{$filterable})}"
137
137
  else
138
- $process_str += "(#$iterable).map{|(#$parameter)|(#$mappable) if (#$filterable)}.compact"
138
+ $process_str += "(#{$iterable}).map{|#{$parameter}|(#{$mappable}) if (#{$filterable})}.compact"
139
139
  end
140
140
  end
141
141
  i += 1
142
- # p $process_str
143
142
  end
144
143
  begin
145
- current_op
146
144
  instance_eval($process_str)
147
145
  rescue SyntaxError => e
148
- 'List imcomprehensible :' + e.backtrace_locations.to_s
146
+ "List incomprehensible: #{e.backtrace_locations.to_s}"
147
+ rescue Error => e
148
+ "Check your assumptions, something is amiss: #{e.backtrace_locations.to_s}"
149
149
  end
150
150
  end
151
151
 
152
152
  def one_shot(str)
153
153
  len = str.scan('for ').length
154
- @nested = (len > 1)
155
- nested = @nested
156
- if nested
157
- nest_mode = str.include?('end end') && !nested ? :flatten : :matrix
154
+ @nested = len > 1
155
+ if @nested
156
+ nest_mode = str.include?('end end') && !@nested ? :flatten : :matrix
158
157
  nest_array = @flattener ? denest_flattener(str) : denest_builder(str)
159
158
  else
160
159
  nest_array = [str]
@@ -162,46 +161,43 @@ module RubyListComprehension
162
161
  op_array = nest_array.map(&method(:op_type))
163
162
  hash = create_protocol(nest_array, op_array)
164
163
  begin
165
- execute_comprehension(hash, nest_mode==nested)
164
+ execute_comprehension(hash, nest_mode==@nested)
166
165
  rescue SyntaxError => se
167
166
  puts 'RESCUED!' + se.backtrace_locations.to_s
168
167
  end
169
168
  end
170
169
 
171
170
  class ListComprehension
172
- # include Singleton
171
+ include Singleton
173
172
  include RubyListComprehension
174
- attr_accessor :cache, :caching, :mappable, :filterable, :iterable, :var, :list, :location, :line, :count
175
- attr_accessor :flattener, :len, :nested, :nested_var, :file, :list_comp, :final_iterable_value
176
- attr_accessor :count
177
- REPL_LIST = %w[:irb :pry].freeze
173
+ attr_accessor :cache, :mappable, :filterable, :line, :flattener
178
174
 
179
- def initialize
180
- @cache = {}
181
- @caching = true
182
- @version = RUBY_VERSION
183
- end
175
+ :TOO_MANY_COMPS_ON_ONE_LINE
184
176
 
185
177
  def [](*iterable)
186
178
  return [] if iterable.empty? || iterable.nil?
187
179
 
188
-
189
180
  @flattener = iterable.length == 1
190
- iterable = iterable[0] if iterable.length == 1
191
- @final_iterable_value = iterable
192
- @list_comp = iterable
193
- $iterable = iterable
181
+ $iterable = iterable[0] if iterable.length == 1
182
+
194
183
  @filename = $PROGRAM_NAME
195
184
  if @filename == "pry" || @filename == "irb"
196
185
  @line = locate_list_repl
197
186
  else
198
187
  @line = locate_list_file
199
188
  end
189
+ return @line if @line == :TOO_MANY_COMPS_ON_ONE_LINE
200
190
  return @cache[@line] if @cache.has_key?(@line)
201
191
 
202
192
  @cache[@line] = one_shot(@line)
203
193
  end
204
194
 
195
+ private
196
+
197
+ def initialize
198
+ @cache = {}
199
+ end
200
+
205
201
  def locate_list_repl
206
202
  @line = Readline::HISTORY.to_a.reverse.uniq.reverse[-1]
207
203
  start = @line.index('l[') + 2
@@ -217,16 +213,12 @@ module RubyListComprehension
217
213
  end
218
214
 
219
215
  def locate_list_file
220
- @location = caller_locations.last.to_s.scan(/\d+/).last.to_i
221
- @line = retrieve_file_data[@location - 1].strip.match(/\$l(?<line>.+)/)[:line][0...-1]
222
- # if @line.is_a? Array
223
- # @line.each_with_index do |list, idx|
224
- # list.split[3] == iterable.to_s
225
- # @line = list[0..list.index('end]') + 2] if list.split[3] == iterable.to_s
226
- # end
227
- # end
216
+ @line = retrieve_file_data[caller_locations.last.to_s.scan(/\d+/).last.to_i - 1]
217
+ .strip.match(/\$l(?<line>.+)/)[:line][0...-1]
218
+ .sub(";", " do ")
219
+ @line = :TOO_MANY_COMPS_ON_ONE_LINE if @line.include?("$l")
228
220
  @line
229
221
  end
230
222
  end
231
- $l = ListComprehension.new
223
+ $l = ListComprehension.instance
232
224
  end
metadata CHANGED
@@ -1,17 +1,17 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ruby_list_comprehension
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.4
4
+ version: 1.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Samuel Michael
8
- autorequire:
8
+ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2019-10-02 00:00:00.000000000 Z
11
+ date: 2020-12-04 00:00:00.000000000 Z
12
12
  dependencies: []
13
13
  description: List Comprehensions for Ruby
14
- email: smichael@appacademy.io
14
+ email: sammomichael@gmail.com
15
15
  executables: []
16
16
  extensions: []
17
17
  extra_rdoc_files: []
@@ -28,7 +28,7 @@ metadata:
28
28
  mailing_list_uri: https://groups.example.com/bestgemever
29
29
  source_code_uri: https://github.com/SammoMichael/Ruby_List_Comprehension/blob/master/lib/ruby_list_comprehension.rb
30
30
  wiki_uri: https://github.com/SammoMichael/Ruby_List_Comprehension/wiki
31
- post_install_message:
31
+ post_install_message:
32
32
  rdoc_options: []
33
33
  require_paths:
34
34
  - lib
@@ -43,8 +43,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
43
43
  - !ruby/object:Gem::Version
44
44
  version: '0'
45
45
  requirements: []
46
- rubygems_version: 3.0.6
47
- signing_key:
46
+ rubygems_version: 3.0.8
47
+ signing_key:
48
48
  specification_version: 4
49
49
  summary: Ruby List Comprehension
50
50
  test_files: []