skn_utils 3.5.2 → 3.6.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.
@@ -1,68 +0,0 @@
1
- ##
2
- # <project.root>/lib/skn_utils/exploring/commander.rb
3
- ##
4
- # ref: https://github.com/saturnflyer/direction
5
- ##
6
- # Provide a feature like the Forwardable library,
7
- # but set the return value to self.
8
- # It provides a class level "command" method to do
9
- # message forwarding.
10
- #
11
- # class SomeClass
12
- # extend SknUtils::Commander
13
- #
14
- # command [:print_details, :setup_things] => :collaborator
15
- # query [:name, :id] => :collaborator, :type => :@partner
16
- # end
17
- #
18
- # This will define methods on instances that forward to the
19
- # provided receiver while enforcing encapsulation of the
20
- # relationship between objects.
21
- #
22
- # the collaborator and you must agree on how results can be exchanged
23
- # you might provide a callback method for it to set its return value on you
24
- # :callback, develop a protocol to exchange messages with collaborator
25
- ##
26
-
27
-
28
- module SknUtils
29
- module Exploring
30
- module Commander
31
-
32
- # Forward messages and return self, protecting the encapsulation of the object
33
- def command(options)
34
- Commander.define_methods(self, options) do |command, accessor|
35
- %{
36
- def #{command}(*args, &block)
37
- #{accessor}.__send__(:#{command}, *args, &block)
38
- self
39
- end
40
- }
41
- end
42
- end
43
-
44
- # Forward messages and return the result of the forwarded message
45
- def query(options)
46
- Commander.define_methods(self, options) do |query, accessor|
47
- %{
48
- def #{query}(*args, &block)
49
- #{accessor}.__send__(:#{query}, *args, &block)
50
- end
51
- }
52
- end
53
- end
54
-
55
- # Commander's class method
56
- def self.define_methods(mod, options)
57
- method_defs = []
58
- options.each_pair do |method_names, accessor|
59
- Array(method_names).map do |message|
60
- method_defs.push yield(message, accessor)
61
- end
62
- end
63
- mod.class_eval method_defs.join("\n"), __FILE__, __LINE__
64
- end
65
-
66
- end # Commander
67
- end # Exploring
68
- end # SknUtils
@@ -1,53 +0,0 @@
1
- ##
2
- # File: <gem-root>/lib/skn_utils/exploring/configuration.rb
3
- #
4
- # Engines and Gem sometimes need a configuration object, this is an example
5
- # Options class, consider OpenStruct2 or ActiveSupport::OrderedOptions as alternatives
6
-
7
- module SknUtils
8
- module Exploring
9
- module Configuration
10
-
11
- module_function
12
-
13
- def option_defaults
14
- @option_defaults ||= {one: 1, two: 2, three: 3}
15
- end
16
- def option_defaults=(parms)
17
- @option_defaults = parms
18
- end
19
-
20
- def reset!
21
- @configuration = Options.new(option_defaults)
22
- true
23
- end
24
-
25
- def config
26
- configure
27
- end
28
-
29
- def configure # Initialize with both the configuration keys and default values
30
- @configuration || reset!
31
- yield(@configuration) if block_given?
32
- @configuration
33
- end
34
-
35
- private
36
-
37
- class Options
38
- def initialize(parms={})
39
- parms.each_pair do |k,v|
40
- self.singleton_class.send(:attr_accessor, k)
41
- instance_variable_set("@#{k}",v)
42
- end
43
- end
44
- end
45
-
46
- end
47
- # require your Gem or Engine here
48
-
49
- end
50
- end
51
-
52
- # In config/initializers/gem_config.rb
53
- # SknUtils::Exploring::Configuration.class_variable_set(:option_defaults, {one: 1, two: 2, three: 3})
@@ -1,161 +0,0 @@
1
- ##
2
- # File <SknUtils>/lib/skn_utils/lists/circular_linked_list.rb
3
- #
4
- # ll = SknUtils::Lists::CircularLinkedList.new(*vargs, &compare_key_proc)
5
- # - or -
6
- # ll = SknUtils::Lists::CircularLinkedList.new(1,2,3,4,5) {|element| element[:key] }
7
- # - or -
8
- # ll = SknUtils::Lists::CircularLinkedList.new(
9
- # {key: 'Z'}, {key: 'K'}, {key: 'S'}, {key: 'n'}, {key: 's'}
10
- # ) {|el| el[:key] }
11
- # - or -
12
- # cmp_proc = lambda { |el| el[:key] }
13
- # vargs = [{key: 'Z'}, {key: 'K'}, {key: 'S'}, {key: 'n'}, {key: 's'}]
14
- # ll = SknUtils::Lists::CircularLinkedList.new(*vargs, &cmp_proc)
15
- ###
16
- # value = ll.first
17
- # value = ll.at_index(4)
18
- # count = ll.insert({key: 'anyValue'})
19
- # ...
20
- # count = ll.sort! -- defaults to :asc
21
- # count = ll.sort!(:desc)
22
- # count = ll.sort!() {|a,b| a[:key] <= b[:key] }
23
- ##
24
-
25
- module SknUtils
26
- module Lists
27
- # Circularly Linked List
28
- # Forward (#next) and Backwards (#prev) navigation
29
- # No Head or Tail
30
-
31
- # LinkedCommons provides;
32
- # - #initialize, #first, #next, #current, #last, #at_index,
33
- # #insert, #prepend, #append, #empty?, #clear,
34
- # #each, #to_a, and #sort!
35
- #
36
- class CircularLinkedList < LinkedCommons
37
-
38
- #
39
- # Navigation
40
- #
41
-
42
-
43
- def prev
44
- @current = @current.prev if @current and @current.prev
45
- @current.value rescue nil
46
- end
47
-
48
- # -+ int position from current node
49
- def nth(index)
50
- node = @current
51
- position = node
52
- if index > 0
53
- while index > 1 and node and node.next
54
- node = node.next
55
- index -= 1
56
- @current = node
57
- break if position.equal?(node)
58
- end
59
- elsif index < 0
60
- while index < 0 and node and node.prev
61
- node = node.prev
62
- index += 1
63
- @current = node
64
- break if position.equal?(node)
65
- end
66
- end
67
- current
68
- end
69
-
70
- #
71
- # Modifications
72
- #
73
- # return new size
74
- def insert(value)
75
- node = @current
76
- @current = LinkNode.call(value, node, :circle_after, self, &@match_value)
77
- if self.size == 0 # only
78
- self.head = @current
79
- self.tail = @current
80
- elsif self.tail == node
81
- self.tail = @current
82
- @current.next = self.head
83
- self.head.prev = @current
84
- end
85
- self.size += 1
86
- end
87
- alias_method :append, :insert
88
-
89
- # return new size
90
- def insert_before(position_value, value)
91
- target = find_by_value(position_value)
92
- node = LinkNode.call(value, target, :circle_before, self, &@match_value)
93
- @current = node
94
- if self.size == 0 # only
95
- self.head = node
96
- self.tail = node
97
- elsif self.head == target # new head
98
- self.head = node
99
- node.prev = self.tail
100
- self.tail.next = node
101
- end
102
- self.size += 1
103
- end
104
-
105
- # return new size
106
- def insert_after(position_value, value)
107
- target = find_by_value(position_value)
108
- node = LinkNode.call(value, target, :circle_after, self, &@match_value)
109
- @current = node
110
- if self.size == 0 # only
111
- self.head = node
112
- self.tail = node
113
- elsif self.tail == target
114
- self.tail = node
115
- node.next = self.head
116
- self.head.prev = node
117
- end
118
- self.size += 1
119
- end
120
-
121
- # return remaining size
122
- def remove(value)
123
- target_node = find_by_value(value)
124
- if target_node
125
- if self.size == 1 # will become zero
126
- @current = nil
127
- self.head = nil
128
- self.tail = nil
129
- elsif target_node.equal?(self.head) # top
130
- @current = target_node.next
131
- @current.prev = target_node.prev
132
- self.tail.next = @current
133
- self.head = @current
134
- elsif target_node.equal?(self.tail) # bottom
135
- @current = target_node.prev
136
- @current.next = target_node.next
137
- self.head.prev = @current
138
- self.tail = @current
139
- else # middle
140
- @current = target_node.prev
141
- @current.next = target_node.next
142
- @current.next.prev = @current
143
- end
144
- target_node.remove!
145
- self.size -= 1
146
- end
147
- end
148
-
149
- protected
150
-
151
- def find_by_index(index)
152
- return nil if ( index > self.size || index < 1 )
153
- node = self.head
154
- node = node.next while ( (index -= 1) > 0 )
155
- @current = node
156
- node
157
- end
158
-
159
- end # end class
160
- end # module
161
- end # end module
@@ -1,139 +0,0 @@
1
- ##
2
- # File <SknUtils>/lib/skn_utils/lists/doubly_linked_list.rb
3
- #
4
- # ll = SknUtils::Lists::DoublyLinkedList.new(*vargs, &compare_key_proc)
5
- # - or -
6
- # ll = SknUtils::Lists::DoublyLinkedList.new(1,2,3,4,5) {|element| element[:key] }
7
- # - or -
8
- # ll = SknUtils::Lists::DoublyLinkedList.new(
9
- # {key: 'Z'}, {key: 'K'}, {key: 'S'}, {key: 'n'}, {key: 's'}
10
- # ) {|el| el[:key] }
11
- # - or -
12
- # cmp_proc = lambda { |el| el[:key] }
13
- # vargs = [{key: 'Z'}, {key: 'K'}, {key: 'S'}, {key: 'n'}, {key: 's'}]
14
- # ll = SknUtils::Lists::DoublyLinkedList.new(*vargs, &cmp_proc)
15
- ###
16
- # value = ll.first
17
- # value = ll.at_index(4)
18
- # count = ll.insert({key: 'anyValue'})
19
- # ...
20
- # count = ll.sort! -- defaults to :asc
21
- # count = ll.sort!(:desc)
22
- # count = ll.sort!() {|a,b| a[:key] <= b[:key] }
23
- ##
24
-
25
- module SknUtils
26
- module Lists
27
- # Doubly Linked List
28
- # Forward (#next) and Backwards (#prev) navigation
29
- # Head when (prev == nil)
30
- # Tail when (next == nil)
31
-
32
- # LinkedCommons provides;
33
- # - #initialize, #first, #next, #current, #last, #at_index,
34
- # #insert, #prepend, #append, #empty?, #clear,
35
- # #each, #to_a, and #sort!
36
- #
37
- class DoublyLinkedList < LinkedCommons
38
-
39
- #
40
- # Navigation
41
- #
42
-
43
- def prev
44
- @current = @current.prev if @current and @current.prev
45
- @current.value rescue nil
46
- end
47
-
48
- # -+ int position from current node
49
- def nth(index)
50
- node = @current
51
- if index > 0
52
- while index > 1 and node and node.next
53
- node = node.next
54
- index -= 1
55
- end
56
- @current = node
57
- elsif index < 0
58
- while index < 0 and node and node.prev
59
- node = node.prev
60
- index += 1
61
- end
62
- @current = node
63
- end
64
- current
65
- end
66
-
67
- #
68
- # Modifications
69
- #
70
-
71
- # return new size
72
- def insert(value)
73
- node = @current
74
- @current = LinkNode.call(value, node, :after, self, &@match_value)
75
- self.head = @current if self.head.nil?
76
- self.tail = @current if self.tail.equal?(node)
77
- self.size += 1
78
- end
79
- alias_method :append, :insert
80
-
81
- # return new size
82
- def insert_before(position_value, value)
83
- target = find_by_value(position_value)
84
- node = LinkNode.call(value, target, :before, self, &@match_value)
85
- @current = node if target
86
- self.head = node if self.head.equal?(target)
87
- self.tail = node if self.tail.nil?
88
- self.size += 1
89
- end
90
-
91
- # return new size
92
- def insert_after(position_value, value)
93
- target = find_by_value(position_value)
94
- node = LinkNode.call(value, target, :after, self, &@match_value)
95
- @current = node
96
- self.head = node if self.head.nil?
97
- self.tail = node if self.tail.equal?(target)
98
- self.size += 1
99
- end
100
-
101
- # return remaining size
102
- def remove(value)
103
- target_node = find_by_value(value)
104
- if target_node
105
- if self.size == 1 # will become zero
106
- @current = nil
107
- self.head = nil
108
- self.tail = nil
109
- elsif target_node.prev.nil? # top
110
- @current = target_node.next
111
- @current.prev = nil
112
- self.head = @current
113
- elsif target_node.next.nil? # bottom
114
- @current = target_node.prev
115
- @current.next = nil
116
- self.tail = @current
117
- else # middle
118
- @current = target_node.prev
119
- @current.next = target_node.next
120
- target_node.next.prev = @current
121
- end
122
- target_node.remove!
123
- self.size -= 1
124
- end
125
- end
126
-
127
- protected
128
-
129
- def find_by_index(index)
130
- return nil if self.head.nil? or index < 1 or index > self.size
131
- node = self.head
132
- node = node.next while ((index -= 1) > 0 and node.next)
133
- @current = node if node
134
- node
135
- end
136
-
137
- end # end class
138
- end # module
139
- end # end module
@@ -1,103 +0,0 @@
1
- ##
2
- # Node.
3
- # - primary object and container of value
4
- ##
5
-
6
- module SknUtils
7
- module Lists
8
-
9
- class LinkNode
10
-
11
- attr_accessor :prev, :next, :value
12
-
13
- def self.call(val, anchor_node=nil, strategy=:after, mgr=nil, &cmp_key)
14
- self.new(val, anchor_node, strategy, mgr, &cmp_key)
15
- end
16
-
17
- def initialize(val, anchor_node=nil, strategy=:after, mgr=nil, &cmp_key)
18
- @value = val
19
- @prev = nil
20
- @next = nil
21
- @provider = mgr
22
- @cmp_proc = block_given? ? cmp_key : lambda {|a| a }
23
-
24
- case strategy
25
- when :single # after logic
26
- if anchor_node
27
- @next = anchor_node.next
28
- anchor_node.next = self
29
- end
30
- when :before
31
- @prev = anchor_node.prev if anchor_node
32
- anchor_node.prev = self if anchor_node
33
- @next = anchor_node
34
- when :after
35
- @next = anchor_node.next if anchor_node
36
- anchor_node.next = self if anchor_node
37
- @prev = anchor_node
38
- when :circle_before
39
- @prev = anchor_node ? anchor_node.prev : self
40
- anchor_node.prev = self if anchor_node
41
- @next = anchor_node ? anchor_node : self
42
- when :circle_after
43
- @next = anchor_node ? anchor_node.next : self
44
- anchor_node.next = self if anchor_node
45
- @prev = anchor_node ? anchor_node : self
46
- end
47
- end
48
-
49
- def match_by_value(other_value)
50
- @cmp_proc.call(self.value) == @cmp_proc.call(other_value)
51
- end
52
-
53
- # returns next node
54
- def remove!
55
- next_node = @next
56
- @value = nil
57
- @prev = nil
58
- @next = nil
59
- @provider = nil
60
- @cmp_proc = nil
61
- next_node
62
- end
63
-
64
- def to_s
65
- "Node with value: #{@value}"
66
- end
67
-
68
- # Reverse API to Parent Linked List Class
69
- def node_value
70
- node_value_request(:current)
71
- end
72
- def first_node
73
- node_request(:first)
74
- end
75
- def next_node
76
- node_request(:next)
77
- end
78
- def current_node
79
- node_request(:current)
80
- end
81
- def prev_node
82
- node_request(:prev)
83
- end
84
- def last_node
85
- node_request(:last)
86
- end
87
-
88
- # Retrieves requested node, not value
89
- def node_request(method_sym=:current, *vargs, &block)
90
- block_given? ? @provider.send(method_sym, *vargs, &block) :
91
- (vargs.size == 0 ? @provider.send(method_sym) : @provider.send(method_sym, *vargs))
92
- @provider.instance_variable_get(:@current)
93
- end
94
-
95
- # Retrieves requested value, not node
96
- def node_value_request(method_sym=:current, *vargs, &block)
97
- block_given? ? @provider.send(method_sym, *vargs, &block) :
98
- (vargs.size == 0 ? @provider.send(method_sym) : @provider.send(method_sym, *vargs))
99
- end
100
-
101
- end
102
- end # module
103
- end