ruby-nuggets 0.9.1 → 0.9.2

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,348 @@
1
+ #--
2
+ ###############################################################################
3
+ # #
4
+ # A component of ruby-nuggets, some extensions to the Ruby programming #
5
+ # language. #
6
+ # #
7
+ # Copyright (C) 2007-2011 Jens Wille #
8
+ # #
9
+ # Authors: #
10
+ # Jens Wille <jens.wille@gmail.com> #
11
+ # #
12
+ # ruby-nuggets is free software; you can redistribute it and/or modify it #
13
+ # under the terms of the GNU Affero General Public License as published by #
14
+ # the Free Software Foundation; either version 3 of the License, or (at your #
15
+ # option) any later version. #
16
+ # #
17
+ # ruby-nuggets is distributed in the hope that it will be useful, but WITHOUT #
18
+ # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or #
19
+ # FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License #
20
+ # for more details. #
21
+ # #
22
+ # You should have received a copy of the GNU Affero General Public License #
23
+ # along with ruby-nuggets. If not, see <http://www.gnu.org/licenses/>. #
24
+ # #
25
+ ###############################################################################
26
+ #++
27
+
28
+ require 'rbconfig'
29
+
30
+ module Nuggets
31
+
32
+ # Heavily based on Phusion Passenger's PlatformInfo module; see
33
+ # {their code}[https://github.com/FooBarWidget/passenger/blob/release-3.0.2/lib/phusion_passenger/platform_info/ruby.rb].
34
+ #
35
+ #--
36
+ # Phusion Passenger - http://www.modrails.com/
37
+ # Copyright (c) 2010 Phusion
38
+ #
39
+ # "Phusion Passenger" is a trademark of Hongli Lai & Ninh Bui.
40
+ #
41
+ # Permission is hereby granted, free of charge, to any person obtaining a
42
+ # copy of this software and associated documentation files (the "Software"),
43
+ # to deal in the Software without restriction, including without limitation
44
+ # the rights to use, copy, modify, merge, publish, distribute, sublicense,
45
+ # and/or sell copies of the Software, and to permit persons to whom the
46
+ # Software is furnished to do so, subject to the following conditions:
47
+ #
48
+ # The above copyright notice and this permission notice shall be included in
49
+ # all copies or substantial portions of the Software.
50
+ #++
51
+
52
+ module Ruby
53
+
54
+ extend self
55
+
56
+ CONFIG = ::RbConfig::CONFIG
57
+
58
+ # Store original $GEM_HOME value so that even if the app customizes
59
+ # $GEM_HOME we can still work with the original value.
60
+ if gem_home = ::ENV['GEM_HOME']
61
+ gem_home = gem_home.strip.freeze
62
+ gem_home = nil if gem_home.empty?
63
+ end
64
+
65
+ GEM_HOME = gem_home
66
+
67
+ RUBY_ENGINE = defined?(::RUBY_ENGINE) ? ::RUBY_ENGINE : 'ruby'
68
+
69
+ OSX_RUBY_RE = %r{\A/System/Library/Frameworks/Ruby.framework/Versions/.*?/usr/bin/ruby\Z}
70
+
71
+ UPDATE_RVM = %q{Please update RVM by running 'rvm update --head && rvm reload && rvm repair all'.} # :nodoc:
72
+
73
+ # Returns correct command for invoking the current Ruby interpreter.
74
+ # In case of RVM this function will return the path to the RVM wrapper script
75
+ # that executes the current Ruby interpreter in the currently active gem set.
76
+ def ruby_command
77
+ return @ruby_command if defined?(@ruby_command)
78
+
79
+ return @ruby_command = ruby_executable unless rvm?
80
+
81
+ if name = rvm_ruby_string and dir = rvm_path
82
+ if ::File.exist?(filename = ::File.join(dir, 'wrappers', name, 'ruby'))
83
+ # Old wrapper scripts reference $HOME which causes
84
+ # things to blow up when run by a different user.
85
+ return @ruby_command = filename unless ::File.read(filename).include?('$HOME')
86
+ end
87
+
88
+ abort 'Your RVM wrapper scripts are too old. ' << UPDATE_RVM
89
+ end
90
+
91
+ # Something's wrong with the user's RVM installation.
92
+ # Raise an error so that the user knows this instead of
93
+ # having things fail randomly later on.
94
+ # 'name' is guaranteed to be non-nil because rvm_ruby_string
95
+ # already raises an exception on error.
96
+ abort 'Your RVM installation appears to be broken: the RVM path cannot be found. ' <<
97
+ 'Please fix your RVM installation or contact the RVM developers for support.'
98
+ end
99
+
100
+ attr_writer :ruby_command
101
+
102
+ # Returns the full path to the current Ruby interpreter's executable file.
103
+ # This might not be the actual correct command to use for invoking the Ruby
104
+ # interpreter; use ruby_command instead.
105
+ def ruby_executable
106
+ @ruby_executable ||= begin
107
+ dir, name, ext = CONFIG.values_at(*%w[bindir RUBY_INSTALL_NAME EXEEXT])
108
+ ::File.join(dir, name + ext).sub(/.*\s.*/m, '"\&"')
109
+ end
110
+ end
111
+
112
+ attr_writer :ruby_executable
113
+
114
+ # Returns whether the Ruby interpreter supports process forking.
115
+ def ruby_supports_fork?
116
+ # MRI >= 1.9.2's respond_to? returns false
117
+ # for methods that are not implemented.
118
+ ::Process.respond_to?(:fork) &&
119
+ RUBY_ENGINE != 'jruby' &&
120
+ RUBY_ENGINE != 'macruby' &&
121
+ CONFIG['target_os'] !~ /mswin|windows|mingw/
122
+ end
123
+
124
+ # Returns whether the current Ruby interpreter is managed by RVM.
125
+ def rvm?
126
+ CONFIG['bindir'] =~ %r{/\.?rvm/}
127
+ end
128
+
129
+ # If the current Ruby interpreter is managed by RVM, returns the
130
+ # directory in which RVM places its working files. Otherwise returns
131
+ # +nil+.
132
+ def rvm_path
133
+ return @rvm_path if defined?(@rvm_path)
134
+
135
+ return @rvm_path = nil unless rvm?
136
+
137
+ [::ENV['rvm_path'], '~/.rvm', '/usr/local/rvm'].compact.each { |path|
138
+ path = ::File.expand_path(path)
139
+ return @rvm_path = path if ::File.directory?(path)
140
+ }
141
+
142
+ # Failure to locate the RVM path is probably caused by the
143
+ # user customizing $rvm_path. Older RVM versions don't
144
+ # export $rvm_path, making us unable to detect its value.
145
+ abort 'Unable to locate the RVM path. Your RVM ' <<
146
+ 'installation is probably too old. ' << UPDATE_RVM
147
+ end
148
+
149
+ attr_writer :rvm_path
150
+
151
+ # If the current Ruby interpreter is managed by RVM, returns the
152
+ # RVM name which identifies the current Ruby interpreter plus the
153
+ # currently active gemset, e.g. something like this:
154
+ # "ruby-1.9.2-p0@mygemset"
155
+ #
156
+ # Returns +nil+ otherwise.
157
+ def rvm_ruby_string
158
+ return @rvm_ruby_string if defined?(@rvm_ruby_string)
159
+
160
+ return @rvm_ruby_string = nil unless rvm?
161
+
162
+ # RVM used to export the necessary information through
163
+ # environment variables, but doesn't always do that anymore
164
+ # in the latest versions in order to fight env var pollution.
165
+ # Scanning $LOAD_PATH seems to be the only way to obtain
166
+ # the information.
167
+
168
+ # Getting the RVM name of the Ruby interpreter ("ruby-1.9.2")
169
+ # isn't so hard, we can extract it from the #ruby_executable
170
+ # string. Getting the gemset name is a bit harder, so let's
171
+ # try various strategies...
172
+
173
+ # $GEM_HOME usually contains the gem set name.
174
+ return @rvm_ruby_string = ::File.basename(GEM_HOME) if GEM_HOME && GEM_HOME.include?('rvm/gems/')
175
+
176
+ # User somehow managed to nuke $GEM_HOME. Extract info from $LOAD_PATH.
177
+ $LOAD_PATH.each { |path| return @rvm_ruby_string = $1 if path =~ %r{^.*rvm/gems/([^/]+)} }
178
+
179
+ # On Ruby 1.9, $LOAD_PATH does not contain any gem paths until
180
+ # at least one gem has been required so the above can fail.
181
+ # We're out of options now, we can't detect the gem set.
182
+ # Raise an exception so that the user knows what's going on
183
+ # instead of having things fail in obscure ways later.
184
+ abort 'Unable to autodetect the currently active RVM gem set ' <<
185
+ "name. Please contact this program's author for support."
186
+ end
187
+
188
+ attr_writer :rvm_ruby_string
189
+
190
+ # Returns either 'sudo' or 'rvmsudo' depending on whether the current
191
+ # Ruby interpreter is managed by RVM.
192
+ def ruby_sudo_command
193
+ "#{'rvm' if rvm?}sudo"
194
+ end
195
+
196
+ # Locates a Ruby tool command +name+, e.g. 'gem', 'rake', 'bundle', etc. Instead
197
+ # of naively looking in $PATH, this function uses a variety of search heuristics
198
+ # to find the command that's really associated with the current Ruby interpreter.
199
+ # It should never locate a command that's actually associated with a different
200
+ # Ruby interpreter.
201
+ #
202
+ # NOTE: The return value may not be the actual correct invocation for the tool.
203
+ # Use command_for_ruby_tool for that.
204
+ #
205
+ # Returns +nil+ when nothing's found.
206
+ def locate_ruby_tool(name)
207
+ extensions = ['', CONFIG['EXEEXT']].compact.uniq
208
+
209
+ # Deduce Ruby's --program-prefix and --program-suffix from its install name
210
+ # and transform the given input name accordingly.
211
+ #
212
+ # "rake" => "jrake", "rake1.8", etc
213
+ [name, CONFIG['RUBY_INSTALL_NAME'].sub('ruby', name)].uniq.each { |basename|
214
+ extensions.each { |ext|
215
+ result = locate_ruby_tool_by_basename("#{basename}#{ext}")
216
+ return result if result
217
+ }
218
+ }
219
+
220
+ nil
221
+ end
222
+
223
+ # Returns the correct command string for invoking the +name+ executable
224
+ # that belongs to the current Ruby interpreter. Returns +nil+ if the
225
+ # command is not found.
226
+ #
227
+ # If the command executable is a Ruby program, then we need to run it
228
+ # in the correct Ruby interpreter just in case the command doesn't
229
+ # have the correct shebang line; we don't want a totally different
230
+ # Ruby than the current one to be invoked.
231
+ #
232
+ # If it's not a Ruby program then it's probably a wrapper
233
+ # script as is the case with e.g. RVM (~/.rvm/wrappers).
234
+ def command_for_ruby_tool(name)
235
+ filename = respond_to?(name) ? send(name) : locate_ruby_tool(name)
236
+ shebang_command(filename) =~ /ruby/ ? "#{ruby_command} #{filename}" : filename
237
+ end
238
+
239
+ %w[gem rake rspec].each { |name|
240
+ class_eval <<-EOT, __FILE__, __LINE__ + 1
241
+ def #{name}
242
+ @#{name} ||= locate_ruby_tool('#{name}')
243
+ end
244
+
245
+ attr_writer :#{name}
246
+
247
+ def #{name}_command
248
+ @#{name}_command ||= command_for_ruby_tool('#{name}')
249
+ end
250
+
251
+ attr_writer :#{name}_command
252
+ EOT
253
+ }
254
+
255
+ def ruby_options_to_argv(args, ruby_command = ruby_command)
256
+ argv = [ruby_command]
257
+
258
+ args.pop.each { |key, val|
259
+ opt = "-#{key.to_s[0, 1]}"
260
+
261
+ if val.is_a?(::Array)
262
+ val.each { |wal|
263
+ argv << opt << wal.to_s
264
+ }
265
+ else
266
+ if opt == '-e'
267
+ argv << opt << val.to_s
268
+ elsif val != false
269
+ argv << "#{opt}#{val unless val == true}"
270
+ end
271
+ end
272
+ } if args.last.is_a?(::Hash)
273
+
274
+ argv.concat(args.map! { |arg| arg.to_s.strip })
275
+ end
276
+
277
+ private
278
+
279
+ def locate_ruby_tool_by_basename(name)
280
+ dir = if ::RUBY_PLATFORM =~ /darwin/ && ruby_command =~ OSX_RUBY_RE
281
+ # On OS X we must look for Ruby binaries in /usr/bin.
282
+ # RubyGems puts executables (e.g. 'rake') in there, not in
283
+ # /System/Libraries/(...)/bin.
284
+ '/usr/bin'
285
+ else
286
+ ::File.dirname(ruby_command)
287
+ end
288
+
289
+ filename = ::File.join(dir, name)
290
+ return filename if ::File.file?(filename) && ::File.executable?(filename)
291
+
292
+ # RubyGems might put binaries in a directory other
293
+ # than Ruby's bindir. Debian packaged RubyGems and
294
+ # DebGem packaged RubyGems are the prime examples.
295
+ begin
296
+ require 'rubygems' unless defined?(::Gem)
297
+
298
+ filename = ::File.join(::Gem.bindir, name)
299
+ return filename if ::File.file?(filename) && ::File.executable?(filename)
300
+ rescue ::LoadError
301
+ end
302
+
303
+ # Looks like it's not in the RubyGems bindir. Search in $PATH, but
304
+ # be very careful about this because whatever we find might belong
305
+ # to a different Ruby interpreter than the current one.
306
+ ::ENV['PATH'].split(::File::PATH_SEPARATOR).each { |path|
307
+ filename = ::File.join(path, name)
308
+
309
+ if ::File.file?(filename) && ::File.executable?(filename)
310
+ return filename if shebang_command(filename) == ruby_command
311
+ end
312
+ }
313
+
314
+ nil
315
+ end
316
+
317
+ def shebang_command(filename)
318
+ ::File.foreach(filename) { |line|
319
+ return $1 if line =~ /\A#!\s*(\S*)/
320
+
321
+ # Allow one extra line for magic comment.
322
+ break if $. > 1
323
+ }
324
+ end
325
+
326
+ end
327
+
328
+ end
329
+
330
+ def File.ruby; ::Nuggets::Ruby.ruby_command; end
331
+
332
+ begin
333
+ require 'open4'
334
+
335
+ def Process.ruby(*args)
336
+ argv = ::Nuggets::Ruby.ruby_options_to_argv(args)
337
+ ::Open4.popen4(*argv, &block_given? ? ::Proc.new : nil)
338
+ end
339
+
340
+ require 'nuggets/io/interact'
341
+
342
+ def Process.interact_ruby(input, *args)
343
+ ruby(*args) { |_, i, o, e|
344
+ ::IO.interact({ input => i }, { o => $stdout, e => $stderr })
345
+ }
346
+ end
347
+ rescue ::LoadError
348
+ end
@@ -1,127 +1,4 @@
1
- #--
2
- ###############################################################################
3
- # #
4
- # A component of ruby-nuggets, some extensions to the Ruby programming #
5
- # language. #
6
- # #
7
- # Copyright (C) 2007-2011 Jens Wille #
8
- # #
9
- # Authors: #
10
- # Jens Wille <jens.wille@gmail.com> #
11
- # #
12
- # ruby-nuggets is free software; you can redistribute it and/or modify it #
13
- # under the terms of the GNU Affero General Public License as published by #
14
- # the Free Software Foundation; either version 3 of the License, or (at your #
15
- # option) any later version. #
16
- # #
17
- # ruby-nuggets is distributed in the hope that it will be useful, but WITHOUT #
18
- # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or #
19
- # FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License #
20
- # for more details. #
21
- # #
22
- # You should have received a copy of the GNU Affero General Public License #
23
- # along with ruby-nuggets. If not, see <http://www.gnu.org/licenses/>. #
24
- # #
25
- ###############################################################################
26
- #++
1
+ require 'nuggets/ansicolor2css'
2
+ module Util; ANSIColor2CSS = ::Nuggets::ANSIColor2CSS; end
27
3
 
28
- module Util
29
-
30
- module ANSIColor2CSS
31
-
32
- extend self
33
-
34
- ATTRIBUTES = {
35
- '0' => nil, # clear
36
- '1' => 'font-weight: bold', # bold
37
- '2' => '', # dark
38
- '3' => 'font-style: italic', # italic -- not widely implemented
39
- '4' => 'text-decoration: underline', # underline
40
- '5' => 'text-decoration: blink', # blink
41
- '6' => 'text-decoration: blink', # rapid blink -- not widely implemented
42
- '7' => '', # reverse
43
- '8' => 'opacity: 0', # concealed
44
- '9' => 'text-decoration: line-through', # strikethrough -- not widely implemented
45
- '22' => 'font-weight: normal', # bold off
46
- '23' => 'font-style: normal', # italic off
47
- '24' => 'text-decoration: none', # underline off
48
- '25' => 'text-decoration: none', # blink off
49
- '27' => '', # reverse off
50
- '28' => 'opacity: 1', # concealed off
51
- '29' => 'text-decoration: none', # strikethrough off
52
- '30' => 'color: black', # black
53
- '31' => 'color: maroon', # red
54
- '32' => 'color: green', # green
55
- '33' => 'color: olive', # yellow
56
- '34' => 'color: navy', # blue
57
- '35' => 'color: purple', # magenta
58
- '36' => 'color: teal', # cyan
59
- '37' => 'color: silver', # white
60
- '39' => 'color: silver', # default (white)
61
- '40' => 'background-color: black', # on black
62
- '41' => 'background-color: maroon', # on red
63
- '42' => 'background-color: green', # on green
64
- '43' => 'background-color: olive', # on yellow
65
- '44' => 'background-color: navy', # on blue
66
- '45' => 'background-color: purple', # on magenta
67
- '46' => 'background-color: teal', # on cyan
68
- '47' => 'background-color: silver', # on white
69
- '49' => 'background-color: black', # on default (black)
70
- '90' => 'color: gray', # bright black
71
- '91' => 'color: red', # bright red
72
- '92' => 'color: lime', # bright green
73
- '93' => 'color: yellow', # bright yellow
74
- '94' => 'color: blue', # bright blue
75
- '95' => 'color: fuchsia', # bright magenta
76
- '96' => 'color: cyan', # bright cyan
77
- '97' => 'color: white', # bright white
78
- '100' => 'background-color: gray', # on bright black
79
- '101' => 'background-color: red', # on bright red
80
- '102' => 'background-color: lime', # on bright green
81
- '103' => 'background-color: yellow', # on bright yellow
82
- '104' => 'background-color: blue', # on bright blue
83
- '105' => 'background-color: fuchsia', # on bright magenta
84
- '106' => 'background-color: cyan', # on bright cyan
85
- '107' => 'background-color: white' # on bright white
86
- }
87
-
88
- ATTRIBUTES_RE = ::Regexp.union(*ATTRIBUTES.keys)
89
-
90
- DELIMITER = ';'
91
-
92
- COLOR_RE = %r{
93
- \e \[ ( #{ATTRIBUTES_RE} (?: #{DELIMITER} #{ATTRIBUTES_RE} )* ) m
94
- }x
95
-
96
- STYLE = '<span style="%s">'
97
- CLEAR = '</span>'
98
-
99
- def convert(string)
100
- string.gsub(COLOR_RE) { format($1.split(DELIMITER).uniq) }
101
- end
102
-
103
- def format(attributes)
104
- "#{clear(attributes)}#{style(attributes) if attributes.any?}"
105
- end
106
-
107
- def clear(attributes)
108
- CLEAR if attributes.delete('0')
109
- end
110
-
111
- def style(attributes)
112
- STYLE % ATTRIBUTES.values_at(*attributes).join('; ')
113
- end
114
-
115
- end
116
-
117
- end
118
-
119
- class String
120
-
121
- def ansicolor2css
122
- ::Util::ANSIColor2CSS.convert(self)
123
- end
124
-
125
- alias_method :ansicolour2css, :ansicolor2css
126
-
127
- end
4
+ warn "#{__FILE__}: Util::ANSIColor2CSS is deprecated, use Nuggets::ANSIColor2CSS instead."