class Byebug::InfoCommand

Implements byebug “info” command.

def description

def description
  %{info[ subcommand]
    Generic command for showing things about the program being debugged.}
end

def execute

def execute
  return print InfoCommand.help(nil) unless @match[1]
  args = @match[1].split(/[ \t]+/)
  param = args.shift
  subcmd = Command.find(Subcommands, param)
  return errmsg "Unknown info command #{param}\n" unless subcmd
  if @state.context
    send("info_#{subcmd.name}", *args)
  else
    errmsg "info_#{subcmd.name} not available without a context.\n"
  end
end

def help(args)

def help(args)
  return description + format_subcmds unless args and args[1]
  return format_subcmd(args[1]) unless 'file' == args[1] and args[2]
  str = subcmd.short_help + '.'
  subsubcmd = Command.find(InfoFileSubcommands, args[2])
  if subsubcmd
    str += "\nInvalid \"file\" attribute \"#{args[2]}\"."
  else
    str += "\n" + subsubcmd.short_help + '.'
  end
  return str
end

def info_args(*args)

def info_args(*args)
  locals = @state.context.frame_locals
  args = @state.context.frame_args
  return if args == [[:rest]]
  args.map do |_, name|
    s = "#{name} = #{locals[name].inspect}"
    pad_with_dots(s)
    print "#{s}\n"
  end
end

def info_breakpoint(brkpt)

def info_breakpoint(brkpt)
  expr = brkpt.expr.nil? ? '' : " if #{brkpt.expr}"
  print "%-3d %-3s at %s:%s%s\n" %
    [brkpt.id, brkpt.enabled? ? 'y' : 'n', brkpt.source, brkpt.pos, expr]
  hits = brkpt.hit_count
  if hits > 0
    s = (hits > 1) ? 's' : ''
    print "\tbreakpoint already hit #{hits} time#{s}\n"
  end
end

def info_breakpoints(*args)

def info_breakpoints(*args)
  return print "No breakpoints.\n" if Byebug.breakpoints.empty?
  brkpts = Byebug.breakpoints.sort_by{|b| b.id}
  unless args.empty?
    indices = args.map{|a| a.to_i}
    brkpts = brkpts.select{|b| indices.member?(b.id)}
    return errmsg "No breakpoints found among list given.\n" if
      brkpts.empty?
  end
  print "Num Enb What\n"
  brkpts.each { |b| info_breakpoint(b) }
end

def info_display(*args)

def info_display(*args)
  return print "There are no auto-display expressions now.\n" unless
    @state.display.find{|d| d[0]}
  print "Auto-display expressions now in effect:\n" \
        "Num Enb Expression\n"
  n = 1
  for d in @state.display
    print "%3d: %s  %s\n" % [n, (d[0] ? 'y' : 'n'), d[1]]
    n += 1
  end
end

def info_file(*args)

def info_file(*args)
  return info_files unless args[0]
  subcmd = Command.find(InfoFileSubcommands, args[1] || 'basic')
  return errmsg "Invalid parameter #{args[1]}\n" unless subcmd
  if %w(all basic).member?(subcmd.name)
    info_file_path(args[0])
    info_file_lines(args[0])
    if subcmd.name == 'all'
      info_file_breakpoints(args[0])
      info_file_mtime(args[0])
      info_file_sha1(args[0])
    end
  else
    print "File #{args[0]}\n" if subcmd.name != 'path'
    send("info_file_#{subcmd.name}", args[0])
  end
end

def info_file_breakpoints(file)

def info_file_breakpoints(file)
  breakpoints = LineCache.trace_line_numbers(file)
  if breakpoints
    print "\tbreakpoint line numbers:\n"
    print columnize(breakpoints.to_a.sort, Command.settings[:width])
  end
end

def info_file_lines(file)

def info_file_lines(file)
  lines = LineCache.size(file)
  print "\t #{lines} lines\n" if lines
end

def info_file_mtime(file)

def info_file_mtime(file)
  stat = LineCache.stat(file)
  print "\t#{stat.mtime}\n" if stat
end

def info_file_path(file)

def info_file_path(file)
  print "File #{file}"
  path = File.expand_path(file)
  print " - #{path}\n" if path and path != file
end

def info_file_sha1(file)

def info_file_sha1(file)
  print "\t#{LineCache.sha1(file)}\n"
end

def info_files(*args)

def info_files(*args)
  files = SCRIPT_LINES__.keys
  files.uniq.sort.each do |file|
    info_file_path(file)
    info_file_mtime(file)
  end
end

def info_global_variables(*args)

def info_global_variables(*args)
  var_global
end

def info_instance_variables(*args)

def info_instance_variables(*args)
  obj = debug_eval('self')
  var_list(obj.instance_variables)
end

def info_line(*args)

def info_line(*args)
  print "Line #{@state.line} of \"#{@state.file}\"\n"
end

def info_locals(*args)

def info_locals(*args)
  locals = @state.context.frame_locals
  print_hash(locals)
end

def info_program(*args)

def info_program(*args)
  return print "The program crashed.\n" + Byebug.last_exception ?
               "Exception: #{Byebug.last_exception.inspect}" : "" + "\n" if
    @state.context.dead?
  print "Program stopped. "
  info_stop_reason @state.context.stop_reason
end

def info_stack(*args)

def info_stack(*args)
  print_backtrace
end

def info_stop_reason(stop_reason)

def info_stop_reason(stop_reason)
  case stop_reason
    when :step
      print "It stopped after stepping, next'ing or initial start.\n"
    when :breakpoint
      print("It stopped at a breakpoint.\n")
    when :catchpoint
      print("It stopped at a catchpoint.\n")
    else
      print "unknown reason: %s\n" % @state.context.stop_reason.to_s
  end
end

def info_variables(*args)

def info_variables(*args)
  locals = @state.context.frame_locals
  locals[:self] = @state.context.frame_self(@state.frame_pos)
  print_hash(locals)
  obj = debug_eval('self')
  var_list(obj.instance_variables, obj.instance_eval{binding()})
  var_class_self
end

def names

def names
  %w(info)
end

def print_hash(vars)

def print_hash(vars)
  vars.keys.sort.each do |name|
    begin
      s = "#{name} = #{vars[name].inspect}"
    rescue
      begin
      s = "#{name} = #{vars[name].to_s}"
      rescue
        s = "#{name} = *Error in evaluation*"
      end
    end
    pad_with_dots(s)
    print "#{s}\n"
  end
end

def regexp

def regexp
  /^\s* i(?:nfo)? (?:\s+(.+))? \s*$/x
end