pry 0.10.0.pre2-universal-mswin32

Sign up to get free protection for your applications and to get access to all the features.
Files changed (131) hide show
  1. checksums.yaml +7 -0
  2. data/CHANGELOG.md +702 -0
  3. data/LICENSE +25 -0
  4. data/README.md +406 -0
  5. data/bin/pry +16 -0
  6. data/lib/pry.rb +161 -0
  7. data/lib/pry/cli.rb +220 -0
  8. data/lib/pry/code.rb +346 -0
  9. data/lib/pry/code/code_file.rb +103 -0
  10. data/lib/pry/code/code_range.rb +71 -0
  11. data/lib/pry/code/loc.rb +92 -0
  12. data/lib/pry/code_object.rb +172 -0
  13. data/lib/pry/color_printer.rb +55 -0
  14. data/lib/pry/command.rb +692 -0
  15. data/lib/pry/command_set.rb +443 -0
  16. data/lib/pry/commands.rb +6 -0
  17. data/lib/pry/commands/amend_line.rb +99 -0
  18. data/lib/pry/commands/bang.rb +20 -0
  19. data/lib/pry/commands/bang_pry.rb +17 -0
  20. data/lib/pry/commands/cat.rb +62 -0
  21. data/lib/pry/commands/cat/abstract_formatter.rb +27 -0
  22. data/lib/pry/commands/cat/exception_formatter.rb +77 -0
  23. data/lib/pry/commands/cat/file_formatter.rb +67 -0
  24. data/lib/pry/commands/cat/input_expression_formatter.rb +43 -0
  25. data/lib/pry/commands/cd.rb +41 -0
  26. data/lib/pry/commands/change_inspector.rb +27 -0
  27. data/lib/pry/commands/change_prompt.rb +26 -0
  28. data/lib/pry/commands/code_collector.rb +165 -0
  29. data/lib/pry/commands/disable_pry.rb +27 -0
  30. data/lib/pry/commands/disabled_commands.rb +2 -0
  31. data/lib/pry/commands/easter_eggs.rb +112 -0
  32. data/lib/pry/commands/edit.rb +195 -0
  33. data/lib/pry/commands/edit/exception_patcher.rb +25 -0
  34. data/lib/pry/commands/edit/file_and_line_locator.rb +36 -0
  35. data/lib/pry/commands/exit.rb +42 -0
  36. data/lib/pry/commands/exit_all.rb +29 -0
  37. data/lib/pry/commands/exit_program.rb +23 -0
  38. data/lib/pry/commands/find_method.rb +193 -0
  39. data/lib/pry/commands/fix_indent.rb +19 -0
  40. data/lib/pry/commands/gem_cd.rb +26 -0
  41. data/lib/pry/commands/gem_install.rb +32 -0
  42. data/lib/pry/commands/gem_list.rb +33 -0
  43. data/lib/pry/commands/gem_open.rb +29 -0
  44. data/lib/pry/commands/gist.rb +101 -0
  45. data/lib/pry/commands/help.rb +164 -0
  46. data/lib/pry/commands/hist.rb +180 -0
  47. data/lib/pry/commands/import_set.rb +22 -0
  48. data/lib/pry/commands/install_command.rb +53 -0
  49. data/lib/pry/commands/jump_to.rb +29 -0
  50. data/lib/pry/commands/list_inspectors.rb +35 -0
  51. data/lib/pry/commands/list_prompts.rb +35 -0
  52. data/lib/pry/commands/ls.rb +114 -0
  53. data/lib/pry/commands/ls/constants.rb +47 -0
  54. data/lib/pry/commands/ls/formatter.rb +49 -0
  55. data/lib/pry/commands/ls/globals.rb +48 -0
  56. data/lib/pry/commands/ls/grep.rb +21 -0
  57. data/lib/pry/commands/ls/instance_vars.rb +39 -0
  58. data/lib/pry/commands/ls/interrogatable.rb +18 -0
  59. data/lib/pry/commands/ls/jruby_hacks.rb +49 -0
  60. data/lib/pry/commands/ls/local_names.rb +35 -0
  61. data/lib/pry/commands/ls/local_vars.rb +39 -0
  62. data/lib/pry/commands/ls/ls_entity.rb +70 -0
  63. data/lib/pry/commands/ls/methods.rb +57 -0
  64. data/lib/pry/commands/ls/methods_helper.rb +46 -0
  65. data/lib/pry/commands/ls/self_methods.rb +32 -0
  66. data/lib/pry/commands/nesting.rb +25 -0
  67. data/lib/pry/commands/play.rb +103 -0
  68. data/lib/pry/commands/pry_backtrace.rb +25 -0
  69. data/lib/pry/commands/pry_version.rb +17 -0
  70. data/lib/pry/commands/raise_up.rb +32 -0
  71. data/lib/pry/commands/reload_code.rb +62 -0
  72. data/lib/pry/commands/reset.rb +18 -0
  73. data/lib/pry/commands/ri.rb +60 -0
  74. data/lib/pry/commands/save_file.rb +61 -0
  75. data/lib/pry/commands/shell_command.rb +48 -0
  76. data/lib/pry/commands/shell_mode.rb +25 -0
  77. data/lib/pry/commands/show_doc.rb +83 -0
  78. data/lib/pry/commands/show_info.rb +195 -0
  79. data/lib/pry/commands/show_input.rb +17 -0
  80. data/lib/pry/commands/show_source.rb +50 -0
  81. data/lib/pry/commands/simple_prompt.rb +22 -0
  82. data/lib/pry/commands/stat.rb +40 -0
  83. data/lib/pry/commands/switch_to.rb +23 -0
  84. data/lib/pry/commands/toggle_color.rb +24 -0
  85. data/lib/pry/commands/watch_expression.rb +105 -0
  86. data/lib/pry/commands/watch_expression/expression.rb +38 -0
  87. data/lib/pry/commands/whereami.rb +190 -0
  88. data/lib/pry/commands/wtf.rb +57 -0
  89. data/lib/pry/config.rb +24 -0
  90. data/lib/pry/config/behavior.rb +139 -0
  91. data/lib/pry/config/convenience.rb +26 -0
  92. data/lib/pry/config/default.rb +165 -0
  93. data/lib/pry/core_extensions.rb +131 -0
  94. data/lib/pry/editor.rb +133 -0
  95. data/lib/pry/exceptions.rb +77 -0
  96. data/lib/pry/helpers.rb +5 -0
  97. data/lib/pry/helpers/base_helpers.rb +113 -0
  98. data/lib/pry/helpers/command_helpers.rb +156 -0
  99. data/lib/pry/helpers/documentation_helpers.rb +75 -0
  100. data/lib/pry/helpers/options_helpers.rb +27 -0
  101. data/lib/pry/helpers/table.rb +109 -0
  102. data/lib/pry/helpers/text.rb +107 -0
  103. data/lib/pry/history.rb +125 -0
  104. data/lib/pry/history_array.rb +121 -0
  105. data/lib/pry/hooks.rb +230 -0
  106. data/lib/pry/indent.rb +406 -0
  107. data/lib/pry/input_completer.rb +242 -0
  108. data/lib/pry/input_lock.rb +132 -0
  109. data/lib/pry/inspector.rb +27 -0
  110. data/lib/pry/last_exception.rb +61 -0
  111. data/lib/pry/method.rb +546 -0
  112. data/lib/pry/method/disowned.rb +53 -0
  113. data/lib/pry/method/patcher.rb +125 -0
  114. data/lib/pry/method/weird_method_locator.rb +186 -0
  115. data/lib/pry/module_candidate.rb +136 -0
  116. data/lib/pry/object_path.rb +82 -0
  117. data/lib/pry/output.rb +50 -0
  118. data/lib/pry/pager.rb +234 -0
  119. data/lib/pry/plugins.rb +103 -0
  120. data/lib/pry/prompt.rb +26 -0
  121. data/lib/pry/pry_class.rb +375 -0
  122. data/lib/pry/pry_instance.rb +654 -0
  123. data/lib/pry/rbx_path.rb +22 -0
  124. data/lib/pry/repl.rb +202 -0
  125. data/lib/pry/repl_file_loader.rb +74 -0
  126. data/lib/pry/rubygem.rb +82 -0
  127. data/lib/pry/terminal.rb +79 -0
  128. data/lib/pry/test/helper.rb +170 -0
  129. data/lib/pry/version.rb +3 -0
  130. data/lib/pry/wrapped_module.rb +373 -0
  131. metadata +248 -0
@@ -0,0 +1,32 @@
1
+ class Pry
2
+ # N.B. using a regular expresion here so that "raise-up 'foo'" does the right thing.
3
+ class Command::RaiseUp < Pry::ClassCommand
4
+ match(/raise-up(!?\b.*)/)
5
+ group 'Context'
6
+ description 'Raise an exception out of the current pry instance.'
7
+ command_options :listing => 'raise-up'
8
+
9
+ banner <<-BANNER
10
+ Raise up, like exit, allows you to quit pry. Instead of returning a value
11
+ however, it raises an exception. If you don't provide the exception to be
12
+ raised, it will use the most recent exception (in pry `_ex_`).
13
+
14
+ When called as raise-up! (with an exclamation mark), this command raises the
15
+ exception through any nested prys you have created by "cd"ing into objects.
16
+
17
+ raise-up "get-me-out-of-here"
18
+
19
+ # This is equivalent to the command above.
20
+ raise "get-me-out-of-here"
21
+ raise-up
22
+ BANNER
23
+
24
+ def process
25
+ return _pry.pager.page help if captures[0] =~ /(-h|--help)\b/
26
+ # Handle 'raise-up', 'raise-up "foo"', 'raise-up RuntimeError, 'farble' in a rubyesque manner
27
+ target.eval("_pry_.raise_up#{captures[0]}")
28
+ end
29
+ end
30
+
31
+ Pry::Commands.add_command(Pry::Command::RaiseUp)
32
+ end
@@ -0,0 +1,62 @@
1
+ class Pry
2
+ class Command::ReloadCode < Pry::ClassCommand
3
+ match 'reload-code'
4
+ group 'Misc'
5
+ description 'Reload the source file that contains the specified code object.'
6
+
7
+ banner <<-'BANNER'
8
+ Reload the source file that contains the specified code object.
9
+
10
+ e.g reload-code MyClass#my_method #=> reload a method
11
+ reload-code MyClass #=> reload a class
12
+ reload-code my-command #=> reload a pry command
13
+ reload-code self #=> reload the current object
14
+ reload-code #=> reload the current file or object
15
+ BANNER
16
+
17
+ def process
18
+ if !args.empty?
19
+ reload_object(args.join(" "))
20
+ elsif internal_binding?(target)
21
+ reload_object("self")
22
+ else
23
+ reload_current_file
24
+ end
25
+ end
26
+
27
+ private
28
+
29
+ def current_file
30
+ File.expand_path target.eval("__FILE__")
31
+ end
32
+
33
+ def reload_current_file
34
+ if !File.exists?(current_file)
35
+ raise CommandError, "Current file: #{current_file} cannot be found on disk!"
36
+ end
37
+
38
+ load current_file
39
+ output.puts "The current file: #{current_file} was reloaded!"
40
+ end
41
+
42
+ def reload_object(identifier)
43
+ code_object = Pry::CodeObject.lookup(identifier, _pry_)
44
+ check_for_reloadability(code_object, identifier)
45
+ load code_object.source_file
46
+ output.puts "#{identifier} was reloaded!"
47
+ end
48
+
49
+ def check_for_reloadability(code_object, identifier)
50
+ if !code_object || !code_object.source_file
51
+ raise CommandError, "Cannot locate #{identifier}!"
52
+ elsif !File.exists?(code_object.source_file)
53
+ raise CommandError,
54
+ "Cannot reload #{identifier} as it has no associated file on disk. " \
55
+ "File found was: #{code_object.source_file}"
56
+ end
57
+ end
58
+ end
59
+
60
+ Pry::Commands.add_command(Pry::Command::ReloadCode)
61
+ Pry::Commands.alias_command 'reload-method', 'reload-code'
62
+ end
@@ -0,0 +1,18 @@
1
+ class Pry
2
+ class Command::Reset < Pry::ClassCommand
3
+ match 'reset'
4
+ group 'Context'
5
+ description 'Reset the REPL to a clean state.'
6
+
7
+ banner <<-'BANNER'
8
+ Reset the REPL to a clean state.
9
+ BANNER
10
+
11
+ def process
12
+ output.puts 'Pry reset.'
13
+ exec 'pry'
14
+ end
15
+ end
16
+
17
+ Pry::Commands.add_command(Pry::Command::Reset)
18
+ end
@@ -0,0 +1,60 @@
1
+ class Pry
2
+ class Command::Ri < Pry::ClassCommand
3
+ match 'ri'
4
+ group 'Introspection'
5
+ description 'View ri documentation.'
6
+
7
+ banner <<-'BANNER'
8
+ Usage: ri [spec]
9
+
10
+ View ri documentation. Relies on the "rdoc" gem being installed.
11
+ See also "show-doc" command.
12
+
13
+ ri Array#each
14
+ BANNER
15
+
16
+ def process(spec)
17
+ # Lazily load RI
18
+ require 'rdoc/ri/driver'
19
+
20
+ unless defined? RDoc::RI::PryDriver
21
+
22
+ # Subclass RI so that it formats its output nicely, and uses `lesspipe`.
23
+ subclass = Class.new(RDoc::RI::Driver) # the hard way.
24
+
25
+ subclass.class_eval do
26
+ def initialize(pager, opts)
27
+ @pager = pager
28
+ super opts
29
+ end
30
+ def page
31
+ paging_text = StringIO.new
32
+ yield paging_text
33
+ @pager.page(paging_text.string)
34
+ end
35
+
36
+ def formatter(io)
37
+ if @formatter_klass
38
+ @formatter_klass.new
39
+ else
40
+ RDoc::Markup::ToAnsi.new
41
+ end
42
+ end
43
+ end
44
+
45
+ RDoc::RI.const_set :PryDriver, subclass # hook it up!
46
+ end
47
+
48
+ # Spin-up an RI insance.
49
+ ri = RDoc::RI::PryDriver.new _pry_.pager, :use_stdout => true, :interactive => false
50
+
51
+ begin
52
+ ri.display_names [spec] # Get the documentation (finally!)
53
+ rescue RDoc::RI::Driver::NotFoundError => e
54
+ output.puts "error: '#{e.name}' not found"
55
+ end
56
+ end
57
+ end
58
+
59
+ Pry::Commands.add_command(Pry::Command::Ri)
60
+ end
@@ -0,0 +1,61 @@
1
+ require 'pry/commands/code_collector'
2
+
3
+ class Pry
4
+ class Command::SaveFile < Pry::ClassCommand
5
+ match 'save-file'
6
+ group 'Input and Output'
7
+ description 'Export to a file using content from the REPL.'
8
+
9
+ banner <<-'BANNER'
10
+ Usage: save-file [OPTIONS] --to [FILE]
11
+
12
+ Export to a file using content from the REPL.
13
+
14
+ save-file my_method --to hello.rb
15
+ save-file -i 1..10 --to hello.rb --append
16
+ save-file show-method --to my_command.rb
17
+ save-file sample_file.rb --lines 2..10 --to output_file.rb
18
+ BANNER
19
+
20
+ def options(opt)
21
+ CodeCollector.inject_options(opt)
22
+
23
+ opt.on :to=, "Specify the output file path"
24
+ opt.on :a, :append, "Append output to file"
25
+ end
26
+
27
+ def process
28
+ @cc = CodeCollector.new(args, opts, _pry_)
29
+ raise CommandError, "Found no code to save." if @cc.content.empty?
30
+
31
+ if !file_name
32
+ display_content
33
+ else
34
+ save_file
35
+ end
36
+ end
37
+
38
+ def file_name
39
+ opts[:to] || nil
40
+ end
41
+
42
+ def save_file
43
+ File.open(file_name, mode) do |f|
44
+ f.puts @cc.content
45
+ end
46
+ output.puts "#{file_name} successfully saved"
47
+ end
48
+
49
+ def display_content
50
+ output.puts @cc.content
51
+ output.puts "\n\n--\nPlease use `--to FILE` to export to a file."
52
+ output.puts "No file saved!\n--"
53
+ end
54
+
55
+ def mode
56
+ opts.present?(:append) ? "a" : "w"
57
+ end
58
+ end
59
+
60
+ Pry::Commands.add_command(Pry::Command::SaveFile)
61
+ end
@@ -0,0 +1,48 @@
1
+ class Pry
2
+ class Command::ShellCommand < Pry::ClassCommand
3
+ match(/\.(.*)/)
4
+ group 'Input and Output'
5
+ description "All text following a '.' is forwarded to the shell."
6
+ command_options :listing => '.<shell command>', :use_prefix => false,
7
+ :takes_block => true
8
+
9
+ banner <<-'BANNER'
10
+ Usage: .COMMAND_NAME
11
+
12
+ All text following a "." is forwarded to the shell.
13
+
14
+ .ls -aF
15
+ .uname
16
+ BANNER
17
+
18
+ def process(cmd)
19
+ if cmd =~ /^cd\s*(.*)/i
20
+ process_cd parse_destination($1)
21
+ else
22
+ pass_block(cmd)
23
+ if command_block
24
+ command_block.call `#{cmd}`
25
+ else
26
+ _pry_.config.system.call(output, cmd, _pry_)
27
+ end
28
+ end
29
+ end
30
+
31
+ private
32
+
33
+ def parse_destination(dest)
34
+ return "~" if dest.empty?
35
+ return dest unless dest == "-"
36
+ state.old_pwd || raise(CommandError, "No prior directory available")
37
+ end
38
+
39
+ def process_cd(dest)
40
+ state.old_pwd = Dir.pwd
41
+ Dir.chdir File.expand_path(dest)
42
+ rescue Errno::ENOENT
43
+ raise CommandError, "No such directory: #{dest}"
44
+ end
45
+ end
46
+
47
+ Pry::Commands.add_command(Pry::Command::ShellCommand)
48
+ end
@@ -0,0 +1,25 @@
1
+ class Pry
2
+ class Command::ShellMode < Pry::ClassCommand
3
+ match 'shell-mode'
4
+ group 'Input and Output'
5
+ description 'Toggle shell mode. Bring in pwd prompt and file completion.'
6
+
7
+ banner <<-'BANNER'
8
+ Toggle shell mode. Bring in pwd prompt and file completion.
9
+ BANNER
10
+
11
+ def process
12
+ case _pry_.prompt
13
+ when Pry::SHELL_PROMPT
14
+ _pry_.pop_prompt
15
+ _pry_.custom_completions = _pry_.config.file_completions
16
+ else
17
+ _pry_.push_prompt Pry::SHELL_PROMPT
18
+ _pry_.custom_completions = _pry_.config.command_completions
19
+ end
20
+ end
21
+ end
22
+
23
+ Pry::Commands.add_command(Pry::Command::ShellMode)
24
+ Pry::Commands.alias_command 'file-mode', 'shell-mode'
25
+ end
@@ -0,0 +1,83 @@
1
+ require 'pry/commands/show_info'
2
+
3
+ class Pry
4
+ class Command::ShowDoc < Command::ShowInfo
5
+ include Pry::Helpers::DocumentationHelpers
6
+
7
+ match 'show-doc'
8
+ group 'Introspection'
9
+ description 'Show the documentation for a method or class.'
10
+
11
+ banner <<-BANNER
12
+ Usage: show-doc [OPTIONS] [METH]
13
+ Aliases: ?
14
+
15
+ Show the documentation for a method or class. Tries instance methods first and
16
+ then methods by default.
17
+
18
+ show-doc hi_method # docs for hi_method
19
+ show-doc Pry # for Pry class
20
+ show-doc Pry -a # for all definitions of Pry class (all monkey patches)
21
+ BANNER
22
+
23
+ # The docs for code_object prepared for display.
24
+ def content_for(code_object)
25
+ Code.new(render_doc_markup_for(code_object),
26
+ start_line_for(code_object), :text).
27
+ with_line_numbers(use_line_numbers?).to_s
28
+ end
29
+
30
+ # process the markup (if necessary) and apply colors
31
+ def render_doc_markup_for(code_object)
32
+ docs = docs_for(code_object)
33
+
34
+ if code_object.command?
35
+ # command '--help' shouldn't use markup highlighting
36
+ docs
37
+ else
38
+ if docs.empty?
39
+ raise CommandError, "No docs found for: #{
40
+ obj_name ? obj_name : 'current context'
41
+ }"
42
+ end
43
+ process_comment_markup(docs)
44
+ end
45
+ end
46
+
47
+ # Return docs for the code_object, adjusting for whether the code_object
48
+ # has yard docs available, in which case it returns those.
49
+ # (note we only have to check yard docs for modules since they can
50
+ # have multiple docs, but methods can only be doc'd once so we
51
+ # dont need to check them)
52
+ def docs_for(code_object)
53
+ if code_object.module_with_yard_docs?
54
+ # yard docs
55
+ code_object.yard_doc
56
+ else
57
+ # normal docs (i.e comments above method/module/command)
58
+ code_object.doc
59
+ end
60
+ end
61
+
62
+ # Which sections to include in the 'header', can toggle: :owner,
63
+ # :signature and visibility.
64
+ def header_options
65
+ super.merge :signature => true
66
+ end
67
+
68
+ # figure out start line of docs by back-calculating based on
69
+ # number of lines in the comment and the start line of the code_object
70
+ # @return [Fixnum] start line of docs
71
+ def start_line_for(code_object)
72
+ if code_object.command? || opts.present?(:'base-one')
73
+ 1
74
+ else
75
+ code_object.source_line.nil? ? 1 :
76
+ (code_object.source_line - code_object.doc.lines.count)
77
+ end
78
+ end
79
+ end
80
+
81
+ Pry::Commands.add_command(Pry::Command::ShowDoc)
82
+ Pry::Commands.alias_command '?', 'show-doc'
83
+ end
@@ -0,0 +1,195 @@
1
+ class Pry
2
+ class Command::ShowInfo < Pry::ClassCommand
3
+ extend Pry::Helpers::BaseHelpers
4
+
5
+ command_options :shellwords => false, :interpolate => false
6
+
7
+ def options(opt)
8
+ opt.on :s, :super, "Select the 'super' method. Can be repeated to traverse the ancestors", :as => :count
9
+ opt.on :l, "line-numbers", "Show line numbers"
10
+ opt.on :b, "base-one", "Show line numbers but start numbering at 1 (useful for `amend-line` and `play` commands)"
11
+ opt.on :a, :all, "Show all definitions and monkeypatches of the module/class"
12
+ end
13
+
14
+ def process
15
+ code_object = Pry::CodeObject.lookup(obj_name, _pry_, :super => opts[:super])
16
+ raise CommandError, no_definition_message if !code_object
17
+ @original_code_object = code_object
18
+
19
+ if show_all_modules?(code_object)
20
+ # show all monkey patches for a module
21
+
22
+ result = content_and_headers_for_all_module_candidates(code_object)
23
+ else
24
+ # show a specific code object
25
+ co = code_object_with_accessible_source(code_object)
26
+ result = content_and_header_for_code_object(co)
27
+ end
28
+
29
+ set_file_and_dir_locals(code_object.source_file)
30
+ _pry_.pager.page result
31
+ end
32
+
33
+ # This method checks whether the `code_object` is a WrappedModule,
34
+ # if it is, then it returns the first candidate (monkeypatch) with
35
+ # accessible source (or docs). If `code_object` is not a WrappedModule (i.e a
36
+ # method or a command) then the `code_object` itself is just
37
+ # returned.
38
+ #
39
+ # @return [Pry::WrappedModule, Pry::Method, Pry::Command]
40
+ def code_object_with_accessible_source(code_object)
41
+ if code_object.is_a?(WrappedModule)
42
+ candidate = code_object.candidates.find(&:source)
43
+ if candidate
44
+ return candidate
45
+ else
46
+ raise CommandError, no_definition_message if !valid_superclass?(code_object)
47
+
48
+ @used_super = true
49
+ code_object_with_accessible_source(code_object.super)
50
+ end
51
+ else
52
+ code_object
53
+ end
54
+ end
55
+
56
+ def valid_superclass?(code_object)
57
+ code_object.super && code_object.super.wrapped != Object
58
+ end
59
+
60
+ def content_and_header_for_code_object(code_object)
61
+ header(code_object) << content_for(code_object)
62
+ end
63
+
64
+ def content_and_headers_for_all_module_candidates(mod)
65
+ result = "Found #{mod.number_of_candidates} candidates for `#{mod.name}` definition:\n"
66
+ mod.number_of_candidates.times do |v|
67
+ candidate = mod.candidate(v)
68
+ begin
69
+ result << "\nCandidate #{v+1}/#{mod.number_of_candidates}: #{candidate.source_file} @ line #{candidate.source_line}:\n"
70
+ content = content_for(candidate)
71
+
72
+ result << "Number of lines: #{content.lines.count}\n\n" << content
73
+ rescue Pry::RescuableException
74
+ result << "\nNo content found.\n"
75
+ next
76
+ end
77
+ end
78
+ result
79
+ end
80
+
81
+ def no_definition_message
82
+ "Couldn't locate a definition for #{obj_name}!"
83
+ end
84
+
85
+ # Generate a header (meta-data information) for all the code
86
+ # object types: methods, modules, commands, procs...
87
+ def header(code_object)
88
+ file_name, line_num = file_and_line_for(code_object)
89
+ h = "\n#{Pry::Helpers::Text.bold('From:')} #{file_name} "
90
+ h << code_object_header(code_object, line_num)
91
+ h << "\n#{Pry::Helpers::Text.bold('Number of lines:')} " <<
92
+ "#{content_for(code_object).lines.count}\n\n"
93
+ h << Helpers::Text.bold('** Warning:') << " Cannot find code for #{@original_code_object.nonblank_name}. Showing superclass #{code_object.nonblank_name} instead. **\n\n" if @used_super
94
+ h
95
+ end
96
+
97
+ def code_object_header(code_object, line_num)
98
+ if code_object.real_method_object?
99
+ method_header(code_object, line_num)
100
+
101
+ # It sucks we have to test for both Pry::WrappedModule and WrappedModule::Candidate,
102
+ # probably indicates a deep refactor needs to happen in those classes.
103
+ elsif code_object.is_a?(Pry::WrappedModule) || code_object.is_a?(Pry::WrappedModule::Candidate)
104
+ module_header(code_object, line_num)
105
+ else
106
+ ""
107
+ end
108
+ end
109
+
110
+ def method_header(code_object, line_num)
111
+ h = ""
112
+ h << (code_object.c_method? ? "(C Method):" : "@ line #{line_num}:")
113
+ h << method_sections(code_object)[:owner]
114
+ h << method_sections(code_object)[:visibility]
115
+ h << method_sections(code_object)[:signature]
116
+ h
117
+ end
118
+
119
+ def module_header(code_object, line_num)
120
+ h = ""
121
+ h << "@ line #{line_num}:\n"
122
+ h << text.bold(code_object.module? ? "Module" : "Class")
123
+ h << " #{text.bold('name:')} #{code_object.nonblank_name}"
124
+
125
+ if code_object.number_of_candidates > 1
126
+ h << (text.bold("\nNumber of monkeypatches: ") << code_object.number_of_candidates.to_s)
127
+ h << ". Use the `-a` option to display all available monkeypatches"
128
+ end
129
+ h
130
+ end
131
+
132
+ def method_sections(code_object)
133
+ {
134
+ :owner => "\n#{text.bold("Owner:")} #{code_object.owner || "N/A"}\n",
135
+ :visibility => "#{text.bold("Visibility:")} #{code_object.visibility}",
136
+ :signature => "\n#{text.bold("Signature:")} #{code_object.signature}"
137
+ }.merge(header_options) { |key, old, new| (new && old).to_s }
138
+ end
139
+
140
+ def header_options
141
+ {
142
+ :owner => true,
143
+ :visibility => true,
144
+ :signature => nil
145
+ }
146
+ end
147
+
148
+ def show_all_modules?(code_object)
149
+ code_object.is_a?(Pry::WrappedModule) && opts.present?(:all)
150
+ end
151
+
152
+ def obj_name
153
+ @obj_name ||= args.empty? ? nil : args.join(' ')
154
+ end
155
+
156
+ def use_line_numbers?
157
+ opts.present?(:b) || opts.present?(:l)
158
+ end
159
+
160
+ def start_line_for(code_object)
161
+ if opts.present?(:'base-one')
162
+ 1
163
+ else
164
+ code_object.source_line || 1
165
+ end
166
+ end
167
+
168
+ # takes into account possible yard docs, and returns yard_file / yard_line
169
+ # Also adjusts for start line of comments (using start_line_for), which it has to infer
170
+ # by subtracting number of lines of comment from start line of code_object
171
+ def file_and_line_for(code_object)
172
+ if code_object.module_with_yard_docs?
173
+ [code_object.yard_file, code_object.yard_line]
174
+ else
175
+ [code_object.source_file, start_line_for(code_object)]
176
+ end
177
+ end
178
+
179
+ def complete(input)
180
+ if input =~ /([^ ]*)#([a-z0-9_]*)\z/
181
+ prefix, search = [$1, $2]
182
+ methods = begin
183
+ Pry::Method.all_from_class(binding.eval(prefix))
184
+ rescue RescuableException
185
+ return super
186
+ end
187
+ methods.map do |method|
188
+ [prefix, method.name].join('#') if method.name.start_with?(search)
189
+ end.compact
190
+ else
191
+ super
192
+ end
193
+ end
194
+ end
195
+ end