irb 1.13.2 → 1.15.2
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 +2 -0
- data/README.md +13 -293
- data/Rakefile +4 -6
- data/irb.gemspec +5 -3
- data/lib/irb/color.rb +1 -0
- data/lib/irb/color_printer.rb +10 -9
- data/lib/irb/command/base.rb +12 -14
- data/lib/irb/command/cd.rb +51 -0
- data/lib/irb/command/copy.rb +73 -0
- data/lib/irb/command/debug.rb +8 -6
- data/lib/irb/command/help.rb +1 -1
- 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 +41 -14
- data/lib/irb/context.rb +131 -54
- data/lib/irb/debug/ui.rb +2 -4
- data/lib/irb/debug.rb +7 -10
- data/lib/irb/default_commands.rb +22 -8
- data/lib/irb/easter-egg.rb +10 -6
- data/lib/irb/history.rb +84 -55
- data/lib/irb/init.rb +4 -2
- data/lib/irb/input-method.rb +31 -24
- data/lib/irb/inspector.rb +42 -36
- data/lib/irb/lc/ja/help-message +4 -4
- data/lib/irb/nesting_parser.rb +196 -194
- data/lib/irb/pager.rb +129 -7
- data/lib/irb/ruby-lex.rb +84 -82
- data/lib/irb/ruby_logo.aa +75 -37
- data/lib/irb/source_finder.rb +3 -4
- data/lib/irb/statement.rb +22 -1
- data/lib/irb/version.rb +2 -2
- data/lib/irb/workspace.rb +13 -31
- data/lib/irb.rb +75 -947
- data/man/irb.1 +37 -2
- metadata +20 -8
- data/.document +0 -4
data/lib/irb/history.rb
CHANGED
@@ -1,6 +1,36 @@
|
|
1
1
|
require "pathname"
|
2
2
|
|
3
3
|
module IRB
|
4
|
+
module History
|
5
|
+
DEFAULT_ENTRY_LIMIT = 1000
|
6
|
+
|
7
|
+
class << self
|
8
|
+
# Integer representation of <code>IRB.conf[:HISTORY_FILE]</code>.
|
9
|
+
def save_history
|
10
|
+
return 0 if IRB.conf[:SAVE_HISTORY] == false
|
11
|
+
return DEFAULT_ENTRY_LIMIT if IRB.conf[:SAVE_HISTORY] == true
|
12
|
+
IRB.conf[:SAVE_HISTORY].to_i
|
13
|
+
end
|
14
|
+
|
15
|
+
def save_history?
|
16
|
+
!save_history.zero?
|
17
|
+
end
|
18
|
+
|
19
|
+
def infinite?
|
20
|
+
save_history.negative?
|
21
|
+
end
|
22
|
+
|
23
|
+
# Might be nil when HOME and XDG_CONFIG_HOME are not available.
|
24
|
+
def history_file
|
25
|
+
if (history_file = IRB.conf[:HISTORY_FILE])
|
26
|
+
File.expand_path(history_file)
|
27
|
+
else
|
28
|
+
IRB.rc_file("_history")
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
4
34
|
module HistorySavingAbility # :nodoc:
|
5
35
|
def support_history_saving?
|
6
36
|
true
|
@@ -11,76 +41,75 @@ module IRB
|
|
11
41
|
end
|
12
42
|
|
13
43
|
def load_history
|
44
|
+
history_file = History.history_file
|
45
|
+
return unless File.exist?(history_file.to_s)
|
46
|
+
|
14
47
|
history = self.class::HISTORY
|
15
48
|
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
history.last << "\n" << l
|
27
|
-
else
|
28
|
-
history << l
|
29
|
-
end
|
30
|
-
}
|
31
|
-
end
|
32
|
-
@loaded_history_lines = history.size
|
33
|
-
@loaded_history_mtime = File.mtime(history_file)
|
49
|
+
File.open(history_file, "r:#{IRB.conf[:LC_MESSAGES].encoding}") do |f|
|
50
|
+
f.each { |l|
|
51
|
+
l = l.chomp
|
52
|
+
if self.class == RelineInputMethod and history.last&.end_with?("\\")
|
53
|
+
history.last.delete_suffix!("\\")
|
54
|
+
history.last << "\n" << l
|
55
|
+
else
|
56
|
+
history << l
|
57
|
+
end
|
58
|
+
}
|
34
59
|
end
|
60
|
+
@loaded_history_lines = history.size
|
61
|
+
@loaded_history_mtime = File.mtime(history_file)
|
35
62
|
end
|
36
63
|
|
37
64
|
def save_history
|
65
|
+
return unless History.save_history?
|
66
|
+
return unless (history_file = History.history_file)
|
67
|
+
unless ensure_history_file_writable(history_file)
|
68
|
+
warn <<~WARN
|
69
|
+
Can't write history to #{History.history_file.inspect} due to insufficient permissions.
|
70
|
+
Please verify the value of `IRB.conf[:HISTORY_FILE]`. Ensure the folder exists and that both the folder and file (if it exists) are writable.
|
71
|
+
WARN
|
72
|
+
return
|
73
|
+
end
|
74
|
+
|
38
75
|
history = self.class::HISTORY.to_a
|
39
76
|
|
40
|
-
if
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
77
|
+
if File.exist?(history_file) &&
|
78
|
+
File.mtime(history_file) != @loaded_history_mtime
|
79
|
+
history = history[@loaded_history_lines..-1] if @loaded_history_lines
|
80
|
+
append_history = true
|
81
|
+
end
|
45
82
|
|
46
|
-
|
47
|
-
|
83
|
+
File.open(history_file, (append_history ? "a" : "w"), 0o600, encoding: IRB.conf[:LC_MESSAGES]&.encoding) do |f|
|
84
|
+
hist = history.map { |l| l.scrub.split("\n").join("\\\n") }
|
48
85
|
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
File.chmod(0600, history_file)
|
53
|
-
end
|
54
|
-
rescue Errno::ENOENT
|
55
|
-
rescue Errno::EPERM
|
56
|
-
return
|
57
|
-
rescue
|
58
|
-
raise
|
86
|
+
unless append_history || History.infinite?
|
87
|
+
# Check size before slicing because array.last(huge_number) raises RangeError.
|
88
|
+
hist = hist.last(History.save_history) if hist.size > History.save_history
|
59
89
|
end
|
60
90
|
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
append_history = true
|
65
|
-
end
|
91
|
+
f.puts(hist)
|
92
|
+
end
|
93
|
+
end
|
66
94
|
|
67
|
-
|
68
|
-
unless Dir.exist?(pathname.dirname)
|
69
|
-
warn "Warning: The directory to save IRB's history file does not exist. Please double check `IRB.conf[:HISTORY_FILE]`'s value."
|
70
|
-
return
|
71
|
-
end
|
95
|
+
private
|
72
96
|
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
97
|
+
# Returns boolean whether writing to +history_file+ will be possible.
|
98
|
+
# Permissions of already existing +history_file+ are changed to
|
99
|
+
# owner-only-readable if necessary [BUG #7694].
|
100
|
+
def ensure_history_file_writable(history_file)
|
101
|
+
history_file = Pathname.new(history_file)
|
102
|
+
|
103
|
+
return false unless history_file.dirname.writable?
|
104
|
+
return true unless history_file.exist?
|
105
|
+
|
106
|
+
begin
|
107
|
+
if history_file.stat.mode & 0o66 != 0
|
108
|
+
history_file.chmod 0o600
|
83
109
|
end
|
110
|
+
true
|
111
|
+
rescue Errno::EPERM # no permissions
|
112
|
+
false
|
84
113
|
end
|
85
114
|
end
|
86
115
|
end
|
data/lib/irb/init.rb
CHANGED
@@ -80,7 +80,7 @@ module IRB # :nodoc:
|
|
80
80
|
@CONF[:USE_SINGLELINE] = false unless defined?(ReadlineInputMethod)
|
81
81
|
@CONF[:USE_COLORIZE] = (nc = ENV['NO_COLOR']).nil? || nc.empty?
|
82
82
|
@CONF[:USE_AUTOCOMPLETE] = ENV.fetch("IRB_USE_AUTOCOMPLETE", "true") != "false"
|
83
|
-
@CONF[:COMPLETOR] = ENV
|
83
|
+
@CONF[:COMPLETOR] = ENV["IRB_COMPLETOR"]&.to_sym
|
84
84
|
@CONF[:INSPECT_MODE] = true
|
85
85
|
@CONF[:USE_TRACER] = false
|
86
86
|
@CONF[:USE_LOADER] = false
|
@@ -93,7 +93,7 @@ module IRB # :nodoc:
|
|
93
93
|
@CONF[:VERBOSE] = nil
|
94
94
|
|
95
95
|
@CONF[:EVAL_HISTORY] = nil
|
96
|
-
@CONF[:SAVE_HISTORY] =
|
96
|
+
@CONF[:SAVE_HISTORY] = History::DEFAULT_ENTRY_LIMIT
|
97
97
|
|
98
98
|
@CONF[:BACK_TRACE_LIMIT] = 16
|
99
99
|
|
@@ -194,6 +194,8 @@ module IRB # :nodoc:
|
|
194
194
|
:'$' => :show_source,
|
195
195
|
:'@' => :whereami,
|
196
196
|
}
|
197
|
+
|
198
|
+
@CONF[:COPY_COMMAND] = ENV.fetch("IRB_COPY_COMMAND", nil)
|
197
199
|
end
|
198
200
|
|
199
201
|
def IRB.set_measure_callback(type = nil, arg = nil, &block)
|
data/lib/irb/input-method.rb
CHANGED
@@ -26,10 +26,11 @@ module IRB
|
|
26
26
|
|
27
27
|
def winsize
|
28
28
|
if instance_variable_defined?(:@stdout) && @stdout.tty?
|
29
|
-
@stdout.winsize
|
30
|
-
|
31
|
-
|
29
|
+
winsize = @stdout.winsize
|
30
|
+
# If width or height is 0, something is wrong.
|
31
|
+
return winsize unless winsize.include? 0
|
32
32
|
end
|
33
|
+
[24, 80]
|
33
34
|
end
|
34
35
|
|
35
36
|
# Whether this input method is still readable when there is no more data to
|
@@ -67,7 +68,9 @@ module IRB
|
|
67
68
|
#
|
68
69
|
# See IO#gets for more information.
|
69
70
|
def gets
|
70
|
-
|
71
|
+
# Workaround for debug compatibility test https://github.com/ruby/debug/pull/1100
|
72
|
+
puts if ENV['RUBY_DEBUG_TEST_UI']
|
73
|
+
|
71
74
|
print @prompt
|
72
75
|
line = @stdin.gets
|
73
76
|
@line[@line_no += 1] = line
|
@@ -171,11 +174,18 @@ module IRB
|
|
171
174
|
end
|
172
175
|
|
173
176
|
class ReadlineInputMethod < StdioInputMethod
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
|
177
|
+
class << self
|
178
|
+
def initialize_readline
|
179
|
+
return if defined?(self::Readline)
|
180
|
+
|
181
|
+
begin
|
182
|
+
require 'readline'
|
183
|
+
const_set(:Readline, ::Readline)
|
184
|
+
rescue LoadError
|
185
|
+
const_set(:Readline, ::Reline)
|
186
|
+
end
|
187
|
+
const_set(:HISTORY, self::Readline::HISTORY)
|
188
|
+
end
|
179
189
|
end
|
180
190
|
|
181
191
|
include HistorySavingAbility
|
@@ -212,8 +222,8 @@ module IRB
|
|
212
222
|
def gets
|
213
223
|
Readline.input = @stdin
|
214
224
|
Readline.output = @stdout
|
215
|
-
if l = readline(@prompt, false)
|
216
|
-
HISTORY.push(l) if !l.empty?
|
225
|
+
if l = Readline.readline(@prompt, false)
|
226
|
+
Readline::HISTORY.push(l) if !l.empty?
|
217
227
|
@line[@line_no += 1] = l + "\n"
|
218
228
|
else
|
219
229
|
@eof = true
|
@@ -235,7 +245,7 @@ module IRB
|
|
235
245
|
|
236
246
|
# For debug message
|
237
247
|
def inspect
|
238
|
-
readline_impl =
|
248
|
+
readline_impl = Readline == ::Reline ? 'Reline' : 'ext/readline'
|
239
249
|
str = "ReadlineInputMethod with #{readline_impl} #{Readline::VERSION}"
|
240
250
|
inputrc_path = File.expand_path(ENV['INPUTRC'] || '~/.inputrc')
|
241
251
|
str += " and #{inputrc_path}" if File.exist?(inputrc_path)
|
@@ -263,18 +273,9 @@ module IRB
|
|
263
273
|
@completion_params = [preposing, target, postposing, bind]
|
264
274
|
@completor.completion_candidates(preposing, target, postposing, bind: bind)
|
265
275
|
}
|
266
|
-
Reline.output_modifier_proc =
|
267
|
-
|
268
|
-
|
269
|
-
next unless IRB::Color.colorable?
|
270
|
-
lvars = IRB.CurrentContext&.local_variables || []
|
271
|
-
IRB::Color.colorize_code(output, complete: complete, local_variables: lvars)
|
272
|
-
end
|
273
|
-
else
|
274
|
-
proc do |output|
|
275
|
-
Reline::Unicode.escape_for_print(output)
|
276
|
-
end
|
277
|
-
end
|
276
|
+
Reline.output_modifier_proc = proc do |input, complete:|
|
277
|
+
IRB.CurrentContext.colorize_input(input, complete: complete)
|
278
|
+
end
|
278
279
|
Reline.dig_perfect_match_proc = ->(matched) { display_document(matched) }
|
279
280
|
Reline.autocompletion = IRB.conf[:USE_AUTOCOMPLETE]
|
280
281
|
|
@@ -353,9 +354,15 @@ module IRB
|
|
353
354
|
if show_easter_egg
|
354
355
|
IRB.__send__(:easter_egg)
|
355
356
|
else
|
357
|
+
# RDoc::RI::Driver#display_names uses pager command internally.
|
358
|
+
# Some pager command like `more` doesn't use alternate screen
|
359
|
+
# so we need to turn on and off alternate screen manually.
|
356
360
|
begin
|
361
|
+
print "\e[?1049h"
|
357
362
|
driver.display_names([name])
|
358
363
|
rescue RDoc::RI::Driver::NotFoundError
|
364
|
+
ensure
|
365
|
+
print "\e[?1049l"
|
359
366
|
end
|
360
367
|
end
|
361
368
|
end
|
data/lib/irb/inspector.rb
CHANGED
@@ -6,7 +6,6 @@
|
|
6
6
|
|
7
7
|
module IRB # :nodoc:
|
8
8
|
|
9
|
-
|
10
9
|
# Convenience method to create a new Inspector, using the given +inspect+
|
11
10
|
# proc, and optional +init+ proc and passes them to Inspector.new
|
12
11
|
#
|
@@ -43,38 +42,40 @@ module IRB # :nodoc:
|
|
43
42
|
# +:marshal+:: Using Marshal.dump
|
44
43
|
INSPECTORS = {}
|
45
44
|
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
# Example
|
53
|
-
#
|
54
|
-
# Inspector.def_inspector(key, init_p=nil){|v| v.inspect}
|
55
|
-
# Inspector.def_inspector([key1,..], init_p=nil){|v| v.inspect}
|
56
|
-
# Inspector.def_inspector(key, inspector)
|
57
|
-
# Inspector.def_inspector([key1,...], inspector)
|
58
|
-
def self.def_inspector(key, arg=nil, &block)
|
59
|
-
if block_given?
|
60
|
-
inspector = IRB::Inspector(block, arg)
|
61
|
-
else
|
62
|
-
inspector = arg
|
45
|
+
class << self
|
46
|
+
# Determines the inspector to use where +inspector+ is one of the keys passed
|
47
|
+
# during inspector definition.
|
48
|
+
def keys_with_inspector(inspector)
|
49
|
+
INSPECTORS.select{|k, v| v == inspector}.collect{|k, v| k}
|
63
50
|
end
|
64
51
|
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
52
|
+
# Example
|
53
|
+
#
|
54
|
+
# Inspector.def_inspector(key, init_p=nil){|v| v.inspect}
|
55
|
+
# Inspector.def_inspector([key1,..], init_p=nil){|v| v.inspect}
|
56
|
+
# Inspector.def_inspector(key, inspector)
|
57
|
+
# Inspector.def_inspector([key1,...], inspector)
|
58
|
+
def def_inspector(key, arg=nil, &block)
|
59
|
+
if block_given?
|
60
|
+
inspector = IRB::Inspector(block, arg)
|
61
|
+
else
|
62
|
+
inspector = arg
|
63
|
+
end
|
64
|
+
|
65
|
+
case key
|
66
|
+
when Array
|
67
|
+
for k in key
|
68
|
+
def_inspector(k, inspector)
|
69
|
+
end
|
70
|
+
when Symbol
|
71
|
+
INSPECTORS[key] = inspector
|
72
|
+
INSPECTORS[key.to_s] = inspector
|
73
|
+
when String
|
74
|
+
INSPECTORS[key] = inspector
|
75
|
+
INSPECTORS[key.intern] = inspector
|
76
|
+
else
|
77
|
+
INSPECTORS[key] = inspector
|
69
78
|
end
|
70
|
-
when Symbol
|
71
|
-
INSPECTORS[key] = inspector
|
72
|
-
INSPECTORS[key.to_s] = inspector
|
73
|
-
when String
|
74
|
-
INSPECTORS[key] = inspector
|
75
|
-
INSPECTORS[key.intern] = inspector
|
76
|
-
else
|
77
|
-
INSPECTORS[key] = inspector
|
78
79
|
end
|
79
80
|
end
|
80
81
|
|
@@ -91,9 +92,14 @@ module IRB # :nodoc:
|
|
91
92
|
@init.call if @init
|
92
93
|
end
|
93
94
|
|
95
|
+
def support_stream_output?
|
96
|
+
second_parameter_type = @inspect.parameters[1]&.first
|
97
|
+
second_parameter_type == :req || second_parameter_type == :opt
|
98
|
+
end
|
99
|
+
|
94
100
|
# Proc to call when the input is evaluated and output in irb.
|
95
|
-
def inspect_value(v)
|
96
|
-
@inspect.call(v)
|
101
|
+
def inspect_value(v, output, colorize: true)
|
102
|
+
support_stream_output? ? @inspect.call(v, output, colorize: colorize) : output << @inspect.call(v, colorize: colorize)
|
97
103
|
rescue => e
|
98
104
|
puts "An error occurred when inspecting the object: #{e.inspect}"
|
99
105
|
|
@@ -109,11 +115,11 @@ module IRB # :nodoc:
|
|
109
115
|
end
|
110
116
|
|
111
117
|
Inspector.def_inspector([false, :to_s, :raw]){|v| v.to_s}
|
112
|
-
Inspector.def_inspector([:p, :inspect]){|v|
|
113
|
-
Color.colorize_code(v.inspect, colorable: Color.colorable? && Color.inspect_colorable?(v))
|
118
|
+
Inspector.def_inspector([:p, :inspect]){|v, colorize: true|
|
119
|
+
Color.colorize_code(v.inspect, colorable: colorize && Color.colorable? && Color.inspect_colorable?(v))
|
114
120
|
}
|
115
|
-
Inspector.def_inspector([true, :pp, :pretty_inspect], proc{require_relative "color_printer"}){|v|
|
116
|
-
IRB::ColorPrinter.pp(v,
|
121
|
+
Inspector.def_inspector([true, :pp, :pretty_inspect], proc{require_relative "color_printer"}){|v, output, colorize: true|
|
122
|
+
IRB::ColorPrinter.pp(v, output, colorize: colorize)
|
117
123
|
}
|
118
124
|
Inspector.def_inspector([:yaml, :YAML], proc{require "yaml"}){|v|
|
119
125
|
begin
|
data/lib/irb/lc/ja/help-message
CHANGED
@@ -8,7 +8,7 @@ Usage: irb.rb [options] [programfile] [arguments]
|
|
8
8
|
-w ruby -w と同じ.
|
9
9
|
-W[level=2] ruby -W と同じ.
|
10
10
|
--context-mode n 新しいワークスペースを作成した時に関連する Binding
|
11
|
-
オブジェクトの作成方法を 0 から
|
11
|
+
オブジェクトの作成方法を 0 から 4 のいずれかに設定する.
|
12
12
|
--extra-doc-dir 指定したディレクトリのドキュメントを追加で読み込む.
|
13
13
|
--echo 実行結果を表示する(デフォルト).
|
14
14
|
--noecho 実行結果を表示しない.
|
@@ -33,9 +33,9 @@ Usage: irb.rb [options] [programfile] [arguments]
|
|
33
33
|
補完に正規表現を利用する.
|
34
34
|
--type-completor 補完に型情報を利用する.
|
35
35
|
--prompt prompt-mode/--prompt-mode prompt-mode
|
36
|
-
|
37
|
-
|
38
|
-
|
36
|
+
プロンプトモードを切り替える.
|
37
|
+
現在定義されているプロンプトモードは,
|
38
|
+
default, classic, simple, inf-ruby, xmp, null.
|
39
39
|
--inf-ruby-mode emacsのinf-ruby-mode用のプロンプト表示を行なう. 特
|
40
40
|
に指定がない限り, シングルラインエディタとマルチラ
|
41
41
|
インエディタは使わなくなる.
|