require "rbconfig" class Pa # In order to reduce the dependencies, this Util class contains some util functions. class Util module Concern def included(base) base.extend const_get(:ClassMethods) if const_defined?(:ClassMethods) end end class << self # Extracts options from a set of arguments. # # @example # # dirs, o = Util.extract_options(["foo", "bar", {a: 1}], b: 2) # -> ["foo", "bar"], {a: 1, b: 2} # # (dir,) o = Util.extract_options(["foo", {a: 1}]) # -> "foo", {a: 1} # # @return [Array] def extract_options(args, default={}) if args.last.instance_of?(Hash) [args[0...-1], default.merge(args[-1])] else [args, default] end end # Wraps its argument in an array unless it is already an array (or array-like). # # Specifically: # # * If the argument is +nil+ an empty list is returned. # * Otherwise, if the argument responds to +to_ary+ it is invoked, and its result returned. # * Otherwise, returns an array with the argument as its single element. # # Array.wrap(nil) # => [] # Array.wrap([1, 2, 3]) # => [1, 2, 3] # Array.wrap(0) # => [0] # # This method is similar in purpose to Kernel#Array, but there are some differences: # # * If the argument responds to +to_ary+ the method is invoked. Kernel#Array # moves on to try +to_a+ if the returned value is +nil+, but Array.wrap returns # such a +nil+ right away. # * If the returned value from +to_ary+ is neither +nil+ nor an +Array+ object, Kernel#Array # raises an exception, while Array.wrap does not, it just returns the value. # * It does not call +to_a+ on the argument, though special-cases +nil+ to return an empty array. # # The last point is particularly worth comparing for some enumerables: # # Array(:foo => :bar) # => [[:foo, :bar]] # Array.wrap(:foo => :bar) # => [{:foo => :bar}] # # Array("foo\nbar") # => ["foo\n", "bar"], in Ruby 1.8 # Array.wrap("foo\nbar") # => ["foo\nbar"] # # There's also a related idiom that uses the splat operator: # # [*object] # # which returns [nil] for +nil+, and calls to Array(object) otherwise. # # Thus, in this case the behavior is different for +nil+, and the differences with # Kernel#Array explained above apply to the rest of +object+s. def wrap_array(object) if object.nil? [] elsif object.respond_to?(:to_ary) object.to_ary || [object] else [object] end end # Slice a hash to include only the given keys. This is useful for # limiting an options hash to valid keys before passing to a method: # # @example # # a = {a: 1, b: 2, c: 3} # a.slaice(:a, :b) -> {a: 1, b: 2} def slice(hash, *keys) keys = keys.map! { |key| hash.convert_key(key) } if hash.respond_to?(:convert_key) h = hash.class.new keys.each { |k| h[k] = hash[k] if hash.has_key?(k) } h end # different to File.join. # # @example # # join_path(".", "foo") -> "foo" not "./foo" # def join_path(dir, *names) dir == "." ? File.join(*names) : File.join(dir, *names) end def linux? RbConfig::CONFIG["host_os"] =~ /linux|cygwin/ end def mac? RbConfig::CONFIG["host_os"] =~ /mac|darwin/ end def bsd? RbConfig::CONFIG["host_os"] =~ /bsd/ end def windows? RbConfig::CONFIG["host_os"] =~ /mswin|mingw/ end def solaris? RbConfig::CONFIG["host_os"] =~ /solaris|sunos/ end # TODO: who knows what symbian returns? def symbian? RbConfig::CONFIG["host_os"] =~ /symbian/ end def posix? linux? or mac? or bsd? or solaris? or begin fork do end true rescue NotImplementedError, NoMethodError false end end end end end