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.
- 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: []
|