skn_utils 3.5.2 → 3.6.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -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