# frozen_string_literal: trueclassPryclassCommandclassShowInfo<Pry::ClassCommandextendPry::Helpers::BaseHelperscommand_optionsshellwords: false,interpolate: falsedefinitialize(*)super@used_super=nilenddefoptions(opt)opt.on:s,:super,"Select the 'super' method. Can be repeated to "\"traverse the ancestors",as: :countopt.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"enddefprocesscode_object=Pry::CodeObject.lookup(obj_name,pry_instance,super: opts[:super])raiseCommandError,no_definition_messageunlesscode_object@original_code_object=code_objectif!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."ifcode_object.candidates.any?result+="\nHowever, you can view monkey-patches applied to this "\"class.\n.Just execute the same command with the '--all' "\"switch."endelsifshow_all_modules?(code_object)# show all monkey patches for a moduleresult=content_and_headers_for_all_module_candidates(code_object)else# show a specific code objectco=code_object_with_accessible_source(code_object)result=content_and_header_for_code_object(co)endset_file_and_dir_locals(code_object.source_file)pry_instance.pager.pageresultend# This method checks whether the `code_object` is a WrappedModule, if it# is, then it returns the first candidate (monkeypatch) with accessible# source (or docs). If `code_object` is not a WrappedModule (i.e a method# or a command) then the `code_object` itself is just returned.## @return [Pry::WrappedModule, Pry::Method, Pry::Command]defcode_object_with_accessible_source(code_object)returncode_objectunlesscode_object.is_a?(WrappedModule)candidate=code_object.candidates.find(&:source)returncandidateifcandidateraiseCommandError,no_definition_messageunlessvalid_superclass?(code_object)@used_super=truecode_object_with_accessible_source(code_object.super)enddefvalid_superclass?(code_object)code_object.super&&code_object.super.wrapped!=Objectenddefcontent_and_header_for_code_object(code_object)header(code_object)+content_for(code_object)enddefcontent_and_headers_for_all_module_candidates(mod)result="Found #{mod.number_of_candidates} candidates for "\"`#{mod.name}` definition:\n"mod.number_of_candidates.timesdo|v|candidate=mod.candidate(v)beginresult+="\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"+contentrescuePry::RescuableExceptionresult+="\nNo content found.\n"nextendendresultenddefno_definition_message"Couldn't locate a definition for #{obj_name}"end# Generate a header (meta-data information) for all the code# object types: methods, modules, commands, procs...defheader(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_superh+=bold('** Warning:')h+=" Cannot find code for #{@original_code_object.nonblank_name}. "\"Showing superclass #{code_object.nonblank_name} instead. **\n\n"endifcontent.lines.none?h+=bold('** Warning:')h+=" Cannot find code for '#{code_object.name}' (source_location is nil)"endhenddefcode_object_header(code_object,line_num)ifcode_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.elsifcode_object.is_a?(Pry::WrappedModule)||code_object.is_a?(Pry::WrappedModule::Candidate)module_header(code_object,line_num)else""endenddefmethod_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]henddefmodule_header(code_object,line_num)h=""h+=":#{line_num}\n"h+=bold(code_object.module??"Module":"Class")h+=" #{bold('name:')}#{code_object.nonblank_name}"ifcode_object.number_of_candidates>1h+=bold("\nNumber of monkeypatches: ")h+=code_object.number_of_candidates.to_sh+=". Use the `-a` option to display all available monkeypatches"endhenddefmethod_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}enddefheader_options{owner: true,visibility: true,signature: nil}enddefshow_all_modules?(code_object)code_object.is_a?(Pry::WrappedModule)&&opts.present?(:all)enddefobj_name@obj_name||=args.empty??nil:args.join(' ')enddefuse_line_numbers?opts.present?(:b)||opts.present?(:l)enddefstart_line_for(code_object)ifopts.present?(:'base-one')1elsecode_object.source_line||1endend# takes into account possible yard docs, and returns yard_file / yard_line# Also adjusts for start line of comments (using start_line_for), which it# has to infer by subtracting number of lines of comment from start line# of code_objectdeffile_and_line_for(code_object)ifcode_object.module_with_yard_docs?[code_object.yard_file,code_object.yard_line]else[code_object.source_file,start_line_for(code_object)]endenddefcomplete(input)ifinput=~/([^ ]*)#([a-z0-9_]*)\z/prefix=Regexp.last_match(1)search=Regexp.last_match(2)methods=begin# rubocop:disable Security/EvalPry::Method.all_from_class(binding.eval(prefix))# rubocop:enable Security/EvalrescueRescuableExceptionreturnsuperendmethods.mapdo|method|[prefix,method.name].join('#')ifmethod.name.start_with?(search)end.compactelsesuperendendendendend