Module: Kernel
- Defined in:
- lib/quality_extensions/object/default.rb,
lib/quality_extensions/kernel/die.rb,
lib/quality_extensions/range_list.rb,
lib/quality_extensions/helpers/numbers.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/kernel/sleep_loudly.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
). -
#number_to_human_size(number, *args) ⇒ Object
Formats the bytes in
size
into a more understandable representation (e.g., giving it 1500 yields 1.5 KB). -
#number_with_delimiter(number, *args) ⇒ Object
Formats a
number
with grouped thousands usingdelimiter
(e.g., 12,324). -
#number_with_precision(number, *args) ⇒ Object
Formats a
number
with the specified level of:precision
(e.g., 112.32 has a precision of 2). -
#pretty_backtrace ⇒ Object
Returns a human-readable backtrace.
- #RangeList(*args) ⇒ Object
-
#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_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.
-
#require_relative_all(dir = './', options = {}) ⇒ Object
require
s all Ruby files indir
(relative toFile.dirname(__FILE__)
) or any of its subdirectories. -
#sleep_loudly(n, step = -1,, options = {}, &block) ⇒ Object
Sleeps for integer
n
number of seconds, by default counting down fromn
(inclusive) to 0, with astep
size of -1, printing the value of the counter at each step (3, 2, 1, 0 (output 4 times) ifn
is 3), each time separated by a ‘, ’. -
#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 |
#number_to_human_size(number, *args) ⇒ Object
Formats the bytes in size
into a more understandable representation (e.g., giving it 1500 yields 1.5 KB). This method is useful for reporting file sizes to users. This method returns nil if size
cannot be converted into a number. You can customize the format in the options
hash.
Options
-
:base
- Pass in 2 (or 1024) to use binary units (KiB, MiB),pass in 10 (or 1000) to use SI (decimal) units (KB, MB) (defaults to base 10).
-
:precision
- Sets the level of precision (defaults to 1). -
:separator
- Sets the separator between the units (defaults to “.”). -
:delimiter
- Sets the thousands delimiter (defaults to “”).
Examples
number_to_human_size(123) # => 123 Bytes
number_to_human_size(1234) # => 1.2 KB
number_to_human_size(12345) # => 12.3 KB
number_to_human_size(1234567) # => 1.2 MB
number_to_human_size(1234567890) # => 1.2 GB
number_to_human_size(1234567890123) # => 1.2 TB
number_to_human_size(1234567, :precision => 2) # => 1.23 MB
number_to_human_size(1234567, :precision => 2, :base => 2) # => 1.18 MiB
number_to_human_size(483989, :precision => 0) # => 484 KB
number_to_human_size(483989, :precision => 0, :base => 2) # => 473 KiB
number_to_human_size(1234567, :precision => 2, :separator => ',') # => 1,23 MB
Differences from ActiveSupport version
The ActiveSupport version defaults to binary (base 2) units, while this one
defaults to SI (base 10) units.
The ActiveSupport incorrectly uses KB to refer to binary units, when the correct
abbreviation would be KiB (see http://en.wikipedia.org/wiki/Binary_prefix).
This version has a :base option to let you change the base; the ActiveSupport
version does not.
142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 |
# File 'lib/quality_extensions/helpers/numbers.rb', line 142 def number_to_human_size(number, *args) return nil if number.nil? = args. .symbolize_keys! precision ||= ([:precision] || 1) separator ||= ([:separator] || '.') delimiter ||= ([:delimiter] || ',') base ||= ([:base] || 10) # http://en.wikipedia.org/wiki/Binary_prefix if base == 10 || base == 1000 storage_units = %w( Bytes KB MB GB TB ).freeze base = 1000 elsif base == 2 || base == 1024 storage_units = %w( Bytes KiB MiB GiB TiB ).freeze base = 1024 else raise ArgumentError, "base must be 1000 or 1024" end storage_units_format = '%n %u' if number.to_i < base unit = number.to_i == 1 ? 'byte' : 'bytes' storage_units_format.gsub(/%n/, number.to_i.to_s).gsub(/%u/, unit) else max_exp = storage_units.size - 1 number = Float(number) exponent = (Math.log(number) / Math.log(base)).to_i # Convert to base 1024 exponent = max_exp if exponent > max_exp # we need this to avoid overflow for the highest unit number /= base ** exponent unit = storage_units[exponent] begin escaped_separator = Regexp.escape(separator) formatted_number = number_with_precision(number, :precision => precision, :separator => separator, :delimiter => delimiter ).sub(/(\d)(#{escaped_separator}[1-9]*)?0+\z/, '\1\2').sub(/#{escaped_separator}\z/, '') storage_units_format.gsub(/%n/, formatted_number).gsub(/%u/, unit) #rescue # number end end end |
#number_with_delimiter(number, *args) ⇒ Object
Formats a number
with grouped thousands using delimiter
(e.g., 12,324). You can customize the format in the options
hash.
Options
-
:delimiter
- Sets the thousands delimiter (defaults to “,”). -
:separator
- Sets the separator between the units (defaults to “.”).
Examples
number_with_delimiter(12345678) # => 12,345,678
number_with_delimiter(12345678.05) # => 12,345,678.05
number_with_delimiter(12345678, :delimiter => ".") # => 12.345.678
number_with_delimiter(12345678, :separator => ",") # => 12,345,678
number_with_delimiter(98765432.98, :delimiter => " ", :separator => ",")
# => 98 765 432,98
You can still use number_with_delimiter
with the old API that accepts the delimiter
as its optional second and the separator
as its optional third parameter:
number_with_delimiter(12345678, " ") # => 12 345.678
number_with_delimiter(12345678.05, ".", ",") # => 12.345.678,05
45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 |
# File 'lib/quality_extensions/helpers/numbers.rb', line 45 def number_with_delimiter(number, *args) = args. .symbolize_keys! unless args.empty? ActiveSupport::Deprecation.warn('number_with_delimiter takes an option hash ' + 'instead of separate delimiter and precision arguments.', caller) delimiter = args[0] || '.' separator = args[1] || ',' end delimiter ||= ([:delimiter] || '.') separator ||= ([:separator] || ',') begin parts = number.to_s.split('.') parts[0].gsub!(/(\d)(?=(\d\d\d)+(?!\d))/, "\\1#{delimiter}") parts.join(separator) #rescue # number end end |
#number_with_precision(number, *args) ⇒ Object
Formats a number
with the specified level of :precision
(e.g., 112.32 has a precision of 2). You can customize the format in the options
hash.
Options
-
:precision
- Sets the level of precision (defaults to 3). -
:separator
- Sets the separator between the units (defaults to “.”). -
:delimiter
- Sets the thousands delimiter (defaults to “”).
Examples
number_with_precision(111.2345) # => 111.235
number_with_precision(111.2345, :precision => 2) # => 111.23
number_with_precision(13, :precision => 5) # => 13.00000
number_with_precision(389.32314, :precision => 0) # => 389
number_with_precision(1111.2345, :precision => 2, :separator => ',', :delimiter => '.')
# => 1.111,23
You can still use number_with_precision
with the old API that accepts the precision
as its optional second parameter:
number_with_precision(number_with_precision(111.2345, 2) # => 111.23
87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 |
# File 'lib/quality_extensions/helpers/numbers.rb', line 87 def number_with_precision(number, *args) = args. .symbolize_keys! precision ||= ([:precision] || 3) separator ||= ([:separator] || '.') delimiter ||= ([:delimiter] || '') begin rounded_number = (Float(number) * (10 ** precision)).round.to_f / 10 ** precision number_with_delimiter("%01.#{precision}f" % rounded_number, :separator => separator, :delimiter => delimiter) #rescue # number 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 |
#RangeList(*args) ⇒ Object
14 15 16 |
# File 'lib/quality_extensions/range_list.rb', line 14 def RangeList(*args) RangeList.new(*args) 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 49 50 51 52 53 54 |
# 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 if (exclusions = .delete(:exclude)) exclusions = [exclusions] if exclusions.is_a? String files = files.exclude(*exclusions) end if (exclusions = .delete(:exclude_files)) exclusions = [exclusions] if exclusions.is_a? String files = files.exclude(*exclusions.map {|a| File.exact_match_regexp(a) }) end files.each do |filename| # puts "requiring #{filename}" if filename =~ /test/ require filename end 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 |
#require_relative_all(dir = './', options = {}) ⇒ Object
63 64 65 66 67 68 69 70 |
# File 'lib/quality_extensions/kernel/require_all.rb', line 63 def require_relative_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 |
#sleep_loudly(n, step = -1,, options = {}, &block) ⇒ Object
Sleeps for integer n
number of seconds, by default counting down from n
(inclusive) to 0, with a step
size of -1, printing the value of the counter at each step (3, 2, 1, 0 (output 4 times) if n
is 3), each time separated by a ‘, ’.
In effect, it is a simple on-screen countdown (or count-up) timer.
To change the step size, supply a value for step
other than -1 (the default). It will sleep for step.abs
seconds between each iteration, and at each iteration will either yield to the supplied block or (the default) output the current value of the counter).
The value of step
also determines in which direction to count: If step
is negative (the default), it counts down from n
down to 0 (inclusive). If step
is positive, it counts up from 0 up to n
(inclusive).
step
does not need to be an integer value.
If n
is not evenly divisible by step
(that is, if step * floor( / ? ) > n), the final step size will be shorter to ensure that the total amount slept is n
seconds. More precisely, the amount of time it sleeps before the final iteration (during which it won’t sleepat all) will
If a block is provided, all of the default output is overridden, and the block will be yielded with the value of the counter i once every second instead of the default behavior, allowing you to customize what gets output, if anything, or what else happens, every n.abs
seconds.
Note that it produces output (or executes your block, if supplied) n+1 times, not n times. This allows you to output (or not) both when the timer is first started and when it finishes. But because it sleeps for 1 second after the first n iterations only and not after the last, the total delay is still only n seconds.
Examples:
sleep_loudly(3)
3<sleep 1>2, <sleep 1>1, <sleep 1>0
sleep_loudly(3) {|i| puts(i == 0 ? 'Done' : i)}
3<sleep 1>
2<sleep 1>
1<sleep 1>
Done
sleep_loudly(10*60, :up, 60) {|i| print i*60, ", "} # sleep for 10 minutes, outputting after every 60 seconds
0<sleep 60>2, <sleep 60>2, <sleep 60>3,
sleep_loudly(3, :up) {|i| print i}
0<sleep 1>1<sleep 1>2<sleep 1>3
sleep_loudly(3, :up) {|i| print i+1 unless i==3}
1<sleep 1>2<sleep 1>3<sleep 1>
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 76 77 78 79 80 81 82 83 84 85 86 87 88 89 |
# File 'lib/quality_extensions/kernel/sleep_loudly.rb', line 41 def sleep_loudly(n, step = -1, = {}, &block) debug = [:debug] == true ? 1 : 0 #debug = 1 old_sync, STDOUT.sync = STDOUT.sync, true if step < 0 starti, endi = n, 0 elsif step > 0 starti, endi = 0, n else raise ArgumentError, "step must be positive or negative, not 0" end puts "Counting from #{starti} to #{endi} in increments of #{step} (total time should be n=#{n})" if debug i = starti final = false loop do print 'final' if final if block_given? yield *[i, final][0..block.arity-1] else print "#{i}" end break if final remaining = (i - endi).abs # if n was a multiple of step, remaining will eventually be 0, telling us that there is one final iteration to go # if n was not a multiple of step, use a different, smaller step as the final step; and we know that there is one final iteration to go if remaining < step.abs s = (step < 0 ? i-endi : endi-i) print " (using smaller final step #{s}) " if debug final = true # the next iteration is the final one else s = step end i += s print " (+#{s}=#{i}) " if debug print ", " unless block_given? print " (sleeping for #{s.abs}) " if debug sleep s.abs end print "\n" unless block_given? STDOUT.sync = old_sync 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 |