pry 0.10.4 → 0.14.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (159) hide show
  1. checksums.yaml +5 -5
  2. data/CHANGELOG.md +439 -16
  3. data/LICENSE +1 -1
  4. data/README.md +362 -302
  5. data/bin/pry +4 -7
  6. data/lib/pry/basic_object.rb +10 -0
  7. data/lib/pry/block_command.rb +22 -0
  8. data/lib/pry/class_command.rb +194 -0
  9. data/lib/pry/cli.rb +84 -97
  10. data/lib/pry/code/code_file.rb +37 -26
  11. data/lib/pry/code/code_range.rb +7 -5
  12. data/lib/pry/code/loc.rb +26 -13
  13. data/lib/pry/code.rb +41 -32
  14. data/lib/pry/code_object.rb +53 -28
  15. data/lib/pry/color_printer.rb +46 -35
  16. data/lib/pry/command.rb +197 -369
  17. data/lib/pry/command_set.rb +89 -114
  18. data/lib/pry/command_state.rb +31 -0
  19. data/lib/pry/commands/amend_line.rb +86 -82
  20. data/lib/pry/commands/bang.rb +18 -14
  21. data/lib/pry/commands/bang_pry.rb +15 -11
  22. data/lib/pry/commands/cat/abstract_formatter.rb +23 -18
  23. data/lib/pry/commands/cat/exception_formatter.rb +85 -72
  24. data/lib/pry/commands/cat/file_formatter.rb +56 -46
  25. data/lib/pry/commands/cat/input_expression_formatter.rb +35 -30
  26. data/lib/pry/commands/cat.rb +62 -54
  27. data/lib/pry/commands/cd.rb +40 -35
  28. data/lib/pry/commands/change_inspector.rb +29 -22
  29. data/lib/pry/commands/change_prompt.rb +48 -23
  30. data/lib/pry/commands/clear_screen.rb +20 -0
  31. data/lib/pry/commands/code_collector.rb +148 -131
  32. data/lib/pry/commands/disable_pry.rb +23 -19
  33. data/lib/pry/commands/easter_eggs.rb +23 -34
  34. data/lib/pry/commands/edit/exception_patcher.rb +21 -17
  35. data/lib/pry/commands/edit/file_and_line_locator.rb +34 -23
  36. data/lib/pry/commands/edit.rb +185 -157
  37. data/lib/pry/commands/exit.rb +40 -35
  38. data/lib/pry/commands/exit_all.rb +24 -20
  39. data/lib/pry/commands/exit_program.rb +20 -16
  40. data/lib/pry/commands/find_method.rb +168 -162
  41. data/lib/pry/commands/fix_indent.rb +16 -12
  42. data/lib/pry/commands/help.rb +140 -133
  43. data/lib/pry/commands/hist.rb +151 -149
  44. data/lib/pry/commands/import_set.rb +20 -15
  45. data/lib/pry/commands/jump_to.rb +25 -21
  46. data/lib/pry/commands/list_inspectors.rb +35 -28
  47. data/lib/pry/commands/ls/constants.rb +59 -31
  48. data/lib/pry/commands/ls/formatter.rb +42 -36
  49. data/lib/pry/commands/ls/globals.rb +38 -36
  50. data/lib/pry/commands/ls/grep.rb +17 -15
  51. data/lib/pry/commands/ls/instance_vars.rb +29 -28
  52. data/lib/pry/commands/ls/interrogatable.rb +18 -12
  53. data/lib/pry/commands/ls/jruby_hacks.rb +47 -41
  54. data/lib/pry/commands/ls/local_names.rb +26 -24
  55. data/lib/pry/commands/ls/local_vars.rb +38 -30
  56. data/lib/pry/commands/ls/ls_entity.rb +47 -52
  57. data/lib/pry/commands/ls/methods.rb +49 -51
  58. data/lib/pry/commands/ls/methods_helper.rb +46 -42
  59. data/lib/pry/commands/ls/self_methods.rb +23 -21
  60. data/lib/pry/commands/ls.rb +124 -103
  61. data/lib/pry/commands/nesting.rb +21 -17
  62. data/lib/pry/commands/play.rb +92 -82
  63. data/lib/pry/commands/pry_backtrace.rb +22 -17
  64. data/lib/pry/commands/pry_version.rb +15 -11
  65. data/lib/pry/commands/raise_up.rb +33 -27
  66. data/lib/pry/commands/reload_code.rb +60 -48
  67. data/lib/pry/commands/reset.rb +16 -12
  68. data/lib/pry/commands/ri.rb +57 -42
  69. data/lib/pry/commands/save_file.rb +45 -43
  70. data/lib/pry/commands/shell_command.rb +56 -29
  71. data/lib/pry/commands/shell_mode.rb +22 -18
  72. data/lib/pry/commands/show_doc.rb +80 -70
  73. data/lib/pry/commands/show_info.rb +193 -160
  74. data/lib/pry/commands/show_input.rb +16 -11
  75. data/lib/pry/commands/show_source.rb +110 -42
  76. data/lib/pry/commands/stat.rb +35 -31
  77. data/lib/pry/commands/switch_to.rb +21 -15
  78. data/lib/pry/commands/toggle_color.rb +20 -16
  79. data/lib/pry/commands/watch_expression/expression.rb +32 -27
  80. data/lib/pry/commands/watch_expression.rb +89 -84
  81. data/lib/pry/commands/whereami.rb +155 -146
  82. data/lib/pry/commands/wtf.rb +78 -40
  83. data/lib/pry/config/attributable.rb +22 -0
  84. data/lib/pry/config/lazy_value.rb +29 -0
  85. data/lib/pry/config/memoized_value.rb +34 -0
  86. data/lib/pry/config/value.rb +24 -0
  87. data/lib/pry/config.rb +310 -20
  88. data/lib/pry/control_d_handler.rb +28 -0
  89. data/lib/pry/core_extensions.rb +22 -9
  90. data/lib/pry/editor.rb +56 -34
  91. data/lib/pry/env.rb +18 -0
  92. data/lib/pry/exception_handler.rb +43 -0
  93. data/lib/pry/exceptions.rb +13 -18
  94. data/lib/pry/forwardable.rb +27 -0
  95. data/lib/pry/helpers/base_helpers.rb +20 -62
  96. data/lib/pry/helpers/command_helpers.rb +52 -62
  97. data/lib/pry/helpers/documentation_helpers.rb +21 -12
  98. data/lib/pry/helpers/options_helpers.rb +15 -8
  99. data/lib/pry/helpers/platform.rb +55 -0
  100. data/lib/pry/helpers/table.rb +44 -32
  101. data/lib/pry/helpers/text.rb +96 -85
  102. data/lib/pry/helpers.rb +3 -0
  103. data/lib/pry/history.rb +81 -55
  104. data/lib/pry/hooks.rb +60 -110
  105. data/lib/pry/indent.rb +74 -68
  106. data/lib/pry/input_completer.rb +199 -158
  107. data/lib/pry/input_lock.rb +7 -10
  108. data/lib/pry/inspector.rb +36 -24
  109. data/lib/pry/last_exception.rb +45 -45
  110. data/lib/pry/method/disowned.rb +19 -5
  111. data/lib/pry/method/patcher.rb +14 -8
  112. data/lib/pry/method/weird_method_locator.rb +79 -45
  113. data/lib/pry/method.rb +178 -124
  114. data/lib/pry/object_path.rb +37 -28
  115. data/lib/pry/output.rb +102 -16
  116. data/lib/pry/pager.rb +187 -177
  117. data/lib/pry/prompt.rb +213 -25
  118. data/lib/pry/pry_class.rb +119 -98
  119. data/lib/pry/pry_instance.rb +261 -224
  120. data/lib/pry/repl.rb +83 -29
  121. data/lib/pry/repl_file_loader.rb +27 -22
  122. data/lib/pry/ring.rb +89 -0
  123. data/lib/pry/slop/LICENSE +20 -0
  124. data/lib/pry/slop/commands.rb +190 -0
  125. data/lib/pry/slop/option.rb +210 -0
  126. data/lib/pry/slop.rb +672 -0
  127. data/lib/pry/syntax_highlighter.rb +26 -0
  128. data/lib/pry/system_command_handler.rb +17 -0
  129. data/lib/pry/testable/evalable.rb +24 -0
  130. data/lib/pry/testable/mockable.rb +22 -0
  131. data/lib/pry/testable/pry_tester.rb +88 -0
  132. data/lib/pry/testable/utility.rb +34 -0
  133. data/lib/pry/testable/variables.rb +52 -0
  134. data/lib/pry/testable.rb +68 -0
  135. data/lib/pry/version.rb +3 -1
  136. data/lib/pry/warning.rb +20 -0
  137. data/lib/pry/{module_candidate.rb → wrapped_module/candidate.rb} +34 -32
  138. data/lib/pry/wrapped_module.rb +67 -63
  139. data/lib/pry.rb +133 -149
  140. metadata +52 -63
  141. data/lib/pry/commands/disabled_commands.rb +0 -2
  142. data/lib/pry/commands/gem_cd.rb +0 -26
  143. data/lib/pry/commands/gem_install.rb +0 -32
  144. data/lib/pry/commands/gem_list.rb +0 -33
  145. data/lib/pry/commands/gem_open.rb +0 -29
  146. data/lib/pry/commands/gist.rb +0 -101
  147. data/lib/pry/commands/install_command.rb +0 -53
  148. data/lib/pry/commands/list_prompts.rb +0 -35
  149. data/lib/pry/commands/simple_prompt.rb +0 -22
  150. data/lib/pry/commands.rb +0 -6
  151. data/lib/pry/config/behavior.rb +0 -139
  152. data/lib/pry/config/convenience.rb +0 -25
  153. data/lib/pry/config/default.rb +0 -161
  154. data/lib/pry/history_array.rb +0 -121
  155. data/lib/pry/plugins.rb +0 -103
  156. data/lib/pry/rbx_path.rb +0 -22
  157. data/lib/pry/rubygem.rb +0 -82
  158. data/lib/pry/terminal.rb +0 -79
  159. data/lib/pry/test/helper.rb +0 -170
@@ -1,226 +1,237 @@
1
+ # frozen_string_literal: true
2
+
1
3
  # taken from irb
2
4
  # Implements tab completion for Readline in Pry
3
- class Pry::InputCompleter
4
- NUMERIC_REGEXP = /^(-?(0[dbo])?[0-9_]+(\.[0-9_]+)?([eE]-?[0-9]+)?)\.([^.]*)$/
5
- ARRAY_REGEXP = /^([^\]]*\])\.([^.]*)$/
6
- SYMBOL_REGEXP = /^(:[^:.]*)$/
7
- SYMBOL_METHOD_CALL_REGEXP = /^(:[^:.]+)\.([^.]*)$/
8
- REGEX_REGEXP = /^(\/[^\/]*\/)\.([^.]*)$/
9
- PROC_OR_HASH_REGEXP = /^([^\}]*\})\.([^.]*)$/
10
- TOPLEVEL_LOOKUP_REGEXP = /^::([A-Z][^:\.\(]*)$/
11
- CONSTANT_REGEXP = /^([A-Z][A-Za-z0-9]*)$/
12
- CONSTANT_OR_METHOD_REGEXP = /^([A-Z].*)::([^:.]*)$/
13
- HEX_REGEXP = /^(-?0x[0-9a-fA-F_]+)\.([^.]*)$/
14
- GLOBALVARIABLE_REGEXP = /^(\$[^.]*)$/
15
- VARIABLE_REGEXP = /^([^."].*)\.([^.]*)$/
16
-
17
- ReservedWords = [
18
- "BEGIN", "END",
19
- "alias", "and",
20
- "begin", "break",
21
- "case", "class",
22
- "def", "defined", "do",
23
- "else", "elsif", "end", "ensure",
24
- "false", "for",
25
- "if", "in",
26
- "module",
27
- "next", "nil", "not",
28
- "or",
29
- "redo", "rescue", "retry", "return",
30
- "self", "super",
31
- "then", "true",
32
- "undef", "unless", "until",
33
- "when", "while",
34
- "yield" ]
35
-
36
- Operators = [
37
- "%", "&", "*", "**", "+", "-", "/",
38
- "<", "<<", "<=", "<=>", "==", "===", "=~", ">", ">=", ">>",
39
- "[]", "[]=", "^", "!", "!=", "!~"
40
- ]
41
-
42
- WORD_ESCAPE_STR = " \t\n\"\\'`><=;|&{("
43
-
44
- def initialize(input, pry = nil)
45
- @pry = pry
46
- @input = input
47
- @input.basic_word_break_characters = WORD_ESCAPE_STR if @input.respond_to?(:basic_word_break_characters=)
48
- @input.completion_append_character = nil if @input.respond_to?(:completion_append_character=)
49
- end
5
+ class Pry
6
+ class InputCompleter
7
+ NUMERIC_REGEXP = /^(-?(0[dbo])?[0-9_]+(\.[0-9_]+)?([eE]-?[0-9]+)?)\.([^.]*)$/.freeze
8
+ ARRAY_REGEXP = /^([^\]]*\])\.([^.]*)$/.freeze
9
+ SYMBOL_REGEXP = /^(:[^:.]*)$/.freeze
10
+ SYMBOL_METHOD_CALL_REGEXP = /^(:[^:.]+)\.([^.]*)$/.freeze
11
+ REGEX_REGEXP = %r{^(/[^/]*/)\.([^.]*)$}.freeze
12
+ PROC_OR_HASH_REGEXP = /^([^\}]*\})\.([^.]*)$/.freeze
13
+ TOPLEVEL_LOOKUP_REGEXP = /^::([A-Z][^:\.\(]*)$/.freeze
14
+ CONSTANT_REGEXP = /^([A-Z][A-Za-z0-9]*)$/.freeze
15
+ CONSTANT_OR_METHOD_REGEXP = /^([A-Z].*)::([^:.]*)$/.freeze
16
+ HEX_REGEXP = /^(-?0x[0-9a-fA-F_]+)\.([^.]*)$/.freeze
17
+ GLOBALVARIABLE_REGEXP = /^(\$[^.]*)$/.freeze
18
+ VARIABLE_REGEXP = /^([^."].*)\.([^.]*)$/.freeze
50
19
 
51
- #
52
- # Return a new completion proc for use by Readline.
53
- #
54
- def call(str, options = {})
55
- custom_completions = options[:custom_completions] || []
56
- # if there are multiple contexts e.g. cd 1/2/3
57
- # get new target for 1/2 and find candidates for 3
58
- path, input = build_path(str)
59
-
60
- if path.call.empty?
61
- target = options[:target]
62
- else
63
- # Assume the user is tab-completing the 'cd' command
64
- begin
65
- target = Pry::ObjectPath.new(path.call, @pry.binding_stack).resolve.last
66
- # but if that doesn't work, assume they're doing division with no spaces
67
- rescue Pry::CommandError
68
- target = options[:target]
20
+ RESERVED_WORDS = %w[
21
+ BEGIN END
22
+ alias and
23
+ begin break
24
+ case class
25
+ def defined do
26
+ else elsif end ensure
27
+ false for
28
+ if in
29
+ module
30
+ next nil not
31
+ or
32
+ redo rescue retry return
33
+ self super
34
+ then true
35
+ undef unless until
36
+ when while
37
+ yield
38
+ ].freeze
39
+
40
+ WORD_ESCAPE_STR = " \t\n\"\\'`><=;|&{(".freeze
41
+
42
+ def initialize(input, pry = nil)
43
+ @pry = pry
44
+ @input = input
45
+ if @input.respond_to?(:basic_word_break_characters=)
46
+ @input.basic_word_break_characters = WORD_ESCAPE_STR
69
47
  end
48
+
49
+ return unless @input.respond_to?(:completion_append_character=)
50
+
51
+ @input.completion_append_character = nil
70
52
  end
71
53
 
72
- begin
73
- bind = target
74
- # Complete stdlib symbols
75
- case input
76
- when REGEX_REGEXP # Regexp
77
- receiver = $1
78
- message = Regexp.quote($2)
79
- candidates = Regexp.instance_methods.collect(&:to_s)
80
- select_message(path, receiver, message, candidates)
81
- when ARRAY_REGEXP # Array
82
- receiver = $1
83
- message = Regexp.quote($2)
84
- candidates = Array.instance_methods.collect(&:to_s)
85
- select_message(path, receiver, message, candidates)
86
- when PROC_OR_HASH_REGEXP # Proc or Hash
87
- receiver = $1
88
- message = Regexp.quote($2)
89
- candidates = Proc.instance_methods.collect(&:to_s)
90
- candidates |= Hash.instance_methods.collect(&:to_s)
91
- select_message(path, receiver, message, candidates)
92
- when SYMBOL_REGEXP # Symbol
93
- if Symbol.respond_to?(:all_symbols)
94
- sym = Regexp.quote($1)
95
- candidates = Symbol.all_symbols.collect{|s| ":" << s.id2name}
96
- candidates.grep(/^#{sym}/)
97
- else
98
- []
99
- end
100
- when TOPLEVEL_LOOKUP_REGEXP # Absolute Constant or class methods
101
- receiver = $1
102
- candidates = Object.constants.collect(&:to_s)
103
- candidates.grep(/^#{receiver}/).collect{|e| "::" << e}
104
- when CONSTANT_REGEXP # Constant
105
- message = $1
54
+ # Return a new completion proc for use by Readline.
55
+ # rubocop:disable Metrics/AbcSize, Metrics/MethodLength
56
+ def call(str, options = {})
57
+ custom_completions = options[:custom_completions] || []
58
+ # if there are multiple contexts e.g. cd 1/2/3
59
+ # get new target for 1/2 and find candidates for 3
60
+ path, input = build_path(str)
61
+
62
+ if path.call.empty?
63
+ target = options[:target]
64
+ else
65
+ # Assume the user is tab-completing the 'cd' command
106
66
  begin
107
- context = target.eval("self")
108
- context = context.class unless context.respond_to? :constants
109
- candidates = context.constants.collect(&:to_s)
110
- rescue
111
- candidates = []
112
- end
67
+ target = Pry::ObjectPath.new(path.call, @pry.binding_stack).resolve.last
68
+ # but if that doesn't work, assume they're doing division with no spaces
69
+ rescue Pry::CommandError
70
+ target = options[:target]
71
+ end
72
+ end
73
+
74
+ begin
75
+ bind = target
76
+ # Complete stdlib symbols
77
+ case input
78
+ when REGEX_REGEXP # Regexp
79
+ receiver = Regexp.last_match(1)
80
+ message = Regexp.quote(Regexp.last_match(2))
81
+ candidates = Regexp.instance_methods.collect(&:to_s)
82
+ select_message(path, receiver, message, candidates)
83
+ when ARRAY_REGEXP # Array
84
+ receiver = Regexp.last_match(1)
85
+ message = Regexp.quote(Regexp.last_match(2))
86
+ candidates = Array.instance_methods.collect(&:to_s)
87
+ select_message(path, receiver, message, candidates)
88
+ when PROC_OR_HASH_REGEXP # Proc or Hash
89
+ receiver = Regexp.last_match(1)
90
+ message = Regexp.quote(Regexp.last_match(2))
91
+ candidates = Proc.instance_methods.collect(&:to_s)
92
+ candidates |= Hash.instance_methods.collect(&:to_s)
93
+ select_message(path, receiver, message, candidates)
94
+ when SYMBOL_REGEXP # Symbol
95
+ if Symbol.respond_to?(:all_symbols)
96
+ sym = Regexp.quote(Regexp.last_match(1))
97
+ candidates = Symbol.all_symbols.collect { |s| ":" + s.id2name }
98
+ candidates.grep(/^#{sym}/)
99
+ else
100
+ []
101
+ end
102
+ when TOPLEVEL_LOOKUP_REGEXP # Absolute Constant or class methods
103
+ receiver = Regexp.last_match(1)
104
+ candidates = Object.constants.collect(&:to_s)
105
+ candidates.grep(/^#{receiver}/).collect { |e| "::" + e }
106
+ when CONSTANT_REGEXP # Constant
107
+ message = Regexp.last_match(1)
108
+ begin
109
+ context = target.eval("self")
110
+ context = context.class unless context.respond_to? :constants
111
+ candidates = context.constants.collect(&:to_s)
112
+ rescue StandardError
113
+ candidates = []
114
+ end
113
115
  candidates = candidates.grep(/^#{message}/).collect(&path)
114
116
  when CONSTANT_OR_METHOD_REGEXP # Constant or class methods
115
- receiver = $1
116
- message = Regexp.quote($2)
117
+ receiver = Regexp.last_match(1)
118
+ message = Regexp.quote(Regexp.last_match(2))
117
119
  begin
118
- candidates = eval("#{receiver}.constants.collect(&:to_s)", bind)
119
- candidates |= eval("#{receiver}.methods.collect(&:to_s)", bind)
120
+ candidates = eval( # rubocop:disable Security/Eval
121
+ "#{receiver}.constants.collect(&:to_s)", bind, __FILE__, __LINE__
122
+ )
123
+ candidates |= eval( # rubocop:disable Security/Eval
124
+ "#{receiver}.methods.collect(&:to_s)", bind, __FILE__, __LINE__
125
+ )
120
126
  rescue Pry::RescuableException
121
127
  candidates = []
122
128
  end
123
- candidates.grep(/^#{message}/).collect{|e| receiver + "::" + e}
129
+ candidates.grep(/^#{message}/).collect { |e| receiver + "::" + e }
124
130
  when SYMBOL_METHOD_CALL_REGEXP # method call on a Symbol
125
- receiver = $1
126
- message = Regexp.quote($2)
131
+ receiver = Regexp.last_match(1)
132
+ message = Regexp.quote(Regexp.last_match(2))
127
133
  candidates = Symbol.instance_methods.collect(&:to_s)
128
134
  select_message(path, receiver, message, candidates)
129
135
  when NUMERIC_REGEXP
130
136
  # Numeric
131
- receiver = $1
132
- message = Regexp.quote($5)
137
+ receiver = Regexp.last_match(1)
138
+ message = Regexp.quote(Regexp.last_match(5))
133
139
  begin
140
+ # rubocop:disable Security/Eval
134
141
  candidates = eval(receiver, bind).methods.collect(&:to_s)
142
+ # rubocop:enable Security/Eval
135
143
  rescue Pry::RescuableException
136
144
  candidates = []
137
145
  end
138
146
  select_message(path, receiver, message, candidates)
139
147
  when HEX_REGEXP
140
148
  # Numeric(0xFFFF)
141
- receiver = $1
142
- message = Regexp.quote($2)
149
+ receiver = Regexp.last_match(1)
150
+ message = Regexp.quote(Regexp.last_match(2))
143
151
  begin
152
+ # rubocop:disable Security/Eval
144
153
  candidates = eval(receiver, bind).methods.collect(&:to_s)
154
+ # rubocop:enable Security/Eval
145
155
  rescue Pry::RescuableException
146
156
  candidates = []
147
157
  end
148
158
  select_message(path, receiver, message, candidates)
149
159
  when GLOBALVARIABLE_REGEXP # global
150
- regmessage = Regexp.new(Regexp.quote($1))
160
+ regmessage = Regexp.new(Regexp.quote(Regexp.last_match(1)))
151
161
  candidates = global_variables.collect(&:to_s).grep(regmessage)
152
162
  when VARIABLE_REGEXP # variable
153
- receiver = $1
154
- message = Regexp.quote($2)
163
+ receiver = Regexp.last_match(1)
164
+ message = Regexp.quote(Regexp.last_match(2))
155
165
 
156
- gv = eval("global_variables", bind).collect(&:to_s)
157
- lv = eval("local_variables", bind).collect(&:to_s)
158
- cv = eval("self.class.constants", bind).collect(&:to_s)
166
+ gv = eval("global_variables", bind, __FILE__, __LINE__).collect(&:to_s)
167
+ lv = eval("local_variables", bind, __FILE__, __LINE__).collect(&:to_s)
168
+ cv = eval("self.class.constants", bind, __FILE__, __LINE__).collect(&:to_s)
159
169
 
160
- if (gv | lv | cv).include?(receiver) or /^[A-Z]/ =~ receiver && /\./ !~ receiver
170
+ if (gv | lv | cv).include?(receiver) || /^[A-Z]/ =~ receiver && /\./ !~ receiver
161
171
  # foo.func and foo is local var. OR
162
172
  # Foo::Bar.func
163
173
  begin
164
- candidates = eval("#{receiver}.methods", bind).collect(&:to_s)
174
+ candidates = eval( # rubocop:disable Security/Eval
175
+ "#{receiver}.methods", bind, __FILE__, __LINE__
176
+ ).collect(&:to_s)
165
177
  rescue Pry::RescuableException
166
178
  candidates = []
167
179
  end
168
180
  else
169
181
  # func1.func2
170
- candidates = []
171
- ObjectSpace.each_object(Module){|m|
172
- begin
173
- name = m.name.to_s
174
- rescue Pry::RescuableException
175
- name = ""
176
- end
177
- next if name != "IRB::Context" and
178
- /^(IRB|SLex|RubyLex|RubyToken)/ =~ name
182
+ require 'set'
183
+ candidates = Set.new
184
+ to_ignore = ignored_modules
185
+ ObjectSpace.each_object(Module) do |m|
186
+ next if begin
187
+ to_ignore.include?(m)
188
+ rescue StandardError
189
+ true
190
+ end
179
191
 
180
192
  # jruby doesn't always provide #instance_methods() on each
181
193
  # object.
182
194
  if m.respond_to?(:instance_methods)
183
- candidates.concat m.instance_methods(false).collect(&:to_s)
195
+ candidates.merge m.instance_methods(false).collect(&:to_s)
184
196
  end
185
- }
186
- candidates.sort!
187
- candidates.uniq!
197
+ end
188
198
  end
189
- select_message(path, receiver, message, candidates)
199
+ select_message(path, receiver, message, candidates.sort)
190
200
  when /^\.([^.]*)$/
191
201
  # Unknown(maybe String)
192
202
  receiver = ""
193
- message = Regexp.quote($1)
203
+ message = Regexp.quote(Regexp.last_match(1))
194
204
  candidates = String.instance_methods(true).collect(&:to_s)
195
205
  select_message(path, receiver, message, candidates)
196
206
  else
197
207
  candidates = eval(
198
- "methods | private_methods | local_variables | " \
199
- "self.class.constants | instance_variables",
200
- bind
201
- ).collect(&:to_s)
208
+ "methods | private_methods | local_variables | " \
209
+ "self.class.constants | instance_variables",
210
+ bind, __FILE__, __LINE__ - 2
211
+ ).collect(&:to_s)
202
212
 
203
- if eval("respond_to?(:class_variables)", bind)
204
- candidates += eval("class_variables", bind).collect(&:to_s)
213
+ if eval("respond_to?(:class_variables)", bind, __FILE__, __LINE__)
214
+ candidates += eval(
215
+ "class_variables", bind, __FILE__, __LINE__
216
+ ).collect(&:to_s)
205
217
  end
206
- candidates = (candidates|ReservedWords|custom_completions).grep(/^#{Regexp.quote(input)}/)
218
+ candidates =
219
+ (candidates | RESERVED_WORDS | custom_completions)
220
+ .grep(/^#{Regexp.quote(input)}/)
207
221
  candidates.collect(&path)
208
222
  end
209
223
  rescue Pry::RescuableException
210
224
  []
211
225
  end
212
226
  end
227
+ # rubocop:enable Metrics/AbcSize, Metrics/MethodLength
213
228
 
214
229
  def select_message(path, receiver, message, candidates)
215
- candidates.grep(/^#{message}/).collect { |e|
216
- case e
217
- when /^[a-zA-Z_]/
218
- path.call(receiver + "." << e)
219
- when /^[0-9]/
220
- when *Operators
221
- #receiver + " " << e
222
- end
223
- }.compact
230
+ candidates.grep(/^#{message}/).collect do |e|
231
+ next unless e =~ /^[a-zA-Z_]/
232
+
233
+ path.call(receiver + "." + e)
234
+ end.compact
224
235
  end
225
236
 
226
237
  # build_path seperates the input into two parts: path and input.
@@ -228,15 +239,45 @@ class Pry::InputCompleter
228
239
  # path is a proc that takes an input and builds a full path.
229
240
  def build_path(input)
230
241
  # check to see if the input is a regex
231
- return proc {|i| i.to_s }, input if input[/\/\./]
242
+ return proc { |i| i.to_s }, input if input[%r{/\.}]
243
+
232
244
  trailing_slash = input.end_with?('/')
233
- contexts = input.chomp('/').split(/\//)
245
+ contexts = input.chomp('/').split(%r{/})
234
246
  input = contexts[-1]
235
247
  path = proc do |i|
236
248
  p = contexts[0..-2].push(i).join('/')
237
249
  p += '/' if trailing_slash && !i.nil?
238
250
  p
239
251
  end
240
- return path, input
252
+ [path, input]
241
253
  end
254
+
255
+ def ignored_modules
256
+ # We could cache the result, but IRB is not loaded by default.
257
+ # And this is very fast anyway.
258
+ # By using this approach, we avoid Module#name calls, which are
259
+ # relatively slow when there are a lot of anonymous modules defined.
260
+ s = Set.new
261
+
262
+ scanner = lambda do |m|
263
+ next if s.include?(m) # IRB::ExtendCommandBundle::EXCB recurses.
264
+
265
+ s << m
266
+ m.constants(false).each do |c|
267
+ value = m.const_get(c)
268
+ scanner.call(value) if value.is_a?(Module)
269
+ end
270
+ end
271
+
272
+ # FIXME: Add Pry here as well?
273
+ %i[IRB SLex RubyLex RubyToken].each do |module_name|
274
+ next unless Object.const_defined?(module_name)
275
+
276
+ scanner.call(Object.const_get(module_name))
277
+ end
278
+
279
+ s.delete(IRB::Context) if defined?(IRB::Context)
280
+ s
281
+ end
282
+ end
242
283
  end
@@ -1,4 +1,4 @@
1
- require 'thread'
1
+ # frozen_string_literal: true
2
2
 
3
3
  class Pry
4
4
  # There is one InputLock per input (such as STDIN) as two REPLs on the same
@@ -6,7 +6,7 @@ class Pry
6
6
  # that threads to not conflict with each other. The latest thread to request
7
7
  # ownership of the input wins.
8
8
  class InputLock
9
- class Interrupt < Exception; end
9
+ class Interrupt < Exception; end # rubocop:disable Lint/InheritException
10
10
 
11
11
  class << self
12
12
  attr_accessor :input_locks
@@ -35,7 +35,7 @@ class Pry
35
35
 
36
36
  # Adds ourselves to the ownership list. The last one in the list may access
37
37
  # the input through interruptible_region().
38
- def __with_ownership(&block)
38
+ def __with_ownership
39
39
  @mutex.synchronize do
40
40
  # Three cases:
41
41
  # 1) There are no owners, in this case we are good to go.
@@ -58,8 +58,7 @@ class Pry
58
58
  @owners << Thread.current
59
59
  end
60
60
 
61
- block.call
62
-
61
+ yield
63
62
  ensure
64
63
  @mutex.synchronize do
65
64
  # We are releasing any desire to have the input ownership by removing
@@ -76,7 +75,7 @@ class Pry
76
75
  def with_ownership(&block)
77
76
  # If we are in a nested with_ownership() call (nested pry context), we do nothing.
78
77
  nested = @mutex.synchronize { @owners.include?(Thread.current) }
79
- nested ? block.call : __with_ownership(&block)
78
+ nested ? yield : __with_ownership(&block)
80
79
  end
81
80
 
82
81
  def enter_interruptible_region
@@ -106,14 +105,13 @@ class Pry
106
105
  retry
107
106
  end
108
107
 
109
- def interruptible_region(&block)
108
+ def interruptible_region
110
109
  enter_interruptible_region
111
110
 
112
111
  # XXX Note that there is a chance that we get the interrupt right after
113
112
  # the readline call succeeded, but we'll never know, and we will retry the
114
113
  # call, discarding that piece of input.
115
- block.call
116
-
114
+ yield
117
115
  rescue Interrupt
118
116
  # We were asked to back off. The one requesting the interrupt will be
119
117
  # waiting on the conditional for the interruptible flag to change to false.
@@ -124,7 +122,6 @@ class Pry
124
122
  leave_interruptible_region
125
123
  sleep 0.01
126
124
  retry
127
-
128
125
  ensure
129
126
  leave_interruptible_region
130
127
  end
data/lib/pry/inspector.rb CHANGED
@@ -1,27 +1,39 @@
1
- class Pry::Inspector
2
- MAP = {
3
- "default" => {
4
- value: Pry::DEFAULT_PRINT,
5
- description: <<-DESCRIPTION.each_line.map(&:lstrip!)
6
- The default Pry inspector. It has paging and color support, and uses
7
- pretty_inspect when printing an object.
8
- DESCRIPTION
9
- },
1
+ # frozen_string_literal: true
10
2
 
11
- "simple" => {
12
- value: Pry::SIMPLE_PRINT,
13
- description: <<-DESCRIPTION.each_line.map(&:lstrip)
14
- A simple inspector that uses #puts and #inspect when printing an
15
- object. It has no pager, color, or pretty_inspect support.
16
- DESCRIPTION
17
- },
3
+ class Pry
4
+ class Inspector
5
+ MAP = {
6
+ "default" => {
7
+ value: Pry.config.print,
8
+ description: <<-DESCRIPTION.each_line.map(&:lstrip!)
9
+ The default Pry inspector. It has paging and color support, and uses
10
+ pretty_inspect when printing an object.
11
+ DESCRIPTION
12
+ },
18
13
 
19
- "clipped" => {
20
- value: Pry::CLIPPED_PRINT,
21
- description: <<-DESCRIPTION.each_line.map(&:lstrip)
22
- The clipped inspector has the same features as the 'simple' inspector
23
- but prints large objects as a smaller string.
24
- DESCRIPTION
25
- }
26
- }
14
+ "simple" => {
15
+ value: proc do |output, value|
16
+ begin
17
+ output.puts value.inspect
18
+ rescue RescuableException
19
+ output.puts "unknown"
20
+ end
21
+ end,
22
+ description: <<-DESCRIPTION.each_line.map(&:lstrip)
23
+ A simple inspector that uses #puts and #inspect when printing an
24
+ object. It has no pager, color, or pretty_inspect support.
25
+ DESCRIPTION
26
+ },
27
+
28
+ "clipped" => {
29
+ value: proc do |output, value|
30
+ output.puts Pry.view_clip(value, id: true)
31
+ end,
32
+ description: <<-DESCRIPTION.each_line.map(&:lstrip)
33
+ The clipped inspector has the same features as the 'simple' inspector
34
+ but prints large objects as a smaller string.
35
+ DESCRIPTION
36
+ }
37
+ }.freeze
38
+ end
27
39
  end