irb 1.14.1 → 1.15.1
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.
- checksums.yaml +4 -4
- data/Gemfile +3 -1
- data/README.md +13 -299
- data/Rakefile +4 -6
- data/irb.gemspec +2 -2
- data/lib/irb/color.rb +1 -0
- data/lib/irb/color_printer.rb +10 -9
- data/lib/irb/command/base.rb +3 -7
- data/lib/irb/command/copy.rb +73 -0
- data/lib/irb/command/history.rb +1 -1
- data/lib/irb/command/internal_helpers.rb +1 -1
- data/lib/irb/command/ls.rb +23 -11
- data/lib/irb/completion.rb +12 -5
- data/lib/irb/context.rb +105 -56
- data/lib/irb/debug/ui.rb +2 -4
- data/lib/irb/debug.rb +1 -0
- data/lib/irb/default_commands.rb +4 -1
- data/lib/irb/easter-egg.rb +2 -1
- data/lib/irb/history.rb +84 -55
- data/lib/irb/init.rb +4 -2
- data/lib/irb/input-method.rb +9 -1
- data/lib/irb/inspector.rb +11 -6
- data/lib/irb/lc/ja/help-message +4 -4
- data/lib/irb/nesting_parser.rb +1 -1
- data/lib/irb/pager.rb +125 -7
- data/lib/irb/source_finder.rb +2 -3
- data/lib/irb/statement.rb +21 -0
- data/lib/irb/version.rb +2 -2
- data/lib/irb/workspace.rb +6 -26
- data/lib/irb.rb +46 -901
- data/man/irb.1 +37 -2
- metadata +19 -8
- data/.document +0 -4
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.
|
@@ -34,7 +36,12 @@ module IRB
|
|
34
36
|
# So to properly terminate the pager with Ctrl-C, we need to catch `IRB::Abort` and kill the pager process
|
35
37
|
rescue IRB::Abort
|
36
38
|
begin
|
37
|
-
|
39
|
+
begin
|
40
|
+
Process.kill("TERM", pid) if pid
|
41
|
+
rescue Errno::EINVAL
|
42
|
+
# SIGTERM not supported (windows)
|
43
|
+
Process.kill("KILL", pid)
|
44
|
+
end
|
38
45
|
rescue Errno::ESRCH
|
39
46
|
# Pager process already terminated
|
40
47
|
end
|
@@ -42,12 +49,42 @@ module IRB
|
|
42
49
|
rescue Errno::EPIPE
|
43
50
|
end
|
44
51
|
|
45
|
-
private
|
46
|
-
|
47
52
|
def should_page?
|
48
53
|
IRB.conf[:USE_PAGER] && STDIN.tty? && (ENV.key?("TERM") && ENV["TERM"] != "dumb")
|
49
54
|
end
|
50
55
|
|
56
|
+
def page_with_preview(width, height, formatter_proc)
|
57
|
+
overflow_callback = ->(lines) do
|
58
|
+
modified_output = formatter_proc.call(lines.join, true)
|
59
|
+
content, = take_first_page(width, [height - 2, 0].max) {|o| o.write modified_output }
|
60
|
+
content = content.chomp
|
61
|
+
content = "#{content}\e[0m" if Color.colorable?
|
62
|
+
$stdout.puts content
|
63
|
+
$stdout.puts 'Preparing full inspection value...'
|
64
|
+
end
|
65
|
+
out = PageOverflowIO.new(width, height, overflow_callback, delay: 0.1)
|
66
|
+
yield out
|
67
|
+
content = formatter_proc.call(out.string, out.multipage?)
|
68
|
+
if out.multipage?
|
69
|
+
page(retain_content: true) do |io|
|
70
|
+
io.puts content
|
71
|
+
end
|
72
|
+
else
|
73
|
+
$stdout.puts content
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
def take_first_page(width, height)
|
78
|
+
overflow_callback = proc do |lines|
|
79
|
+
return lines.join, true
|
80
|
+
end
|
81
|
+
out = Pager::PageOverflowIO.new(width, height, overflow_callback)
|
82
|
+
yield out
|
83
|
+
[out.string, false]
|
84
|
+
end
|
85
|
+
|
86
|
+
private
|
87
|
+
|
51
88
|
def content_exceeds_screen_height?(content)
|
52
89
|
screen_height, screen_width = begin
|
53
90
|
Reline.get_screen_size
|
@@ -57,10 +94,10 @@ module IRB
|
|
57
94
|
|
58
95
|
pageable_height = screen_height - 3 # leave some space for previous and the current prompt
|
59
96
|
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
97
|
+
return true if content.lines.size > pageable_height
|
98
|
+
|
99
|
+
_, overflow = take_first_page(screen_width, pageable_height) {|out| out.write content }
|
100
|
+
overflow
|
64
101
|
end
|
65
102
|
|
66
103
|
def setup_pager(retain_content:)
|
@@ -91,5 +128,86 @@ module IRB
|
|
91
128
|
nil
|
92
129
|
end
|
93
130
|
end
|
131
|
+
|
132
|
+
# Writable IO that has page overflow callback
|
133
|
+
class PageOverflowIO
|
134
|
+
attr_reader :string, :first_page_lines
|
135
|
+
|
136
|
+
# Maximum size of a single cell in terminal
|
137
|
+
# Assumed worst case: "\e[1;3;4;9;38;2;255;128;128;48;2;128;128;255mA\e[0m"
|
138
|
+
# bold, italic, underline, crossed_out, RGB forgound, RGB background
|
139
|
+
MAX_CHAR_PER_CELL = 50
|
140
|
+
|
141
|
+
def initialize(width, height, overflow_callback, delay: nil)
|
142
|
+
@lines = []
|
143
|
+
@first_page_lines = nil
|
144
|
+
@width = width
|
145
|
+
@height = height
|
146
|
+
@buffer = +''
|
147
|
+
@overflow_callback = overflow_callback
|
148
|
+
@col = 0
|
149
|
+
@string = +''
|
150
|
+
@multipage = false
|
151
|
+
@delay_until = (Time.now + delay if delay)
|
152
|
+
end
|
153
|
+
|
154
|
+
def puts(text = '')
|
155
|
+
text = text.to_s unless text.is_a?(String)
|
156
|
+
write(text)
|
157
|
+
write("\n") unless text.end_with?("\n")
|
158
|
+
end
|
159
|
+
|
160
|
+
def write(text)
|
161
|
+
text = text.to_s unless text.is_a?(String)
|
162
|
+
@string << text
|
163
|
+
if @multipage
|
164
|
+
if @delay_until && Time.now > @delay_until
|
165
|
+
@overflow_callback.call(@first_page_lines)
|
166
|
+
@delay_until = nil
|
167
|
+
end
|
168
|
+
return
|
169
|
+
end
|
170
|
+
|
171
|
+
overflow_size = (@width * (@height - @lines.size) + @width - @col) * MAX_CHAR_PER_CELL
|
172
|
+
if text.size >= overflow_size
|
173
|
+
text = text[0, overflow_size]
|
174
|
+
overflow = true
|
175
|
+
end
|
176
|
+
@buffer << text
|
177
|
+
@col += Reline::Unicode.calculate_width(text, true)
|
178
|
+
if text.include?("\n") || @col >= @width
|
179
|
+
@buffer.lines.each do |line|
|
180
|
+
wrapped_lines = Reline::Unicode.split_by_width(line.chomp, @width).first.compact
|
181
|
+
wrapped_lines.pop if wrapped_lines.last == ''
|
182
|
+
@lines.concat(wrapped_lines)
|
183
|
+
if line.end_with?("\n")
|
184
|
+
if @lines.empty? || @lines.last.end_with?("\n")
|
185
|
+
@lines << "\n"
|
186
|
+
else
|
187
|
+
@lines[-1] += "\n"
|
188
|
+
end
|
189
|
+
end
|
190
|
+
end
|
191
|
+
@buffer.clear
|
192
|
+
@buffer << @lines.pop unless @lines.last.end_with?("\n")
|
193
|
+
@col = Reline::Unicode.calculate_width(@buffer, true)
|
194
|
+
end
|
195
|
+
if overflow || @lines.size > @height || (@lines.size == @height && @col > 0)
|
196
|
+
@first_page_lines = @lines.take(@height)
|
197
|
+
if !@delay_until || Time.now > @delay_until
|
198
|
+
@overflow_callback.call(@first_page_lines)
|
199
|
+
@delay_until = nil
|
200
|
+
end
|
201
|
+
@multipage = true
|
202
|
+
end
|
203
|
+
end
|
204
|
+
|
205
|
+
def multipage?
|
206
|
+
@multipage
|
207
|
+
end
|
208
|
+
|
209
|
+
alias print write
|
210
|
+
alias << write
|
211
|
+
end
|
94
212
|
end
|
95
213
|
end
|
data/lib/irb/source_finder.rb
CHANGED
@@ -125,9 +125,8 @@ module IRB
|
|
125
125
|
end
|
126
126
|
|
127
127
|
def eval_receiver_or_owner(code)
|
128
|
-
|
129
|
-
|
130
|
-
rescue NameError
|
128
|
+
@irb_context.workspace.binding.eval(code)
|
129
|
+
rescue Exception
|
131
130
|
raise EvaluationError
|
132
131
|
end
|
133
132
|
|
data/lib/irb/statement.rb
CHANGED
@@ -54,6 +54,27 @@ module IRB
|
|
54
54
|
end
|
55
55
|
end
|
56
56
|
|
57
|
+
class IncorrectAlias < Statement
|
58
|
+
attr_reader :message
|
59
|
+
|
60
|
+
def initialize(message)
|
61
|
+
@code = ""
|
62
|
+
@message = message
|
63
|
+
end
|
64
|
+
|
65
|
+
def should_be_handled_by_debugger?
|
66
|
+
false
|
67
|
+
end
|
68
|
+
|
69
|
+
def is_assignment?
|
70
|
+
false
|
71
|
+
end
|
72
|
+
|
73
|
+
def suppresses_echo?
|
74
|
+
true
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
57
78
|
class Command < Statement
|
58
79
|
attr_reader :command_class, :arg
|
59
80
|
|
data/lib/irb/version.rb
CHANGED
data/lib/irb/workspace.rb
CHANGED
@@ -4,8 +4,6 @@
|
|
4
4
|
# by Keiju ISHITSUKA(keiju@ruby-lang.org)
|
5
5
|
#
|
6
6
|
|
7
|
-
require "delegate"
|
8
|
-
|
9
7
|
require_relative "helper_method"
|
10
8
|
|
11
9
|
IRB::TOPLEVEL_BINDING = binding
|
@@ -16,7 +14,7 @@ module IRB # :nodoc:
|
|
16
14
|
# set self to main if specified, otherwise
|
17
15
|
# inherit main from TOPLEVEL_BINDING.
|
18
16
|
def initialize(*main)
|
19
|
-
if main[0]
|
17
|
+
if Binding === main[0]
|
20
18
|
@binding = main.shift
|
21
19
|
elsif IRB.conf[:SINGLE_IRB]
|
22
20
|
@binding = TOPLEVEL_BINDING
|
@@ -70,37 +68,16 @@ EOF
|
|
70
68
|
unless main.empty?
|
71
69
|
case @main
|
72
70
|
when Module
|
73
|
-
@binding = eval("IRB.conf[:__MAIN__].module_eval('binding', __FILE__, __LINE__)", @binding, __FILE__, __LINE__)
|
71
|
+
@binding = eval("::IRB.conf[:__MAIN__].module_eval('::Kernel.binding', __FILE__, __LINE__)", @binding, __FILE__, __LINE__)
|
74
72
|
else
|
75
73
|
begin
|
76
|
-
@binding = eval("IRB.conf[:__MAIN__].instance_eval('binding', __FILE__, __LINE__)", @binding, __FILE__, __LINE__)
|
74
|
+
@binding = eval("::IRB.conf[:__MAIN__].instance_eval('::Kernel.binding', __FILE__, __LINE__)", @binding, __FILE__, __LINE__)
|
77
75
|
rescue TypeError
|
78
76
|
fail CantChangeBinding, @main.inspect
|
79
77
|
end
|
80
78
|
end
|
81
79
|
end
|
82
80
|
|
83
|
-
case @main
|
84
|
-
when Object
|
85
|
-
use_delegator = @main.frozen?
|
86
|
-
else
|
87
|
-
use_delegator = true
|
88
|
-
end
|
89
|
-
|
90
|
-
if use_delegator
|
91
|
-
@main = SimpleDelegator.new(@main)
|
92
|
-
IRB.conf[:__MAIN__] = @main
|
93
|
-
@main.singleton_class.class_eval do
|
94
|
-
private
|
95
|
-
define_method(:binding, Kernel.instance_method(:binding))
|
96
|
-
define_method(:local_variables, Kernel.instance_method(:local_variables))
|
97
|
-
# Define empty method to avoid delegator warning, will be overridden.
|
98
|
-
define_method(:exit) {|*a, &b| }
|
99
|
-
define_method(:exit!) {|*a, &b| }
|
100
|
-
end
|
101
|
-
@binding = eval("IRB.conf[:__MAIN__].instance_eval('binding', __FILE__, __LINE__)", @binding, *@binding.source_location)
|
102
|
-
end
|
103
|
-
|
104
81
|
@binding.local_variable_set(:_, nil)
|
105
82
|
end
|
106
83
|
|
@@ -111,6 +88,9 @@ EOF
|
|
111
88
|
attr_reader :main
|
112
89
|
|
113
90
|
def load_helper_methods_to_main
|
91
|
+
# Do not load helper methods to frozen objects and BasicObject
|
92
|
+
return unless Object === @main && !@main.frozen?
|
93
|
+
|
114
94
|
ancestors = class<<main;ancestors;end
|
115
95
|
main.extend ExtendCommandBundle if !ancestors.include?(ExtendCommandBundle)
|
116
96
|
main.extend HelpersContainer if !ancestors.include?(HelpersContainer)
|