garcun 0.0.2

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.
Files changed (139) hide show
  1. checksums.yaml +7 -0
  2. data/.gitattributes +17 -0
  3. data/.gitignore +197 -0
  4. data/.rspec +2 -0
  5. data/Gemfile +22 -0
  6. data/LICENSE +201 -0
  7. data/README.md +521 -0
  8. data/Rakefile +47 -0
  9. data/garcun.gemspec +83 -0
  10. data/lib/garcon.rb +290 -0
  11. data/lib/garcon/chef/chef_helpers.rb +343 -0
  12. data/lib/garcon/chef/coerce/coercer.rb +134 -0
  13. data/lib/garcon/chef/coerce/coercions/boolean_definitions.rb +34 -0
  14. data/lib/garcon/chef/coerce/coercions/date_definitions.rb +32 -0
  15. data/lib/garcon/chef/coerce/coercions/date_time_definitions.rb +32 -0
  16. data/lib/garcon/chef/coerce/coercions/fixnum_definitions.rb +34 -0
  17. data/lib/garcon/chef/coerce/coercions/float_definitions.rb +32 -0
  18. data/lib/garcon/chef/coerce/coercions/hash_definitions.rb +29 -0
  19. data/lib/garcon/chef/coerce/coercions/integer_definitions.rb +31 -0
  20. data/lib/garcon/chef/coerce/coercions/string_definitions.rb +45 -0
  21. data/lib/garcon/chef/coerce/coercions/time_definitions.rb +32 -0
  22. data/lib/garcon/chef/handler/devreporter.rb +127 -0
  23. data/lib/garcon/chef/log.rb +64 -0
  24. data/lib/garcon/chef/node.rb +100 -0
  25. data/lib/garcon/chef/provider/civilize.rb +209 -0
  26. data/lib/garcon/chef/provider/development.rb +159 -0
  27. data/lib/garcon/chef/provider/download.rb +420 -0
  28. data/lib/garcon/chef/provider/house_keeping.rb +265 -0
  29. data/lib/garcon/chef/provider/node_cache.rb +31 -0
  30. data/lib/garcon/chef/provider/partial.rb +183 -0
  31. data/lib/garcon/chef/provider/recovery.rb +80 -0
  32. data/lib/garcon/chef/provider/zip_file.rb +271 -0
  33. data/lib/garcon/chef/resource/attribute.rb +52 -0
  34. data/lib/garcon/chef/resource/base_dsl.rb +174 -0
  35. data/lib/garcon/chef/resource/blender.rb +140 -0
  36. data/lib/garcon/chef/resource/lazy_eval.rb +66 -0
  37. data/lib/garcon/chef/resource/resource_name.rb +109 -0
  38. data/lib/garcon/chef/secret_bag.rb +204 -0
  39. data/lib/garcon/chef/validations.rb +76 -0
  40. data/lib/garcon/chef_inclusions.rb +151 -0
  41. data/lib/garcon/configuration.rb +138 -0
  42. data/lib/garcon/core_ext.rb +39 -0
  43. data/lib/garcon/core_ext/array.rb +27 -0
  44. data/lib/garcon/core_ext/binding.rb +64 -0
  45. data/lib/garcon/core_ext/boolean.rb +66 -0
  46. data/lib/garcon/core_ext/duration.rb +271 -0
  47. data/lib/garcon/core_ext/enumerable.rb +34 -0
  48. data/lib/garcon/core_ext/file.rb +127 -0
  49. data/lib/garcon/core_ext/filetest.rb +62 -0
  50. data/lib/garcon/core_ext/hash.rb +279 -0
  51. data/lib/garcon/core_ext/kernel.rb +159 -0
  52. data/lib/garcon/core_ext/lazy.rb +222 -0
  53. data/lib/garcon/core_ext/method_access.rb +243 -0
  54. data/lib/garcon/core_ext/module.rb +92 -0
  55. data/lib/garcon/core_ext/nil.rb +53 -0
  56. data/lib/garcon/core_ext/numeric.rb +44 -0
  57. data/lib/garcon/core_ext/object.rb +342 -0
  58. data/lib/garcon/core_ext/pathname.rb +152 -0
  59. data/lib/garcon/core_ext/process.rb +41 -0
  60. data/lib/garcon/core_ext/random.rb +497 -0
  61. data/lib/garcon/core_ext/string.rb +312 -0
  62. data/lib/garcon/core_ext/struct.rb +49 -0
  63. data/lib/garcon/core_ext/symbol.rb +170 -0
  64. data/lib/garcon/core_ext/time.rb +234 -0
  65. data/lib/garcon/exceptions.rb +101 -0
  66. data/lib/garcon/inflections.rb +237 -0
  67. data/lib/garcon/inflections/defaults.rb +79 -0
  68. data/lib/garcon/inflections/inflections.rb +182 -0
  69. data/lib/garcon/inflections/rules_collection.rb +37 -0
  70. data/lib/garcon/secret.rb +271 -0
  71. data/lib/garcon/stash/format.rb +114 -0
  72. data/lib/garcon/stash/journal.rb +226 -0
  73. data/lib/garcon/stash/queue.rb +83 -0
  74. data/lib/garcon/stash/serializer.rb +86 -0
  75. data/lib/garcon/stash/store.rb +435 -0
  76. data/lib/garcon/task.rb +31 -0
  77. data/lib/garcon/task/atomic.rb +151 -0
  78. data/lib/garcon/task/atomic_boolean.rb +127 -0
  79. data/lib/garcon/task/condition.rb +99 -0
  80. data/lib/garcon/task/copy_on_notify_observer_set.rb +154 -0
  81. data/lib/garcon/task/copy_on_write_observer_set.rb +153 -0
  82. data/lib/garcon/task/count_down_latch.rb +92 -0
  83. data/lib/garcon/task/delay.rb +196 -0
  84. data/lib/garcon/task/dereferenceable.rb +144 -0
  85. data/lib/garcon/task/event.rb +119 -0
  86. data/lib/garcon/task/executor.rb +275 -0
  87. data/lib/garcon/task/executor_options.rb +59 -0
  88. data/lib/garcon/task/future.rb +107 -0
  89. data/lib/garcon/task/immediate_executor.rb +84 -0
  90. data/lib/garcon/task/ivar.rb +171 -0
  91. data/lib/garcon/task/lazy_reference.rb +74 -0
  92. data/lib/garcon/task/monotonic_time.rb +69 -0
  93. data/lib/garcon/task/obligation.rb +256 -0
  94. data/lib/garcon/task/observable.rb +101 -0
  95. data/lib/garcon/task/priority_queue.rb +234 -0
  96. data/lib/garcon/task/processor_count.rb +128 -0
  97. data/lib/garcon/task/read_write_lock.rb +304 -0
  98. data/lib/garcon/task/safe_task_executor.rb +58 -0
  99. data/lib/garcon/task/single_thread_executor.rb +97 -0
  100. data/lib/garcon/task/thread_pool/cached.rb +71 -0
  101. data/lib/garcon/task/thread_pool/executor.rb +294 -0
  102. data/lib/garcon/task/thread_pool/fixed.rb +61 -0
  103. data/lib/garcon/task/thread_pool/worker.rb +90 -0
  104. data/lib/garcon/task/timer.rb +44 -0
  105. data/lib/garcon/task/timer_set.rb +194 -0
  106. data/lib/garcon/task/timer_task.rb +377 -0
  107. data/lib/garcon/task/waitable_list.rb +58 -0
  108. data/lib/garcon/utility/ansi.rb +199 -0
  109. data/lib/garcon/utility/at_random.rb +77 -0
  110. data/lib/garcon/utility/crypto.rb +292 -0
  111. data/lib/garcon/utility/equalizer.rb +146 -0
  112. data/lib/garcon/utility/faker/extensions/array.rb +22 -0
  113. data/lib/garcon/utility/faker/extensions/symbol.rb +9 -0
  114. data/lib/garcon/utility/faker/faker.rb +164 -0
  115. data/lib/garcon/utility/faker/faker/company.rb +17 -0
  116. data/lib/garcon/utility/faker/faker/hacker.rb +30 -0
  117. data/lib/garcon/utility/faker/faker/version.rb +3 -0
  118. data/lib/garcon/utility/faker/locales/en-US.yml +83 -0
  119. data/lib/garcon/utility/faker/locales/en.yml +21 -0
  120. data/lib/garcon/utility/file_helper.rb +170 -0
  121. data/lib/garcon/utility/hookers.rb +178 -0
  122. data/lib/garcon/utility/interpolation.rb +90 -0
  123. data/lib/garcon/utility/memstash.rb +364 -0
  124. data/lib/garcon/utility/misc.rb +54 -0
  125. data/lib/garcon/utility/msg_from_god.rb +62 -0
  126. data/lib/garcon/utility/retry.rb +238 -0
  127. data/lib/garcon/utility/timeout.rb +58 -0
  128. data/lib/garcon/utility/uber/builder.rb +91 -0
  129. data/lib/garcon/utility/uber/callable.rb +7 -0
  130. data/lib/garcon/utility/uber/delegates.rb +13 -0
  131. data/lib/garcon/utility/uber/inheritable_attr.rb +37 -0
  132. data/lib/garcon/utility/uber/options.rb +101 -0
  133. data/lib/garcon/utility/uber/uber_version.rb +3 -0
  134. data/lib/garcon/utility/uber/version.rb +33 -0
  135. data/lib/garcon/utility/url_helper.rb +100 -0
  136. data/lib/garcon/utils.rb +29 -0
  137. data/lib/garcon/version.rb +62 -0
  138. data/lib/garcun.rb +24 -0
  139. metadata +680 -0
@@ -0,0 +1,312 @@
1
+ # encoding: UTF-8
2
+ #
3
+ # Author: Stefano Harding <riddopic@gmail.com>
4
+ # License: Apache License, Version 2.0
5
+ # Copyright: (C) 2014-2015 Stefano Harding
6
+ #
7
+ # Licensed under the Apache License, Version 2.0 (the "License");
8
+ # you may not use this file except in compliance with the License.
9
+ # You may obtain a copy of the License at
10
+ #
11
+ # http://www.apache.org/licenses/LICENSE-2.0
12
+ #
13
+ # Unless required by applicable law or agreed to in writing, software
14
+ # distributed under the License is distributed on an "AS IS" BASIS,
15
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16
+ # See the License for the specific language governing permissions and
17
+ # limitations under the License.
18
+ #
19
+
20
+ # Adds `#contains?`, `#blank?` and `#shatter` methods to strings
21
+ #
22
+ class String
23
+
24
+ # Get or set state of object. You can think of #object_state as an in-code
25
+ # form of marshalling.
26
+ #
27
+ def object_state(data=nil)
28
+ data ? replace(data) : dup
29
+ end
30
+
31
+ # Common Unix cryptography method.
32
+ # This adds a default salt to the built-in crypt method.
33
+ #
34
+ def crypt(salt=nil)
35
+ salt ||= ((SecureRandom.random_number(26) +
36
+ (SecureRandom.random_number(2) == 0 ? 65 : 97)).chr +
37
+ (SecureRandom.random_number(26) +
38
+ (SecureRandom.random_number(2) == 0 ? 65 : 97)).chr)
39
+ _crypt(salt)
40
+ end
41
+
42
+ # Search a text file for a matching string
43
+ #
44
+ # @return [Boolean]
45
+ # True if the file is present and a match was found, otherwise returns
46
+ # false if file does not exist and/or does not contain a match
47
+ #
48
+ # @api public
49
+ def contains?(str)
50
+ return false unless ::File.exist?(self)
51
+ ::File.open(self, &:readlines).collect { |l| return true if l.match(str) }
52
+ false
53
+ end
54
+
55
+ # Turns a string into a regular expression.
56
+ #
57
+ # "a?".to_re #=> /a?/
58
+ #
59
+ def to_re(esc=false)
60
+ Regexp.new((esc ? Regexp.escape(self) : self))
61
+ end
62
+
63
+ # Turns a string into a regular expression.
64
+ # By default it will escape all characters.
65
+ # Use <tt>false</tt> argument to turn off escaping.
66
+ #
67
+ # "[".to_rx #=> /\[/
68
+ #
69
+ def to_rx(esc=true)
70
+ Regexp.new((esc ? Regexp.escape(self) : self))
71
+ end
72
+
73
+ # Strips out whitespace then tests if the string is empty.
74
+ #
75
+ # @example
76
+ # "".blank? # => true
77
+ # " ".blank? # => true
78
+ # " sup? ".blank? # => false
79
+ #
80
+ # @return [Boolean]
81
+ # True if blank, else false.
82
+ #
83
+ # @api public
84
+ def blank?
85
+ strip.empty?
86
+ end
87
+
88
+ # Breaks a string up into an array based on a regular expression.
89
+ # Similar to scan, but includes the matches.
90
+ #
91
+ # @example
92
+ # s = "<p>This<b>is</b>a test.</p>"
93
+ # s.shatter(/\<.*?\>/)
94
+ # => [
95
+ # [0] "<p>",
96
+ # [1] "This",
97
+ # [2] "<b>",
98
+ # [3] "is",
99
+ # [4] "</b>",
100
+ # [5] "a test.",
101
+ # [6] "</p>"
102
+ # ]
103
+ #
104
+ # @param [Regexp] regex
105
+ # Regular expression for breaking string into array.
106
+ #
107
+ # @return [String]
108
+ #
109
+ # @api public
110
+ def shatter(re)
111
+ r = self.gsub(re) { |s| "\1" + s + "\1" }
112
+ while r[ 0, 1] == "\1"; r[0] = ''; end
113
+ while r[-1, 1] == "\1"; r[-1] = ''; end
114
+ r.split("\1")
115
+ end
116
+
117
+ # Left-flush a string based off of the number of whitespace characters on the
118
+ # first line. This is especially useful for heredocs when whitespace matters.
119
+ #
120
+ # @example Remove leading whitespace and flush
121
+ # <<-EOH.flush
122
+ # def method
123
+ # 'This is a string!'
124
+ # end
125
+ # EOH # =>"def method\n 'This is a string!'\nend"
126
+ #
127
+ # @return [String]
128
+ #
129
+ # @api public
130
+ def flush
131
+ gsub(/^#{self[/\A\s*/]}/, '').chomp
132
+ end unless method_defined?(:flush)
133
+
134
+ # Escape all regexp special characters.
135
+ #
136
+ # @example
137
+ # "*?{}.".escape_regexp # => "\\*\\?\\{\\}\\."
138
+ #
139
+ # @return [String]
140
+ # Receiver with all regexp special characters escaped.
141
+ #
142
+ # @api public
143
+ def escape_regexp
144
+ Regexp.escape self
145
+ end
146
+
147
+ # Unescape all regexp special characters.
148
+ #
149
+ # @example
150
+ # "\\*\\?\\{\\}\\.".unescape_regexp # => "*?{}."
151
+ #
152
+ # @return [String]
153
+ # Receiver with all regexp special characters unescaped.
154
+ #
155
+ # @api public
156
+ def unescape_regexp
157
+ self.gsub(/\\([\.\?\|\(\)\[\]\{\}\^\$\*\+\-])/, '\1')
158
+ end
159
+
160
+ # Convert a path string to a constant name.
161
+ #
162
+ # @example
163
+ # "chef/mixin/checksum".to_const_string # => "Chef::Mixin::Checksum"
164
+ #
165
+ # @return [String]
166
+ # Receiver converted to a constant name.
167
+ #
168
+ # @api public
169
+ def to_const_string
170
+ gsub(/\/(.?)/) { "::#{$1.upcase}" }.gsub(/(?:^|_)(.)/) { $1.upcase }
171
+ end
172
+
173
+ # Convert a constant name to a path, assuming a conventional structure.
174
+ #
175
+ # @example
176
+ # "FooBar::Baz".to_const_path # => "foo_bar/baz"
177
+ #
178
+ # @return [String]
179
+ # Path to the file containing the constant named by receiver (constantized
180
+ # string), assuming a conventional structure.
181
+ #
182
+ # @api public
183
+ def to_const_path
184
+ snake_case.gsub(/::/, "/")
185
+ end
186
+
187
+ # Join with _o_ as a file path.
188
+ #
189
+ # @example
190
+ # 'usr'/'local' # => 'usr/local'
191
+ #
192
+ # @param [String] other
193
+ # Path component(s) to join with receiver.
194
+ #
195
+ # @return [String]
196
+ # Receiver joined with other as a file path.
197
+ #
198
+ # @api public
199
+ def /(other)
200
+ File.join(self, other.to_s)
201
+ end
202
+
203
+ # Calculate a relative path *from* _other_.
204
+ #
205
+ # @example
206
+ # '/opt/chefdk/'.relative_path_from '/opt/chefdk/embedded/bin' # => '../..'
207
+ #
208
+ # @param [String] other
209
+ # Base path to calculate *from*.
210
+ #
211
+ # @return [String]
212
+ # Relative path from _other_ to receiver.
213
+ #
214
+ # @api public
215
+ def relative_path_from(other)
216
+ Pathname.new(self).relative_path_from(Pathname.new(other)).to_s
217
+ end
218
+
219
+ # Replace sequences of whitespace (including newlines) with either
220
+ # a single space or remove them entirely (according to param _spaced_)
221
+ #
222
+ # @example
223
+ # <<QUERY.compress_lines
224
+ # SELECT name
225
+ # FROM users
226
+ # QUERY => 'SELECT name FROM users'
227
+ #
228
+ # @param [Boolean] spaced (default=true)
229
+ # Determines whether returned string has whitespace collapsed or removed
230
+ #
231
+ # @return [String]
232
+ # Receiver with whitespace (including newlines) replaced
233
+ #
234
+ # @api public
235
+ def compress_lines(spaced = true)
236
+ split($/).map { |line| line.strip }.join(spaced ? ' ' : '')
237
+ end
238
+
239
+ # Remove whitespace margin.
240
+ #
241
+ # @return [String]
242
+ # Receiver with whitespace margin removed.
243
+ #
244
+ # @api public
245
+ def margin(indicator = nil)
246
+ lines = self.dup.split($/)
247
+
248
+ min_margin = 0
249
+ lines.each do |line|
250
+ if line =~ /^(\s+)/ && (min_margin == 0 || $1.size < min_margin)
251
+ min_margin = $1.size
252
+ end
253
+ end
254
+ lines.map { |line| line.sub(/^\s{#{min_margin}}/, '') }.join($/)
255
+ end
256
+
257
+ # Formats String for easy translation. Replaces an arbitrary number of
258
+ # values using numeric identifier replacement.
259
+ #
260
+ # @example
261
+ # "%s %s %s" % %w(one two three) # => 'one two three'
262
+ # "%3$s %2$s %1$s" % %w(one two three) # => 'three two one'
263
+ #
264
+ # @param [#to_s] values
265
+ # A list of values to translate and interpolate into receiver
266
+ #
267
+ # @return [String]
268
+ # Receiver translated with values translated and interpolated positionally
269
+ #
270
+ # @api public
271
+ def t(*values)
272
+ self.class::translate(self) % values.collect! do |value|
273
+ value.frozen? ? value : self.class::translate(value.to_s)
274
+ end
275
+ end
276
+
277
+ def clear; colorize(self, "\e[0m"); end
278
+ def erase_line; colorize(self, "\e[K"); end
279
+ def erase_char; colorize(self, "\e[P"); end
280
+ def bold; colorize(self, "\e[1m"); end
281
+ def dark; colorize(self, "\e[2m"); end
282
+ def underline; colorize(self, "\e[4m"); end
283
+ def blink; colorize(self, "\e[5m"); end
284
+ def reverse; colorize(self, "\e[7m"); end
285
+ def concealed; colorize(self, "\e[8m"); end
286
+ def black; colorize(self, "\e[0;30m"); end
287
+ def gray; colorize(self, "\e[1;30m"); end
288
+ def red; colorize(self, "\e[0;31m"); end
289
+ def magenta; colorize(self, "\e[1;31m"); end
290
+ def green; colorize(self, "\e[0;32m"); end
291
+ def olive; colorize(self, "\e[1;32m"); end
292
+ def yellow; colorize(self, "\e[0;33m"); end
293
+ def cream; colorize(self, "\e[1;33m"); end
294
+ def blue; colorize(self, "\e[0;34m"); end
295
+ def purple; colorize(self, "\e[1;34m"); end
296
+ def orange; colorize(self, "\e[0;35m"); end
297
+ def mustard; colorize(self, "\e[1;35m"); end
298
+ def cyan; colorize(self, "\e[0;36m"); end
299
+ def cyan2; colorize(self, "\e[1;36m"); end
300
+ def light_gray; colorize(self, "\e[2;37m"); end
301
+ def bright_red; colorize(self, "\e[1;41m"); end
302
+ def white; colorize(self, "\e[0;97m"); end
303
+ def on_black; colorize(self, "\e[40m"); end
304
+ def on_red; colorize(self, "\e[41m"); end
305
+ def on_green; colorize(self, "\e[42m"); end
306
+ def on_yellow; colorize(self, "\e[43m"); end
307
+ def on_blue; colorize(self, "\e[44m"); end
308
+ def on_magenta; colorize(self, "\e[45m"); end
309
+ def on_cyan; colorize(self, "\e[46m"); end
310
+ def on_white; colorize(self, "\e[47m"); end
311
+ def colorize(text, color_code) "#{color_code}#{text}\e[0m" end
312
+ end
@@ -0,0 +1,49 @@
1
+ # encoding: UTF-8
2
+ #
3
+ # Author: Stefano Harding <riddopic@gmail.com>
4
+ # License: Apache License, Version 2.0
5
+ # Copyright: (C) 2014-2015 Stefano Harding
6
+ #
7
+ # Licensed under the Apache License, Version 2.0 (the "License");
8
+ # you may not use this file except in compliance with the License.
9
+ # You may obtain a copy of the License at
10
+ #
11
+ # http://www.apache.org/licenses/LICENSE-2.0
12
+ #
13
+ # Unless required by applicable law or agreed to in writing, software
14
+ # distributed under the License is distributed on an "AS IS" BASIS,
15
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16
+ # See the License for the specific language governing permissions and
17
+ # limitations under the License.
18
+ #
19
+
20
+ class Struct
21
+
22
+ # Get or set state of object. You can think of #object_state as an in-code
23
+ # form of marshalling.
24
+ #
25
+ def object_state(data=nil)
26
+ if data
27
+ data.each_pair {|k,v| send(k.to_s + "=", v)}
28
+ else
29
+ data = {}
30
+ each_pair{|k,v| data[k] = v}
31
+ data
32
+ end
33
+ end
34
+
35
+ # Get a hash with names and values of all instance variables.
36
+ #
37
+ # @example
38
+ # class Foo < Struct.new(:name, :age, :gender); end
39
+ # f = Foo.new("Jill", 50, :female)
40
+ # f.attributes # => {:name => "Jill", :age => 50, :gender => :female}
41
+ #
42
+ # @return [Hash]
43
+ # Hash of instance variables in receiver, keyed by ivar name
44
+ def attributes
45
+ h = {}
46
+ each_pair { |key, value| h[key] = value }
47
+ h
48
+ end
49
+ end
@@ -0,0 +1,170 @@
1
+ # encoding: UTF-8
2
+ #
3
+ # Author: Stefano Harding <riddopic@gmail.com>
4
+ # License: Apache License, Version 2.0
5
+ # Copyright: (C) 2014-2015 Stefano Harding
6
+ #
7
+ # Licensed under the Apache License, Version 2.0 (the "License");
8
+ # you may not use this file except in compliance with the License.
9
+ # You may obtain a copy of the License at
10
+ #
11
+ # http://www.apache.org/licenses/LICENSE-2.0
12
+ #
13
+ # Unless required by applicable law or agreed to in writing, software
14
+ # distributed under the License is distributed on an "AS IS" BASIS,
15
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16
+ # See the License for the specific language governing permissions and
17
+ # limitations under the License.
18
+ #
19
+
20
+ class Symbol
21
+
22
+ # Override this in a child if it cannot be dup'ed
23
+ #
24
+ # @return [Object]
25
+ def try_dup
26
+ self
27
+ end
28
+
29
+ # Since Symbol is immutable it cannot be duplicated.
30
+ # For this reason #try_dup returns +self+.
31
+ #
32
+ # :a.dup! #=> :a
33
+ #
34
+ def dup! ; self ; end
35
+ def dup? ; false ; end
36
+ def clone? ; false ; end
37
+
38
+ # Join with _o_ as a file path.
39
+ #
40
+ # @example
41
+ # :chef/'provider' # => 'chef/provider'
42
+ # :chef/ :provider # => 'chef/provider'
43
+ #
44
+ # @param [#to_s] other
45
+ # Path component(s) to join with receiver.
46
+ #
47
+ # @return [String]
48
+ # Receiver joined with other as a file path.
49
+ #
50
+ # @api public
51
+ def /(other)
52
+ File.join(self.to_s, other.to_s)
53
+ end
54
+
55
+ # Symbol does not end in `!`, `=`, or `?`.
56
+ #
57
+ # :a.plain? #=> true
58
+ # :a?.plain? #=> false
59
+ # :a!.plain? #=> false
60
+ # :a=.plain? #=> false
61
+ #
62
+ def plain?
63
+ c = to_s[-1,1]
64
+ !(c == '=' || c == '?' || c == '!')
65
+ end
66
+
67
+ # Alias for `#plain?` method. Likely this should have been the original
68
+ # and only name, but such is life.
69
+ alias_method :reader?, :plain?
70
+
71
+ # Symbol ends in `=`.
72
+ #
73
+ # :a=.setter? #=> true
74
+ # :a.setter? #=> false
75
+ #
76
+ def setter?
77
+ to_s[-1,1] == '='
78
+ end
79
+
80
+ # Alias for `#setter?` method. Likely this should have been the original
81
+ # and only name, but such is life.
82
+ alias_method :writer?, :setter?
83
+
84
+ # Symbol ends in `?`.
85
+ #
86
+ # :a?.query? #=> true
87
+ # :a.query? #=> false
88
+ #
89
+ def query?
90
+ to_s[-1,1] == '?'
91
+ end
92
+
93
+ # Symbol ends in `!`.
94
+ #
95
+ # :a!.bang? #=> true
96
+ # :a.bang? #=> false
97
+ #
98
+ def bang?
99
+ to_s[-1,1] == '!'
100
+ end
101
+
102
+ # Does a symbol have a "not" sign?
103
+ #
104
+ # "friend".to_sym.not? #=> false
105
+ # "~friend".to_sym.not? #=> true
106
+ #
107
+ def not?
108
+ self.to_s.slice(0,1) == '~'
109
+ end
110
+
111
+ # Add a "not" sign to the front of a symbol.
112
+ #
113
+ # (~:friend) #=> :"~friend"
114
+ #
115
+ def ~@
116
+ if self.to_s.slice(0,1) == '~'
117
+ "#{self.to_s[1..-1]}".to_sym
118
+ else
119
+ "~#{self}".to_sym
120
+ end
121
+ end
122
+
123
+ # Generate a unique symbol.
124
+ #
125
+ # Symbol.generate #=> :"-1"
126
+ #
127
+ # If +key+ is given the new symbol will be prefixed with it.
128
+ #
129
+ # Symbol.generate(:foo) #=> :"foo-1"
130
+ #
131
+ def self.generate(key = nil)
132
+ key = key.to_sym if key
133
+ @symbol_generate_counter ||= {}
134
+ @symbol_generate_counter[key] ||= 0
135
+ num = @symbol_generate_counter[key] += 1
136
+ ("#{key}-%X" % num).to_sym
137
+ end
138
+
139
+ # This allows us to call obj(&:method) instead of obj { |i| i.method }
140
+ unless method_defined?(:to_proc)
141
+ def to_proc
142
+ proc { |obj, args| obj.send(self, *args) }
143
+ # lambda { |obj, args=nil| obj.send(self, *args) }
144
+ end
145
+ end
146
+
147
+ # Useful extension for &:symbol which makes it possible
148
+ # to pass arguments for method in block
149
+ #
150
+ # ['abc','','','def','ghi'].tap(&:delete.(''))
151
+ # #=> ['abc','def','ghi']
152
+ #
153
+ # [1,2,3].map(&:to_s.(2))
154
+ # #=> ['1','10','11']
155
+ #
156
+ # ['abc','cdef','xy','z','wwww'].select(&:size.() == 4)
157
+ # #=> ['cdef', 'wwww']
158
+ #
159
+ # ['abc','aaA','AaA','z'].count(&:upcase.().succ == 'AAB')
160
+ # #=> 2
161
+ #
162
+ # [%w{1 2 3 4 5},%w{6 7 8 9}].map(&:join.().length)
163
+ # #=> [5,4]
164
+ #
165
+ def call(*args, &block)
166
+ proc do |recv|
167
+ recv.__send__(self, *args, &block)
168
+ end
169
+ end
170
+ end