irb 1.14.3 → 1.18.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (48) hide show
  1. checksums.yaml +4 -4
  2. data/.rdoc_options +5 -0
  3. data/CONTRIBUTING.md +52 -0
  4. data/EXTEND_IRB.md +3 -0
  5. data/Gemfile +11 -1
  6. data/README.md +13 -310
  7. data/doc/COMMAND_LINE_OPTIONS.md +69 -0
  8. data/doc/COMPARED_WITH_PRY.md +22 -0
  9. data/doc/Configurations.md +274 -0
  10. data/doc/EXTEND_IRB.md +122 -0
  11. data/doc/Index.md +705 -0
  12. data/doc/irb/irb.rd.ja +1 -1
  13. data/lib/irb/color.rb +251 -162
  14. data/lib/irb/color_printer.rb +10 -9
  15. data/lib/irb/command/base.rb +35 -0
  16. data/lib/irb/command/copy.rb +83 -0
  17. data/lib/irb/command/history.rb +1 -1
  18. data/lib/irb/command/internal_helpers.rb +6 -3
  19. data/lib/irb/command/ls.rb +6 -4
  20. data/lib/irb/completion.rb +69 -52
  21. data/lib/irb/context.rb +100 -64
  22. data/lib/irb/debug.rb +3 -3
  23. data/lib/irb/default_commands.rb +4 -1
  24. data/lib/irb/easter-egg.rb +3 -1
  25. data/lib/irb/ext/multi-irb.rb +2 -0
  26. data/lib/irb/history.rb +4 -0
  27. data/lib/irb/init.rb +6 -1
  28. data/lib/irb/input-method.rb +158 -122
  29. data/lib/irb/inspector.rb +12 -7
  30. data/lib/irb/lc/help-message +2 -2
  31. data/lib/irb/lc/ja/help-message +1 -1
  32. data/lib/irb/nesting_parser.rb +362 -213
  33. data/lib/irb/pager.rb +127 -6
  34. data/lib/irb/ruby-lex.rb +225 -299
  35. data/lib/irb/ruby_logo.aa +4 -0
  36. data/lib/irb/source_finder.rb +12 -18
  37. data/lib/irb/startup_message.rb +83 -0
  38. data/lib/irb/statement.rb +21 -0
  39. data/lib/irb/version.rb +2 -2
  40. data/lib/irb/workspace.rb +9 -0
  41. data/lib/irb.rb +112 -927
  42. data/man/irb.1 +2 -0
  43. metadata +42 -12
  44. data/.document +0 -8
  45. data/Rakefile +0 -52
  46. data/bin/console +0 -6
  47. data/bin/setup +0 -6
  48. data/irb.gemspec +0 -46
data/lib/irb/pager.rb CHANGED
@@ -1,5 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require 'reline'
4
+
3
5
  module IRB
4
6
  # The implementation of this class is borrowed from RDoc's lib/rdoc/ri/driver.rb.
5
7
  # Please do NOT use this class directly outside of IRB.
@@ -40,6 +42,14 @@ module IRB
40
42
  # SIGTERM not supported (windows)
41
43
  Process.kill("KILL", pid)
42
44
  end
45
+
46
+ begin
47
+ # Wait for the pager process to terminate.
48
+ # Reading next input from Reline before the pager process is fully terminated
49
+ # may cause issues like raw/cooked mode not being controlled properly.
50
+ Process.waitpid(pid) if pid
51
+ rescue Errno::ECHILD, Errno::ESRCH
52
+ end
43
53
  rescue Errno::ESRCH
44
54
  # Pager process already terminated
45
55
  end
@@ -47,12 +57,42 @@ module IRB
47
57
  rescue Errno::EPIPE
48
58
  end
49
59
 
50
- private
51
-
52
60
  def should_page?
53
61
  IRB.conf[:USE_PAGER] && STDIN.tty? && (ENV.key?("TERM") && ENV["TERM"] != "dumb")
54
62
  end
55
63
 
64
+ def page_with_preview(width, height, formatter_proc)
65
+ overflow_callback = ->(lines) do
66
+ modified_output = formatter_proc.call(lines.join, true)
67
+ content, = take_first_page(width, [height - 2, 0].max) {|o| o.write modified_output }
68
+ content = content.chomp
69
+ content = "#{content}\e[0m" if Color.colorable?
70
+ $stdout.puts content
71
+ $stdout.puts 'Preparing full inspection value...'
72
+ end
73
+ out = PageOverflowIO.new(width, height, overflow_callback, delay: 0.1)
74
+ yield out
75
+ content = formatter_proc.call(out.string, out.multipage?)
76
+ if out.multipage?
77
+ page(retain_content: true) do |io|
78
+ io.puts content
79
+ end
80
+ else
81
+ $stdout.puts content
82
+ end
83
+ end
84
+
85
+ def take_first_page(width, height)
86
+ overflow_callback = proc do |lines|
87
+ return lines.join, true
88
+ end
89
+ out = Pager::PageOverflowIO.new(width, height, overflow_callback)
90
+ yield out
91
+ [out.string, false]
92
+ end
93
+
94
+ private
95
+
56
96
  def content_exceeds_screen_height?(content)
57
97
  screen_height, screen_width = begin
58
98
  Reline.get_screen_size
@@ -62,10 +102,10 @@ module IRB
62
102
 
63
103
  pageable_height = screen_height - 3 # leave some space for previous and the current prompt
64
104
 
65
- # If the content has more lines than the pageable height
66
- content.lines.count > pageable_height ||
67
- # Or if the content is a few long lines
68
- pageable_height * screen_width < Reline::Unicode.calculate_width(content, true)
105
+ return true if content.lines.size > pageable_height
106
+
107
+ _, overflow = take_first_page(screen_width, pageable_height) {|out| out.write content }
108
+ overflow
69
109
  end
70
110
 
71
111
  def setup_pager(retain_content:)
@@ -96,5 +136,86 @@ module IRB
96
136
  nil
97
137
  end
98
138
  end
139
+
140
+ # Writable IO that has page overflow callback
141
+ class PageOverflowIO
142
+ attr_reader :string, :first_page_lines
143
+
144
+ # Maximum size of a single cell in terminal
145
+ # Assumed worst case: "\e[1;3;4;9;38;2;255;128;128;48;2;128;128;255mA\e[0m"
146
+ # bold, italic, underline, crossed_out, RGB forgound, RGB background
147
+ MAX_CHAR_PER_CELL = 50
148
+
149
+ def initialize(width, height, overflow_callback, delay: nil)
150
+ @lines = []
151
+ @first_page_lines = nil
152
+ @width = width
153
+ @height = height
154
+ @buffer = +''
155
+ @overflow_callback = overflow_callback
156
+ @col = 0
157
+ @string = +''
158
+ @multipage = false
159
+ @delay_until = (Time.now + delay if delay)
160
+ end
161
+
162
+ def puts(text = '')
163
+ text = text.to_s unless text.is_a?(String)
164
+ write(text)
165
+ write("\n") unless text.end_with?("\n")
166
+ end
167
+
168
+ def write(text)
169
+ text = text.to_s unless text.is_a?(String)
170
+ @string << text
171
+ if @multipage
172
+ if @delay_until && Time.now > @delay_until
173
+ @overflow_callback.call(@first_page_lines)
174
+ @delay_until = nil
175
+ end
176
+ return
177
+ end
178
+
179
+ overflow_size = (@width * (@height - @lines.size) + @width - @col) * MAX_CHAR_PER_CELL
180
+ if text.size >= overflow_size
181
+ text = text[0, overflow_size]
182
+ overflow = true
183
+ end
184
+ @buffer << text
185
+ @col += Reline::Unicode.calculate_width(text, true)
186
+ if text.include?("\n") || @col >= @width
187
+ @buffer.lines.each do |line|
188
+ wrapped_lines = Reline::Unicode.split_by_width(line.chomp, @width).first.compact
189
+ wrapped_lines.pop if wrapped_lines.last == ''
190
+ @lines.concat(wrapped_lines)
191
+ if line.end_with?("\n")
192
+ if @lines.empty? || @lines.last.end_with?("\n")
193
+ @lines << "\n"
194
+ else
195
+ @lines[-1] += "\n"
196
+ end
197
+ end
198
+ end
199
+ @buffer.clear
200
+ @buffer << @lines.pop if !@lines.empty? && !@lines.last.end_with?("\n")
201
+ @col = Reline::Unicode.calculate_width(@buffer, true)
202
+ end
203
+ if overflow || @lines.size > @height || (@lines.size == @height && @col > 0)
204
+ @first_page_lines = @lines.take(@height)
205
+ if !@delay_until || Time.now > @delay_until
206
+ @overflow_callback.call(@first_page_lines)
207
+ @delay_until = nil
208
+ end
209
+ @multipage = true
210
+ end
211
+ end
212
+
213
+ def multipage?
214
+ @multipage
215
+ end
216
+
217
+ alias print write
218
+ alias << write
219
+ end
99
220
  end
100
221
  end