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.
- checksums.yaml +4 -4
- data/lib/ruby_list_comprehension.rb +64 -72
- metadata +7 -7
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 95831203a1a00b6e900cb5fa9ec453fdf798ac177eeed2b7ca5fd7f5ea152afd
|
4
|
+
data.tar.gz: 3672b3b9fc66ee631e34f9535868093aaf2a88294edfbc0fba20249f8bd97374
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
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
|
-
|
31
|
-
|
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
|
-
|
40
|
+
:filter
|
37
41
|
end
|
38
42
|
end
|
39
43
|
|
40
44
|
def denest_builder(nested_list)
|
41
|
-
nested_list
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
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
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
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 += "(
|
100
|
+
$process_str += "(#{$iterable}).map"
|
101
101
|
elsif i.zero? && @flattener
|
102
|
-
$process_str += "(
|
102
|
+
$process_str += "(#{$iterable}).flat_map"
|
103
103
|
elsif !i.zero? && i != start_index
|
104
|
-
$process_str += "{(
|
104
|
+
$process_str += "{(#{$iterable}).map"
|
105
105
|
elsif i == start_index
|
106
|
-
$process_str += "{(
|
106
|
+
$process_str += "{(#{$iterable_string}).map(&:itself)"
|
107
107
|
$process_str += '}' * (start_index)
|
108
108
|
elsif nested && i.zero? && !flatten
|
109
|
-
$process_str += "(
|
109
|
+
$process_str += "(#{$iterable}).map"
|
110
110
|
elsif i != 0 && nested
|
111
|
-
$process_str += "(
|
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 += "(
|
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 += "(
|
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 += "(
|
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 += "{(
|
125
|
+
$process_str += "{(#{$iterable}).map{|#{$parameter}|(#{$mappable})"
|
126
126
|
$process_str += '}' * (start_index+1)
|
127
127
|
elsif i != start_index
|
128
|
-
$process_str += "{(
|
128
|
+
$process_str += "{(#{$iterable_string}).map{|#{$parameter}|(#{$mappable})"
|
129
129
|
end
|
130
130
|
when :filter
|
131
131
|
if op_array.empty?
|
132
|
-
$process_str += "(
|
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 += "(
|
136
|
+
$process_str += "(#{$iterable}).filter_map{|#{$parameter}|(#{$mappable}) if (#{$filterable})}"
|
137
137
|
else
|
138
|
-
$process_str += "(
|
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
|
-
|
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 =
|
155
|
-
|
156
|
-
|
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
|
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
|
-
|
171
|
+
include Singleton
|
173
172
|
include RubyListComprehension
|
174
|
-
attr_accessor :cache, :
|
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
|
-
|
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
|
-
|
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
|
-
@
|
221
|
-
|
222
|
-
|
223
|
-
|
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.
|
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.
|
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:
|
11
|
+
date: 2020-12-04 00:00:00.000000000 Z
|
12
12
|
dependencies: []
|
13
13
|
description: List Comprehensions for Ruby
|
14
|
-
email:
|
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.
|
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: []
|