irb 1.7.0 → 1.7.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/lib/irb/cmd/irb_info.rb +14 -18
- data/lib/irb/cmd/nop.rb +4 -8
- data/lib/irb/cmd/show_source.rb +3 -3
- data/lib/irb/completion.rb +2 -2
- data/lib/irb/context.rb +19 -16
- data/lib/irb/ext/loader.rb +2 -0
- data/lib/irb/extend-command.rb +1 -1
- data/lib/irb/nesting_parser.rb +227 -0
- data/lib/irb/ruby-lex.rb +220 -495
- data/lib/irb/version.rb +2 -2
- data/lib/irb.rb +23 -29
- metadata +3 -3
- data/lib/irb/cmd/fork.rb +0 -34
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: d8dc3e14a57010a1ece61f5ca0111e98742f29daea5ab1ad1bdc48e0de6e55b2
|
4
|
+
data.tar.gz: 7da9b8c9e3e3c68384c0f65eb030d7874c8f0d07c20ce651ab7b54f5bfdfb9bd
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 73173c7af8ffa50bfa26a49ad1c2b7a2db12a89b006980b2b0d649bc6a03b776359ce03d20a9a7dde493c3c64e70e85864809436b546b571f23e77774748f35e
|
7
|
+
data.tar.gz: 371777b42d560af3196092e98555a46d9c93c4efa592e8f38365dd0f5be6863ea4a50d6160baedf7d7d7c6914087394cde33e0fd57e17bec68a63f64f8265a89
|
data/lib/irb/cmd/irb_info.rb
CHANGED
@@ -11,24 +11,20 @@ module IRB
|
|
11
11
|
description "Show information about IRB."
|
12
12
|
|
13
13
|
def execute
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
str
|
29
|
-
end
|
30
|
-
alias_method :to_s, :inspect
|
31
|
-
}.new
|
14
|
+
str = "Ruby version: #{RUBY_VERSION}\n"
|
15
|
+
str += "IRB version: #{IRB.version}\n"
|
16
|
+
str += "InputMethod: #{IRB.CurrentContext.io.inspect}\n"
|
17
|
+
str += ".irbrc path: #{IRB.rc_file}\n" if File.exist?(IRB.rc_file)
|
18
|
+
str += "RUBY_PLATFORM: #{RUBY_PLATFORM}\n"
|
19
|
+
str += "LANG env: #{ENV["LANG"]}\n" if ENV["LANG"] && !ENV["LANG"].empty?
|
20
|
+
str += "LC_ALL env: #{ENV["LC_ALL"]}\n" if ENV["LC_ALL"] && !ENV["LC_ALL"].empty?
|
21
|
+
str += "East Asian Ambiguous Width: #{Reline.ambiguous_width.inspect}\n"
|
22
|
+
if RbConfig::CONFIG['host_os'] =~ /mswin|msys|mingw|cygwin|bccwin|wince|emc/
|
23
|
+
codepage = `chcp`.b.sub(/.*: (\d+)\n/, '\1')
|
24
|
+
str += "Code page: #{codepage}\n"
|
25
|
+
end
|
26
|
+
puts str
|
27
|
+
nil
|
32
28
|
end
|
33
29
|
end
|
34
30
|
end
|
data/lib/irb/cmd/nop.rb
CHANGED
@@ -30,23 +30,19 @@ module IRB
|
|
30
30
|
end
|
31
31
|
end
|
32
32
|
|
33
|
-
def self.execute(
|
34
|
-
command = new(
|
33
|
+
def self.execute(irb_context, *opts, **kwargs, &block)
|
34
|
+
command = new(irb_context)
|
35
35
|
command.execute(*opts, **kwargs, &block)
|
36
36
|
rescue CommandArgumentError => e
|
37
37
|
puts e.message
|
38
38
|
end
|
39
39
|
|
40
|
-
def initialize(
|
41
|
-
@irb_context =
|
40
|
+
def initialize(irb_context)
|
41
|
+
@irb_context = irb_context
|
42
42
|
end
|
43
43
|
|
44
44
|
attr_reader :irb_context
|
45
45
|
|
46
|
-
def irb
|
47
|
-
@irb_context.irb
|
48
|
-
end
|
49
|
-
|
50
46
|
def execute(*opts)
|
51
47
|
#nop
|
52
48
|
end
|
data/lib/irb/cmd/show_source.rb
CHANGED
@@ -58,9 +58,9 @@ module IRB
|
|
58
58
|
tokens.chunk { |tok| tok.pos[0] }.each do |lnum, chunk|
|
59
59
|
code = lines[0..lnum].join
|
60
60
|
prev_tokens.concat chunk
|
61
|
-
continue = lex.
|
62
|
-
|
63
|
-
if !continue &&
|
61
|
+
continue = lex.should_continue?(prev_tokens)
|
62
|
+
syntax = lex.check_code_syntax(code)
|
63
|
+
if !continue && syntax == :valid
|
64
64
|
return first_line + lnum
|
65
65
|
end
|
66
66
|
end
|
data/lib/irb/completion.rb
CHANGED
@@ -218,7 +218,7 @@ module IRB
|
|
218
218
|
else
|
219
219
|
sym = $1
|
220
220
|
candidates = Symbol.all_symbols.collect do |s|
|
221
|
-
|
221
|
+
s.inspect
|
222
222
|
rescue EncodingError
|
223
223
|
# ignore
|
224
224
|
end
|
@@ -233,7 +233,7 @@ module IRB
|
|
233
233
|
if doc_namespace
|
234
234
|
candidates.find { |i| i == receiver }
|
235
235
|
else
|
236
|
-
candidates.grep(/^#{receiver}/).collect{|e| "::" + e}
|
236
|
+
candidates.grep(/^#{Regexp.quote(receiver)}/).collect{|e| "::" + e}
|
237
237
|
end
|
238
238
|
|
239
239
|
when /^([A-Z].*)::([^:.]*)$/
|
data/lib/irb/context.rb
CHANGED
@@ -473,28 +473,31 @@ module IRB
|
|
473
473
|
@inspect_mode
|
474
474
|
end
|
475
475
|
|
476
|
-
def evaluate(line, line_no
|
476
|
+
def evaluate(line, line_no) # :nodoc:
|
477
477
|
@line_no = line_no
|
478
|
-
|
479
|
-
line_no -= 1
|
480
|
-
line = "begin ::Kernel.raise _; rescue _.class\n#{line}\n""end"
|
481
|
-
@workspace.local_variable_set(:_, exception)
|
482
|
-
end
|
478
|
+
result = nil
|
483
479
|
|
484
|
-
|
485
|
-
|
486
|
-
if original = command_aliases[command.to_sym]
|
487
|
-
line = line.gsub(/\A#{Regexp.escape(command)}/, original.to_s)
|
488
|
-
command = original
|
480
|
+
if IRB.conf[:MEASURE] && IRB.conf[:MEASURE_CALLBACKS].empty?
|
481
|
+
IRB.set_measure_callback
|
489
482
|
end
|
490
483
|
|
491
|
-
|
492
|
-
|
493
|
-
|
494
|
-
|
484
|
+
if IRB.conf[:MEASURE] && !IRB.conf[:MEASURE_CALLBACKS].empty?
|
485
|
+
last_proc = proc do
|
486
|
+
result = @workspace.evaluate(line, irb_path, line_no)
|
487
|
+
end
|
488
|
+
IRB.conf[:MEASURE_CALLBACKS].inject(last_proc) do |chain, item|
|
489
|
+
_name, callback, arg = item
|
490
|
+
proc do
|
491
|
+
callback.(self, line, line_no, arg) do
|
492
|
+
chain.call
|
493
|
+
end
|
494
|
+
end
|
495
|
+
end.call
|
496
|
+
else
|
497
|
+
result = @workspace.evaluate(line, irb_path, line_no)
|
495
498
|
end
|
496
499
|
|
497
|
-
set_last_value(
|
500
|
+
set_last_value(result)
|
498
501
|
end
|
499
502
|
|
500
503
|
def inspect_last_value # :nodoc:
|
data/lib/irb/ext/loader.rb
CHANGED
@@ -42,6 +42,7 @@ module IRB # :nodoc:
|
|
42
42
|
#
|
43
43
|
# See Irb#suspend_input_method for more information.
|
44
44
|
def source_file(path)
|
45
|
+
irb = irb_context.irb
|
45
46
|
irb.suspend_name(path, File.basename(path)) do
|
46
47
|
FileInputMethod.open(path) do |io|
|
47
48
|
irb.suspend_input_method(io) do
|
@@ -66,6 +67,7 @@ module IRB # :nodoc:
|
|
66
67
|
#
|
67
68
|
# See Irb#suspend_input_method for more information.
|
68
69
|
def load_file(path, priv = nil)
|
70
|
+
irb = irb_context.irb
|
69
71
|
irb.suspend_name(path, File.basename(path)) do
|
70
72
|
|
71
73
|
if priv
|
data/lib/irb/extend-command.rb
CHANGED
@@ -0,0 +1,227 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
module IRB
|
3
|
+
module NestingParser
|
4
|
+
IGNORE_TOKENS = %i[on_sp on_ignored_nl on_comment on_embdoc_beg on_embdoc on_embdoc_end]
|
5
|
+
|
6
|
+
# Scan each token and call the given block with array of token and other information for parsing
|
7
|
+
def self.scan_opens(tokens)
|
8
|
+
opens = []
|
9
|
+
pending_heredocs = []
|
10
|
+
first_token_on_line = true
|
11
|
+
tokens.each do |t|
|
12
|
+
skip = false
|
13
|
+
last_tok, state, args = opens.last
|
14
|
+
case state
|
15
|
+
when :in_unquoted_symbol
|
16
|
+
unless IGNORE_TOKENS.include?(t.event)
|
17
|
+
opens.pop
|
18
|
+
skip = true
|
19
|
+
end
|
20
|
+
when :in_lambda_head
|
21
|
+
opens.pop if t.event == :on_tlambeg || (t.event == :on_kw && t.tok == 'do')
|
22
|
+
when :in_method_head
|
23
|
+
unless IGNORE_TOKENS.include?(t.event)
|
24
|
+
next_args = []
|
25
|
+
body = nil
|
26
|
+
if args.include?(:receiver)
|
27
|
+
case t.event
|
28
|
+
when :on_lparen, :on_ivar, :on_gvar, :on_cvar
|
29
|
+
# def (receiver). | def @ivar. | def $gvar. | def @@cvar.
|
30
|
+
next_args << :dot
|
31
|
+
when :on_kw
|
32
|
+
case t.tok
|
33
|
+
when 'self', 'true', 'false', 'nil'
|
34
|
+
# def self(arg) | def self.
|
35
|
+
next_args.push(:arg, :dot)
|
36
|
+
else
|
37
|
+
# def if(arg)
|
38
|
+
skip = true
|
39
|
+
next_args << :arg
|
40
|
+
end
|
41
|
+
when :on_op, :on_backtick
|
42
|
+
# def +(arg)
|
43
|
+
skip = true
|
44
|
+
next_args << :arg
|
45
|
+
when :on_ident, :on_const
|
46
|
+
# def a(arg) | def a.
|
47
|
+
next_args.push(:arg, :dot)
|
48
|
+
end
|
49
|
+
end
|
50
|
+
if args.include?(:dot)
|
51
|
+
# def receiver.name
|
52
|
+
next_args << :name if t.event == :on_period || (t.event == :on_op && t.tok == '::')
|
53
|
+
end
|
54
|
+
if args.include?(:name)
|
55
|
+
if %i[on_ident on_const on_op on_kw on_backtick].include?(t.event)
|
56
|
+
# def name(arg) | def receiver.name(arg)
|
57
|
+
next_args << :arg
|
58
|
+
skip = true
|
59
|
+
end
|
60
|
+
end
|
61
|
+
if args.include?(:arg)
|
62
|
+
case t.event
|
63
|
+
when :on_nl, :on_semicolon
|
64
|
+
# def recever.f;
|
65
|
+
body = :normal
|
66
|
+
when :on_lparen
|
67
|
+
# def recever.f()
|
68
|
+
next_args << :eq
|
69
|
+
else
|
70
|
+
if t.event == :on_op && t.tok == '='
|
71
|
+
# def receiver.f =
|
72
|
+
body = :oneliner
|
73
|
+
else
|
74
|
+
# def recever.f arg
|
75
|
+
next_args << :arg_without_paren
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
79
|
+
if args.include?(:eq)
|
80
|
+
if t.event == :on_op && t.tok == '='
|
81
|
+
body = :oneliner
|
82
|
+
else
|
83
|
+
body = :normal
|
84
|
+
end
|
85
|
+
end
|
86
|
+
if args.include?(:arg_without_paren)
|
87
|
+
if %i[on_semicolon on_nl].include?(t.event)
|
88
|
+
# def f a;
|
89
|
+
body = :normal
|
90
|
+
else
|
91
|
+
# def f a, b
|
92
|
+
next_args << :arg_without_paren
|
93
|
+
end
|
94
|
+
end
|
95
|
+
if body == :oneliner
|
96
|
+
opens.pop
|
97
|
+
elsif body
|
98
|
+
opens[-1] = [last_tok, nil]
|
99
|
+
else
|
100
|
+
opens[-1] = [last_tok, :in_method_head, next_args]
|
101
|
+
end
|
102
|
+
end
|
103
|
+
when :in_for_while_until_condition
|
104
|
+
if t.event == :on_semicolon || t.event == :on_nl || (t.event == :on_kw && t.tok == 'do')
|
105
|
+
skip = true if t.event == :on_kw && t.tok == 'do'
|
106
|
+
opens[-1] = [last_tok, nil]
|
107
|
+
end
|
108
|
+
end
|
109
|
+
|
110
|
+
unless skip
|
111
|
+
case t.event
|
112
|
+
when :on_kw
|
113
|
+
case t.tok
|
114
|
+
when 'begin', 'class', 'module', 'do', 'case'
|
115
|
+
opens << [t, nil]
|
116
|
+
when 'end'
|
117
|
+
opens.pop
|
118
|
+
when 'def'
|
119
|
+
opens << [t, :in_method_head, [:receiver, :name]]
|
120
|
+
when 'if', 'unless'
|
121
|
+
unless t.state.allbits?(Ripper::EXPR_LABEL)
|
122
|
+
opens << [t, nil]
|
123
|
+
end
|
124
|
+
when 'while', 'until'
|
125
|
+
unless t.state.allbits?(Ripper::EXPR_LABEL)
|
126
|
+
opens << [t, :in_for_while_until_condition]
|
127
|
+
end
|
128
|
+
when 'ensure', 'rescue'
|
129
|
+
unless t.state.allbits?(Ripper::EXPR_LABEL)
|
130
|
+
opens.pop
|
131
|
+
opens << [t, nil]
|
132
|
+
end
|
133
|
+
when 'elsif', 'else', 'when'
|
134
|
+
opens.pop
|
135
|
+
opens << [t, nil]
|
136
|
+
when 'for'
|
137
|
+
opens << [t, :in_for_while_until_condition]
|
138
|
+
when 'in'
|
139
|
+
if last_tok&.event == :on_kw && %w[case in].include?(last_tok.tok) && first_token_on_line
|
140
|
+
opens.pop
|
141
|
+
opens << [t, nil]
|
142
|
+
end
|
143
|
+
end
|
144
|
+
when :on_tlambda
|
145
|
+
opens << [t, :in_lambda_head]
|
146
|
+
when :on_lparen, :on_lbracket, :on_lbrace, :on_tlambeg, :on_embexpr_beg, :on_embdoc_beg
|
147
|
+
opens << [t, nil]
|
148
|
+
when :on_rparen, :on_rbracket, :on_rbrace, :on_embexpr_end, :on_embdoc_end
|
149
|
+
opens.pop
|
150
|
+
when :on_heredoc_beg
|
151
|
+
pending_heredocs << t
|
152
|
+
when :on_heredoc_end
|
153
|
+
opens.pop
|
154
|
+
when :on_backtick
|
155
|
+
opens << [t, nil] if t.state.allbits?(Ripper::EXPR_BEG)
|
156
|
+
when :on_tstring_beg, :on_words_beg, :on_qwords_beg, :on_symbols_beg, :on_qsymbols_beg, :on_regexp_beg
|
157
|
+
opens << [t, nil]
|
158
|
+
when :on_tstring_end, :on_regexp_end, :on_label_end
|
159
|
+
opens.pop
|
160
|
+
when :on_symbeg
|
161
|
+
if t.tok == ':'
|
162
|
+
opens << [t, :in_unquoted_symbol]
|
163
|
+
else
|
164
|
+
opens << [t, nil]
|
165
|
+
end
|
166
|
+
end
|
167
|
+
end
|
168
|
+
if t.event == :on_nl || t.event == :on_semicolon
|
169
|
+
first_token_on_line = true
|
170
|
+
elsif t.event != :on_sp
|
171
|
+
first_token_on_line = false
|
172
|
+
end
|
173
|
+
if pending_heredocs.any? && t.tok.include?("\n")
|
174
|
+
pending_heredocs.reverse_each { |t| opens << [t, nil] }
|
175
|
+
pending_heredocs = []
|
176
|
+
end
|
177
|
+
yield t, opens if block_given?
|
178
|
+
end
|
179
|
+
opens.map(&:first) + pending_heredocs.reverse
|
180
|
+
end
|
181
|
+
|
182
|
+
def self.open_tokens(tokens)
|
183
|
+
# scan_opens without block will return a list of open tokens at last token position
|
184
|
+
scan_opens(tokens)
|
185
|
+
end
|
186
|
+
|
187
|
+
# Calculates token information [line_tokens, prev_opens, next_opens, min_depth] for each line.
|
188
|
+
# Example code
|
189
|
+
# ["hello
|
190
|
+
# world"+(
|
191
|
+
# First line
|
192
|
+
# line_tokens: [[lbracket, '['], [tstring_beg, '"'], [tstring_content("hello\nworld"), "hello\n"]]
|
193
|
+
# prev_opens: []
|
194
|
+
# next_tokens: [lbracket, tstring_beg]
|
195
|
+
# min_depth: 0 (minimum at beginning of line)
|
196
|
+
# Second line
|
197
|
+
# line_tokens: [[tstring_content("hello\nworld"), "world"], [tstring_end, '"'], [op, '+'], [lparen, '(']]
|
198
|
+
# prev_opens: [lbracket, tstring_beg]
|
199
|
+
# next_tokens: [lbracket, lparen]
|
200
|
+
# min_depth: 1 (minimum just after tstring_end)
|
201
|
+
def self.parse_by_line(tokens)
|
202
|
+
line_tokens = []
|
203
|
+
prev_opens = []
|
204
|
+
min_depth = 0
|
205
|
+
output = []
|
206
|
+
last_opens = scan_opens(tokens) do |t, opens|
|
207
|
+
depth = t == opens.last&.first ? opens.size - 1 : opens.size
|
208
|
+
min_depth = depth if depth < min_depth
|
209
|
+
if t.tok.include?("\n")
|
210
|
+
t.tok.each_line do |line|
|
211
|
+
line_tokens << [t, line]
|
212
|
+
next if line[-1] != "\n"
|
213
|
+
next_opens = opens.map(&:first)
|
214
|
+
output << [line_tokens, prev_opens, next_opens, min_depth]
|
215
|
+
prev_opens = next_opens
|
216
|
+
min_depth = prev_opens.size
|
217
|
+
line_tokens = []
|
218
|
+
end
|
219
|
+
else
|
220
|
+
line_tokens << [t, t.tok]
|
221
|
+
end
|
222
|
+
end
|
223
|
+
output << [line_tokens, prev_opens, last_opens, min_depth] if line_tokens.any?
|
224
|
+
output
|
225
|
+
end
|
226
|
+
end
|
227
|
+
end
|