irb 1.16.0 → 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.
- checksums.yaml +4 -4
- data/Gemfile +8 -2
- data/lib/irb/color.rb +251 -163
- data/lib/irb/command/base.rb +35 -0
- data/lib/irb/command/copy.rb +11 -1
- data/lib/irb/command/internal_helpers.rb +6 -3
- data/lib/irb/command/ls.rb +6 -4
- data/lib/irb/completion.rb +38 -16
- data/lib/irb/context.rb +1 -1
- data/lib/irb/debug.rb +2 -2
- data/lib/irb/init.rb +3 -0
- data/lib/irb/input-method.rb +141 -111
- data/lib/irb/nesting_parser.rb +362 -213
- data/lib/irb/pager.rb +8 -0
- data/lib/irb/ruby-lex.rb +204 -303
- data/lib/irb/ruby_logo.aa +4 -0
- data/lib/irb/source_finder.rb +5 -14
- data/lib/irb/startup_message.rb +83 -0
- data/lib/irb/version.rb +2 -2
- data/lib/irb.rb +39 -17
- metadata +16 -1
data/lib/irb/source_finder.rb
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
require 'prism'
|
|
4
4
|
|
|
5
5
|
module IRB
|
|
6
6
|
class SourceFinder
|
|
@@ -44,21 +44,12 @@ module IRB
|
|
|
44
44
|
private
|
|
45
45
|
|
|
46
46
|
def find_end
|
|
47
|
-
lex = RubyLex.new
|
|
48
47
|
code = file_content
|
|
49
48
|
lines = code.lines[(@line - 1)..-1]
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
tokens.chunk { |tok| tok.pos[0] }.each do |lnum, chunk|
|
|
55
|
-
code = lines[0..lnum].join
|
|
56
|
-
prev_tokens.concat chunk
|
|
57
|
-
continue = lex.should_continue?(prev_tokens)
|
|
58
|
-
syntax = lex.check_code_syntax(code, local_variables: [])
|
|
59
|
-
if !continue && syntax == :valid
|
|
60
|
-
return @line + lnum
|
|
61
|
-
end
|
|
49
|
+
|
|
50
|
+
lines.each_with_index do |line, index|
|
|
51
|
+
sub_code = lines.take(index + 1).join
|
|
52
|
+
return @line + index if Prism.parse_success?(sub_code)
|
|
62
53
|
end
|
|
63
54
|
@line
|
|
64
55
|
end
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative "color"
|
|
4
|
+
require_relative "version"
|
|
5
|
+
|
|
6
|
+
module IRB
|
|
7
|
+
module StartupMessage
|
|
8
|
+
TIPS = [
|
|
9
|
+
'Type "help" for commands, "help <cmd>" for details',
|
|
10
|
+
'"show_doc method" to view documentation',
|
|
11
|
+
'"ls [object]" to see methods and properties',
|
|
12
|
+
'"ls [object] -g pattern" to filter methods and properties',
|
|
13
|
+
'"edit method" to open the method\'s source in editor',
|
|
14
|
+
'"cd object" to navigate into an object',
|
|
15
|
+
'"show_source method" to view source code',
|
|
16
|
+
'"copy expr" to copy the output to clipboard',
|
|
17
|
+
'"debug" to start integration with the "debug" gem',
|
|
18
|
+
'"history -g pattern" to search history',
|
|
19
|
+
].freeze
|
|
20
|
+
|
|
21
|
+
class << self
|
|
22
|
+
def display
|
|
23
|
+
logo_lines = load_logo
|
|
24
|
+
info_lines = build_info_lines
|
|
25
|
+
|
|
26
|
+
output = if logo_lines
|
|
27
|
+
combine_logo_and_info(logo_lines, info_lines)
|
|
28
|
+
else
|
|
29
|
+
info_lines.join("\n")
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
# Add a blank line to not immediately touch warning messages
|
|
33
|
+
puts
|
|
34
|
+
puts output
|
|
35
|
+
puts
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
private
|
|
39
|
+
|
|
40
|
+
def load_logo
|
|
41
|
+
encoding = STDOUT.external_encoding || Encoding.default_external
|
|
42
|
+
return nil unless encoding == Encoding::UTF_8
|
|
43
|
+
|
|
44
|
+
logo = IRB.send(:easter_egg_logo, :unicode_small)
|
|
45
|
+
return nil unless logo
|
|
46
|
+
|
|
47
|
+
logo.chomp.lines.map(&:chomp)
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
def build_info_lines
|
|
51
|
+
version_line = "#{Color.colorize('IRB', [:BOLD])} v#{VERSION} - Ruby #{RUBY_VERSION}"
|
|
52
|
+
tip_line = colorize_tip(TIPS.sample)
|
|
53
|
+
dir_line = Color.colorize(short_pwd, [:CYAN])
|
|
54
|
+
|
|
55
|
+
[version_line, tip_line, dir_line]
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
def colorize_tip(tip)
|
|
59
|
+
tip.gsub(/"[^"]*"/) { |match| Color.colorize(match, [:YELLOW]) }
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
def combine_logo_and_info(logo_lines, info_lines)
|
|
63
|
+
max_lines = [logo_lines.size, info_lines.size].max
|
|
64
|
+
lines = max_lines.times.map do |i|
|
|
65
|
+
logo_part = logo_lines[i] || ""
|
|
66
|
+
info_part = info_lines[i] || ""
|
|
67
|
+
colored_logo = Color.colorize(logo_part, [:RED, :BOLD])
|
|
68
|
+
"#{colored_logo} #{info_part}"
|
|
69
|
+
end
|
|
70
|
+
lines.join("\n")
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
def short_pwd
|
|
74
|
+
dir = Dir.pwd
|
|
75
|
+
home = ENV['HOME']
|
|
76
|
+
if home && (dir == home || dir.start_with?("#{home}/"))
|
|
77
|
+
dir = "~#{dir[home.size..]}"
|
|
78
|
+
end
|
|
79
|
+
dir
|
|
80
|
+
end
|
|
81
|
+
end
|
|
82
|
+
end
|
|
83
|
+
end
|
data/lib/irb/version.rb
CHANGED
data/lib/irb.rb
CHANGED
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
# by Keiju ISHITSUKA(keiju@ruby-lang.org)
|
|
6
6
|
#
|
|
7
7
|
|
|
8
|
-
require "
|
|
8
|
+
require "prism"
|
|
9
9
|
require "reline"
|
|
10
10
|
|
|
11
11
|
require_relative "irb/init"
|
|
@@ -21,6 +21,7 @@ require_relative "irb/color"
|
|
|
21
21
|
|
|
22
22
|
require_relative "irb/version"
|
|
23
23
|
require_relative "irb/easter-egg"
|
|
24
|
+
require_relative "irb/startup_message"
|
|
24
25
|
require_relative "irb/debug"
|
|
25
26
|
require_relative "irb/pager"
|
|
26
27
|
|
|
@@ -50,7 +51,13 @@ module IRB
|
|
|
50
51
|
irb = Irb.new(nil, @CONF[:SCRIPT])
|
|
51
52
|
else
|
|
52
53
|
irb = Irb.new
|
|
54
|
+
|
|
55
|
+
# Only display the banner in the irb executable
|
|
56
|
+
if @CONF[:SHOW_BANNER] && ap_path&.end_with?("exe/irb")
|
|
57
|
+
StartupMessage.display
|
|
58
|
+
end
|
|
53
59
|
end
|
|
60
|
+
|
|
54
61
|
irb.run(@CONF)
|
|
55
62
|
end
|
|
56
63
|
|
|
@@ -77,6 +84,15 @@ module IRB
|
|
|
77
84
|
PROMPT_MAIN_TRUNCATE_OMISSION = '...'
|
|
78
85
|
CONTROL_CHARACTERS_PATTERN = "\x00-\x1F"
|
|
79
86
|
|
|
87
|
+
# Track the nesting depth of run loops. This is used for history management
|
|
88
|
+
# only the outermost run loop should load/save history.
|
|
89
|
+
@run_nesting_depth = 0
|
|
90
|
+
|
|
91
|
+
class << self
|
|
92
|
+
# TODO: When refactoring to v2.0, find a better way to manage and track nesting sessions.
|
|
93
|
+
attr_accessor :run_nesting_depth
|
|
94
|
+
end
|
|
95
|
+
|
|
80
96
|
# Returns the current context of this irb session
|
|
81
97
|
attr_reader :context
|
|
82
98
|
# The lexer used by this irb session
|
|
@@ -148,7 +164,10 @@ module IRB
|
|
|
148
164
|
end
|
|
149
165
|
|
|
150
166
|
def run(conf = IRB.conf)
|
|
151
|
-
|
|
167
|
+
# Use run_nesting_depth to determine if we're in a nested session.
|
|
168
|
+
in_nested_session = Irb.run_nesting_depth > 0
|
|
169
|
+
Irb.run_nesting_depth += 1
|
|
170
|
+
|
|
152
171
|
conf[:IRB_RC].call(context) if conf[:IRB_RC]
|
|
153
172
|
prev_context = conf[:MAIN_CONTEXT]
|
|
154
173
|
conf[:MAIN_CONTEXT] = context
|
|
@@ -174,6 +193,8 @@ module IRB
|
|
|
174
193
|
eval_input
|
|
175
194
|
end
|
|
176
195
|
ensure
|
|
196
|
+
Irb.run_nesting_depth -= 1
|
|
197
|
+
|
|
177
198
|
# Do not restore to nil. It will cause IRB crash when used with threads.
|
|
178
199
|
IRB.conf[:MAIN_CONTEXT] = prev_context if prev_context
|
|
179
200
|
|
|
@@ -251,11 +272,10 @@ module IRB
|
|
|
251
272
|
code << line
|
|
252
273
|
return code if command?(code)
|
|
253
274
|
|
|
254
|
-
|
|
275
|
+
continue, opens, terminated = @scanner.check_code_state(code, local_variables: @context.local_variables)
|
|
255
276
|
return code if terminated
|
|
256
277
|
|
|
257
278
|
line_offset += 1
|
|
258
|
-
continue = @scanner.should_continue?(tokens)
|
|
259
279
|
prompt = generate_prompt(opens, continue, line_offset)
|
|
260
280
|
end
|
|
261
281
|
end
|
|
@@ -316,23 +336,25 @@ module IRB
|
|
|
316
336
|
else
|
|
317
337
|
next true if command?(code)
|
|
318
338
|
|
|
319
|
-
|
|
339
|
+
_continue, _opens, terminated = @scanner.check_code_state(code, local_variables: @context.local_variables)
|
|
320
340
|
terminated
|
|
321
341
|
end
|
|
322
342
|
end
|
|
323
343
|
end
|
|
324
344
|
if @context.io.respond_to?(:dynamic_prompt)
|
|
325
345
|
@context.io.dynamic_prompt do |lines|
|
|
326
|
-
|
|
327
|
-
|
|
346
|
+
code = lines.map{ |l| l + "\n" }.join
|
|
347
|
+
parse_lex_result = Prism.parse_lex(code, scopes: [@context.local_variables])
|
|
348
|
+
line_results = IRB::NestingParser.parse_by_line(parse_lex_result)
|
|
349
|
+
|
|
350
|
+
tokens = parse_lex_result.value[1].map(&:first)
|
|
351
|
+
tokens_by_line = tokens.group_by {|t| t.location.start_line - 1 }
|
|
352
|
+
|
|
328
353
|
tokens_until_line = []
|
|
329
|
-
line_results.map.with_index do |(
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
tokens_until_line << token if token != tokens_until_line.last
|
|
334
|
-
end
|
|
335
|
-
continue = @scanner.should_continue?(tokens_until_line)
|
|
354
|
+
line_results.map.with_index do |(_prev_opens, next_opens, _min_depth), line_num_offset|
|
|
355
|
+
line = lines[line_num_offset]
|
|
356
|
+
tokens_until_line.concat(tokens_by_line[line_num_offset] || [])
|
|
357
|
+
continue = @scanner.should_continue?(tokens_until_line, line, line_num_offset + 1)
|
|
336
358
|
generate_prompt(next_opens, continue, line_num_offset)
|
|
337
359
|
end
|
|
338
360
|
end
|
|
@@ -344,8 +366,8 @@ module IRB
|
|
|
344
366
|
next nil if !is_newline && lines[line_index]&.byteslice(0, byte_pointer)&.match?(/\A\s*\z/)
|
|
345
367
|
|
|
346
368
|
code = lines[0..line_index].map { |l| "#{l}\n" }.join
|
|
347
|
-
|
|
348
|
-
@scanner.process_indent_level(
|
|
369
|
+
parse_lex_result = Prism.parse_lex(code, scopes: [@context.local_variables])
|
|
370
|
+
@scanner.process_indent_level(parse_lex_result, lines, line_index, is_newline)
|
|
349
371
|
end
|
|
350
372
|
end
|
|
351
373
|
end
|
|
@@ -584,7 +606,7 @@ module IRB
|
|
|
584
606
|
end
|
|
585
607
|
|
|
586
608
|
def generate_prompt(opens, continue, line_offset)
|
|
587
|
-
ltype = @scanner.
|
|
609
|
+
ltype = @scanner.ltype_from_open_nestings(opens)
|
|
588
610
|
indent = @scanner.calc_indent_level(opens)
|
|
589
611
|
continue = opens.any? || continue
|
|
590
612
|
line_no = @line_no + line_offset
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: irb
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 1.
|
|
4
|
+
version: 1.18.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- aycabta
|
|
@@ -10,6 +10,20 @@ bindir: exe
|
|
|
10
10
|
cert_chain: []
|
|
11
11
|
date: 1980-01-02 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
|
+
- !ruby/object:Gem::Dependency
|
|
14
|
+
name: prism
|
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
|
16
|
+
requirements:
|
|
17
|
+
- - ">="
|
|
18
|
+
- !ruby/object:Gem::Version
|
|
19
|
+
version: 1.3.0
|
|
20
|
+
type: :runtime
|
|
21
|
+
prerelease: false
|
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
23
|
+
requirements:
|
|
24
|
+
- - ">="
|
|
25
|
+
- !ruby/object:Gem::Version
|
|
26
|
+
version: 1.3.0
|
|
13
27
|
- !ruby/object:Gem::Dependency
|
|
14
28
|
name: reline
|
|
15
29
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -145,6 +159,7 @@ files:
|
|
|
145
159
|
- lib/irb/ruby-lex.rb
|
|
146
160
|
- lib/irb/ruby_logo.aa
|
|
147
161
|
- lib/irb/source_finder.rb
|
|
162
|
+
- lib/irb/startup_message.rb
|
|
148
163
|
- lib/irb/statement.rb
|
|
149
164
|
- lib/irb/version.rb
|
|
150
165
|
- lib/irb/workspace.rb
|