Module: Kernel
- Defined in:
- lib/quality_extensions/object/default.rb,
lib/quality_extensions/kernel/die.rb,
lib/quality_extensions/kernel/backtrace.rb,
lib/quality_extensions/kernel/trap_chain.rb,
lib/quality_extensions/kernel/require_all.rb,
lib/quality_extensions/global_variable_set.rb,
lib/quality_extensions/kernel/remove_const.rb,
lib/quality_extensions/kernel/require_once.rb,
lib/quality_extensions/module/remove_const.rb,
lib/quality_extensions/kernel/remove_module.rb,
lib/quality_extensions/kernel/capture_output.rb,
lib/quality_extensions/kernel/windows_platform.rb
Overview
–
- Author
-
Tyler Rick
- Copyright
-
Copyright © 2007 QualitySmith, Inc.
- License
-
Ruby License
- Submit to Facets?
-
No, too ugly and unreliable.
++
Instance Method Summary collapse
-
#backtrace ⇒ Object
Equivalent to calling caller(0).
-
#backtrace_using_exception ⇒ Object
I thought I ran into some case where it didn’t work to use caller(0)…which prompted me to do it this way (raise and rescue an exception)…but now I can’t duplicate that problem, so I will deprecate this method.
-
#capture_output(output_streams = $stdout, &block) ⇒ Object
Captures the output (stdout by default) that
block
tries to generate and returns it as a string. - #default!(object, default_value) ⇒ Object
- #die(message, exit_code = 1) ⇒ Object
-
#global_variable_get(var, options = {}) ⇒ Object
Gets the global variable
var
, which can either be a symbol or an actual global variable (use:match_object
). -
#global_variable_name(var) ⇒ Object
Looks up the name of global variable
var
, which must be an actual global variable. -
#global_variable_set(var, value, options = {}) ⇒ Object
Sets the global variable
var
, which can either be a symbol or an actual global variable (use:match_object
). -
#pretty_backtrace ⇒ Object
Returns a human-readable backtrace.
-
#remove_const(const_name) ⇒ Object
This is similar to the built-in
Module#remove_const
, but it is accessible from all “levels” (because it is defined inKernel
) and can handle hierarchy. -
#remove_const! ⇒ Object
This is similar to Kernel#remove_const, but it only works for modules/classes.
-
#remove_module(const) ⇒ Object
This is similar to
remove_const
, but it only works for modules/classes. -
#require_all(what, options = {}) ⇒ Object
require
s all Ruby files specified bywhat
, but not matching any of the exclude filters. -
#require_local_all(dir = './', options = {}) ⇒ Object
require
s all Ruby files indir
(relative toFile.dirname(__FILE__)
) or any of its subdirectories. -
#require_once(name) ⇒ Object
Fixes bug in Ruby (1.8, at least – not sure if 2.0 fixes it) where a file can be required twice if the path is spelled differently.
-
#trap_chain(signal_name, *args, &block) ⇒ Object
Calling
Kernel#trap()
by itself will replace any previously registered handler code. - #windows_platform? ⇒ Boolean
Instance Method Details
#backtrace ⇒ Object
Equivalent to calling caller(0)
11 12 13 14 |
# File 'lib/quality_extensions/kernel/backtrace.rb', line 11 def backtrace full_backtrace = caller(0) return full_backtrace[1..-1] # We don't want this call to backtrace showing up in the backtrace, so skip top 1 frame. end |
#backtrace_using_exception ⇒ Object
I thought I ran into some case where it didn’t work to use caller(0)…which prompted me to do it this way (raise and rescue an exception)…but now I can’t duplicate that problem, so I will deprecate this method.
23 24 25 26 27 28 29 30 |
# File 'lib/quality_extensions/kernel/backtrace.rb', line 23 def backtrace_using_exception begin raise "Where am I?" rescue Exception => exception full_backtrace = exception.backtrace return full_backtrace[1..-1] # We don't want this call to backtrace showing up in the backtrace, so skip top 1 frame. end end |
#capture_output(output_streams = $stdout, &block) ⇒ Object
Captures the output (stdout by default) that block
tries to generate and returns it as a string.
output = capture_output($stderr) { noisy_command }
output = capture_output([$stdout, $stderr]) do
noisy_command
end
Note: If you specify more than one output stream, the entire results of each will be concatenated in the order you listed them, not necessarily in the order that you wrote to those streams.
36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 |
# File 'lib/quality_extensions/kernel/capture_output.rb', line 36 def capture_output(output_streams = $stdout, &block) output_streams = [output_streams] unless output_streams.is_a? Array saved_output_streams = Dictionary.new output_streams.each do |output_stream| case output_stream.object_id when $stdout.object_id saved_output_streams[:$stdout] = $stdout $stdout = StringIO.new when $stderr.object_id saved_output_streams[:$stderr] = $stderr $stderr = StringIO.new end end what_they_tried_to_output = '' begin yield rescue Exception raise ensure saved_output_streams.each do |name, output_stream| case name when :$stdout what_they_tried_to_output += $stdout.string when :$stderr what_they_tried_to_output += $stderr.string end # Restore the original output_stream that we saved. case name when :$stdout $stdout = saved_output_streams[:$stdout] when :$stderr $stderr = saved_output_streams[:$stderr] end end end return what_they_tried_to_output end |
#default!(object, default_value) ⇒ Object
9 10 11 12 13 14 15 16 |
# File 'lib/quality_extensions/object/default.rb', line 9 def default!(object, default_value) case object when NilClass #object.become default_value #object.replace default_value else end end |
#die(message, exit_code = 1) ⇒ Object
11 12 13 14 |
# File 'lib/quality_extensions/kernel/die.rb', line 11 def die(, exit_code = 1) $stderr.puts exit exit_code end |
#global_variable_get(var, options = {}) ⇒ Object
Gets the global variable var
, which can either be a symbol or an actual global variable (use :match_object
).
global_variable_get(:$a)
global_variable_get($a, :match_object => true)
12 13 14 15 16 17 18 19 20 21 22 23 |
# File 'lib/quality_extensions/global_variable_set.rb', line 12 def global_variable_get(var, = {}) if .delete(:match_object) return global_variable_get(global_variable_name(var), ) else if var.is_a? Symbol raise NameError.new("#{var} is not a valid global variable name") unless var.to_s[0..0] == '$' return eval("#{var}") else raise ArgumentError.new("var must be a symbol unless :match_object => true") end end end |
#global_variable_name(var) ⇒ Object
Looks up the name of global variable var
, which must be an actual global variable.
global_variable_name($a)
27 28 29 30 31 32 33 34 35 36 37 |
# File 'lib/quality_extensions/global_variable_set.rb', line 27 def global_variable_name(var) global_variables.each do |test_var| #if eval(test_var).eql?(var) if eval(test_var).object_id == var.object_id #$stderr.puts "Checking #{test_var}. #{eval(test_var).inspect}" #$stderr.puts " #{$stdout.inspect}" return test_var.to_sym end end raise ArgumentError.new("The given object (#{var.inspect}) (#{var.object_id}) is not a valid global variable") end |
#global_variable_set(var, value, options = {}) ⇒ Object
Sets the global variable var
, which can either be a symbol or an actual global variable (use :match_object
).
global_variable_set(:$a, 'new')
global_variable_set($a, 'new', :match_object => true)
global_variable_set(:$a, "StringIO.new", :eval_string => true)
43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 |
# File 'lib/quality_extensions/global_variable_set.rb', line 43 def global_variable_set(var, value, = {}) #puts "global_variable_set(#{var}, #{value.inspect}, #{options.inspect}" if .delete(:match_object) return global_variable_set(global_variable_name(var), value, ) else if var.is_a? Symbol raise NameError.new("#{var} is not a valid global variable name") unless var.to_s[0..0] == '$' if .delete(:eval_string) #puts("About to eval: #{var} = #{value}") eval("#{var} = #{value}") else marshalled_data = Marshal.dump(value) eval("#{var} = Marshal.load(%Q<#{marshalled_data}>)") end return var else raise ArgumentError.new("var must be a symbol unless :match_object => true") end end end |
#pretty_backtrace ⇒ Object
Returns a human-readable backtrace
17 18 19 20 |
# File 'lib/quality_extensions/kernel/backtrace.rb', line 17 def pretty_backtrace "Backtrace:\n" + backtrace[1..-1].map{|frame| "* " + frame}.join("\n") end |
#remove_const(const_name) ⇒ Object
This is similar to the built-in Module#remove_const
, but it is accessible from all “levels” (because it is defined in Kernel
) and can handle hierarchy.
Makes it possible to write simply:
remove_const(A::B::C.name)
rather than having to think about which module the constant is actually defined in and calling remove_const
on that module.
This is how you would otherwise have to do it:
A::B.send(:remove_const, :C)
const_name
must be an object that responds to to_s
.
const_name
must be a fully qualified name. For example, this will not work as expected:
module Mod
Foo = 'foo'
remove_const(:Foo)
end
because it will try to remove ::Foo instead of Mod::Foo. Fortunately, however, this will work as expected:
module Mod
Foo = 'foo'
remove_const(Foo.name)
end
This method is partially inspired by Facets’ Kernel#constant method, which provided a more user-friendly alternative to const_get.
48 49 50 51 52 53 54 55 56 57 58 59 60 |
# File 'lib/quality_extensions/kernel/remove_const.rb', line 48 def remove_const(const_name) #require 'pp' #puts "remove_const(#{const_name})" raise ArgumentError unless const_name.respond_to?(:to_s) nesting = const_name.to_s.split(/::/).map(&:to_sym) if nesting.size > 1 parent_module = constant(nesting[0..-2].join('::')) # For example, would be A::B for A::B::C const_to_remove = nesting[-1] # For example, would be :C for A::B::C parent_module.ignore_access.remove_const_before_was_added_to_Kernel(const_to_remove) else ignore_access.remove_const_before_was_added_to_Kernel(const_name) end end |
#remove_const! ⇒ Object
This is similar to Kernel#remove_const, but it only works for modules/classes.
This is similar to the built-in Module#remove_module
, but it lets you do it in a more object oriented manner, calling remove!
on the module/class/constant itself that you want to remove, rather than on its parent.
Makes it possible to write simply:
A::B::C.remove_const!
rather than having to think about which module the constant is actually defined in and calling remove_const
on that module. This is how you would have to otherwise do it:
A::B.send(:remove_const, :C)
28 29 30 31 32 33 34 35 36 |
# File 'lib/quality_extensions/module/remove_const.rb', line 28 def remove_const! if split.size > 1 parent_module = modspace # For example, would be A::B for A::B::C const_to_remove = split.last # For example, would be :C for A::B::C parent_module.ignore_access.remove_const(const_to_remove) else Object.ignore_access.remove_const(name) end end |
#remove_module(const) ⇒ Object
This is similar to remove_const
, but it only works for modules/classes.
This is similar to the built-in Module#remove_module
, but it is accessible from all “levels” (because it is defined in Kernel
) and can handle hierarchy.
Makes it possible to write simply:
remove_module(A::B::C)
rather than having to think about which module the constant is actually defined in and calling remove_const
on that module. This is how you would have to otherwise do it:
A::B.send(:remove_const, :C)
You can pass in either a constant or a symbol. Passing in a constant is preferred
This method is partially inspired by Facets’ Kernel#constant method, which provided a more user-friendly alternative to const_get.
33 34 35 36 37 38 39 40 41 42 |
# File 'lib/quality_extensions/kernel/remove_module.rb', line 33 def remove_module(const) const = Module.by_name(const.to_s) if const.is_a?(Symbol) if const.split.size > 1 parent_module = const.modspace # For example, would be A::B for A::B::C const_to_remove = const.split.last # For example, would be :C for A::B::C parent_module.ignore_access.remove_const(const_to_remove) else Object.ignore_access.remove_const(const.name) end end |
#require_all(what, options = {}) ⇒ Object
require
s all Ruby files specified by what
, but not matching any of the exclude filters.
-
If
what
is a string, recursivelyrequire
s all Ruby files in the directory namedwhat
or any of its subdirectories. -
If
what
is a FileList,require
s all Ruby files that match thewhat
FileList.
Options: :exclude
: An array of regular expressions or glob patterns that will be passed to FileList#exclude. If you specify this option, a file will not be included if it matches any of these patterns. :exclude_files
: An array of filenames to exclude. These will be matched exactly, so if you tell it to exclude ‘bar.rb’, ‘foobar.rb’ will not be excluded.
Examples:
require_all 'lib/', :exclude => [/ignore/, /bogus/] # will require 'lib/a.rb', 'lib/long/path/b.rb', but not 'lib/ignore/c.rb'
require_all File.dirname(__FILE__), :exclude_files => ['blow_up_stuff.rb']
28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 |
# File 'lib/quality_extensions/kernel/require_all.rb', line 28 def require_all(what, = {}) files, exclusions = [nil]*2 case what when String base_dir = what base_dir += '/' unless base_dir[-1].chr == '/' files = FileList[base_dir + "**/*.rb"] when FileList files = what else raise ArgumentError.new("Expected a String or a FileList") end files = files.exclude(*exclusions) if (exclusions = .delete(:exclude)) files = files.exclude(*exclusions.map {|a| File.exact_match_regexp(a) }) if (exclusions = .delete(:exclude_files)) files.each do |filename| # puts "requiring #{filename}" if filename =~ /test/ require filename end end |
#require_local_all(dir = './', options = {}) ⇒ Object
57 58 59 60 61 62 63 64 |
# File 'lib/quality_extensions/kernel/require_all.rb', line 57 def require_local_all(dir = './', = {}) raise ArgumentError.new("dir must be a String") unless dir.is_a?(String) local_dir = File.dirname( caller[0] ) require_all( File.(File.join(local_dir, dir)), ) end |
#require_once(name) ⇒ Object
Fixes bug in Ruby (1.8, at least – not sure if 2.0 fixes it) where a file can be required twice if the path is spelled differently.
13 14 15 16 17 |
# File 'lib/quality_extensions/kernel/require_once.rb', line 13 def require_once(name) raise NotImplementedError # store expand_path(name) in an array ($required_files or something) # only do the require if it wasn't already in the array end |
#trap_chain(signal_name, *args, &block) ⇒ Object
Calling Kernel#trap()
by itself will replace any previously registered handler code. Kernel#trap_chain()
, on the other hand, will add the block you supply to the existing “list” of registered handler blocks. Similar to the way Kernel#at_exit()
works, Kernel#trap_chain()
will prepend the given block
to the call chain for the given signal_name
. When the signal occurs, your block will be executed first and then the previously registered handler will be invoked. This can be called repeatedly to create a “chain” of handlers.
15 16 17 18 19 20 21 |
# File 'lib/quality_extensions/kernel/trap_chain.rb', line 15 def trap_chain(signal_name, *args, &block) previous_interrupt_handler = trap(signal_name, *args) {} trap(signal_name, *args) do block.call previous_interrupt_handler.call unless previous_interrupt_handler == "DEFAULT" end end |
#windows_platform? ⇒ Boolean
12 13 14 15 16 17 18 19 |
# File 'lib/quality_extensions/kernel/windows_platform.rb', line 12 def windows_platform? RUBY_PLATFORM =~ /mswin32/ # What about mingw32 or cygwin32? #RUBY_PLATFORM =~ /(win|w)32$/ # What about 64-bit Windows? end |