rubycut-babushka 0.10.6

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 (171) hide show
  1. data/Gemfile +8 -0
  2. data/Gemfile.lock +31 -0
  3. data/README.markdown +246 -0
  4. data/Rakefile +26 -0
  5. data/bin/babushka +11 -0
  6. data/deps/babushka.rb +101 -0
  7. data/deps/dev.rb +12 -0
  8. data/deps/fhs.rb +31 -0
  9. data/deps/git.rb +29 -0
  10. data/deps/homebrew.rb +30 -0
  11. data/deps/os_x.rb +33 -0
  12. data/deps/packages.rb +22 -0
  13. data/deps/pkg_managers.rb +110 -0
  14. data/deps/ruby.rb +23 -0
  15. data/deps/rubygems.rb +24 -0
  16. data/deps/system.rb +10 -0
  17. data/deps/templates/app.rb +68 -0
  18. data/deps/templates/external.rb +12 -0
  19. data/deps/templates/installer.rb +31 -0
  20. data/deps/templates/managed.rb +105 -0
  21. data/deps/templates/ppa.rb +24 -0
  22. data/deps/templates/src.rb +42 -0
  23. data/deps/templates/tmbundle.rb +15 -0
  24. data/lib/babushka.rb +28 -0
  25. data/lib/babushka/accepts_block_for.rb +72 -0
  26. data/lib/babushka/accepts_list_for.rb +49 -0
  27. data/lib/babushka/accepts_value_for.rb +24 -0
  28. data/lib/babushka/base.rb +78 -0
  29. data/lib/babushka/bug_reporter.rb +55 -0
  30. data/lib/babushka/cmdline.rb +133 -0
  31. data/lib/babushka/cmdline/handler.rb +41 -0
  32. data/lib/babushka/cmdline/helpers.rb +127 -0
  33. data/lib/babushka/cmdline/parser.rb +69 -0
  34. data/lib/babushka/colorizer.rb +59 -0
  35. data/lib/babushka/core_patches/array.rb +171 -0
  36. data/lib/babushka/core_patches/blank.rb +22 -0
  37. data/lib/babushka/core_patches/bytes.rb +52 -0
  38. data/lib/babushka/core_patches/hash.rb +107 -0
  39. data/lib/babushka/core_patches/hashish.rb +14 -0
  40. data/lib/babushka/core_patches/integer.rb +25 -0
  41. data/lib/babushka/core_patches/io.rb +8 -0
  42. data/lib/babushka/core_patches/numeric.rb +16 -0
  43. data/lib/babushka/core_patches/object.rb +27 -0
  44. data/lib/babushka/core_patches/string.rb +116 -0
  45. data/lib/babushka/core_patches/symbol.rb +12 -0
  46. data/lib/babushka/core_patches/try.rb +15 -0
  47. data/lib/babushka/core_patches/uri.rb +24 -0
  48. data/lib/babushka/dep.rb +470 -0
  49. data/lib/babushka/dep_context.rb +18 -0
  50. data/lib/babushka/dep_definer.rb +115 -0
  51. data/lib/babushka/dep_pool.rb +49 -0
  52. data/lib/babushka/dep_runner.rb +85 -0
  53. data/lib/babushka/dsl.rb +26 -0
  54. data/lib/babushka/git_repo.rb +185 -0
  55. data/lib/babushka/helpers/git_helpers.rb +32 -0
  56. data/lib/babushka/helpers/log_helpers.rb +176 -0
  57. data/lib/babushka/helpers/path_helpers.rb +34 -0
  58. data/lib/babushka/helpers/run_helpers.rb +145 -0
  59. data/lib/babushka/helpers/shell_helpers.rb +229 -0
  60. data/lib/babushka/helpers/suggest_helpers.rb +16 -0
  61. data/lib/babushka/helpers/uri_helpers.rb +36 -0
  62. data/lib/babushka/ip.rb +160 -0
  63. data/lib/babushka/lambda_chooser.rb +40 -0
  64. data/lib/babushka/levenshtein.rb +125 -0
  65. data/lib/babushka/meta_dep.rb +65 -0
  66. data/lib/babushka/meta_dep_context.rb +15 -0
  67. data/lib/babushka/parameter.rb +143 -0
  68. data/lib/babushka/pkg_helper.rb +81 -0
  69. data/lib/babushka/pkg_helpers/apt_helper.rb +61 -0
  70. data/lib/babushka/pkg_helpers/base_helper.rb +19 -0
  71. data/lib/babushka/pkg_helpers/binpkgsrc_helper.rb +48 -0
  72. data/lib/babushka/pkg_helpers/binports_helper.rb +34 -0
  73. data/lib/babushka/pkg_helpers/brew_helper.rb +110 -0
  74. data/lib/babushka/pkg_helpers/gem_helper.rb +120 -0
  75. data/lib/babushka/pkg_helpers/macports_helper.rb +22 -0
  76. data/lib/babushka/pkg_helpers/npm_helper.rb +45 -0
  77. data/lib/babushka/pkg_helpers/pacman_helper.rb +27 -0
  78. data/lib/babushka/pkg_helpers/pip_helper.rb +45 -0
  79. data/lib/babushka/pkg_helpers/src_helper.rb +16 -0
  80. data/lib/babushka/pkg_helpers/yum_helper.rb +25 -0
  81. data/lib/babushka/popen.rb +40 -0
  82. data/lib/babushka/prompt.rb +176 -0
  83. data/lib/babushka/renderable.rb +67 -0
  84. data/lib/babushka/resource.rb +215 -0
  85. data/lib/babushka/run_reporter.rb +60 -0
  86. data/lib/babushka/shell.rb +108 -0
  87. data/lib/babushka/source.rb +216 -0
  88. data/lib/babushka/source_pool.rb +146 -0
  89. data/lib/babushka/system_definitions.rb +97 -0
  90. data/lib/babushka/system_profile.rb +210 -0
  91. data/lib/babushka/task.rb +142 -0
  92. data/lib/babushka/vars.rb +108 -0
  93. data/lib/babushka/version_of.rb +65 -0
  94. data/lib/babushka/version_str.rb +57 -0
  95. data/lib/babushka/xml_string.rb +28 -0
  96. data/lib/components.rb +82 -0
  97. data/lib/fancypath/fancypath.rb +200 -0
  98. data/lib/inkan/inkan.rb +76 -0
  99. data/spec/acceptance/acceptance.rb +43 -0
  100. data/spec/acceptance_helper.rb +113 -0
  101. data/spec/archives/Blah.app.zip +0 -0
  102. data/spec/archives/archive.tar +0 -0
  103. data/spec/archives/archive.tar.bz2 +0 -0
  104. data/spec/archives/archive.tar.gz +0 -0
  105. data/spec/archives/archive.tbz2 +0 -0
  106. data/spec/archives/archive.tgz +0 -0
  107. data/spec/archives/archive.zip +0 -0
  108. data/spec/archives/content.txt +5 -0
  109. data/spec/archives/invalid_archive +5 -0
  110. data/spec/archives/nested archive/content.txt +5 -0
  111. data/spec/archives/nested_archive.tar +0 -0
  112. data/spec/archives/really_a_gzip.zip +0 -0
  113. data/spec/archives/test-0.3.1.tgz +0 -0
  114. data/spec/archives/tgz_archive +0 -0
  115. data/spec/archives/zip_without_extension +0 -0
  116. data/spec/babushka/accepts_for_spec.rb +174 -0
  117. data/spec/babushka/accepts_for_support.rb +72 -0
  118. data/spec/babushka/cmdline/console_spec.rb +11 -0
  119. data/spec/babushka/cmdline/help_spec.rb +61 -0
  120. data/spec/babushka/cmdline/version_spec.rb +10 -0
  121. data/spec/babushka/core_patches_spec.rb +171 -0
  122. data/spec/babushka/dep_context_spec.rb +58 -0
  123. data/spec/babushka/dep_definer_spec.rb +152 -0
  124. data/spec/babushka/dep_definer_support.rb +36 -0
  125. data/spec/babushka/dep_spec.rb +567 -0
  126. data/spec/babushka/dep_support.rb +29 -0
  127. data/spec/babushka/deps_spec.rb +113 -0
  128. data/spec/babushka/gem_helper_spec.rb +90 -0
  129. data/spec/babushka/git_repo_spec.rb +396 -0
  130. data/spec/babushka/ip_spec.rb +131 -0
  131. data/spec/babushka/lambda_chooser_spec.rb +115 -0
  132. data/spec/babushka/meta_dep_definer_spec.rb +127 -0
  133. data/spec/babushka/meta_dep_wrapper_spec.rb +32 -0
  134. data/spec/babushka/parameter_spec.rb +135 -0
  135. data/spec/babushka/path_helpers_spec.rb +102 -0
  136. data/spec/babushka/prompt_spec.rb +188 -0
  137. data/spec/babushka/renderable_spec.rb +100 -0
  138. data/spec/babushka/resource_spec.rb +141 -0
  139. data/spec/babushka/run_helpers_spec.rb +26 -0
  140. data/spec/babushka/shell_helpers_spec.rb +244 -0
  141. data/spec/babushka/shell_spec.rb +19 -0
  142. data/spec/babushka/source_pool_spec.rb +320 -0
  143. data/spec/babushka/source_pool_support.rb +31 -0
  144. data/spec/babushka/source_spec.rb +382 -0
  145. data/spec/babushka/source_support.rb +17 -0
  146. data/spec/babushka/system_profile_spec.rb +61 -0
  147. data/spec/babushka/task_spec.rb +141 -0
  148. data/spec/babushka/uri_spec.rb +13 -0
  149. data/spec/babushka/vars_spec.rb +59 -0
  150. data/spec/babushka/version_of_spec.rb +110 -0
  151. data/spec/babushka/version_str_spec.rb +130 -0
  152. data/spec/babushka/version_str_support.rb +37 -0
  153. data/spec/babushka/xml_string_spec.rb +98 -0
  154. data/spec/deps/bad/broken.rb +7 -0
  155. data/spec/deps/bad/working.rb +3 -0
  156. data/spec/deps/good/meta.rb +14 -0
  157. data/spec/deps/good/test.rb +11 -0
  158. data/spec/deps/outer/deps.rb +19 -0
  159. data/spec/deps/outer/more deps.rb +11 -0
  160. data/spec/deps/params/params.rb +10 -0
  161. data/spec/fancypath/fancypath_spec.rb +272 -0
  162. data/spec/fancypath_support.rb +10 -0
  163. data/spec/inkan/inkan_spec.rb +217 -0
  164. data/spec/renderable/different_example.conf.erb +4 -0
  165. data/spec/renderable/example.conf.erb +3 -0
  166. data/spec/renderable/example.sh +6 -0
  167. data/spec/renderable/with_binding.conf.erb +4 -0
  168. data/spec/renderable/xml_example.conf.erb +8 -0
  169. data/spec/repos/remote.git.tgz +0 -0
  170. data/spec/spec_helper.rb +87 -0
  171. metadata +238 -0
@@ -0,0 +1,22 @@
1
+ # #blank? means (nil? or empty?). Instead of defining it on all objects and
2
+ # checking if they respond to the #empty? method when #blank? is called, we
3
+ # define it only on the classes where it has meaning. That means we also
4
+ # have to define it on nil, since it is also considered 'blank'.
5
+
6
+ module Enumerable
7
+ def blank?
8
+ empty?
9
+ end
10
+ end
11
+
12
+ class String
13
+ def blank?
14
+ empty?
15
+ end
16
+ end
17
+
18
+ class NilClass
19
+ def blank?
20
+ true
21
+ end
22
+ end
@@ -0,0 +1,52 @@
1
+ # Lifted from activesupport-3.0.5/lib/active_support/core_ext/numeric/bytes.rb
2
+ class Numeric
3
+ KILOBYTE = 1024
4
+ MEGABYTE = KILOBYTE * 1024
5
+ GIGABYTE = MEGABYTE * 1024
6
+ TERABYTE = GIGABYTE * 1024
7
+ PETABYTE = TERABYTE * 1024
8
+ EXABYTE = PETABYTE * 1024
9
+
10
+ # Enables the use of byte calculations and declarations, like 45.bytes + 2.6.megabytes
11
+ def bytes
12
+ self
13
+ end
14
+ alias :byte :bytes
15
+
16
+ def kilobytes
17
+ self * KILOBYTE
18
+ end
19
+ alias :kilobyte :kilobytes
20
+
21
+ def megabytes
22
+ self * MEGABYTE
23
+ end
24
+ alias :megabyte :megabytes
25
+
26
+ def gigabytes
27
+ self * GIGABYTE
28
+ end
29
+ alias :gigabyte :gigabytes
30
+
31
+ def terabytes
32
+ self * TERABYTE
33
+ end
34
+ alias :terabyte :terabytes
35
+
36
+ def petabytes
37
+ self * PETABYTE
38
+ end
39
+ alias :petabyte :petabytes
40
+
41
+ def exabytes
42
+ self * EXABYTE
43
+ end
44
+ alias :exabyte :exabytes
45
+
46
+ alias :kb :kilobytes
47
+ alias :mb :megabytes
48
+ alias :gb :gigabytes
49
+ alias :tb :terabytes
50
+ alias :pb :petabytes
51
+ alias :eb :exabytes
52
+ end
@@ -0,0 +1,107 @@
1
+ class Hash
2
+ # Return a new hash filtered to exclude any key-value pairs whose keys appear
3
+ # in +keys+.
4
+ def discard *keys
5
+ dup.discard!(*keys)
6
+ end
7
+
8
+ # Filter this hash in-place so any key-value pairs whose keys appear in
9
+ # +keys+ are removed.
10
+ def discard! *keys
11
+ keys.each {|k| delete k }
12
+ self
13
+ end
14
+
15
+ # Return a new hash filtered to contain only the key-value pairs whose keys
16
+ # appear in +keys+.
17
+ def slice *keys
18
+ dup.slice!(*keys)
19
+ end
20
+
21
+ # Filter this hash in-place so it contains only the key-value pairs whose
22
+ # keys appear in +keys+.
23
+ def slice! *keys
24
+ keys.inject({}) {|acc,key|
25
+ acc[key] = self.delete(key) if self.has_key?(key)
26
+ acc
27
+ }
28
+ end
29
+
30
+ # Reverse-merge +other+ into this hash in-place; that is, merge all
31
+ # key-value pairs in +other+ whose keys are not already present in self.
32
+ def defaults! other
33
+ replace other.merge(self)
34
+ end
35
+
36
+ # Return a new hash consisting of +other+ reverse-merged into this hash;
37
+ # that is, equal to +other.merge(self)+.
38
+ def defaults other
39
+ dup.defaults! other
40
+ end
41
+
42
+ # Return a new hash with the same keys as this hash, but with values
43
+ # generated by yielding each key-value pair to +block+.
44
+ def map_values &block
45
+ dup.map_values!(&block)
46
+ end
47
+
48
+ # Update this hash in-place by replacing each value with the result of
49
+ # yielding the corresponding key-value pair to the block.
50
+ def map_values! &block
51
+ keys.each {|k|
52
+ self[k] = yield k, self[k]
53
+ }
54
+ self
55
+ end
56
+
57
+ # Return a new hash filtered to contain just the key-value pairs for which
58
+ # the block returns true. That is, like Hash#select, but returning a hash
59
+ # instead of an array of tuples.
60
+ def selekt &block
61
+ hsh = {}
62
+ each_pair {|k,v|
63
+ hsh[k] = v if yield(k,v)
64
+ }
65
+ hsh
66
+ end
67
+
68
+ # Return a new hash recursively filtered to remove all key-value pairs for
69
+ # which the block returned true. That is, like Hash#reject, except sub-hashes
70
+ # are also filtered.
71
+ def reject_r &block
72
+ dup.reject_r!(&block)
73
+ end
74
+
75
+ # Recursively filter this hash in-place to remove all key-value pairs for
76
+ # which the block returned true. That is, like Hash#reject!, except
77
+ # sub-hashes are also filtered.
78
+ def reject_r! &block
79
+ each_pair {|k,v|
80
+ if yield k, v
81
+ self.delete k
82
+ elsif v.is_a? Hash
83
+ self[k] = v.reject_r(&block)
84
+ end
85
+ }
86
+ end
87
+
88
+ # Converts this hash to a string that can be submitted as HTTP parameters.
89
+ # The keys and values are encoded, so the string is safe to submit exactly as
90
+ # it is returned.
91
+ #
92
+ # This isn't a recursive implementation, because I didn't need it to be :)
93
+ #
94
+ # Example:
95
+ # {'name' => 'Sigur Rós', 'album' => 'Takk...'}.to_http_params
96
+ # #=> "name=Sigur%20R%C3%B3s&album=Takk..."
97
+ def to_http_params
98
+ require 'uri'
99
+
100
+ keys.map {|key|
101
+ [
102
+ URI.escape(key.to_s),
103
+ URI.escape(fetch(key).to_s)
104
+ ].join('=')
105
+ }.join( '&')
106
+ end
107
+ end
@@ -0,0 +1,14 @@
1
+ class Hashish
2
+ # Return a new hash whose default value is an empty array; i.e. querying any
3
+ # un-assigned key will assign and return an empty array to that key.
4
+ def self.array
5
+ Hash.new {|hsh,k| hsh[k] = [] }
6
+ end
7
+
8
+ # Return a new hash whose default value is an empty hash; i.e. querying any
9
+ # un-assigned key will assign and return an empty hash to that key. Note that
10
+ # the empty hash is a regular hash and doesn't have any default keys of its own.
11
+ def self.hash
12
+ Hash.new {|hsh,k| hsh[k] = {} }
13
+ end
14
+ end
@@ -0,0 +1,25 @@
1
+ class Integer
2
+ # Return a string describing this integer as a human-readable, approximated
3
+ # duration, assuming it is a number of seconds. The description will be
4
+ # either 'now', 'less than a minute', or a value in minutes, hours or days.
5
+ # Some examples:
6
+ # 12.xsecs #=> "less than a minute"
7
+ # 80.xsecs #=> "1 minute"
8
+ # 1337.xsecs #=> "22 minutes"
9
+ # 1234567.xsecs #=> "14 days"
10
+ def xsecs
11
+ value = self.abs
12
+ past = (self < 0)
13
+
14
+ case value
15
+ when 0; return 'now'
16
+ when 1...60; return "less than a minute#{' ago' if past}"
17
+ when 61...3600; value /= 60; unit = 'minute'
18
+ when 3600...(3600*24); value /= 3600; unit = 'hour'
19
+ else value /= (3600*24); unit = 'day'
20
+ end
21
+
22
+ value = 1 if value == 0
23
+ "#{value.commas} #{unit}#{'s' unless value == 1}#{' ago' if past}"
24
+ end
25
+ end
@@ -0,0 +1,8 @@
1
+ class IO
2
+ # Return true iff reading from this IO object would return data immediately,
3
+ # and not block while waiting for data.
4
+ def ready_for_read?
5
+ result = IO.select([self], [], [], 0)
6
+ result && (result.first.first == self)
7
+ end
8
+ end
@@ -0,0 +1,16 @@
1
+ class Numeric
2
+ # Return a string representation of this value with commas between the
3
+ # thousands groupings.
4
+ # Some examples:
5
+ # 3.commas #=> "3"
6
+ # 314.commas #=> "314"
7
+ # 31459.commas #=> "31,459"
8
+ def commas
9
+ if self < 1000
10
+ to_s
11
+ else
12
+ whole, fract = self.to_s.split('.')
13
+ [ whole.reverse.scan(/\d{1,3}/).join(',').reverse, fract ].squash.join('.')
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,27 @@
1
+ alias :L :proc
2
+
3
+ class Object
4
+ # Return this object's metaclass; i.e. the value of self within a
5
+ # 'class << self' block.
6
+ def metaclass
7
+ class << self; self end
8
+ end
9
+
10
+ # Return this object after yielding it to the block. This is useful for
11
+ # neatly working with an object in some way before returning it:
12
+ # def valmorphanize
13
+ # process.tap {|result|
14
+ # log "Oops!" unless result
15
+ # }
16
+ # end
17
+ def tap &block
18
+ yield self
19
+ self
20
+ end unless Object.respond_to?(:tap)
21
+
22
+ # Return self unmodified after logging the output of #inspect, along with
23
+ # the point at which +tapp+ was called.
24
+ def tapp
25
+ tap { puts "#{File.basename caller[2]}: #{self.inspect}" }
26
+ end
27
+ end
@@ -0,0 +1,116 @@
1
+ class String
2
+ # Return a Dep::Requirement that specifies the dep that should later be
3
+ # called, and the arguments that should be passed. This allows requiring
4
+ # deps with a less noisy syntax, and the lookup is lazy (it happens at
5
+ # the point the dep is invoked, from its parent dep in Dep#process_deps).
6
+ #
7
+ # dep 'user has a password', :username do
8
+ # requires 'user exists'.with(username)
9
+ # end
10
+ def with *args
11
+ Babushka::Dep::Requirement.new(self, args)
12
+ end
13
+
14
+ # Returns true iff +other+ appears exactly at the start of +self+.
15
+ def starts_with? other
16
+ self[0, other.length] == other
17
+ end
18
+
19
+ # Returns true iff +other+ appears exactly at the end of +self+.
20
+ def ends_with? other
21
+ self[-other.length, other.length] == other
22
+ end
23
+
24
+ # Return a duplicate of +self+, with +other+ prepended to it if it doesn't already start with +other+.
25
+ def start_with other
26
+ starts_with?(other) ? self : other + self
27
+ end
28
+
29
+ # Return a duplicate of +self+, with +other+ appended to it if it doesn't already end with +other+.
30
+ def end_with other
31
+ ends_with?(other) ? self : self + other
32
+ end
33
+
34
+ # Extracts specified values from arbitrary, multiline strings. Most common
35
+ # formats are handled. When there are multiple matches across a multi-line
36
+ # string, the first is returned. If there is no match, the empty string is
37
+ # returned.
38
+ #
39
+ # With a simple key/value format:
40
+ # 'key: value'.val_for('key') #=> 'value'
41
+ # 'key = value'.val_for('key') #=> 'value'
42
+ # 'key value'.val_for('key') #=> 'value'
43
+ #
44
+ # Whitespace is handled correctly:
45
+ # ' key: value '.val_for('key') #=> 'value'
46
+ # ' key value '.val_for('key') #=> 'value'
47
+ #
48
+ # Leading non-word characters form part of the key:
49
+ # '*key: value'.val_for('*key') #=> 'value'
50
+ # '-key: value'.val_for('-key') #=> 'value'
51
+ # '-key: value'.val_for('key') #=> nil
52
+ #
53
+ # But not if they're separated from the key:
54
+ # '* key: value'.val_for('key') #=> 'value'
55
+ #
56
+ # Spaces within the key are handled properly:
57
+ # 'key with spaces: value'.val_for('key with spaces') #=> 'value'
58
+ # '- key with spaces: value'.val_for('key with spaces') #=> 'value'
59
+ # ' -- key with spaces: value'.val_for('key with spaces') #=> 'value'
60
+ # 'space-separated key: value'.val_for('space-separated key') #=> 'value'
61
+ #
62
+ # As are values containing spaces:
63
+ # 'key: space-separated value'.val_for('key') #=> 'space-separated value'
64
+ # 'key with spaces: space-separated value'.val_for('key with spaces') #=> 'space-separated value'
65
+ def val_for key
66
+ split("\n").grep(
67
+ # The key we're after, maybe preceded by non-word chars and spaces, and
68
+ # followed either by a word/non-word boundary or whitespace.
69
+ key.is_a?(Regexp) ? key : /(^|^[^\w]*\s+)#{Regexp.escape(key)}(\b|(?=\s))/
70
+ ).map {|l|
71
+ l.sub(/^[^\w]*\s+/, '').
72
+ sub(key.is_a?(Regexp) ? key : /^#{Regexp.escape(key)}(\b|(?=\s))\s*[:=]?/, '').
73
+ sub(/[;,]\s*$/, '').
74
+ strip
75
+ }.first
76
+ end
77
+
78
+ def / other
79
+ (empty? ? other.p : (p / other))
80
+ end
81
+
82
+ # Create a VersionStr from this string.
83
+ def to_version
84
+ Babushka::VersionStr.new self
85
+ end
86
+
87
+ # Return a new string with the contents of this string surrounded in escape
88
+ # sequences such that it will render as described in +description+.
89
+ # Some examples:
90
+ # 'Hello world!'.colorize('green') #=> "\e[0;32;29mHello world!\e[0m"
91
+ # 'Hello world!'.colorize('on red') #=> "\e[0;29;41mHello world!\e[0m"
92
+ # 'Hello world!'.colorize('reverse') #=> "\e[0;29;7mHello world!\e[0m"
93
+ def colorize description = '', start_at = nil
94
+ if start_at.nil? || (cut_point = index(start_at)).nil?
95
+ Colorizer.instance.colorize self, description
96
+ else
97
+ self[0...cut_point] + Colorizer.instance.colorize(self[cut_point..-1], description)
98
+ end
99
+ end
100
+
101
+ # As +colorize+, but modify this string in-place instead of returning a new one.
102
+ def colorize! description = nil, start_at = nil
103
+ replace colorize(description, start_at) unless description.nil?
104
+ end
105
+
106
+ # Return a new string with all color-related escape sequences removed.
107
+ def decolorize
108
+ dup.decolorize!
109
+ end
110
+
111
+ # Remove all color-related escape sequences from this string in-place.
112
+ def decolorize!
113
+ gsub!(/\e\[\d+[;\d]*m/, '')
114
+ self
115
+ end
116
+ end
@@ -0,0 +1,12 @@
1
+ unless :to_proc.respond_to? :to_proc
2
+ class Symbol
3
+ # Returns a Proc object which responds to a method whose name is this
4
+ # symbol.
5
+ #
6
+ # This is a fallback implementation for older rubies that don't have
7
+ # a built-in Symbol#to_proc.
8
+ def to_proc
9
+ L{|*args| args.shift.__send__ self, *args }
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,15 @@
1
+ # The implementation of #try as found in activesupport:
2
+ # lib/active_support/core_ext/object/try.rb
3
+ #
4
+ # Try is just a nil-swallowing send, which means return nil when called on
5
+ # nil and just send like normal when called on any other object.
6
+
7
+ class Object
8
+ alias_method :try, :__send__
9
+ end
10
+
11
+ class NilClass
12
+ def try *args
13
+ nil
14
+ end
15
+ end
@@ -0,0 +1,24 @@
1
+ require 'uri'
2
+ module URI
3
+ module Escape
4
+ alias_method :original_escape, :escape
5
+
6
+ # Patch URI.escape to prevent multiple escapes, by unescaping the input
7
+ # before escaping it.
8
+ #
9
+ # For example, URI.escape normally behaves like this:
10
+ # URI.escape "path with spaces" #=> "path%20with%20spaces"
11
+ # URI.escape "/path%20with%20spaces" #=> "/path%2520with%2520spaces"
12
+ #
13
+ # This patched version behaves like this:
14
+ # URI.escape "/path with spaces" #=> "/path%20with%20spaces"
15
+ # URI.escape "/path%20with%20spaces" #=> "/path%20with%20spaces"
16
+ #
17
+ # This is pretty cheeky, but as far as I can see it won't cause any
18
+ # problems - I can't see any situation where a doubly-escaped entity is a
19
+ # good thing.
20
+ def escape str, unsafe = URI::UNSAFE
21
+ URI.original_escape URI.unescape(str), unsafe
22
+ end
23
+ end
24
+ end