class Pry::Command::ShowInfo

def code_object_header(code_object, line_num)

def code_object_header(code_object, line_num)
  if code_object.real_method_object?
    method_header(code_object, line_num)
    # It sucks we have to test for both Pry::WrappedModule and
    # WrappedModule::Candidate, probably indicates a deep refactor needs
    # to happen in those classes.
  elsif code_object.is_a?(Pry::WrappedModule) ||
        code_object.is_a?(Pry::WrappedModule::Candidate)
    module_header(code_object, line_num)
  else
    ""
  end
end

def code_object_with_accessible_source(code_object)

Returns:
  • (Pry::WrappedModule, Pry::Method, Pry::Command) -
def code_object_with_accessible_source(code_object)
  return code_object unless code_object.is_a?(WrappedModule)
  candidate = code_object.candidates.find(&:source)
  return candidate if candidate
  raise CommandError, no_definition_message unless valid_superclass?(code_object)
  @used_super = true
  code_object_with_accessible_source(code_object.super)
end

def complete(input)

def complete(input)
  if input =~ /([^ ]*)#([a-z0-9_]*)\z/
    prefix = Regexp.last_match(1)
    search = Regexp.last_match(2)
    methods =
      begin
        # rubocop:disable Security/Eval
        Pry::Method.all_from_class(binding.eval(prefix))
        # rubocop:enable Security/Eval
      rescue RescuableException
        return super
      end
    methods.map do |method|
      [prefix, method.name].join('#') if method.name.start_with?(search)
    end.compact
  else
    super
  end
end

def content_and_header_for_code_object(code_object)

def content_and_header_for_code_object(code_object)
  header(code_object) + content_for(code_object)
end

def content_and_headers_for_all_module_candidates(mod)

def content_and_headers_for_all_module_candidates(mod)
  result = "Found #{mod.number_of_candidates} candidates for " \
           "`#{mod.name}` definition:\n"
  mod.number_of_candidates.times do |v|
    candidate = mod.candidate(v)
    begin
      result += "\nCandidate #{v + 1}/#{mod.number_of_candidates}: " \
                "#{candidate.source_file}:#{candidate.source_line}\n"
      content = content_for(candidate)
      result += "Number of lines: #{content.lines.count}\n\n" + content
    rescue Pry::RescuableException
      result += "\nNo content found.\n"
      next
    end
  end
  result
end

def file_and_line_for(code_object)

of code_object
has to infer by subtracting number of lines of comment from start line
Also adjusts for start line of comments (using start_line_for), which it
takes into account possible yard docs, and returns yard_file / yard_line
def file_and_line_for(code_object)
  if code_object.module_with_yard_docs?
    [code_object.yard_file, code_object.yard_line]
  else
    [code_object.source_file, start_line_for(code_object)]
  end
end

def header(code_object)

object types: methods, modules, commands, procs...
Generate a header (meta-data information) for all the code
def header(code_object)
  file_name, line_num = file_and_line_for(code_object)
  content = content_for(code_object)
  h = "\n#{bold('From:')} #{file_name}"
  h += code_object_header(code_object, line_num)
  h += "\n#{bold('Number of lines:')} " + "#{content.lines.count}\n\n"
  if @used_super
    h += bold('** Warning:')
    h += " Cannot find code for #{@original_code_object.nonblank_name}. " \
         "Showing superclass #{code_object.nonblank_name} instead. **\n\n"
  end
  if content.lines.none?
    h += bold('** Warning:')
    h += " Cannot find code for '#{code_object.name}' (source_location is nil)"
  end
  h
end

def header_options

def header_options
  {
    owner: true,
    visibility: true,
    signature: nil
  }
end

def initialize(*)

def initialize(*)
  super
  @used_super = nil
end

def method_header(code_object, line_num)

def method_header(code_object, line_num)
  h = ""
  h += (code_object.c_method? ? ' (C Method):' : ":#{line_num}:")
  h += method_sections(code_object)[:owner]
  h += method_sections(code_object)[:visibility]
  h += method_sections(code_object)[:signature]
  h
end

def method_sections(code_object)

def method_sections(code_object)
  {
    owner: "\n#{bold('Owner:')} #{code_object.owner || 'N/A'}\n",
    visibility: "#{bold('Visibility:')} #{code_object.visibility}",
    signature: "\n#{bold('Signature:')} #{code_object.signature}"
  }.merge(header_options) { |_key, old, new| (new && old).to_s }
end

def module_header(code_object, line_num)

def module_header(code_object, line_num)
  h = ""
  h += ":#{line_num}\n"
  h += bold(code_object.module? ? "Module" : "Class")
  h += " #{bold('name:')} #{code_object.nonblank_name}"
  if code_object.number_of_candidates > 1
    h += bold("\nNumber of monkeypatches: ")
    h += code_object.number_of_candidates.to_s
    h += ". Use the `-a` option to display all available monkeypatches"
  end
  h
end

def no_definition_message

def no_definition_message
  "Couldn't locate a definition for #{obj_name}"
end

def obj_name

def obj_name
  @obj_name ||= args.empty? ? nil : args.join(' ')
end

def options(opt)

def options(opt)
  opt.on :s, :super, "Select the 'super' method. Can be repeated to " \
                     "traverse the ancestors", as: :count
  opt.on :l, "line-numbers", "Show line numbers"
  opt.on :b, "base-one", "Show line numbers but start numbering at 1 " \
                         "(useful for `amend-line` and `play` commands)"
  opt.on :a, :all, "Show all definitions and monkeypatches of the " \
                   "module/class"
end

def process

def process
  code_object = Pry::CodeObject.lookup(obj_name, pry_instance, super: opts[:super])
  raise CommandError, no_definition_message unless code_object
  @original_code_object = code_object
  if !obj_name && code_object.c_module? && !opts[:all]
    result = "You're inside an object, whose class is defined by means of " \
             "the C Ruby API.\nPry cannot display the information for this " \
             "class."
    if code_object.candidates.any?
      result += "\nHowever, you can view monkey-patches applied to this " \
                "class.\n.Just execute the same command with the '--all' " \
                "switch."
    end
  elsif show_all_modules?(code_object)
    # show all monkey patches for a module
    result = content_and_headers_for_all_module_candidates(code_object)
  else
    # show a specific code object
    co = code_object_with_accessible_source(code_object)
    result = content_and_header_for_code_object(co)
  end
  set_file_and_dir_locals(code_object.source_file)
  pry_instance.pager.page result
end

def show_all_modules?(code_object)

def show_all_modules?(code_object)
  code_object.is_a?(Pry::WrappedModule) && opts.present?(:all)
end

def start_line_for(code_object)

def start_line_for(code_object)
  if opts.present?(:'base-one')
    1
  else
    code_object.source_line || 1
  end
end

def use_line_numbers?

def use_line_numbers?
  opts.present?(:b) || opts.present?(:l)
end

def valid_superclass?(code_object)

def valid_superclass?(code_object)
  code_object.super && code_object.super.wrapped != Object
end