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

Instance Method Details

#backtraceObject

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_exceptionObject

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.



35
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
# File 'lib/quality_extensions/kernel/capture_output.rb', line 35

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(message, exit_code = 1)
  $stderr.puts message
  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, options = {})
  if options.delete(:match_object)
    return global_variable_get(global_variable_name(var), options)
  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)

Raises:

  • (ArgumentError)


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, options = {})
  #puts "global_variable_set(#{var}, #{value.inspect}, #{options.inspect}"
  if options.delete(:match_object)
    return global_variable_set(global_variable_name(var), value, options)
  else 
    if var.is_a? Symbol
      raise NameError.new("#{var} is not a valid global variable name") unless var.to_s[0..0] == '$'
      if options.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?

  options = args.extract_options!
  options.symbolize_keys!

  precision ||= (options[:precision] || 1)
  separator ||= (options[:separator] || '.')
  delimiter ||= (options[:delimiter] || ',')
  base      ||= (options[: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)
  options = args.extract_options!
  options.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 ||= (options[:delimiter] || '.')
  separator ||= (options[: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)
  options = args.extract_options!
  options.symbolize_keys!

  precision ||= (options[:precision] || 3)
  separator ||= (options[:separator] || '.')
  delimiter ||= (options[: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_backtraceObject

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.

Raises:

  • (ArgumentError)


47
48
49
50
51
52
53
54
55
56
57
58
59
# File 'lib/quality_extensions/kernel/remove_const.rb', line 47

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)


27
28
29
30
31
32
33
34
35
# File 'lib/quality_extensions/module/remove_const.rb', line 27

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.



32
33
34
35
36
37
38
39
40
41
# File 'lib/quality_extensions/kernel/remove_module.rb', line 32

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

requires all Ruby files specified by what, but not matching any of the exclude filters.

  • If what is a string, recursively requires all Ruby files in the directory named what or any of its subdirectories.

  • If what is a FileList, requires all Ruby files that match the what 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']


26
27
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
# File 'lib/quality_extensions/kernel/require_all.rb', line 26

def require_all(what, options = {})
  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 = options.delete(:exclude))
    exclusions = [exclusions] if exclusions.is_a? String
    files = files.exclude(*exclusions)
  end
  if (exclusions = options.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.

Raises:

  • (NotImplementedError)


12
13
14
15
16
# File 'lib/quality_extensions/kernel/require_once.rb', line 12

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

requires all Ruby files in dir (relative to File.dirname(__FILE__)) or any of its subdirectories.

This is just a shortcut for this:

require_all File.expand_path(File.join(File.dirname(__FILE__), dir))

All of the options available for require_all are still available here.

Raises:

  • (ArgumentError)


61
62
63
64
65
66
67
68
# File 'lib/quality_extensions/kernel/require_all.rb', line 61

def require_relative_all(dir = './', options = {})
  raise ArgumentError.new("dir must be a String") unless dir.is_a?(String)
  local_dir = File.dirname( caller[0] )
  require_all(
    File.expand_path(File.join(local_dir, dir)),
    options
  )
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, options = {}, &block)
  debug = options[: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

Returns:

  • (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