pry 0.12.2 → 0.13.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (158) hide show
  1. checksums.yaml +5 -5
  2. data/CHANGELOG.md +110 -1
  3. data/LICENSE +1 -1
  4. data/README.md +331 -269
  5. data/bin/pry +5 -0
  6. data/lib/pry.rb +133 -119
  7. data/lib/pry/basic_object.rb +8 -4
  8. data/lib/pry/block_command.rb +22 -0
  9. data/lib/pry/class_command.rb +194 -0
  10. data/lib/pry/cli.rb +40 -31
  11. data/lib/pry/code.rb +39 -27
  12. data/lib/pry/code/code_file.rb +28 -24
  13. data/lib/pry/code/code_range.rb +4 -2
  14. data/lib/pry/code/loc.rb +15 -8
  15. data/lib/pry/code_object.rb +40 -38
  16. data/lib/pry/color_printer.rb +47 -46
  17. data/lib/pry/command.rb +166 -369
  18. data/lib/pry/command_set.rb +76 -73
  19. data/lib/pry/command_state.rb +31 -0
  20. data/lib/pry/commands/amend_line.rb +86 -81
  21. data/lib/pry/commands/bang.rb +18 -14
  22. data/lib/pry/commands/bang_pry.rb +15 -11
  23. data/lib/pry/commands/cat.rb +61 -54
  24. data/lib/pry/commands/cat/abstract_formatter.rb +23 -18
  25. data/lib/pry/commands/cat/exception_formatter.rb +71 -60
  26. data/lib/pry/commands/cat/file_formatter.rb +55 -49
  27. data/lib/pry/commands/cat/input_expression_formatter.rb +35 -30
  28. data/lib/pry/commands/cd.rb +40 -35
  29. data/lib/pry/commands/change_inspector.rb +29 -22
  30. data/lib/pry/commands/change_prompt.rb +44 -39
  31. data/lib/pry/commands/clear_screen.rb +16 -10
  32. data/lib/pry/commands/code_collector.rb +148 -133
  33. data/lib/pry/commands/disable_pry.rb +23 -19
  34. data/lib/pry/commands/easter_eggs.rb +19 -30
  35. data/lib/pry/commands/edit.rb +184 -161
  36. data/lib/pry/commands/edit/exception_patcher.rb +21 -17
  37. data/lib/pry/commands/edit/file_and_line_locator.rb +34 -23
  38. data/lib/pry/commands/exit.rb +39 -35
  39. data/lib/pry/commands/exit_all.rb +24 -20
  40. data/lib/pry/commands/exit_program.rb +20 -16
  41. data/lib/pry/commands/find_method.rb +168 -160
  42. data/lib/pry/commands/fix_indent.rb +16 -12
  43. data/lib/pry/commands/help.rb +140 -133
  44. data/lib/pry/commands/hist.rb +151 -150
  45. data/lib/pry/commands/import_set.rb +20 -16
  46. data/lib/pry/commands/jump_to.rb +25 -21
  47. data/lib/pry/commands/list_inspectors.rb +35 -28
  48. data/lib/pry/commands/ls.rb +124 -102
  49. data/lib/pry/commands/ls/constants.rb +59 -42
  50. data/lib/pry/commands/ls/formatter.rb +50 -46
  51. data/lib/pry/commands/ls/globals.rb +38 -34
  52. data/lib/pry/commands/ls/grep.rb +17 -13
  53. data/lib/pry/commands/ls/instance_vars.rb +29 -27
  54. data/lib/pry/commands/ls/interrogatable.rb +18 -12
  55. data/lib/pry/commands/ls/jruby_hacks.rb +47 -41
  56. data/lib/pry/commands/ls/local_names.rb +26 -22
  57. data/lib/pry/commands/ls/local_vars.rb +38 -28
  58. data/lib/pry/commands/ls/ls_entity.rb +47 -51
  59. data/lib/pry/commands/ls/methods.rb +44 -43
  60. data/lib/pry/commands/ls/methods_helper.rb +46 -42
  61. data/lib/pry/commands/ls/self_methods.rb +23 -22
  62. data/lib/pry/commands/nesting.rb +21 -17
  63. data/lib/pry/commands/play.rb +93 -82
  64. data/lib/pry/commands/pry_backtrace.rb +24 -17
  65. data/lib/pry/commands/pry_version.rb +15 -11
  66. data/lib/pry/commands/raise_up.rb +27 -22
  67. data/lib/pry/commands/reload_code.rb +60 -48
  68. data/lib/pry/commands/reset.rb +16 -12
  69. data/lib/pry/commands/ri.rb +55 -45
  70. data/lib/pry/commands/save_file.rb +45 -43
  71. data/lib/pry/commands/shell_command.rb +51 -51
  72. data/lib/pry/commands/shell_mode.rb +21 -17
  73. data/lib/pry/commands/show_doc.rb +81 -68
  74. data/lib/pry/commands/show_info.rb +189 -171
  75. data/lib/pry/commands/show_input.rb +16 -11
  76. data/lib/pry/commands/show_source.rb +109 -45
  77. data/lib/pry/commands/stat.rb +35 -31
  78. data/lib/pry/commands/switch_to.rb +21 -15
  79. data/lib/pry/commands/toggle_color.rb +20 -16
  80. data/lib/pry/commands/watch_expression.rb +89 -86
  81. data/lib/pry/commands/watch_expression/expression.rb +32 -27
  82. data/lib/pry/commands/whereami.rb +156 -148
  83. data/lib/pry/commands/wtf.rb +75 -50
  84. data/lib/pry/config.rb +311 -25
  85. data/lib/pry/config/attributable.rb +22 -0
  86. data/lib/pry/config/lazy_value.rb +29 -0
  87. data/lib/pry/config/memoized_value.rb +34 -0
  88. data/lib/pry/config/value.rb +24 -0
  89. data/lib/pry/control_d_handler.rb +28 -0
  90. data/lib/pry/core_extensions.rb +9 -7
  91. data/lib/pry/editor.rb +48 -21
  92. data/lib/pry/env.rb +18 -0
  93. data/lib/pry/exception_handler.rb +43 -0
  94. data/lib/pry/exceptions.rb +13 -16
  95. data/lib/pry/forwardable.rb +5 -1
  96. data/lib/pry/helpers.rb +2 -0
  97. data/lib/pry/helpers/base_helpers.rb +68 -197
  98. data/lib/pry/helpers/command_helpers.rb +50 -61
  99. data/lib/pry/helpers/documentation_helpers.rb +20 -13
  100. data/lib/pry/helpers/options_helpers.rb +14 -7
  101. data/lib/pry/helpers/platform.rb +7 -5
  102. data/lib/pry/helpers/table.rb +33 -26
  103. data/lib/pry/helpers/text.rb +17 -14
  104. data/lib/pry/history.rb +48 -56
  105. data/lib/pry/hooks.rb +21 -12
  106. data/lib/pry/indent.rb +54 -50
  107. data/lib/pry/input_completer.rb +248 -230
  108. data/lib/pry/input_lock.rb +8 -9
  109. data/lib/pry/inspector.rb +36 -24
  110. data/lib/pry/last_exception.rb +45 -45
  111. data/lib/pry/method.rb +141 -94
  112. data/lib/pry/method/disowned.rb +16 -4
  113. data/lib/pry/method/patcher.rb +12 -3
  114. data/lib/pry/method/weird_method_locator.rb +68 -44
  115. data/lib/pry/object_path.rb +33 -25
  116. data/lib/pry/output.rb +121 -35
  117. data/lib/pry/pager.rb +41 -42
  118. data/lib/pry/plugins.rb +25 -8
  119. data/lib/pry/prompt.rb +123 -54
  120. data/lib/pry/pry_class.rb +61 -98
  121. data/lib/pry/pry_instance.rb +217 -215
  122. data/lib/pry/repl.rb +18 -22
  123. data/lib/pry/repl_file_loader.rb +27 -21
  124. data/lib/pry/ring.rb +11 -6
  125. data/lib/pry/slop.rb +574 -563
  126. data/lib/pry/slop/commands.rb +164 -169
  127. data/lib/pry/slop/option.rb +172 -168
  128. data/lib/pry/syntax_highlighter.rb +26 -0
  129. data/lib/pry/system_command_handler.rb +17 -0
  130. data/lib/pry/testable.rb +59 -61
  131. data/lib/pry/testable/evalable.rb +21 -12
  132. data/lib/pry/testable/mockable.rb +18 -10
  133. data/lib/pry/testable/pry_tester.rb +71 -56
  134. data/lib/pry/testable/utility.rb +29 -21
  135. data/lib/pry/testable/variables.rb +49 -43
  136. data/lib/pry/version.rb +3 -1
  137. data/lib/pry/warning.rb +27 -0
  138. data/lib/pry/wrapped_module.rb +51 -42
  139. data/lib/pry/wrapped_module/candidate.rb +21 -14
  140. metadata +31 -30
  141. data/lib/pry/commands.rb +0 -6
  142. data/lib/pry/commands/disabled_commands.rb +0 -2
  143. data/lib/pry/commands/gem_cd.rb +0 -26
  144. data/lib/pry/commands/gem_install.rb +0 -32
  145. data/lib/pry/commands/gem_list.rb +0 -33
  146. data/lib/pry/commands/gem_open.rb +0 -29
  147. data/lib/pry/commands/gem_readme.rb +0 -25
  148. data/lib/pry/commands/gem_search.rb +0 -40
  149. data/lib/pry/commands/gem_stats.rb +0 -83
  150. data/lib/pry/commands/gist.rb +0 -102
  151. data/lib/pry/commands/install_command.rb +0 -54
  152. data/lib/pry/config/behavior.rb +0 -255
  153. data/lib/pry/config/convenience.rb +0 -28
  154. data/lib/pry/config/default.rb +0 -159
  155. data/lib/pry/config/memoization.rb +0 -48
  156. data/lib/pry/platform.rb +0 -91
  157. data/lib/pry/rubygem.rb +0 -84
  158. data/lib/pry/terminal.rb +0 -91
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  class Pry
2
4
  class Method
3
5
  # A Disowned Method is one that's been removed from the class on which it was defined.
@@ -21,7 +23,8 @@ class Pry
21
23
  # @param [Object] receiver
22
24
  # @param [String] method_name
23
25
  def initialize(receiver, method_name)
24
- @receiver, @name = receiver, method_name
26
+ @receiver = receiver
27
+ @name = method_name
25
28
  @method = nil
26
29
  end
27
30
 
@@ -45,10 +48,19 @@ class Pry
45
48
  end
46
49
 
47
50
  # Raise a more useful error message instead of trying to forward to nil.
48
- def method_missing(meth_name, *args, &block)
49
- raise "Cannot call '#{meth_name}' on an undef'd method." if method(:name).respond_to?(meth_name)
51
+ # rubocop:disable Style/MethodMissingSuper
52
+ def method_missing(method_name, *args, &block)
53
+ if method(:name).respond_to?(method_name)
54
+ raise "Cannot call '#{method_name}' on an undef'd method."
55
+ end
56
+
57
+ method = Object.instance_method(:method_missing).bind(self)
58
+ method.call(method_name, *args, &block)
59
+ end
60
+ # rubocop:enable Style/MethodMissingSuper
50
61
 
51
- Object.instance_method(:method_missing).bind(self).call(meth_name, *args, &block)
62
+ def respond_to_missing?(method_name, include_private = false)
63
+ !method(:name).respond_to?(method_name) || super
52
64
  end
53
65
  end
54
66
  end
@@ -1,9 +1,13 @@
1
+ # frozen_string_literal: true
2
+
1
3
  class Pry
2
4
  class Method
3
5
  class Patcher
4
6
  attr_accessor :method
5
7
 
8
+ # rubocop:disable Style/ClassVars
6
9
  @@source_cache = {}
10
+ # rubocop:enable Style/ClassVars
7
11
 
8
12
  def initialize(method)
9
13
  @method = method
@@ -51,9 +55,12 @@ class Pry
51
55
  alias_method method.name, method.original_name
52
56
  alias_method method.original_name, temp_name
53
57
  end
54
-
55
58
  ensure
56
- method.send(:remove_method, temp_name) rescue nil
59
+ begin
60
+ method.send(:remove_method, temp_name)
61
+ rescue StandardError
62
+ nil
63
+ end
57
64
  end
58
65
 
59
66
  # Update the definition line so that it can be eval'd directly on the Method's
@@ -72,7 +79,9 @@ class Pry
72
79
  if line =~ /\Adef (?:.*?\.)?#{Regexp.escape(method.original_name)}(?=[\(\s;]|$)/
73
80
  "def #{method.original_name}#{$'}"
74
81
  else
75
- raise CommandError, "Could not find original `def #{method.original_name}` line to patch."
82
+ raise CommandError,
83
+ "Could not find original `def #{method.original_name}` line " \
84
+ "to patch."
76
85
  end
77
86
  end
78
87
 
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  class Pry
2
4
  class Method
3
5
  # This class is responsible for locating the *real* `Pry::Method`
@@ -6,10 +8,11 @@ class Pry
6
8
  # Given a `Binding` from inside a method and a 'seed' Pry::Method object,
7
9
  # there are primarily two situations where the seed method doesn't match
8
10
  # the Binding:
9
- # 1. The Pry::Method is from a subclass 2. The Pry::Method represents a method of the same name
10
- # while the original was renamed to something else. For 1. we
11
- # search vertically up the inheritance chain,
12
- # and for 2. we search laterally along the object's method table.
11
+ # 1. The Pry::Method is from a subclass
12
+ # 2. The Pry::Method represents a method of the same name while the original
13
+ # was renamed to something else. For 1. we search vertically up the
14
+ # inheritance chain, and for 2. we search laterally along the object's
15
+ # method table.
13
16
  #
14
17
  # When we locate the method that matches the Binding we wrap it in
15
18
  # Pry::Method and return it, or return nil if we fail.
@@ -21,20 +24,25 @@ class Pry
21
24
  # must commence a search.
22
25
  #
23
26
  # @param [Pry::Method] method
24
- # @param [Binding] b
27
+ # @param [Binding] binding
25
28
  # @return [Boolean]
26
- def normal_method?(method, b)
27
- if method and method.source_file and method.source_range
28
- binding_file, binding_line = b.eval('__FILE__'), b.eval('__LINE__')
29
- File.expand_path(method.source_file) == File.expand_path(binding_file) and
30
- method.source_range.include?(binding_line)
29
+ def normal_method?(method, binding)
30
+ if method && method.source_file && method.source_range
31
+ if binding.respond_to?(:source_location)
32
+ binding_file, binding_line = binding.source_location
33
+ else
34
+ binding_file = binding.eval('__FILE__')
35
+ binding_line = binding.eval('__LINE__')
36
+ end
37
+ (File.expand_path(method.source_file) == File.expand_path(binding_file)) &&
38
+ method.source_range.include?(binding_line)
31
39
  end
32
- rescue
40
+ rescue StandardError
33
41
  false
34
42
  end
35
43
 
36
- def weird_method?(method, b)
37
- not normal_method?(method, b)
44
+ def weird_method?(method, binding)
45
+ !normal_method?(method, binding)
38
46
  end
39
47
  end
40
48
 
@@ -45,12 +53,13 @@ class Pry
45
53
  # @param [Binding] target The Binding that captures the method
46
54
  # we want to locate.
47
55
  def initialize(method, target)
48
- @method, @target = method, target
56
+ @method = method
57
+ @target = target
49
58
  end
50
59
 
51
60
  # @return [Pry::Method, nil] The Pry::Method that matches the
52
61
  # given binding.
53
- def get_method
62
+ def find_method
54
63
  find_method_in_superclass || find_renamed_method
55
64
  end
56
65
 
@@ -58,7 +67,7 @@ class Pry
58
67
  # This usually happens when the method captured by the Binding
59
68
  # has been subsequently deleted.
60
69
  def lost_method?
61
- !!(get_method.nil? && renamed_method_source_location)
70
+ !!(find_method.nil? && renamed_method_source_location)
62
71
  end
63
72
 
64
73
  private
@@ -77,47 +86,59 @@ class Pry
77
86
  end
78
87
 
79
88
  def target_file
80
- pry_file? ? target.eval('__FILE__') : File.expand_path(target.eval('__FILE__'))
89
+ file =
90
+ if target.respond_to?(:source_location)
91
+ target.source_location.first
92
+ else
93
+ target.eval('__FILE__')
94
+ end
95
+ pry_file? ? file : File.expand_path(file)
81
96
  end
82
97
 
83
98
  def target_line
84
- target.eval('__LINE__')
99
+ if target.respond_to?(:source_location)
100
+ target.source_location.last
101
+ else
102
+ target.eval('__LINE__')
103
+ end
85
104
  end
86
105
 
87
106
  def pry_file?
88
- Pry.eval_path == target.eval('__FILE__')
107
+ file =
108
+ if target.respond_to?(:source_location)
109
+ target.source_location.first
110
+ else
111
+ target.eval('__FILE__')
112
+ end
113
+ Pry.eval_path == file
89
114
  end
90
115
 
91
- # it's possible in some cases that the method we find by this approach is a sub-method of
92
- # the one we're currently in, consider:
116
+ # it's possible in some cases that the method we find by this approach is
117
+ # a sub-method of the one we're currently in, consider:
93
118
  #
94
119
  # class A; def b; binding.pry; end; end
95
120
  # class B < A; def b; super; end; end
96
121
  #
97
- # Given that we can normally find the source_range of methods, and that we know which
98
- # __FILE__ and __LINE__ the binding is at, we can hope to disambiguate these cases.
122
+ # Given that we can normally find the source_range of methods, and that we
123
+ # know which __FILE__ and __LINE__ the binding is at, we can hope to
124
+ # disambiguate these cases.
99
125
  #
100
- # This obviously won't work if the source is unavaiable for some reason, or if both
101
- # methods have the same __FILE__ and __LINE__.
126
+ # This obviously won't work if the source is unavaiable for some reason,
127
+ # or if both methods have the same __FILE__ and __LINE__.
102
128
  #
103
129
  # @return [Pry::Method, nil] The Pry::Method representing the
104
130
  # superclass method.
105
131
  def find_method_in_superclass
106
132
  guess = method
107
- if skip_superclass_search?
108
- return guess
109
- end
133
+ return guess if skip_superclass_search?
110
134
 
111
135
  while guess
112
136
  # needs rescue if this is a Disowned method or a C method or something...
113
137
  # TODO: Fix up the exception handling so we don't need a bare rescue
114
- if normal_method?(guess)
115
- return guess
116
- elsif guess != guess.super
117
- guess = guess.super
118
- else
119
- break
120
- end
138
+ return guess if normal_method?(guess)
139
+ break if guess == guess.super
140
+
141
+ guess = guess.super
121
142
  end
122
143
 
123
144
  # Uhoh... none of the methods in the chain had the right `__FILE__` and
@@ -133,22 +154,23 @@ class Pry
133
154
  # @return [Pry::Method, nil] The Pry::Method representing the
134
155
  # renamed method
135
156
  def find_renamed_method
136
- return if !valid_file?(target_file)
157
+ return unless valid_file?(target_file)
137
158
 
138
159
  alias_name = all_methods_for(target_self).find do |v|
139
- expanded_source_location(target_self.method(v).source_location) == renamed_method_source_location
160
+ location = target_self.method(v).source_location
161
+ expanded_source_location(location) == renamed_method_source_location
140
162
  end
141
163
 
142
164
  alias_name && Pry::Method(target_self.method(alias_name))
143
165
  end
144
166
 
145
- def expanded_source_location(sl)
146
- return if !sl
167
+ def expanded_source_location(source_location)
168
+ return unless source_location
147
169
 
148
170
  if pry_file?
149
- sl
171
+ source_location
150
172
  else
151
- [File.expand_path(sl.first), sl.last]
173
+ [File.expand_path(source_location.first), source_location.last]
152
174
  end
153
175
  end
154
176
 
@@ -160,14 +182,16 @@ class Pry
160
182
  # @return [Array<String, Fixnum>] The `source_location` of the
161
183
  # renamed method
162
184
  def renamed_method_source_location
163
- return @original_method_source_location if defined?(@original_method_source_location)
185
+ if defined?(@original_method_source_location)
186
+ return @original_method_source_location
187
+ end
164
188
 
165
189
  source_index = lines_for_file(target_file)[0..(target_line - 1)].rindex do |v|
166
190
  Pry::Method.method_definition?(method.name, v)
167
191
  end
168
192
 
169
- @original_method_source_location = source_index &&
170
- [target_file, index_to_line_number(source_index)]
193
+ @original_method_source_location =
194
+ source_index && [target_file, index_to_line_number(source_index)]
171
195
  end
172
196
 
173
197
  def index_to_line_number(index)
@@ -1,3 +1,7 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'strscan'
4
+
1
5
  class Pry
2
6
  # `ObjectPath` implements the resolution of "object paths", which are strings
3
7
  # that are similar to filesystem paths but meant for traversing Ruby objects.
@@ -11,7 +15,7 @@ class Pry
11
15
  # Object paths are mostly relevant in the context of the `cd` command.
12
16
  # @see https://github.com/pry/pry/wiki/State-navigation
13
17
  class ObjectPath
14
- SPECIAL_TERMS = ["", "::", ".", ".."]
18
+ SPECIAL_TERMS = ["", "::", ".", ".."].freeze
15
19
 
16
20
  # @param [String] path_string The object path expressed as a string.
17
21
  # @param [Array<Binding>] current_stack The current state of the binding
@@ -27,36 +31,40 @@ class Pry
27
31
  scanner = StringScanner.new(@path_string.strip)
28
32
  stack = @current_stack.dup
29
33
 
30
- begin
31
- next_segment = ""
34
+ loop do
35
+ begin
36
+ next_segment = ""
32
37
 
33
- loop do
34
- # Scan for as long as we don't see a slash
35
- next_segment << scanner.scan(/[^\/]*/)
38
+ loop do
39
+ # Scan for as long as we don't see a slash
40
+ next_segment += scanner.scan(%r{[^/]*})
36
41
 
37
- if complete?(next_segment) || scanner.eos?
38
- scanner.getch # consume the slash
39
- break
42
+ if complete?(next_segment) || scanner.eos?
43
+ scanner.getch # consume the slash
44
+ break
45
+ else
46
+ next_segment += scanner.getch # append the slash
47
+ end
48
+ end
49
+
50
+ case next_segment.chomp
51
+ when ""
52
+ stack = [stack.first]
53
+ when "::"
54
+ stack.push(TOPLEVEL_BINDING)
55
+ when "."
56
+ next
57
+ when ".."
58
+ stack.pop unless stack.size == 1
40
59
  else
41
- next_segment << scanner.getch # append the slash
60
+ stack.push(Pry.binding_for(stack.last.eval(next_segment)))
42
61
  end
62
+ rescue RescuableException => e
63
+ return handle_failure(next_segment, e)
43
64
  end
44
65
 
45
- case next_segment.chomp
46
- when ""
47
- stack = [stack.first]
48
- when "::"
49
- stack.push(TOPLEVEL_BINDING)
50
- when "."
51
- next
52
- when ".."
53
- stack.pop unless stack.size == 1
54
- else
55
- stack.push(Pry.binding_for(stack.last.eval(next_segment)))
56
- end
57
- rescue RescuableException => e
58
- return handle_failure(next_segment, e)
59
- end until scanner.eos?
66
+ break if scanner.eos?
67
+ end
60
68
 
61
69
  stack
62
70
  end
@@ -1,50 +1,136 @@
1
- class Pry::Output
2
- attr_reader :_pry_
1
+ # frozen_string_literal: true
3
2
 
4
- def initialize(_pry_)
5
- @_pry_ = _pry_
6
- @boxed_io = _pry_.config.output
7
- end
3
+ class Pry
4
+ class Output
5
+ # @return [Array<Integer>] default terminal screen size [rows, cols]
6
+ DEFAULT_SIZE = [27, 80].freeze
7
+
8
+ attr_reader :pry_instance
9
+
10
+ def initialize(pry_instance)
11
+ @output = pry_instance.config.output
12
+ @color = pry_instance.config.color
13
+ end
14
+
15
+ def puts(*objs)
16
+ return print "\n" if objs.empty?
17
+
18
+ objs.each do |obj|
19
+ if (ary = Array.try_convert(obj))
20
+ puts(*ary)
21
+ else
22
+ print "#{obj.to_s.chomp}\n"
23
+ end
24
+ end
25
+ nil
26
+ end
27
+
28
+ def print(*objs)
29
+ objs.each do |obj|
30
+ @output.print decolorize_maybe(obj.to_s)
31
+ end
32
+ nil
33
+ end
34
+ alias << print
35
+ alias write print
8
36
 
9
- def puts(*objs)
10
- return print "\n" if objs.empty?
37
+ def tty?
38
+ @output.respond_to?(:tty?) && @output.tty?
39
+ end
11
40
 
12
- objs.each do |obj|
13
- if (ary = Array.try_convert(obj))
14
- puts(*ary)
41
+ def method_missing(method_name, *args, &block)
42
+ if @output.respond_to?(method_name)
43
+ @output.__send__(method_name, *args, &block)
15
44
  else
16
- print "#{obj.to_s.chomp}\n"
45
+ super
17
46
  end
18
47
  end
19
- nil
20
- end
21
48
 
22
- def print(*objs)
23
- objs.each do |obj|
24
- @boxed_io.print decolorize_maybe(obj.to_s)
49
+ def respond_to_missing?(method_name, include_private = false)
50
+ @output.respond_to?(method_name, include_private)
25
51
  end
26
- nil
27
- end
28
- alias << print
29
- alias write print
30
52
 
31
- def tty?
32
- @boxed_io.respond_to?(:tty?) and @boxed_io.tty?
33
- end
53
+ def decolorize_maybe(str)
54
+ return str if @color
34
55
 
35
- def method_missing(name, *args, &block)
36
- @boxed_io.__send__(name, *args, &block)
37
- end
56
+ Pry::Helpers::Text.strip_color(str)
57
+ end
38
58
 
39
- def respond_to_missing?(m, include_all = false)
40
- @boxed_io.respond_to?(m, include_all)
41
- end
59
+ # @return [Array<Integer>] a pair of [rows, columns] which gives the size of
60
+ # the window. If the window size cannot be determined, the default value.
61
+ def size
62
+ rows, cols = actual_screen_size
63
+ return [rows.to_i, cols.to_i] if rows.to_i != 0 && cols.to_i != 0
64
+
65
+ DEFAULT_SIZE
66
+ end
67
+
68
+ # Return a screen width or the default if that fails.
69
+ def width
70
+ size.last
71
+ end
72
+
73
+ # Return a screen height or the default if that fails.
74
+ def height
75
+ size.first
76
+ end
77
+
78
+ private
79
+
80
+ def actual_screen_size
81
+ # The best way, if possible (requires non-jruby >=1.9 or io-console gem).
82
+ io_console_size ||
83
+ # Fall back to the old standby, though it might be stale.
84
+ env_size ||
85
+ # Fall further back, though this one is also out of date without
86
+ # something calling Readline.set_screen_size.
87
+ readline_size ||
88
+ # Windows users can otherwise run ansicon and get a decent answer.
89
+ ansicon_env_size
90
+ end
91
+
92
+ def io_console_size
93
+ return if Pry::Helpers::Platform.jruby?
94
+
95
+ begin
96
+ require 'io/console'
97
+
98
+ begin
99
+ @output.winsize if tty? && @output.respond_to?(:winsize)
100
+ rescue Errno::EOPNOTSUPP # rubocop:disable Lint/HandleExceptions
101
+ # Output is probably a socket, which doesn't support #winsize.
102
+ end
103
+ rescue LoadError # rubocop:disable Lint/HandleExceptions
104
+ # They probably don't have the io/console stdlib or the io-console gem.
105
+ # We'll keep trying.
106
+ end
107
+ end
108
+
109
+ def env_size
110
+ size = [Pry::Env['LINES'] || Pry::Env['ROWS'], Pry::Env['COLUMNS']]
111
+ size if nonzero_column?(size)
112
+ end
113
+
114
+ def readline_size
115
+ return unless defined?(Readline) && Readline.respond_to?(:get_screen_size)
116
+
117
+ size = Readline.get_screen_size
118
+ size if nonzero_column?(size)
119
+ rescue Java::JavaLang::NullPointerException
120
+ # This rescue won't happen on jrubies later than:
121
+ # https://github.com/jruby/jruby/pull/436
122
+ nil
123
+ end
124
+
125
+ def ansicon_env_size
126
+ return unless Pry::Env['ANSICON'] =~ /\((.*)x(.*)\)/
127
+
128
+ size = [Regexp.last_match(2), Regexp.last_match(1)]
129
+ size if nonzero_column?(size)
130
+ end
42
131
 
43
- def decolorize_maybe(str)
44
- if _pry_.config.color
45
- str
46
- else
47
- Pry::Helpers::Text.strip_color str
132
+ def nonzero_column?(size)
133
+ size[1].to_i > 0
48
134
  end
49
135
  end
50
136
  end