ruby_list_comprehension 0.2.4 → 1.0.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 (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: []