irb 1.1.0.pre.1 → 1.1.0.pre.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/irb.gemspec +2 -1
- data/lib/irb.rb +25 -13
- data/lib/irb/cmd/help.rb +9 -5
- data/lib/irb/color.rb +218 -0
- data/lib/irb/completion.rb +3 -3
- data/lib/irb/context.rb +4 -4
- data/lib/irb/ext/history.rb +2 -1
- data/lib/irb/ext/save-history.rb +18 -3
- data/lib/irb/ext/use-loader.rb +3 -0
- data/lib/irb/init.rb +2 -2
- data/lib/irb/input-method.rb +10 -0
- data/lib/irb/lc/help-message +1 -1
- data/lib/irb/lc/ja/help-message +1 -1
- data/lib/irb/ruby-lex.rb +162 -26
- data/lib/irb/version.rb +2 -2
- metadata +17 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 81da8e8b11979aca60cc0806c7a679f8a854a2f9f38d215f714d377aaac579ae
|
4
|
+
data.tar.gz: 05f6c327f9226f5789498c182c5b5c4cfe2ada443f65fc3daa577c76e5dcad8e
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 5ab9d21b32e138399ac7eafee532f15f07b85dadc0acb35eb1cd41814a000cb74c69f98455d90b2f7930d23eb79d708468387dcc5b5efb82ac866720e7227cbe
|
7
|
+
data.tar.gz: 2d2836d6c47a4040c7e8b27442b504e9eced9ffd6c2169f7d50dd5439b6534c6f477d51ffa5f5b14fa02c3cecd0f400b9ea8762d399db0d81532b65b2af3ce62
|
data/irb.gemspec
CHANGED
@@ -16,11 +16,12 @@ Gem::Specification.new do |spec|
|
|
16
16
|
spec.homepage = "https://github.com/ruby/irb"
|
17
17
|
spec.license = "BSD-2-Clause"
|
18
18
|
|
19
|
-
spec.files = ["LICENSE.txt", "README.md", "exe/irb", "irb.gemspec", "lib/irb.rb", "lib/irb/cmd/chws.rb", "lib/irb/cmd/fork.rb", "lib/irb/cmd/help.rb", "lib/irb/cmd/load.rb", "lib/irb/cmd/nop.rb", "lib/irb/cmd/pushws.rb", "lib/irb/cmd/subirb.rb", "lib/irb/completion.rb", "lib/irb/context.rb", "lib/irb/ext/change-ws.rb", "lib/irb/ext/history.rb", "lib/irb/ext/loader.rb", "lib/irb/ext/multi-irb.rb", "lib/irb/ext/save-history.rb", "lib/irb/ext/tracer.rb", "lib/irb/ext/use-loader.rb", "lib/irb/ext/workspaces.rb", "lib/irb/extend-command.rb", "lib/irb/frame.rb", "lib/irb/help.rb", "lib/irb/init.rb", "lib/irb/input-method.rb", "lib/irb/inspector.rb", "lib/irb/lc/.document", "lib/irb/lc/error.rb", "lib/irb/lc/help-message", "lib/irb/lc/ja/encoding_aliases.rb", "lib/irb/lc/ja/error.rb", "lib/irb/lc/ja/help-message", "lib/irb/locale.rb", "lib/irb/magic-file.rb", "lib/irb/notifier.rb", "lib/irb/output-method.rb", "lib/irb/ruby-lex.rb", "lib/irb/ruby-token.rb", "lib/irb/slex.rb", "lib/irb/src_encoding.rb", "lib/irb/version.rb", "lib/irb/workspace.rb", "lib/irb/ws-for-case-2.rb", "lib/irb/xmp.rb"]
|
19
|
+
spec.files = ["LICENSE.txt", "README.md", "exe/irb", "irb.gemspec", "lib/irb.rb", "lib/irb/cmd/chws.rb", "lib/irb/cmd/fork.rb", "lib/irb/cmd/help.rb", "lib/irb/cmd/load.rb", "lib/irb/cmd/nop.rb", "lib/irb/cmd/pushws.rb", "lib/irb/cmd/subirb.rb", "lib/irb/completion.rb", "lib/irb/context.rb", "lib/irb/color.rb", "lib/irb/ext/change-ws.rb", "lib/irb/ext/history.rb", "lib/irb/ext/loader.rb", "lib/irb/ext/multi-irb.rb", "lib/irb/ext/save-history.rb", "lib/irb/ext/tracer.rb", "lib/irb/ext/use-loader.rb", "lib/irb/ext/workspaces.rb", "lib/irb/extend-command.rb", "lib/irb/frame.rb", "lib/irb/help.rb", "lib/irb/init.rb", "lib/irb/input-method.rb", "lib/irb/inspector.rb", "lib/irb/lc/.document", "lib/irb/lc/error.rb", "lib/irb/lc/help-message", "lib/irb/lc/ja/encoding_aliases.rb", "lib/irb/lc/ja/error.rb", "lib/irb/lc/ja/help-message", "lib/irb/locale.rb", "lib/irb/magic-file.rb", "lib/irb/notifier.rb", "lib/irb/output-method.rb", "lib/irb/ruby-lex.rb", "lib/irb/ruby-token.rb", "lib/irb/slex.rb", "lib/irb/src_encoding.rb", "lib/irb/version.rb", "lib/irb/workspace.rb", "lib/irb/ws-for-case-2.rb", "lib/irb/xmp.rb"]
|
20
20
|
spec.bindir = "exe"
|
21
21
|
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
22
22
|
spec.require_paths = ["lib"]
|
23
23
|
|
24
|
+
spec.add_dependency "reline", ">= 0.0.1"
|
24
25
|
spec.add_development_dependency "bundler"
|
25
26
|
spec.add_development_dependency "rake"
|
26
27
|
end
|
data/lib/irb.rb
CHANGED
@@ -110,9 +110,9 @@ require "irb/version"
|
|
110
110
|
#
|
111
111
|
# === Auto indentation
|
112
112
|
#
|
113
|
-
# To
|
113
|
+
# To disable auto-indent mode in irb, add the following to your +.irbrc+:
|
114
114
|
#
|
115
|
-
# IRB.conf[:AUTO_INDENT] =
|
115
|
+
# IRB.conf[:AUTO_INDENT] = false
|
116
116
|
#
|
117
117
|
# === Autocompletion
|
118
118
|
#
|
@@ -122,13 +122,12 @@ require "irb/version"
|
|
122
122
|
#
|
123
123
|
# === History
|
124
124
|
#
|
125
|
-
# By default, irb
|
125
|
+
# By default, irb will store the last 1000 commands you used in
|
126
|
+
# <code>~/.irb_history</code>.
|
126
127
|
#
|
127
|
-
# If you want to
|
128
|
+
# If you want to disable history, add the following to your +.irbrc+:
|
128
129
|
#
|
129
|
-
# IRB.conf[:SAVE_HISTORY] =
|
130
|
-
#
|
131
|
-
# This will now store the last 1000 commands in <code>~/.irb_history</code>.
|
130
|
+
# IRB.conf[:SAVE_HISTORY] = nil
|
132
131
|
#
|
133
132
|
# See IRB::Context#save_history= for more information.
|
134
133
|
#
|
@@ -141,7 +140,7 @@ require "irb/version"
|
|
141
140
|
# This example can be used in your +.irbrc+
|
142
141
|
#
|
143
142
|
# IRB.conf[:PROMPT][:MY_PROMPT] = { # name of prompt mode
|
144
|
-
# :AUTO_INDENT =>
|
143
|
+
# :AUTO_INDENT => false, # disables auto-indent mode
|
145
144
|
# :PROMPT_I => ">> ", # simple prompt
|
146
145
|
# :PROMPT_S => nil, # prompt for continuated strings
|
147
146
|
# :PROMPT_C => nil, # prompt for continuated statement
|
@@ -170,6 +169,7 @@ require "irb/version"
|
|
170
169
|
#
|
171
170
|
# IRB.conf[:PROMPT_MODE][:DEFAULT] = {
|
172
171
|
# :PROMPT_I => "%N(%m):%03n:%i> ",
|
172
|
+
# :PROMPT_N => "%N(%m):%03n:%i> ",
|
173
173
|
# :PROMPT_S => "%N(%m):%03n:%i%l ",
|
174
174
|
# :PROMPT_C => "%N(%m):%03n:%i* ",
|
175
175
|
# :RETURN => "%s\n" # used to printf
|
@@ -461,14 +461,16 @@ module IRB
|
|
461
461
|
else
|
462
462
|
@context.io.prompt = p = ""
|
463
463
|
end
|
464
|
-
if @context.auto_indent_mode
|
464
|
+
if @context.auto_indent_mode and !@context.io.respond_to?(:auto_indent)
|
465
465
|
unless ltype
|
466
|
-
|
466
|
+
prompt_i = @context.prompt_i.nil? ? "" : @context.prompt_i
|
467
|
+
ind = prompt(prompt_i, ltype, indent, line_no)[/.*\z/].size +
|
467
468
|
indent * 2 - p.size
|
468
469
|
ind += 2 if continue
|
469
470
|
@context.io.prompt = p + " " * ind if ind > 0
|
470
471
|
end
|
471
472
|
end
|
473
|
+
@context.io.prompt
|
472
474
|
end
|
473
475
|
|
474
476
|
@scanner.set_input(@context.io) do
|
@@ -489,6 +491,8 @@ module IRB
|
|
489
491
|
end
|
490
492
|
end
|
491
493
|
|
494
|
+
@scanner.set_auto_indent(@context) if @context.auto_indent_mode
|
495
|
+
|
492
496
|
@scanner.each_top_level_statement do |line, line_no|
|
493
497
|
signal_status(:IN_EVAL) do
|
494
498
|
begin
|
@@ -666,10 +670,18 @@ module IRB
|
|
666
670
|
when "l"
|
667
671
|
ltype
|
668
672
|
when "i"
|
669
|
-
if
|
670
|
-
|
673
|
+
if indent < 0
|
674
|
+
if $1
|
675
|
+
"-".rjust($1.to_i)
|
676
|
+
else
|
677
|
+
"-"
|
678
|
+
end
|
671
679
|
else
|
672
|
-
|
680
|
+
if $1
|
681
|
+
format("%" + $1 + "d", indent)
|
682
|
+
else
|
683
|
+
indent.to_s
|
684
|
+
end
|
673
685
|
end
|
674
686
|
when "n"
|
675
687
|
if $1
|
data/lib/irb/cmd/help.rb
CHANGED
@@ -9,17 +9,18 @@
|
|
9
9
|
#
|
10
10
|
#
|
11
11
|
|
12
|
-
require 'rdoc/ri/driver'
|
13
|
-
|
14
12
|
require_relative "nop"
|
15
13
|
|
16
14
|
# :stopdoc:
|
17
15
|
module IRB
|
18
16
|
module ExtendCommand
|
19
17
|
class Help < Nop
|
20
|
-
|
21
|
-
|
22
|
-
|
18
|
+
def execute(*names)
|
19
|
+
require 'rdoc/ri/driver'
|
20
|
+
IRB::ExtendCommand::Help.const_set(:Ri, RDoc::RI::Driver.new)
|
21
|
+
rescue LoadError, SystemExit
|
22
|
+
IRB::ExtendCommand::Help.remove_method(:execute)
|
23
|
+
# raise NoMethodError in ensure
|
23
24
|
else
|
24
25
|
def execute(*names)
|
25
26
|
if names.empty?
|
@@ -35,6 +36,9 @@ module IRB
|
|
35
36
|
end
|
36
37
|
nil
|
37
38
|
end
|
39
|
+
nil
|
40
|
+
ensure
|
41
|
+
execute(*names)
|
38
42
|
end
|
39
43
|
end
|
40
44
|
end
|
data/lib/irb/color.rb
ADDED
@@ -0,0 +1,218 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
require 'reline'
|
3
|
+
require 'ripper'
|
4
|
+
|
5
|
+
module IRB # :nodoc:
|
6
|
+
module Color
|
7
|
+
CLEAR = 0
|
8
|
+
BOLD = 1
|
9
|
+
UNDERLINE = 4
|
10
|
+
REVERSE = 7
|
11
|
+
RED = 31
|
12
|
+
GREEN = 32
|
13
|
+
YELLOW = 33
|
14
|
+
BLUE = 34
|
15
|
+
MAGENTA = 35
|
16
|
+
CYAN = 36
|
17
|
+
|
18
|
+
TOKEN_KEYWORDS = {
|
19
|
+
on_kw: ['nil', 'self', 'true', 'false', '__FILE__', '__LINE__'],
|
20
|
+
on_const: ['ENV'],
|
21
|
+
}
|
22
|
+
private_constant :TOKEN_KEYWORDS
|
23
|
+
|
24
|
+
# A constant of all-bit 1 to match any Ripper's state in #dispatch_seq
|
25
|
+
ALL = -1
|
26
|
+
private_constant :ALL
|
27
|
+
|
28
|
+
begin
|
29
|
+
# Following pry's colors where possible, but sometimes having a compromise like making
|
30
|
+
# backtick and regexp as red (string's color, because they're sharing tokens).
|
31
|
+
TOKEN_SEQ_EXPRS = {
|
32
|
+
on_CHAR: [[BLUE, BOLD], ALL],
|
33
|
+
on_backtick: [[RED], ALL],
|
34
|
+
on_comment: [[BLUE, BOLD], ALL],
|
35
|
+
on_const: [[BLUE, BOLD, UNDERLINE], ALL],
|
36
|
+
on_embexpr_beg: [[RED], ALL],
|
37
|
+
on_embexpr_end: [[RED], ALL],
|
38
|
+
on_embvar: [[RED], ALL],
|
39
|
+
on_float: [[MAGENTA, BOLD], ALL],
|
40
|
+
on_gvar: [[GREEN, BOLD], ALL],
|
41
|
+
on_heredoc_beg: [[RED], ALL],
|
42
|
+
on_heredoc_end: [[RED], ALL],
|
43
|
+
on_ident: [[BLUE, BOLD], Ripper::EXPR_ENDFN],
|
44
|
+
on_imaginary: [[BLUE, BOLD], ALL],
|
45
|
+
on_int: [[BLUE, BOLD], ALL],
|
46
|
+
on_kw: [[GREEN], ALL],
|
47
|
+
on_label: [[MAGENTA], ALL],
|
48
|
+
on_label_end: [[RED], ALL],
|
49
|
+
on_qsymbols_beg: [[RED], ALL],
|
50
|
+
on_qwords_beg: [[RED], ALL],
|
51
|
+
on_rational: [[BLUE, BOLD], ALL],
|
52
|
+
on_regexp_beg: [[RED, BOLD], ALL],
|
53
|
+
on_regexp_end: [[RED, BOLD], ALL],
|
54
|
+
on_symbeg: [[YELLOW], ALL],
|
55
|
+
on_tstring_beg: [[RED], ALL],
|
56
|
+
on_tstring_content: [[RED], ALL],
|
57
|
+
on_tstring_end: [[RED], ALL],
|
58
|
+
on_words_beg: [[RED], ALL],
|
59
|
+
on_parse_error: [[RED, REVERSE], ALL],
|
60
|
+
compile_error: [[RED, REVERSE], ALL],
|
61
|
+
}
|
62
|
+
rescue NameError
|
63
|
+
# Give up highlighting Ripper-incompatible older Ruby
|
64
|
+
TOKEN_SEQ_EXPRS = {}
|
65
|
+
end
|
66
|
+
private_constant :TOKEN_SEQ_EXPRS
|
67
|
+
|
68
|
+
class << self
|
69
|
+
def colorable?
|
70
|
+
$stdout.tty? && supported? && (/mswin|mingw/ =~ RUBY_PLATFORM || (ENV.key?('TERM') && ENV['TERM'] != 'dumb'))
|
71
|
+
end
|
72
|
+
|
73
|
+
def inspect_colorable?(obj)
|
74
|
+
case obj
|
75
|
+
when String, Symbol, Regexp, Integer, Float, FalseClass, TrueClass, NilClass
|
76
|
+
true
|
77
|
+
when Hash
|
78
|
+
obj.all? { |k, v| inspect_colorable?(k) && inspect_colorable?(v) }
|
79
|
+
when Array
|
80
|
+
obj.all? { |o| inspect_colorable?(o) }
|
81
|
+
when Range
|
82
|
+
inspect_colorable?(obj.begin) && inspect_colorable?(obj.end)
|
83
|
+
when Module
|
84
|
+
!obj.name.nil?
|
85
|
+
else
|
86
|
+
false
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
def clear
|
91
|
+
return '' unless colorable?
|
92
|
+
"\e[#{CLEAR}m"
|
93
|
+
end
|
94
|
+
|
95
|
+
def colorize(text, seq)
|
96
|
+
return text unless colorable?
|
97
|
+
seq = seq.map { |s| "\e[#{const_get(s)}m" }.join('')
|
98
|
+
"#{seq}#{text}#{clear}"
|
99
|
+
end
|
100
|
+
|
101
|
+
# If `complete` is false (code is incomplete), this does not warn compile_error.
|
102
|
+
# This option is needed to avoid warning a user when the compile_error is happening
|
103
|
+
# because the input is not wrong but just incomplete.
|
104
|
+
def colorize_code(code, complete: true)
|
105
|
+
return code unless colorable?
|
106
|
+
|
107
|
+
symbol_state = SymbolState.new
|
108
|
+
colored = +''
|
109
|
+
length = 0
|
110
|
+
|
111
|
+
scan(code, allow_last_error: !complete) do |token, str, expr|
|
112
|
+
in_symbol = symbol_state.scan_token(token)
|
113
|
+
str.each_line do |line|
|
114
|
+
line = Reline::Unicode.escape_for_print(line)
|
115
|
+
if seq = dispatch_seq(token, expr, line, in_symbol: in_symbol)
|
116
|
+
colored << seq.map { |s| "\e[#{s}m" }.join('')
|
117
|
+
colored << line.sub(/\Z/, clear)
|
118
|
+
else
|
119
|
+
colored << line
|
120
|
+
end
|
121
|
+
end
|
122
|
+
length += str.bytesize
|
123
|
+
end
|
124
|
+
|
125
|
+
# give up colorizing incomplete Ripper tokens
|
126
|
+
if length != code.bytesize
|
127
|
+
return Reline::Unicode.escape_for_print(code)
|
128
|
+
end
|
129
|
+
|
130
|
+
colored
|
131
|
+
end
|
132
|
+
|
133
|
+
private
|
134
|
+
|
135
|
+
# Ripper::Lexer::Elem#state is supported on Ruby 2.5+
|
136
|
+
def supported?
|
137
|
+
return @supported if defined?(@supported)
|
138
|
+
@supported = Gem::Version.new(RUBY_VERSION) >= Gem::Version.new('2.5.0')
|
139
|
+
end
|
140
|
+
|
141
|
+
def scan(code, allow_last_error:)
|
142
|
+
pos = [1, 0]
|
143
|
+
|
144
|
+
lexer = Ripper::Lexer.new(code)
|
145
|
+
if lexer.respond_to?(:scan) # Ruby 2.7+
|
146
|
+
lexer.scan.each do |elem|
|
147
|
+
str = elem.tok
|
148
|
+
next if allow_last_error and /meets end of file|unexpected end-of-input/ =~ elem.message
|
149
|
+
next if ([elem.pos[0], elem.pos[1] + str.bytesize] <=> pos) <= 0
|
150
|
+
|
151
|
+
str.each_line do |line|
|
152
|
+
if line.end_with?("\n")
|
153
|
+
pos[0] += 1
|
154
|
+
pos[1] = 0
|
155
|
+
else
|
156
|
+
pos[1] += line.bytesize
|
157
|
+
end
|
158
|
+
end
|
159
|
+
|
160
|
+
yield(elem.event, str, elem.state)
|
161
|
+
end
|
162
|
+
else
|
163
|
+
lexer.parse.each do |elem|
|
164
|
+
yield(elem.event, elem.tok, elem.state)
|
165
|
+
end
|
166
|
+
end
|
167
|
+
end
|
168
|
+
|
169
|
+
def dispatch_seq(token, expr, str, in_symbol:)
|
170
|
+
if token == :on_parse_error or token == :compile_error
|
171
|
+
TOKEN_SEQ_EXPRS[token][0]
|
172
|
+
elsif in_symbol
|
173
|
+
[YELLOW]
|
174
|
+
elsif TOKEN_KEYWORDS.fetch(token, []).include?(str)
|
175
|
+
[CYAN, BOLD]
|
176
|
+
elsif (seq, exprs = TOKEN_SEQ_EXPRS[token]; (expr & (exprs || 0)) != 0)
|
177
|
+
seq
|
178
|
+
else
|
179
|
+
nil
|
180
|
+
end
|
181
|
+
end
|
182
|
+
end
|
183
|
+
|
184
|
+
# A class to manage a state to know whether the current token is for Symbol or not.
|
185
|
+
class SymbolState
|
186
|
+
def initialize
|
187
|
+
# Push `true` to detect Symbol. `false` to increase the nest level for non-Symbol.
|
188
|
+
@stack = []
|
189
|
+
end
|
190
|
+
|
191
|
+
# Return true if the token is a part of Symbol.
|
192
|
+
def scan_token(token)
|
193
|
+
prev_state = @stack.last
|
194
|
+
case token
|
195
|
+
when :on_symbeg
|
196
|
+
@stack << true
|
197
|
+
when :on_ident, :on_op, :on_const, :on_ivar, :on_cvar, :on_gvar, :on_kw
|
198
|
+
if @stack.last # Pop only when it's Symbol
|
199
|
+
@stack.pop
|
200
|
+
return prev_state
|
201
|
+
end
|
202
|
+
when :on_tstring_beg
|
203
|
+
@stack << false
|
204
|
+
when :on_embexpr_beg
|
205
|
+
@stack << false
|
206
|
+
return prev_state
|
207
|
+
when :on_tstring_end # :on_tstring_end may close Symbol
|
208
|
+
@stack.pop
|
209
|
+
return prev_state
|
210
|
+
when :on_embexpr_end
|
211
|
+
@stack.pop
|
212
|
+
end
|
213
|
+
@stack.last
|
214
|
+
end
|
215
|
+
end
|
216
|
+
private_constant :SymbolState
|
217
|
+
end
|
218
|
+
end
|
data/lib/irb/completion.rb
CHANGED
@@ -8,7 +8,7 @@
|
|
8
8
|
#
|
9
9
|
|
10
10
|
require "readline"
|
11
|
-
|
11
|
+
autoload :RDoc, "rdoc"
|
12
12
|
|
13
13
|
module IRB
|
14
14
|
module InputCompletor # :nodoc:
|
@@ -237,7 +237,7 @@ module IRB
|
|
237
237
|
candidates.uniq!
|
238
238
|
end
|
239
239
|
if doc_namespace
|
240
|
-
"#{rec.
|
240
|
+
"#{rec.name}#{sep}#{candidates.find{ |i| i == message }}"
|
241
241
|
else
|
242
242
|
select_message(receiver, message, candidates, sep)
|
243
243
|
end
|
@@ -267,8 +267,8 @@ module IRB
|
|
267
267
|
end
|
268
268
|
end
|
269
269
|
|
270
|
-
RDocRIDriver = RDoc::RI::Driver.new
|
271
270
|
PerfectMatchedProc = ->(matched) {
|
271
|
+
RDocRIDriver ||= RDoc::RI::Driver.new
|
272
272
|
if matched =~ /\A(?:::)?RubyVM/ and not ENV['RUBY_YES_I_AM_NOT_A_NORMAL_USER']
|
273
273
|
File.open(File.join(__dir__, 'ruby_logo.aa')) do |f|
|
274
274
|
RDocRIDriver.page do |io|
|
data/lib/irb/context.rb
CHANGED
@@ -194,17 +194,17 @@ module IRB
|
|
194
194
|
# Can be either the default <code>IRB.conf[:AUTO_INDENT]</code>, or the
|
195
195
|
# mode set by #prompt_mode=
|
196
196
|
#
|
197
|
-
# To
|
197
|
+
# To disable auto-indentation in irb:
|
198
198
|
#
|
199
|
-
# IRB.conf[:AUTO_INDENT] =
|
199
|
+
# IRB.conf[:AUTO_INDENT] = false
|
200
200
|
#
|
201
201
|
# or
|
202
202
|
#
|
203
|
-
# irb_context.auto_indent_mode =
|
203
|
+
# irb_context.auto_indent_mode = false
|
204
204
|
#
|
205
205
|
# or
|
206
206
|
#
|
207
|
-
# IRB.CurrentContext.auto_indent_mode =
|
207
|
+
# IRB.CurrentContext.auto_indent_mode = false
|
208
208
|
#
|
209
209
|
# See IRB@Configuration for more information.
|
210
210
|
attr_accessor :auto_indent_mode
|
data/lib/irb/ext/history.rb
CHANGED
@@ -22,7 +22,7 @@ module IRB # :nodoc:
|
|
22
22
|
def set_last_value(value)
|
23
23
|
_set_last_value(value)
|
24
24
|
|
25
|
-
if @eval_history
|
25
|
+
if defined?(@eval_history) && @eval_history
|
26
26
|
@eval_history_values.push @line_no, @last_value
|
27
27
|
@workspace.evaluate self, "__ = IRB.CurrentContext.instance_eval{@eval_history_values}"
|
28
28
|
end
|
@@ -30,6 +30,7 @@ module IRB # :nodoc:
|
|
30
30
|
@last_value
|
31
31
|
end
|
32
32
|
|
33
|
+
remove_method :eval_history= if method_defined?(:eval_history=)
|
33
34
|
# The command result history limit.
|
34
35
|
attr_reader :eval_history
|
35
36
|
# Sets command result history limit.
|
data/lib/irb/ext/save-history.rb
CHANGED
@@ -27,7 +27,7 @@ module IRB
|
|
27
27
|
IRB.conf[:SAVE_HISTORY]
|
28
28
|
end
|
29
29
|
|
30
|
-
remove_method :save_history= if
|
30
|
+
remove_method :save_history= if method_defined?(:save_history=)
|
31
31
|
# Sets <code>IRB.conf[:SAVE_HISTORY]</code> to the given +val+ and calls
|
32
32
|
# #init_save_history with this context.
|
33
33
|
#
|
@@ -73,7 +73,15 @@ module IRB
|
|
73
73
|
history_file = IRB.rc_file("_history") unless history_file
|
74
74
|
if File.exist?(history_file)
|
75
75
|
open(history_file) do |f|
|
76
|
-
f.each {|l|
|
76
|
+
f.each { |l|
|
77
|
+
l = l.chomp
|
78
|
+
if history.last&.end_with?("\\")
|
79
|
+
history.last.delete_suffix!("\\")
|
80
|
+
history.last << "\n" << l
|
81
|
+
else
|
82
|
+
history << l
|
83
|
+
end
|
84
|
+
}
|
77
85
|
end
|
78
86
|
end
|
79
87
|
end
|
@@ -98,7 +106,14 @@ module IRB
|
|
98
106
|
end
|
99
107
|
|
100
108
|
open(history_file, 'w', 0600 ) do |f|
|
101
|
-
hist = history.to_a
|
109
|
+
hist = history.to_a.map { |l|
|
110
|
+
split_lines = l.split("\n")
|
111
|
+
if split_lines.size == 1
|
112
|
+
l
|
113
|
+
else
|
114
|
+
split_lines.join("\\\n")
|
115
|
+
end
|
116
|
+
}
|
102
117
|
f.puts(hist[-num..-1] || hist)
|
103
118
|
end
|
104
119
|
end
|
data/lib/irb/ext/use-loader.rb
CHANGED
@@ -20,10 +20,12 @@ end
|
|
20
20
|
|
21
21
|
module IRB
|
22
22
|
module ExtendCommandBundle
|
23
|
+
remove_method :irb_load if method_defined?(:irb_load)
|
23
24
|
# Loads the given file similarly to Kernel#load, see IrbLoader#irb_load
|
24
25
|
def irb_load(*opts, &b)
|
25
26
|
ExtendCommand::Load.execute(irb_context, *opts, &b)
|
26
27
|
end
|
28
|
+
remove_method :irb_require if method_defined?(:irb_require)
|
27
29
|
# Loads the given file similarly to Kernel#require
|
28
30
|
def irb_require(*opts, &b)
|
29
31
|
ExtendCommand::Require.execute(irb_context, *opts, &b)
|
@@ -44,6 +46,7 @@ module IRB
|
|
44
46
|
|
45
47
|
alias use_loader? use_loader
|
46
48
|
|
49
|
+
remove_method :use_loader= if method_defined?(:use_loader=)
|
47
50
|
# Sets IRB.conf[:USE_LOADER]
|
48
51
|
#
|
49
52
|
# See #use_loader for more information.
|
data/lib/irb/init.rb
CHANGED
@@ -54,7 +54,7 @@ module IRB # :nodoc:
|
|
54
54
|
@CONF[:VERBOSE] = nil
|
55
55
|
|
56
56
|
@CONF[:EVAL_HISTORY] = nil
|
57
|
-
@CONF[:SAVE_HISTORY] =
|
57
|
+
@CONF[:SAVE_HISTORY] = 1000
|
58
58
|
|
59
59
|
@CONF[:BACK_TRACE_LIMIT] = 16
|
60
60
|
|
@@ -105,7 +105,7 @@ module IRB # :nodoc:
|
|
105
105
|
}
|
106
106
|
|
107
107
|
@CONF[:PROMPT_MODE] = (STDIN.tty? ? :DEFAULT : :NULL)
|
108
|
-
@CONF[:AUTO_INDENT] =
|
108
|
+
@CONF[:AUTO_INDENT] = true
|
109
109
|
|
110
110
|
@CONF[:CONTEXT_MODE] = 3 # use binding in function on TOPLEVEL_BINDING
|
111
111
|
@CONF[:SINGLE_IRB] = false
|
data/lib/irb/input-method.rb
CHANGED
@@ -240,12 +240,22 @@ module IRB
|
|
240
240
|
@check_termination_proc = block
|
241
241
|
end
|
242
242
|
|
243
|
+
def dynamic_prompt(&block)
|
244
|
+
@prompt_proc = block
|
245
|
+
end
|
246
|
+
|
247
|
+
def auto_indent(&block)
|
248
|
+
@auto_indent_proc = block
|
249
|
+
end
|
250
|
+
|
243
251
|
# Reads the next line from this input method.
|
244
252
|
#
|
245
253
|
# See IO#gets for more information.
|
246
254
|
def gets
|
247
255
|
Reline.input = @stdin
|
248
256
|
Reline.output = @stdout
|
257
|
+
Reline.prompt_proc = @prompt_proc
|
258
|
+
Reline.auto_indent_proc = @auto_indent_proc if @auto_indent_proc
|
249
259
|
if l = readmultiline(@prompt, false, &@check_termination_proc)
|
250
260
|
HISTORY.push(l) if !l.empty?
|
251
261
|
@line[@line_no += 1] = l + "\n"
|
data/lib/irb/lc/help-message
CHANGED
@@ -22,7 +22,7 @@ Usage: irb.rb [options] [programfile] [arguments]
|
|
22
22
|
when new workspace was created
|
23
23
|
--echo Show result(default)
|
24
24
|
--noecho Don't show result
|
25
|
-
--inspect Use `inspect' for output
|
25
|
+
--inspect Use `inspect' for output
|
26
26
|
--noinspect Don't use inspect for output
|
27
27
|
--readline Use Readline extension module
|
28
28
|
--noreadline Don't use Readline extension module
|
data/lib/irb/lc/ja/help-message
CHANGED
@@ -21,7 +21,7 @@ Usage: irb.rb [options] [programfile] [arguments]
|
|
21
21
|
オブジェクトの作成方法を 0 から 3 のいずれかに設定する.
|
22
22
|
--echo 実行結果を表示する(デフォルト).
|
23
23
|
--noecho 実行結果を表示しない.
|
24
|
-
--inspect 結果出力にinspect
|
24
|
+
--inspect 結果出力にinspectを用いる.
|
25
25
|
--noinspect 結果出力にinspectを用いない.
|
26
26
|
--readline readlineライブラリを利用する.
|
27
27
|
--noreadline readlineライブラリを利用しない.
|
data/lib/irb/ruby-lex.rb
CHANGED
@@ -33,18 +33,26 @@ class RubyLex
|
|
33
33
|
if @io.respond_to?(:check_termination)
|
34
34
|
@io.check_termination do |code|
|
35
35
|
code.gsub!(/\s*\z/, '').concat("\n")
|
36
|
-
|
37
|
-
continue
|
38
|
-
code_block_open = check_code_block(code)
|
39
|
-
indent = process_nesting_level
|
40
|
-
ltype = process_literal_type
|
41
|
-
if code_block_open or ltype or continue or indent > 0
|
36
|
+
ltype, indent, continue, code_block_open = check_state(code)
|
37
|
+
if ltype or indent > 0 or continue or code_block_open
|
42
38
|
false
|
43
39
|
else
|
44
40
|
true
|
45
41
|
end
|
46
42
|
end
|
47
43
|
end
|
44
|
+
if @io.respond_to?(:dynamic_prompt)
|
45
|
+
@io.dynamic_prompt do |lines|
|
46
|
+
lines << '' if lines.empty?
|
47
|
+
result = []
|
48
|
+
lines.each_index { |i|
|
49
|
+
c = lines[0..i].map{ |l| l + "\n" }.join
|
50
|
+
ltype, indent, continue, code_block_open = check_state(c)
|
51
|
+
result << @prompt.call(ltype, indent, continue || code_block_open, @line_no + i)
|
52
|
+
}
|
53
|
+
result
|
54
|
+
end
|
55
|
+
end
|
48
56
|
if p.respond_to?(:call)
|
49
57
|
@input = p
|
50
58
|
elsif block_given?
|
@@ -63,6 +71,40 @@ class RubyLex
|
|
63
71
|
end
|
64
72
|
end
|
65
73
|
|
74
|
+
def set_auto_indent(context)
|
75
|
+
if @io.respond_to?(:auto_indent) and context.auto_indent_mode
|
76
|
+
@io.auto_indent do |lines, line_index, byte_pointer, is_newline|
|
77
|
+
if is_newline
|
78
|
+
md = lines[line_index - 1].match(/(\A +)/)
|
79
|
+
prev_spaces = md.nil? ? 0 : md[1].count(' ')
|
80
|
+
@tokens = Ripper.lex(lines[0..line_index].join("\n"))
|
81
|
+
depth_difference = check_newline_depth_difference
|
82
|
+
prev_spaces + depth_difference * 2
|
83
|
+
else
|
84
|
+
code = line_index.zero? ? '' : lines[0..(line_index - 1)].map{ |l| l + "\n" }.join
|
85
|
+
last_line = lines[line_index]&.byteslice(0, byte_pointer)
|
86
|
+
code += last_line if last_line
|
87
|
+
@tokens = Ripper.lex(code)
|
88
|
+
corresponding_token_depth = check_corresponding_token_depth
|
89
|
+
if corresponding_token_depth
|
90
|
+
corresponding_token_depth
|
91
|
+
else
|
92
|
+
nil
|
93
|
+
end
|
94
|
+
end
|
95
|
+
end
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
99
|
+
def check_state(code)
|
100
|
+
@tokens = Ripper.lex(code)
|
101
|
+
ltype = process_literal_type
|
102
|
+
indent = process_nesting_level
|
103
|
+
continue = process_continue
|
104
|
+
code_block_open = check_code_block(code)
|
105
|
+
[ltype, indent, continue, code_block_open]
|
106
|
+
end
|
107
|
+
|
66
108
|
def prompt
|
67
109
|
if @prompt
|
68
110
|
@prompt.call(@ltype, @indent, @continue, @line_no)
|
@@ -87,7 +129,7 @@ class RubyLex
|
|
87
129
|
unless l = lex
|
88
130
|
throw :TERM_INPUT if @line == ''
|
89
131
|
else
|
90
|
-
@line_no +=
|
132
|
+
@line_no += l.count("\n")
|
91
133
|
next if l == "\n"
|
92
134
|
@line.concat l
|
93
135
|
if @code_block_open or @ltype or @continue or @indent > 0
|
@@ -127,14 +169,13 @@ class RubyLex
|
|
127
169
|
end
|
128
170
|
|
129
171
|
def process_continue
|
130
|
-
continued_bits = Ripper::EXPR_BEG | Ripper::EXPR_FNAME
|
131
172
|
# last token is always newline
|
132
173
|
if @tokens.size >= 2 and @tokens[-2][1] == :on_regexp_end
|
133
174
|
# end of regexp literal
|
134
175
|
return false
|
135
176
|
elsif @tokens.size >= 2 and @tokens[-2][1] == :on_semicolon
|
136
177
|
return false
|
137
|
-
elsif @tokens.size >= 2 and @tokens[-2][1] == :on_kw and
|
178
|
+
elsif @tokens.size >= 2 and @tokens[-2][1] == :on_kw and ['begin', 'else', 'ensure'].include?(@tokens[-2][2])
|
138
179
|
return false
|
139
180
|
elsif @tokens.size >= 3 and @tokens[-3][1] == :on_symbeg and @tokens[-2][1] == :on_ivar
|
140
181
|
# This is for :@a or :@1 because :@1 ends with EXPR_FNAME
|
@@ -149,7 +190,7 @@ class RubyLex
|
|
149
190
|
return true
|
150
191
|
elsif @tokens.size >= 1 and @tokens[-1][1] == :on_heredoc_end # "EOH\n"
|
151
192
|
return false
|
152
|
-
elsif @tokens.size >= 2 and @tokens[-2][3].anybits?(
|
193
|
+
elsif @tokens.size >= 2 and defined?(Ripper::EXPR_BEG) and @tokens[-2][3].anybits?(Ripper::EXPR_BEG | Ripper::EXPR_FNAME)
|
153
194
|
# end of literal except for regexp
|
154
195
|
return true
|
155
196
|
end
|
@@ -221,36 +262,40 @@ class RubyLex
|
|
221
262
|
$VERBOSE = verbose
|
222
263
|
end
|
223
264
|
|
224
|
-
|
225
|
-
|
226
|
-
|
227
|
-
|
228
|
-
|
229
|
-
|
230
|
-
|
231
|
-
|
232
|
-
|
233
|
-
|
234
|
-
|
235
|
-
|
236
|
-
|
265
|
+
if defined?(Ripper::EXPR_BEG)
|
266
|
+
last_lex_state = @tokens.last[3]
|
267
|
+
if last_lex_state.allbits?(Ripper::EXPR_BEG)
|
268
|
+
return false
|
269
|
+
elsif last_lex_state.allbits?(Ripper::EXPR_DOT)
|
270
|
+
return true
|
271
|
+
elsif last_lex_state.allbits?(Ripper::EXPR_CLASS)
|
272
|
+
return true
|
273
|
+
elsif last_lex_state.allbits?(Ripper::EXPR_FNAME)
|
274
|
+
return true
|
275
|
+
elsif last_lex_state.allbits?(Ripper::EXPR_VALUE)
|
276
|
+
return true
|
277
|
+
elsif last_lex_state.allbits?(Ripper::EXPR_ARG)
|
278
|
+
return false
|
279
|
+
end
|
237
280
|
end
|
238
281
|
|
239
282
|
false
|
240
283
|
end
|
241
284
|
|
242
285
|
def process_nesting_level
|
243
|
-
|
286
|
+
indent = 0
|
287
|
+
@tokens.each_with_index { |t, index|
|
244
288
|
case t[1]
|
245
289
|
when :on_lbracket, :on_lbrace, :on_lparen
|
246
290
|
indent += 1
|
247
291
|
when :on_rbracket, :on_rbrace, :on_rparen
|
248
292
|
indent -= 1
|
249
293
|
when :on_kw
|
294
|
+
next if index > 0 and @tokens[index - 1][3].allbits?(Ripper::EXPR_FNAME)
|
250
295
|
case t[2]
|
251
296
|
when 'def', 'do', 'case', 'for', 'begin', 'class', 'module'
|
252
297
|
indent += 1
|
253
|
-
when 'if', 'unless', 'while', 'until'
|
298
|
+
when 'if', 'unless', 'while', 'until'
|
254
299
|
# postfix if/unless/while/until/rescue must be Ripper::EXPR_LABEL
|
255
300
|
indent += 1 unless t[3].allbits?(Ripper::EXPR_LABEL)
|
256
301
|
when 'end'
|
@@ -258,8 +303,99 @@ class RubyLex
|
|
258
303
|
end
|
259
304
|
end
|
260
305
|
# percent literals are not indented
|
261
|
-
indent
|
262
306
|
}
|
307
|
+
indent
|
308
|
+
end
|
309
|
+
|
310
|
+
def check_newline_depth_difference
|
311
|
+
depth_difference = 0
|
312
|
+
@tokens.each_with_index do |t, index|
|
313
|
+
case t[1]
|
314
|
+
when :on_ignored_nl, :on_nl
|
315
|
+
if index != (@tokens.size - 1)
|
316
|
+
depth_difference = 0
|
317
|
+
end
|
318
|
+
next
|
319
|
+
when :on_sp
|
320
|
+
next
|
321
|
+
end
|
322
|
+
case t[1]
|
323
|
+
when :on_lbracket, :on_lbrace, :on_lparen
|
324
|
+
depth_difference += 1
|
325
|
+
when :on_rbracket, :on_rbrace, :on_rparen
|
326
|
+
depth_difference -= 1
|
327
|
+
when :on_kw
|
328
|
+
next if index > 0 and @tokens[index - 1][3].allbits?(Ripper::EXPR_FNAME)
|
329
|
+
case t[2]
|
330
|
+
when 'def', 'do', 'case', 'for', 'begin', 'class', 'module'
|
331
|
+
depth_difference += 1
|
332
|
+
when 'if', 'unless', 'while', 'until'
|
333
|
+
# postfix if/unless/while/until/rescue must be Ripper::EXPR_LABEL
|
334
|
+
unless t[3].allbits?(Ripper::EXPR_LABEL)
|
335
|
+
depth_difference += 1
|
336
|
+
end
|
337
|
+
when 'else', 'elsif', 'rescue', 'ensure', 'when', 'in'
|
338
|
+
depth_difference += 1
|
339
|
+
end
|
340
|
+
end
|
341
|
+
end
|
342
|
+
depth_difference
|
343
|
+
end
|
344
|
+
|
345
|
+
def check_corresponding_token_depth
|
346
|
+
corresponding_token_depth = nil
|
347
|
+
is_first_spaces_of_line = true
|
348
|
+
is_first_printable_of_line = true
|
349
|
+
spaces_of_nest = []
|
350
|
+
spaces_at_line_head = 0
|
351
|
+
@tokens.each_with_index do |t, index|
|
352
|
+
corresponding_token_depth = nil
|
353
|
+
case t[1]
|
354
|
+
when :on_ignored_nl, :on_nl
|
355
|
+
spaces_at_line_head = 0
|
356
|
+
is_first_spaces_of_line = true
|
357
|
+
is_first_printable_of_line = true
|
358
|
+
next
|
359
|
+
when :on_sp
|
360
|
+
spaces_at_line_head = t[2].count(' ') if is_first_spaces_of_line
|
361
|
+
is_first_spaces_of_line = false
|
362
|
+
next
|
363
|
+
end
|
364
|
+
case t[1]
|
365
|
+
when :on_lbracket, :on_lbrace, :on_lparen
|
366
|
+
spaces_of_nest.push(spaces_at_line_head)
|
367
|
+
when :on_rbracket, :on_rbrace, :on_rparen
|
368
|
+
if is_first_printable_of_line
|
369
|
+
corresponding_token_depth = spaces_of_nest.pop
|
370
|
+
else
|
371
|
+
spaces_of_nest.pop
|
372
|
+
corresponding_token_depth = nil
|
373
|
+
end
|
374
|
+
when :on_kw
|
375
|
+
next if index > 0 and @tokens[index - 1][3].allbits?(Ripper::EXPR_FNAME)
|
376
|
+
case t[2]
|
377
|
+
when 'def', 'do', 'case', 'for', 'begin', 'class', 'module'
|
378
|
+
spaces_of_nest.push(spaces_at_line_head)
|
379
|
+
when 'if', 'unless', 'while', 'until'
|
380
|
+
# postfix if/unless/while/until/rescue must be Ripper::EXPR_LABEL
|
381
|
+
unless t[3].allbits?(Ripper::EXPR_LABEL)
|
382
|
+
spaces_of_nest.push(spaces_at_line_head)
|
383
|
+
end
|
384
|
+
when 'else', 'elsif', 'rescue', 'ensure', 'when', 'in'
|
385
|
+
corresponding_token_depth = spaces_of_nest.last
|
386
|
+
when 'end'
|
387
|
+
if is_first_printable_of_line
|
388
|
+
corresponding_token_depth = spaces_of_nest.pop
|
389
|
+
else
|
390
|
+
spaces_of_nest.pop
|
391
|
+
corresponding_token_depth = nil
|
392
|
+
end
|
393
|
+
end
|
394
|
+
end
|
395
|
+
is_first_spaces_of_line = false
|
396
|
+
is_first_printable_of_line = false
|
397
|
+
end
|
398
|
+
corresponding_token_depth
|
263
399
|
end
|
264
400
|
|
265
401
|
def check_string_literal
|
data/lib/irb/version.rb
CHANGED
metadata
CHANGED
@@ -1,15 +1,29 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: irb
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.1.0.pre.
|
4
|
+
version: 1.1.0.pre.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Keiju ISHITSUKA
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2019-07-
|
11
|
+
date: 2019-07-14 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: reline
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ">="
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: 0.0.1
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ">="
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: 0.0.1
|
13
27
|
- !ruby/object:Gem::Dependency
|
14
28
|
name: bundler
|
15
29
|
requirement: !ruby/object:Gem::Requirement
|
@@ -58,6 +72,7 @@ files:
|
|
58
72
|
- lib/irb/cmd/nop.rb
|
59
73
|
- lib/irb/cmd/pushws.rb
|
60
74
|
- lib/irb/cmd/subirb.rb
|
75
|
+
- lib/irb/color.rb
|
61
76
|
- lib/irb/completion.rb
|
62
77
|
- lib/irb/context.rb
|
63
78
|
- lib/irb/ext/change-ws.rb
|