accessory 0.1.6 → 0.1.11
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/accessory.rb +0 -3
- data/lib/accessory/access.rb +39 -39
- data/lib/accessory/accessor.rb +16 -16
- data/lib/accessory/accessors/all_accessor.rb +14 -3
- data/lib/accessory/accessors/attribute_accessor.rb +8 -6
- data/lib/accessory/accessors/between_each_accessor.rb +13 -4
- data/lib/accessory/accessors/betwixt_accessor.rb +9 -6
- data/lib/accessory/accessors/filter_accessor.rb +13 -3
- data/lib/accessory/accessors/first_accessor.rb +8 -6
- data/lib/accessory/accessors/instance_variable_accessor.rb +6 -4
- data/lib/accessory/accessors/last_accessor.rb +8 -6
- data/lib/accessory/accessors/subscript_accessor.rb +7 -5
- data/lib/accessory/lens.rb +16 -5
- data/lib/accessory/version.rb +1 -1
- metadata +8 -8
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 1a19c2c9d6ea2aeed4a4b0140c027220e383faa178d89689ebc667256fd9e228
|
4
|
+
data.tar.gz: 0c4ead2a9dd32de8b51c9c9da52aefafa16b05c272da5393b0e3d365dc920708
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: fddd92947828fe5fd287ac183a5e7a3d0215da01314dd766737d7b8bf26c7e078a9207c1b1504e69522964e6e9a72b9b45372b10f35111a41c67bec4798da90d
|
7
|
+
data.tar.gz: 4ad13454e5adcd7b6243075c53e0b52539cbbc1402ab19d118ff065dfd25d5ac2fc5d3b052a3cec3055837bedae117fb4bddb226a3bbf66915a996c1344d47ef
|
data/lib/accessory.rb
CHANGED
data/lib/accessory/access.rb
CHANGED
@@ -18,59 +18,59 @@ require 'accessory/accessors/last_accessor'
|
|
18
18
|
# include Accessory
|
19
19
|
|
20
20
|
module Accessory::Access
|
21
|
-
# (see Accessory::SubscriptAccessor)
|
21
|
+
# (see Accessory::Accessors::SubscriptAccessor)
|
22
22
|
def self.subscript(...)
|
23
|
-
Accessory::SubscriptAccessor.new(...)
|
23
|
+
Accessory::Accessors::SubscriptAccessor.new(...)
|
24
24
|
end
|
25
25
|
|
26
|
-
# (see Accessory::AttributeAccessor)
|
26
|
+
# (see Accessory::Accessors::AttributeAccessor)
|
27
27
|
def self.attr(...)
|
28
|
-
Accessory::AttributeAccessor.new(...)
|
28
|
+
Accessory::Accessors::AttributeAccessor.new(...)
|
29
29
|
end
|
30
30
|
|
31
|
-
# (see Accessory::InstanceVariableAccessor)
|
31
|
+
# (see Accessory::Accessors::InstanceVariableAccessor)
|
32
32
|
def self.ivar(...)
|
33
|
-
Accessory::InstanceVariableAccessor.new(...)
|
33
|
+
Accessory::Accessors::InstanceVariableAccessor.new(...)
|
34
34
|
end
|
35
35
|
|
36
|
-
# (see Accessory::BetwixtAccessor)
|
36
|
+
# (see Accessory::Accessors::BetwixtAccessor)
|
37
37
|
def self.betwixt(...)
|
38
|
-
Accessory::BetwixtAccessor.new(...)
|
38
|
+
Accessory::Accessors::BetwixtAccessor.new(...)
|
39
39
|
end
|
40
40
|
|
41
|
-
# Alias for +Accessory::Access.betwixt(0)+. See {Access.betwixt}
|
41
|
+
# Alias for +Accessory::Accessors::Access.betwixt(0)+. See {Access.betwixt}
|
42
42
|
def self.before_first
|
43
43
|
self.betwixt(0)
|
44
44
|
end
|
45
45
|
|
46
|
-
# Alias for +Accessory::Access.betwixt(-1)+. See {Access.betwixt}
|
46
|
+
# Alias for +Accessory::Accessors::Access.betwixt(-1)+. See {Access.betwixt}
|
47
47
|
def self.after_last
|
48
48
|
self.betwixt(-1)
|
49
49
|
end
|
50
50
|
|
51
|
-
# (see Accessory::BetweenEachAccessor)
|
51
|
+
# (see Accessory::Accessors::BetweenEachAccessor)
|
52
52
|
def self.between_each
|
53
|
-
Accessory::BetweenEachAccessor.new
|
53
|
+
Accessory::Accessors::BetweenEachAccessor.new
|
54
54
|
end
|
55
55
|
|
56
|
-
# (see Accessory::AllAccessor)
|
56
|
+
# (see Accessory::Accessors::AllAccessor)
|
57
57
|
def self.all
|
58
|
-
Accessory::AllAccessor.new
|
58
|
+
Accessory::Accessors::AllAccessor.new
|
59
59
|
end
|
60
60
|
|
61
|
-
# (see Accessory::FirstAccessor)
|
61
|
+
# (see Accessory::Accessors::FirstAccessor)
|
62
62
|
def self.first
|
63
|
-
Accessory::FirstAccessor.new
|
63
|
+
Accessory::Accessors::FirstAccessor.new
|
64
64
|
end
|
65
65
|
|
66
|
-
# (see Accessory::LastAccessor)
|
66
|
+
# (see Accessory::Accessors::LastAccessor)
|
67
67
|
def self.last
|
68
|
-
Accessory::LastAccessor.new
|
68
|
+
Accessory::Accessors::LastAccessor.new
|
69
69
|
end
|
70
70
|
|
71
|
-
# (see Accessory::FilterAccessor)
|
71
|
+
# (see Accessory::Accessors::FilterAccessor)
|
72
72
|
def self.filter(&pred)
|
73
|
-
Accessory::FilterAccessor.new(pred)
|
73
|
+
Accessory::Accessors::FilterAccessor.new(pred)
|
74
74
|
end
|
75
75
|
end
|
76
76
|
|
@@ -83,29 +83,29 @@ end
|
|
83
83
|
# {Lens} or {BoundLens} from the addition of the accessor.
|
84
84
|
|
85
85
|
module Accessory::Access::FluentHelpers
|
86
|
-
# (see Accessory::SubscriptAccessor)
|
86
|
+
# (see Accessory::Accessors::SubscriptAccessor)
|
87
87
|
def subscript(...)
|
88
|
-
self.then(Accessory::SubscriptAccessor.new(...))
|
88
|
+
self.then(Accessory::Accessors::SubscriptAccessor.new(...))
|
89
89
|
end
|
90
90
|
|
91
91
|
# Alias for {#subscript}
|
92
92
|
def [](...)
|
93
|
-
self.then(Accessory::SubscriptAccessor.new(...))
|
93
|
+
self.then(Accessory::Accessors::SubscriptAccessor.new(...))
|
94
94
|
end
|
95
95
|
|
96
|
-
# (see Accessory::AttributeAccessor)
|
96
|
+
# (see Accessory::Accessors::AttributeAccessor)
|
97
97
|
def attr(...)
|
98
|
-
self.then(Accessory::AttributeAccessor.new(...))
|
98
|
+
self.then(Accessory::Accessors::AttributeAccessor.new(...))
|
99
99
|
end
|
100
100
|
|
101
|
-
# (see Accessory::InstanceVariableAccessor)
|
101
|
+
# (see Accessory::Accessors::InstanceVariableAccessor)
|
102
102
|
def ivar(...)
|
103
|
-
self.then(Accessory::InstanceVariableAccessor.new(...))
|
103
|
+
self.then(Accessory::Accessors::InstanceVariableAccessor.new(...))
|
104
104
|
end
|
105
105
|
|
106
|
-
# (see Accessory::BetwixtAccessor)
|
106
|
+
# (see Accessory::Accessors::BetwixtAccessor)
|
107
107
|
def betwixt(...)
|
108
|
-
self.then(Accessory::BetwixtAccessor.new(...))
|
108
|
+
self.then(Accessory::Accessors::BetwixtAccessor.new(...))
|
109
109
|
end
|
110
110
|
|
111
111
|
# Alias for +#betwixt(0)+. See {#betwixt}
|
@@ -118,29 +118,29 @@ module Accessory::Access::FluentHelpers
|
|
118
118
|
self.betwixt(-1)
|
119
119
|
end
|
120
120
|
|
121
|
-
# (see Accessory::BetweenEachAccessor)
|
121
|
+
# (see Accessory::Accessors::BetweenEachAccessor)
|
122
122
|
def between_each
|
123
|
-
self.then(Accessory::BetweenEachAccessor.new)
|
123
|
+
self.then(Accessory::Accessors::BetweenEachAccessor.new)
|
124
124
|
end
|
125
125
|
|
126
|
-
# (see Accessory::AllAccessor)
|
126
|
+
# (see Accessory::Accessors::AllAccessor)
|
127
127
|
def all
|
128
|
-
self.then(Accessory::AllAccessor.new)
|
128
|
+
self.then(Accessory::Accessors::AllAccessor.new)
|
129
129
|
end
|
130
130
|
|
131
|
-
# (see Accessory::FirstAccessor)
|
131
|
+
# (see Accessory::Accessors::FirstAccessor)
|
132
132
|
def first
|
133
|
-
self.then(Accessory::FirstAccessor.new)
|
133
|
+
self.then(Accessory::Accessors::FirstAccessor.new)
|
134
134
|
end
|
135
135
|
|
136
|
-
# (see Accessory::LastAccessor)
|
136
|
+
# (see Accessory::Accessors::LastAccessor)
|
137
137
|
def last
|
138
|
-
self.then(Accessory::LastAccessor.new)
|
138
|
+
self.then(Accessory::Accessors::LastAccessor.new)
|
139
139
|
end
|
140
140
|
|
141
|
-
# (see Accessory::FilterAccessor)
|
141
|
+
# (see Accessory::Accessors::FilterAccessor)
|
142
142
|
def filter(&pred)
|
143
|
-
self.then(Accessory::FilterAccessor.new(pred))
|
143
|
+
self.then(Accessory::Accessors::FilterAccessor.new(pred))
|
144
144
|
end
|
145
145
|
end
|
146
146
|
|
data/lib/accessory/accessor.rb
CHANGED
@@ -19,7 +19,7 @@ module Accessory; end
|
|
19
19
|
# info):
|
20
20
|
#
|
21
21
|
# * {Accessor#traverse}
|
22
|
-
# * {Accessor#
|
22
|
+
# * {Accessor#ensure_valid}
|
23
23
|
|
24
24
|
class Accessory::Accessor
|
25
25
|
TERMINAL_DEFAULT_FN = lambda{ nil }
|
@@ -78,16 +78,13 @@ class Accessory::Accessor
|
|
78
78
|
# call <tt>traverse_or_default(data)</tt> within your implementation to safely
|
79
79
|
# get a traversal-result to operate on.
|
80
80
|
#
|
81
|
-
#
|
82
|
-
#
|
83
|
-
# {
|
84
|
-
#
|
85
|
-
#
|
86
|
-
#
|
87
|
-
#
|
88
|
-
# implementation calling <tt>super(default)</tt>; or it's the result of
|
89
|
-
# calling {default_data_constructor} on the successor-accessor in the accessor
|
90
|
-
# chain.
|
81
|
+
# The value returned by your {traverse} callback will be validated by your
|
82
|
+
# calling the {ensure_valid} callback of the _successor accessor_ in the Lens
|
83
|
+
# path. {ensure_valid} will replace any value it considers invalid with a
|
84
|
+
# reasonable default. This means you don't need to worry about what will
|
85
|
+
# happen if your traversal doesn't find a value and so returns +nil+. The
|
86
|
+
# successor's {ensure_valid} will replace that +nil+ with a value that works
|
87
|
+
# for it.
|
91
88
|
def traverse_or_default(data)
|
92
89
|
traversal_result = traverse(data) || @default_value
|
93
90
|
|
@@ -137,7 +134,8 @@ class Accessory::Accessor
|
|
137
134
|
# of the +get_result+s should replicate the data flow of {get}.
|
138
135
|
# * the +new_value+ should be used to *replace* or *overwrite* the result of
|
139
136
|
# this accessor's traversal within +data+. For example, in
|
140
|
-
# {SubscriptAccessor}, <tt>data[key] = new_value</tt> is
|
137
|
+
# {Accessors::SubscriptAccessor}, <tt>data[key] = new_value</tt> is
|
138
|
+
# executed.
|
141
139
|
#
|
142
140
|
# In the <tt>:pop</tt> command case:
|
143
141
|
# * the result of the traversal (*before* the yield) should be returned. This
|
@@ -145,7 +143,7 @@ class Accessory::Accessor
|
|
145
143
|
# traversal-results before feeding them into yield, in order to return them
|
146
144
|
# here.
|
147
145
|
# * the traversal-result should be *removed* from +data+. For example, in
|
148
|
-
# {SubscriptAccessor}, <tt>data.delete(key)</tt> is executed.
|
146
|
+
# {Accessors::SubscriptAccessor}, <tt>data.delete(key)</tt> is executed.
|
149
147
|
#
|
150
148
|
# The successor in the accessor chain will receive the yielded
|
151
149
|
# traversal-results as its own +data+.
|
@@ -198,9 +196,9 @@ class Accessory::Accessor
|
|
198
196
|
#
|
199
197
|
#
|
200
198
|
# For example, if your accessor operates on +Enumerable+ values (like
|
201
|
-
# {AllAccessor}), then this method should validate that the
|
202
|
-
# is +Enumerable+; and, if it isn't, return something that
|
203
|
-
# +Array+.
|
199
|
+
# {Accessors::AllAccessor}), then this method should validate that the
|
200
|
+
# +traversal_result+ is +Enumerable+; and, if it isn't, return something that
|
201
|
+
# is — e.g. an empty +Array+.
|
204
202
|
#
|
205
203
|
# This logic is used to replace invalid intermediate values (e.g. `nil`s and
|
206
204
|
# scalars) with containers during {Lens#put_in} et al.
|
@@ -214,3 +212,5 @@ class Accessory::Accessor
|
|
214
212
|
|
215
213
|
# @!endgroup
|
216
214
|
end
|
215
|
+
|
216
|
+
module Accessory::Accessors; end
|
@@ -15,7 +15,7 @@ require 'accessory/accessor'
|
|
15
15
|
#
|
16
16
|
# * +Array.new+
|
17
17
|
|
18
|
-
class Accessory::AllAccessor < Accessory::Accessor
|
18
|
+
class Accessory::Accessors::AllAccessor < Accessory::Accessor
|
19
19
|
# @!visibility private
|
20
20
|
def ensure_valid(traversal_result)
|
21
21
|
if traversal_result.kind_of?(Enumerable)
|
@@ -50,17 +50,28 @@ class Accessory::AllAccessor < Accessory::Accessor
|
|
50
50
|
def get_and_update(data)
|
51
51
|
results = []
|
52
52
|
new_data = []
|
53
|
+
dirty = false
|
53
54
|
|
54
55
|
(data || []).each do |pos|
|
55
56
|
case yield(pos)
|
56
|
-
in [result,
|
57
|
+
in [:clean, result, _]
|
58
|
+
results.push(result)
|
59
|
+
new_data.push(pos)
|
60
|
+
# ok
|
61
|
+
in [:dirty, result, new_value]
|
57
62
|
results.push(result)
|
58
63
|
new_data.push(new_value)
|
64
|
+
dirty = true
|
59
65
|
in :pop
|
60
66
|
results.push(pos)
|
67
|
+
dirty = true
|
61
68
|
end
|
62
69
|
end
|
63
70
|
|
64
|
-
|
71
|
+
if dirty
|
72
|
+
[:dirty, results, new_data]
|
73
|
+
else
|
74
|
+
[:clean, results, data]
|
75
|
+
end
|
65
76
|
end
|
66
77
|
end
|
@@ -8,8 +8,8 @@ require 'accessory/accessor'
|
|
8
8
|
# the getter/setter pair <tt>.foo</tt> and <tt>.foo=</tt>.
|
9
9
|
#
|
10
10
|
# The abstract "attribute" does not have to correspond to an actual
|
11
|
-
# +attr_accessor+; the
|
12
|
-
# named getter/setter methods exist on the receiver.
|
11
|
+
# +attr_accessor+; the AttributeAccessor will work as long as the
|
12
|
+
# relevant named getter/setter methods exist on the receiver.
|
13
13
|
#
|
14
14
|
# *Aliases*
|
15
15
|
# * {Access.attr}
|
@@ -19,7 +19,7 @@ require 'accessory/accessor'
|
|
19
19
|
#
|
20
20
|
# * +OpenStruct.new+
|
21
21
|
|
22
|
-
class Accessory::AttributeAccessor < Accessory::Accessor
|
22
|
+
class Accessory::Accessors::AttributeAccessor < Accessory::Accessor
|
23
23
|
# @param attr_name [Symbol] the attribute name (i.e. name of the getter method)
|
24
24
|
# @param default [Object] the default to use if the predecessor accessor passes +nil+ data
|
25
25
|
def initialize(attr_name, default: nil)
|
@@ -88,12 +88,14 @@ class Accessory::AttributeAccessor < Accessory::Accessor
|
|
88
88
|
value = traverse_or_default(data)
|
89
89
|
|
90
90
|
case yield(value)
|
91
|
-
in [result,
|
91
|
+
in [:clean, result, _]
|
92
|
+
[:clean, result, data]
|
93
|
+
in [:dirty, result, new_value]
|
92
94
|
data.send(@setter_method_name, new_value)
|
93
|
-
[result, data]
|
95
|
+
[:dirty, result, data]
|
94
96
|
in :pop
|
95
97
|
data.send(@setter_method_name, nil)
|
96
|
-
[value, data]
|
98
|
+
[:dirty, value, data]
|
97
99
|
end
|
98
100
|
end
|
99
101
|
end
|
@@ -5,7 +5,7 @@ require 'accessory/traversal_position/enumerable_before_offset'
|
|
5
5
|
# Traverses the positions "between" the elements of an +Enumerable+, including
|
6
6
|
# the positions at the "edges" (i.e. before the first, and after the last.)
|
7
7
|
#
|
8
|
-
#
|
8
|
+
# BetweenEachAccessor can be used with {Lens#put_in} to insert new
|
9
9
|
# elements into an Enumerable between the existing ones.
|
10
10
|
#
|
11
11
|
# *Aliases*
|
@@ -16,7 +16,7 @@ require 'accessory/traversal_position/enumerable_before_offset'
|
|
16
16
|
#
|
17
17
|
# * +Array.new+
|
18
18
|
|
19
|
-
class Accessory::BetweenEachAccessor < Accessory::Accessor
|
19
|
+
class Accessory::Accessors::BetweenEachAccessor < Accessory::Accessor
|
20
20
|
# @!visibility private
|
21
21
|
def ensure_valid(traversal_result)
|
22
22
|
if traversal_result.kind_of?(Enumerable)
|
@@ -75,15 +75,20 @@ class Accessory::BetweenEachAccessor < Accessory::Accessor
|
|
75
75
|
def get_and_update(data)
|
76
76
|
results = []
|
77
77
|
new_data = []
|
78
|
+
dirty = false
|
78
79
|
|
79
80
|
positions = traverse_or_default(data || [])
|
80
81
|
|
81
82
|
positions.each do |pos|
|
82
83
|
case yield(pos)
|
83
|
-
in [result,
|
84
|
+
in [:clean, result, _]
|
85
|
+
results.push(result)
|
86
|
+
in [:dirty, result, new_value]
|
84
87
|
new_data.push(new_value)
|
85
88
|
results.push(result)
|
89
|
+
dirty = true
|
86
90
|
in :pop
|
91
|
+
# ok
|
87
92
|
end
|
88
93
|
|
89
94
|
unless pos.last?
|
@@ -91,6 +96,10 @@ class Accessory::BetweenEachAccessor < Accessory::Accessor
|
|
91
96
|
end
|
92
97
|
end
|
93
98
|
|
94
|
-
|
99
|
+
if dirty
|
100
|
+
[:dirty, results, new_data]
|
101
|
+
else
|
102
|
+
[:clean, results, data]
|
103
|
+
end
|
95
104
|
end
|
96
105
|
end
|
@@ -13,10 +13,11 @@ require 'accessory/traversal_position/enumerable_before_offset'
|
|
13
13
|
# The +offset+ in this accessor has equivalent semantics to the offset in
|
14
14
|
# <tt>Array#insert(offset, obj)</tt>.
|
15
15
|
#
|
16
|
-
# {BetwixtAccessor} can be used with {Lens#put_in} to insert new
|
16
|
+
# {Accessors::BetwixtAccessor} can be used with {Lens#put_in} to insert new
|
17
17
|
# elements into an Enumerable between the existing ones. If you want to extend
|
18
18
|
# an +Enumerable+ as you would with <tt>#push</tt> or <tt>#unshift</tt>, this
|
19
|
-
# accessor will have better behavior than using {SubscriptAccessor}
|
19
|
+
# accessor will have better behavior than using {Accessors::SubscriptAccessor}
|
20
|
+
# would.
|
20
21
|
#
|
21
22
|
# *Aliases*
|
22
23
|
# * {Access.betwixt}
|
@@ -26,7 +27,7 @@ require 'accessory/traversal_position/enumerable_before_offset'
|
|
26
27
|
#
|
27
28
|
# * +Array.new+
|
28
29
|
|
29
|
-
class Accessory::BetwixtAccessor < Accessory::Accessor
|
30
|
+
class Accessory::Accessors::BetwixtAccessor < Accessory::Accessor
|
30
31
|
# @param offset [Integer] the cursor position (i.e. the index of the element after the cursor)
|
31
32
|
# @param default [Object] the default to use if the predecessor accessor passes +nil+ data
|
32
33
|
def initialize(offset, default: nil)
|
@@ -99,12 +100,14 @@ class Accessory::BetwixtAccessor < Accessory::Accessor
|
|
99
100
|
pos = traverse_or_default(data || [])
|
100
101
|
|
101
102
|
case yield(pos)
|
102
|
-
in [result, new_value]
|
103
|
+
in [:dirty, result, new_value]
|
103
104
|
data ||= []
|
104
105
|
data.insert(@offset, new_value)
|
105
|
-
[result, data]
|
106
|
+
[:dirty, result, data]
|
106
107
|
in :pop
|
107
|
-
[nil, data]
|
108
|
+
[:clean, nil, data]
|
109
|
+
in [:clean, result, _]
|
110
|
+
[:clean, result, data]
|
108
111
|
end
|
109
112
|
end
|
110
113
|
end
|
@@ -15,7 +15,7 @@ require 'accessory/accessor'
|
|
15
15
|
#
|
16
16
|
# * +Array.new+
|
17
17
|
|
18
|
-
class Accessory::FilterAccessor < Accessory::Accessor
|
18
|
+
class Accessory::Accessors::FilterAccessor < Accessory::Accessor
|
19
19
|
# Returns a new instance of {FilterAccessor}.
|
20
20
|
#
|
21
21
|
# The predicate function may be passed in as either a positional argument,
|
@@ -65,6 +65,7 @@ class Accessory::FilterAccessor < Accessory::Accessor
|
|
65
65
|
def get_and_update(data)
|
66
66
|
results = []
|
67
67
|
new_data = []
|
68
|
+
dirty = false
|
68
69
|
|
69
70
|
(data || []).each do |pos|
|
70
71
|
unless @pred.call(pos)
|
@@ -73,14 +74,23 @@ class Accessory::FilterAccessor < Accessory::Accessor
|
|
73
74
|
end
|
74
75
|
|
75
76
|
case yield(pos)
|
76
|
-
in [result,
|
77
|
+
in [:clean, result, _]
|
78
|
+
results.push(result)
|
79
|
+
new_data.push(pos)
|
80
|
+
in [:dirty, result, new_value]
|
77
81
|
results.push(result)
|
78
82
|
new_data.push(new_value)
|
83
|
+
dirty = true
|
79
84
|
in :pop
|
80
85
|
results.push(pos)
|
86
|
+
dirty = true
|
81
87
|
end
|
82
88
|
end
|
83
89
|
|
84
|
-
|
90
|
+
if dirty
|
91
|
+
[:dirty, results, new_data]
|
92
|
+
else
|
93
|
+
[:clean, results, data]
|
94
|
+
end
|
85
95
|
end
|
86
96
|
end
|
@@ -4,8 +4,8 @@ require 'accessory/accessor'
|
|
4
4
|
# Traverses into the "first" element within an +Enumerable+, using
|
5
5
|
# <tt>#first</tt>.
|
6
6
|
#
|
7
|
-
# This accessor can be preferable to {SubscriptAccessor} for objects
|
8
|
-
# are not subscriptable, e.g.
|
7
|
+
# This accessor can be preferable to {Accessors::SubscriptAccessor} for objects
|
8
|
+
# that are not subscriptable, e.g. +Range+.
|
9
9
|
#
|
10
10
|
# *Aliases*
|
11
11
|
# * {Access.first}
|
@@ -15,7 +15,7 @@ require 'accessory/accessor'
|
|
15
15
|
#
|
16
16
|
# * +Array.new+
|
17
17
|
|
18
|
-
class Accessory::FirstAccessor < Accessory::Accessor
|
18
|
+
class Accessory::Accessors::FirstAccessor < Accessory::Accessor
|
19
19
|
# @!visibility private
|
20
20
|
def ensure_valid(traversal_result)
|
21
21
|
if traversal_result.kind_of?(Enumerable)
|
@@ -58,16 +58,18 @@ class Accessory::FirstAccessor < Accessory::Accessor
|
|
58
58
|
old_value = traverse_or_default(data)
|
59
59
|
|
60
60
|
case yield(old_value)
|
61
|
-
in [result,
|
61
|
+
in [:clean, result, _]
|
62
|
+
[:clean, result, data]
|
63
|
+
in [:dirty, result, new_value]
|
62
64
|
if data.respond_to?(:"first=")
|
63
65
|
data.first = new_value
|
64
66
|
else
|
65
67
|
data[0] = new_value
|
66
68
|
end
|
67
|
-
[result, data]
|
69
|
+
[:dirty, result, data]
|
68
70
|
in :pop
|
69
71
|
data.delete_at(0)
|
70
|
-
[old_value, data]
|
72
|
+
[:dirty, old_value, data]
|
71
73
|
end
|
72
74
|
end
|
73
75
|
end
|
@@ -14,7 +14,7 @@ require 'accessory/accessor'
|
|
14
14
|
#
|
15
15
|
# * +Object.new+
|
16
16
|
|
17
|
-
class Accessory::InstanceVariableAccessor < Accessory::Accessor
|
17
|
+
class Accessory::Accessors::InstanceVariableAccessor < Accessory::Accessor
|
18
18
|
# @param ivar_name [Symbol] the instance-variable name
|
19
19
|
# @param default [Object] the default to use if the predecessor accessor passes +nil+ data
|
20
20
|
def initialize(ivar_name, default: nil)
|
@@ -70,12 +70,14 @@ class Accessory::InstanceVariableAccessor < Accessory::Accessor
|
|
70
70
|
value = traverse_or_default(data)
|
71
71
|
|
72
72
|
case yield(value)
|
73
|
-
in [result,
|
73
|
+
in [:clean, result, _]
|
74
|
+
[:clean, result, data]
|
75
|
+
in [:dirty, result, new_value]
|
74
76
|
data.instance_variable_set(@ivar_name, new_value)
|
75
|
-
[result, data]
|
77
|
+
[:dirty, result, data]
|
76
78
|
in :pop
|
77
79
|
data.remove_instance_variable(@ivar_name)
|
78
|
-
[value, data]
|
80
|
+
[:dirty, value, data]
|
79
81
|
end
|
80
82
|
end
|
81
83
|
end
|
@@ -4,8 +4,8 @@ require 'accessory/accessor'
|
|
4
4
|
# Traverses into the "last" element within an +Enumerable+, using
|
5
5
|
# <tt>#last</tt>.
|
6
6
|
#
|
7
|
-
# This accessor can be preferable to {SubscriptAccessor} for objects
|
8
|
-
# are not subscriptable, e.g.
|
7
|
+
# This accessor can be preferable to {Accessors::SubscriptAccessor} for objects
|
8
|
+
# that are not subscriptable, e.g. +Range+.
|
9
9
|
#
|
10
10
|
# *Aliases*
|
11
11
|
# * {Access.last}
|
@@ -15,7 +15,7 @@ require 'accessory/accessor'
|
|
15
15
|
#
|
16
16
|
# * +Array.new+
|
17
17
|
|
18
|
-
class Accessory::LastAccessor < Accessory::Accessor
|
18
|
+
class Accessory::Accessors::LastAccessor < Accessory::Accessor
|
19
19
|
# @!visibility private
|
20
20
|
def ensure_valid(traversal_result)
|
21
21
|
if traversal_result.kind_of?(Enumerable)
|
@@ -58,16 +58,18 @@ class Accessory::LastAccessor < Accessory::Accessor
|
|
58
58
|
old_value = traverse_or_default(data)
|
59
59
|
|
60
60
|
case yield(old_value)
|
61
|
-
in [result,
|
61
|
+
in [:clean, result, _]
|
62
|
+
[:clean, result, data]
|
63
|
+
in [:dirty, result, new_value]
|
62
64
|
if data.respond_to?(:"last=")
|
63
65
|
data.last = new_value
|
64
66
|
else
|
65
67
|
data[-1] = new_value
|
66
68
|
end
|
67
|
-
[result, data]
|
69
|
+
[:dirty, result, data]
|
68
70
|
in :pop
|
69
71
|
data.delete_at(-1)
|
70
|
-
[old_value, data]
|
72
|
+
[:dirty, old_value, data]
|
71
73
|
end
|
72
74
|
end
|
73
75
|
end
|
@@ -29,9 +29,9 @@ require 'accessory/accessor'
|
|
29
29
|
# # default-constructs a Hash, not an Array
|
30
30
|
# [].lens[0][0].put_in(1) # => [{0=>1}]
|
31
31
|
#
|
32
|
-
# Other accessors ({FirstAccessor}, {BetwixtAccessor}, etc.) may fit your expectations more closely for +Array+ traversal.
|
32
|
+
# Other accessors ({Accessors::FirstAccessor}, {Accessors::BetwixtAccessor}, etc.) may fit your expectations more closely for +Array+ traversal.
|
33
33
|
|
34
|
-
class Accessory::SubscriptAccessor < Accessory::Accessor
|
34
|
+
class Accessory::Accessors::SubscriptAccessor < Accessory::Accessor
|
35
35
|
# @!visibility private
|
36
36
|
def initialize(key, **kwargs)
|
37
37
|
super(**kwargs)
|
@@ -92,12 +92,14 @@ class Accessory::SubscriptAccessor < Accessory::Accessor
|
|
92
92
|
value = traverse_or_default(data)
|
93
93
|
|
94
94
|
case yield(value)
|
95
|
-
in [result,
|
95
|
+
in [:clean, result, _]
|
96
|
+
[:clean, result, data]
|
97
|
+
in [:dirty, result, new_value]
|
96
98
|
data[@key] = new_value
|
97
|
-
[result, data]
|
99
|
+
[:dirty, result, data]
|
98
100
|
in :pop
|
99
101
|
data.delete(@key)
|
100
|
-
[value, data]
|
102
|
+
[:dirty, value, data]
|
101
103
|
end
|
102
104
|
end
|
103
105
|
end
|
data/lib/accessory/lens.rb
CHANGED
@@ -164,7 +164,17 @@ class Accessory::Lens
|
|
164
164
|
# 1. the _old_ value(s) found after all traversals, and
|
165
165
|
# 2. the updated +subject+
|
166
166
|
def update_in(subject, &new_value_fn)
|
167
|
-
_, new_data = self.get_and_update_in(
|
167
|
+
_, _, new_data = self.get_and_update_in(subject) do |v|
|
168
|
+
case new_value_fn.call(v)
|
169
|
+
in [:set, new_value]
|
170
|
+
[:dirty, nil, new_value]
|
171
|
+
in :keep
|
172
|
+
[:clean, nil, v]
|
173
|
+
in :pop
|
174
|
+
:pop
|
175
|
+
end
|
176
|
+
end
|
177
|
+
|
168
178
|
new_data
|
169
179
|
end
|
170
180
|
|
@@ -178,7 +188,7 @@ class Accessory::Lens
|
|
178
188
|
# @param new_value [Object] a replacement value at the traversal position.
|
179
189
|
# @return [Object] the updated +subject+
|
180
190
|
def put_in(subject, new_value)
|
181
|
-
_, new_data = self.get_and_update_in(subject){ [nil, new_value] }
|
191
|
+
_, _, new_data = self.get_and_update_in(subject){ [:dirty, nil, new_value] }
|
182
192
|
new_data
|
183
193
|
end
|
184
194
|
|
@@ -191,7 +201,8 @@ class Accessory::Lens
|
|
191
201
|
# @param subject [Object] the data-structure to traverse
|
192
202
|
# @return [Object] the updated +subject+
|
193
203
|
def pop_in(subject)
|
194
|
-
self.get_and_update_in(subject){ :pop }
|
204
|
+
_, popped_item, new_data = self.get_and_update_in(subject){ :pop }
|
205
|
+
[popped_item, new_data]
|
195
206
|
end
|
196
207
|
|
197
208
|
def append_accessor!(part)
|
@@ -200,9 +211,9 @@ class Accessory::Lens
|
|
200
211
|
when Accessory::Accessor
|
201
212
|
part
|
202
213
|
when Array
|
203
|
-
Accessory::SubscriptAccessor.new(part[0], default: part[1])
|
214
|
+
Accessory::Accessors::SubscriptAccessor.new(part[0], default: part[1])
|
204
215
|
else
|
205
|
-
Accessory::SubscriptAccessor.new(part)
|
216
|
+
Accessory::Accessors::SubscriptAccessor.new(part)
|
206
217
|
end
|
207
218
|
|
208
219
|
unless @parts.empty?
|
data/lib/accessory/version.rb
CHANGED
metadata
CHANGED
@@ -1,16 +1,16 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: accessory
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.11
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Levi Aul
|
8
|
-
autorequire:
|
8
|
+
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2021-
|
11
|
+
date: 2021-02-03 00:00:00.000000000 Z
|
12
12
|
dependencies: []
|
13
|
-
description:
|
13
|
+
description:
|
14
14
|
email:
|
15
15
|
- levi@leviaul.com
|
16
16
|
executables: []
|
@@ -40,7 +40,7 @@ licenses:
|
|
40
40
|
metadata:
|
41
41
|
homepage_uri: https://github.com/tsutsu/accessory
|
42
42
|
source_code_uri: https://github.com/tsutsu/accessory
|
43
|
-
post_install_message:
|
43
|
+
post_install_message:
|
44
44
|
rdoc_options: []
|
45
45
|
require_paths:
|
46
46
|
- lib
|
@@ -48,15 +48,15 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
48
48
|
requirements:
|
49
49
|
- - ">="
|
50
50
|
- !ruby/object:Gem::Version
|
51
|
-
version: 2.
|
51
|
+
version: 2.6.0
|
52
52
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
53
53
|
requirements:
|
54
54
|
- - ">="
|
55
55
|
- !ruby/object:Gem::Version
|
56
56
|
version: '0'
|
57
57
|
requirements: []
|
58
|
-
rubygems_version: 3.
|
59
|
-
signing_key:
|
58
|
+
rubygems_version: 3.0.3
|
59
|
+
signing_key:
|
60
60
|
specification_version: 4
|
61
61
|
summary: Functional lenses for Ruby, borrowed from Elixir
|
62
62
|
test_files: []
|