西山和広です。

In <86n0whaqpe.wl / archon.local.idaemons.org>
On Sat, 6 Apr 2002 22:42:38 +0900
"Akinori MUSHA" <knu / iDaemons.org> wrote:
>  そこで、 1.6 用の追加モジュール集のようなものを作りたいと思って
> います。あるいは、 1.7 early access kit のような名前で、互換性を
> 容易に取れるようなヘルパーモジュールとともに配布するという手も
> 考えています。
> 
>  もう少し詳細を詰めてから何らかの形で実行に移したいと思いますが、
> みなさんはどう思われますか?
> 
>  「1.7 だとこれで一発なんだけど、 1.6 を考えるとこれは使えない
> なあ」などと考えていると、いつまで経っても移行に踏み切れません。
> ごく一例なんですが、私も手元で
> 
> if RUBY_VERSION < "1.7"
>   Dir.instance_eval %{
>     alias _chdir chdir
> 
>     def chdir(dir)
>       if block_given?
>         pwd = Dir.pwd
> 
>         begin
>           Dir._chdir(dir)
>           yield
>         ensure
>           Dir._chdir(pwd)
>         end
>       else
>         Dir._chdir(dir)
>       end
>     end
>   }
> end
> 
> みたいなことをして Dir.chdir(dir) { ... } を使ってたりします。

以下につけたようなのを作ろうとしてましたが、$_をいじる組み込み関数が
どうにもできなかったというところで止まってしまってました。

ruby17.rbという名前もどうかと思ってしまってroughに入れることも
できずに放置してしまってました。


-- 
|ZnZ(ゼット エヌ ゼット)
|西山和広(Kazuhiro NISHIYAMA)


% cat ruby17.rb
#!/usr/bin/env ruby

if __FILE__ == $0
  require 'runit/testcase'
  require 'runit/cui/testrunner'
end

# http://www.ruby-lang.org/~eban/diary/200201a.html#200201021
if [].method(:select).arity == 0
  ['class Array', 'class Hash', 'ENV.instance_eval do'].each do |e|
    eval %{
      #{e}
        def select(*x, &block)
          if block
            super(*x, &block)
          else
            indexes(*x)
          end
        end
      end
    }
  end
end

unless MatchData.method_defined? :select
  class MatchData
    def select(*args, &block)
      to_a.indexes(*args, &block)
    end
  end
end

if __FILE__ == $0
  class Test_ruby17 < RUNIT::TestCase
    def test_select
      assert_equal([2,3], [1,2,3,4,5].select(1,2))
      assert_equal([2,4], {1,2,3,4,5,6}.select(1,3))
      assert_equal([ENV['PATH'],ENV['USER']], ENV.select('PATH','USER'))

      #m = "foobarbaz".match(/(foo)(bar)(baz)/)
      m = /(foo)(bar)(baz)/.match("foobarbaz")
      assert_equal(["foobarbaz", "foo", "bar", "baz", nil],
                   m.select(0,1,2,3,4))
      assert_equal(["baz", "bar", "foo"],
                   m.select(-1,-2,-3))
    end
  end
end

# http://www.ruby-lang.org/~eban/diary/200112c.html#200112253
if $-v or __FILE__ == $0
  Dir.instance_eval {
    alias :original_glob :glob
    def [](*args, &block)
      raise ArgumentError, "use {,} for patterns" if args.to_s.index(' ')
      original_glob(*args, &block)
    end
    def glob(*args, &block)
      raise ArgumentError, "use {,} for patterns" if args.to_s.index(' ')
      original_glob(*args, &block)
    end
  }
end

if __FILE__ == $0
  class Test_ruby17 < RUNIT::TestCase
    def test_glob
      assert_exception(ArgumentError) { Dir[' '] }
      assert_exception(ArgumentError) { Dir.glob(' ') }
    end
  end
end

begin
  $ruby17 = nil
  trace_var :$ruby17, ''.taint
rescue SecurityError
else
  def trap(*args, &block)
    if args[1].tainted?
      raise SecurityError, 'Insecure: tainted signal trap'
    else
      Kernel.trap(*args, &block)
    end
  end

  def trace_var(*args, &block)
    if args[1].tainted?
      raise SecurityError, 'Insecure: tainted variable trace'
    else
      Kernel.trace_var(*args, &block)
    end
  end
ensure
  untrace_var :$ruby17
end

if __FILE__ == $0
  class Test_ruby17 < RUNIT::TestCase
    def test_trap
      assert_exception(SecurityError) { trap(:USR1, ''.taint) }
      assert_exception(SecurityError) { trap(:USR1, proc{}.taint) }
      assert_no_exception(SecurityError) { trap(:USR1, &proc{}.taint) }
    end
    def test_trace_var
      $test = nil
      assert_exception(SecurityError) { trace_var(:$ruby17, ''.taint) }
      assert_exception(SecurityError) { trace_var(:$ruby17, proc{}.taint) }
      assert_no_exception(SecurityError) { trace_var(:$ruby17, &proc{}.taint) }
    end
  end
end

if 0.method(:to_s).arity == 0
  ['Integer', 'Fixnum', 'Bignum'].each do |klass|
    eval %{
      class #{klass}
        def to_s(base=10)
          case base
          when 10
            '%d' % self
          when 16
            '%x' % self
          when 8
            '%o' % self
          when 2
            '%b' % self
          else
            raise ArgumentError, "illegal radix \#{radix}"
          end
        end
      end
    }
  end
end

if __FILE__ == $0
  class Test_ruby17 < RUNIT::TestCase
    def test_Integer_to_s
      assert_equal('123', 123.to_s)
      assert_equal('123', 123.to_s(10))
      assert_equal('7b', 123.to_s(16))
      assert_equal('173', 123.to_s(8))
      assert_equal('1111011', 123.to_s(2))
      assert_equal("10000000000000000", (2**64).to_s(16))
    end
  end
end

if "ruby17\r\n".chomp == "ruby17\r"
  class String
    alias :original_chomp_bang :chomp!
    def chomp!(rs=$/)
      if "\n" == rs
        sub!(/\r\n?\z|\n\z/, '')
      else
        original_chomp_bang(rs)
      end
    end
    def chomp(rs=$/)
      s = dup
      s.chomp!(rs)
      s
    end
  end

  # chomp and chomp! can't redefine bacause `$_' is in local scope.
end

if __FILE__ == $0
  class Test_ruby17 < RUNIT::TestCase
    def test_chomp
      s = "ruby17\r\n"
      assert_equal("ruby17", s.chomp!)
      assert_equal(nil, s.chomp!)

      assert_equal("ruby17", "ruby17\r\n".chomp)
      assert_equal("ruby17", "ruby17\r".chomp)
      assert_equal("ruby17", "ruby17\n".chomp)
      assert_equal("ruby17\n", "ruby17\n\r".chomp)

      assert_equal("ruby17", "ruby17\r\n".chomp("\r\n"))
      assert_equal("ruby", "ruby17\r\n".chomp("17\r\n"))
    end
  end
end

module Enumerable
  unless method_defined? :all?
    def all?
      each{ |v|
        return false unless yield(v)
      }
      return true
    end
  end
  unless method_defined? :any?
    def any?
      each{ |v|
        return true if yield(v)
      }
      return false
    end
  end
  unless method_defined? :inject
    def inject(result)
      each {|e|
        result = yield result, e
      }
      result
    end
  end

  unless method_defined? :sort_by
    def sort_by
      self.collect {|i| [yield(i),i]}.
        sort {|a,b| a[0] <=> b[0]}.
        collect! {|i| i[1]}
    end
  end
end

if __FILE__ == $0
  class Test_ruby17 < RUNIT::TestCase
    def test_enum
      assert_equal(true, [1,2,3].all? {|v| v > 0})
      assert_equal(false, [1,2,3].all? {|v| v > 1})
      assert_equal(15, [1,2,3,4,5].inject(0) {|result, item| result + item })
      i = 0
      assert_equal(["BAR", "bar", "FOO", "foo"],
                   ["BAR", "FOO", "bar", "foo"].
                   sort_by {|v| [v.downcase, i += 1] })
    end
  end
end

if __FILE__ == $0
  if ARGV.size == 0
    suite = Test_ruby17.suite
  else
    suite = RUNIT::TestSuite.new
    ARGV.each do |testmethod|
      suite.add_test(Test_NUI_CUI.new(testmethod))
    end
  end
  RUNIT::CUI::TestRunner.run(suite)
end