module Utils::IRB::Shell

def capture_output(with_stderr = false)

def capture_output(with_stderr = false)
  require 'tempfile'
  begin
    old_stdout, $stdout = $stdout, Tempfile.new('irb')
    if with_stderr
      old_stderr, $stderr = $stderr, $stdout
    end
    yield
  ensure
    $stdout, temp = old_stdout, $stdout
    with_stderr and $stderr = old_stderr
  end
  temp.rewind
  temp.read
end

def ed(*files)

def ed(*files)
  if files.empty?
    $editor.full?(:edit, self)
  else
    $editor.full?(:edit, *files)
  end
end

def irb_all_class_instance_methods(obj = self)

Return all instance methods of obj's class.
def irb_all_class_instance_methods(obj = self)
  methods = obj.class.instance_methods
  irb_wrap_methods obj, methods
end

def irb_all_instance_methods(modul = self)

Return all instance methods defined in module modul.
def irb_all_instance_methods(modul = self)
  methods = modul.instance_methods
  irb_wrap_methods modul, methods, true
end

def irb_all_methods(obj = self)

Return all methods of obj (including obj's eigenmethods.)
def irb_all_methods(obj = self)
  methods = obj.methods
  irb_wrap_methods obj, methods
end

def irb_class_instance_methods(obj = self)

methods.
Return instance methods of obj's class without the inherited/mixed in
def irb_class_instance_methods(obj = self)
  methods = obj.class.instance_methods(false)
  irb_wrap_methods obj, methods
end

def irb_constants(modul = self)

Return all the constants defined in +modul+.
def irb_constants(modul = self)
  modul.constants.map { |c| ConstantWrapper.new(modul.const_get(c), c) }.sort
end

def irb_eigen_methods(obj = self)

Return all eigen methods of obj.
def irb_eigen_methods(obj = self)
  irb_wrap_methods obj, obj.methods(false)
end

def irb_instance_methods(modul = self)

in methods.
Return instance methods defined in module modul without the inherited/mixed
def irb_instance_methods(modul = self)
  methods = modul.instance_methods(false)
  irb_wrap_methods modul, methods, true
end

def irb_load!(*files)

def irb_load!(*files)
  files = files.map { |f| f.gsub(/(\.rb)?\Z/, '.rb') }
  loaded = {}
  for file in files
    catch :found do
      Find.find('.') do |f|
        File.directory?(f) and next
        md5_f = Utils::MD5.md5(f)
        if f.end_with?(file) and !loaded[md5_f]
          Kernel.load f
          loaded[md5_f] = true
          STDERR.puts "Loaded '#{f}'."
        end
      end
    end
  end
  nil
end

def irb_methods(obj = self)

methods, but including obj's eigenmethods.
Return instance methods of obj's class without the inherited/mixed in
def irb_methods(obj = self)
  methods = obj.class.ancestors[1..-1].inject(obj.methods) do |all, a|
    all -= a.instance_methods
  end
  irb_wrap_methods obj, methods
end

def irb_open(url = nil, &block)

def irb_open(url = nil, &block)
  case
  when url
    system 'open', url
  when block
    Tempfile.open('wb') do |t|
      t.write capture_output(&block)
      t.rewind
      system 'open', t.path
    end
  when url = receiver_unless_main(method(__method__))
    irb_open url
  else
    raise ArgumentError, 'need an url or block'
  end
end

def irb_read(filename, chunk_size = 8_192)

def irb_read(filename, chunk_size = 8_192)
  if block_given?
    File.open(filename) do |file|
      until file.eof?
        yield file.read(chunk_size)
      end
    end
  else
    File.read filename
  end
end

def irb_subclasses(klass = self)

Return all the subclasses of +klass+. TODO implement subclasses w/out rails
def irb_subclasses(klass = self)
  klass.subclasses.map { |c| ConstantWrapper.new(eval(c), c) }.sort
end

def irb_time(n = 1)

def irb_time(n = 1)
  s = Time.now
  n.times do
    yield
  end
  d = Time.now - s
  if n == 1
    warn "Took %.3fs seconds." % d
  else
    warn "Took %.3fs seconds, %.3fs per call (avg)." % [ d, d / n ]
  end
  d
end

def irb_time_tap(n = 1)

def irb_time_tap(n = 1)
  r = nil
  irb_time(n) { r = yield }
  r
end

def irb_time_watch(duration = 1)

def irb_time_watch(duration = 1)
  start = Time.now
  pre = nil
  avg = Hash.new
  loop do
    cur = [ yield ].flatten
    unless pre
      pre = cur.map(&:to_f)
      cur = [ yield ].flatten
    end
    expired = Time.now - start
    diffs = cur.zip(pre).map { |c, p| c - p }
    rates = diffs.map { |d| d / duration }
    durs = cur.zip(rates).each_with_index.map { |(c, r), i|
      if r < 0
        x = c.to_f / -r
        a = avg[i].to_f
        a -= a / 2
        a += x / 2
        d = Tins::Duration.new(a)
        ds = d.to_s
        ds.singleton_class { define_method(:to_f) { d.to_f } }
        avg[i] = ds
      end
      avg[i]
    }
    warn "#{expired} #{cur.zip(diffs, rates, durs).map(&:inspect) * ' '} 𝝙 / per sec."
    pre = cur.map(&:to_f)
    sleep duration
  end
end

def irb_toggle_logging

def irb_toggle_logging
  require 'logger'
  if ActiveRecord::Base.logger != $logger
    $old_logger = ActiveRecord::Base.logger
    ActiveRecord::Base.logger = $logger
    true
  else
    ActiveRecord::Base.logger = $old_logger
    false
  end
end

def irb_wrap_methods(obj = self, methods = methods(), modul = false)

def irb_wrap_methods(obj = self, methods = methods(), modul = false)
  methods.map do |name|
    MethodWrapper.new(obj, name, modul) rescue nil
  end.compact.sort!
end

def irb_write(filename, text = nil, &block)

def irb_write(filename, text = nil, &block)
  if text.nil? && block
    File.secure_write filename, nil, 'wb', &block
  else
    File.secure_write filename, text, 'wb'
  end
end

def le(with_stderr = false, &block)

def le(with_stderr = false, &block)
  less(with_stderr) { block.call(self) }
end

def less(with_stderr = false, &block)

Use pager on the output of the commands given in the block.
def less(with_stderr = false, &block)
  IO.popen($pager, 'w') do |f|
    f.write capture_output(with_stderr, &block)
    f.close_write
  end
  nil
end

def receiver_unless_main(method, &block)

def receiver_unless_main(method, &block)
  receiver_name = method.receiver.to_s
  if receiver_name != 'main'
    if block
      block.(receiver_name)
    else
      receiver_name
    end
  end
end

def ri(*patterns, doc: 'ri')

pattern.class.name as argument.
Start _ri_ for +pattern+. If +pattern+ is not string like, call it with
def ri(*patterns, doc: 'ri')
  patterns.empty? and
    receiver_unless_main(method(__method__)) do |pattern|
      return ri(pattern, doc: doc)
    end
  patterns.map! { |p|
    case
    when Module === p
      p.name
    when p.respond_to?(:to_str)
      p.to_str
    else
      p.class.name
    end
  }
  system "#{doc} #{patterns.map { |p| "'#{p}'" } * ' ' } | #$pager"
end

def yri(*patterns)

def yri(*patterns)
  ri(*patterns, doc: 'yri')
end