irb 1.3.4 → 1.3.8.pre.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: e897a7306cd4fde4a54fa2cc4c8dff34ccf4ecd5e69e324d9c91901c9a683cde
4
- data.tar.gz: d424e3853889fef65b7e01df7d58e27bbd7467e081c733d7937aadde0544f4e9
3
+ metadata.gz: 98ac31009e423fdea5f0151f5b48e3199dc98427484d5465088e1a9e0bac88fd
4
+ data.tar.gz: 180d9637906858acb3abba279ee49934d397979da0f4e9e7fab373c4d7313d4d
5
5
  SHA512:
6
- metadata.gz: 77001229102437b40664c561a4b2ef1f5672e2e82661332be8a9f770356640a7de588b17c6d66164edbcd504158effd2b075b58172b2863b3862aa8735a1a72f
7
- data.tar.gz: f83d98526ea74c4f015c85377f3c8d569a4d2a1f507331db80c41ab2225d4512c8ad6937d9bb90f703b7c95c214cb36e2f1c1e5107bed62554ecf2ba2cc2aa91
6
+ metadata.gz: 89acce9899ac0fefa699639a514ada88bb2b9e3c18e3a1b5f83e139800d99b18445269ef5703b45c794f69a186c99cfd4f02fbfd24a883ed2164c9d1eacceb21
7
+ data.tar.gz: a16a4ba0f9505da943a29a6138b29b8d92e9fff6cad5fcea14ca3666095d0e02b467eaaf83eb425b4da4971c047b10eab73ba28bde5794d2e46f58d67476a182
data/Gemfile CHANGED
@@ -3,3 +3,13 @@ source "https://rubygems.org"
3
3
  git_source(:github) {|repo_name| "https://github.com/#{repo_name}" }
4
4
 
5
5
  gemspec
6
+
7
+ group :development do
8
+ gem "bundler"
9
+ is_unix = RUBY_PLATFORM =~ /(aix|darwin|linux|(net|free|open)bsd|cygwin|solaris|irix|hpux)/i
10
+ is_truffleruby = RUBY_DESCRIPTION =~ /truffleruby/
11
+ gem 'vterm', '>= 0.0.5' if is_unix && ENV['WITH_VTERM']
12
+ gem 'yamatanooroti', '>= 0.0.6'
13
+ gem "rake"
14
+ gem "stackprof" if is_unix && !is_truffleruby
15
+ end
data/Rakefile CHANGED
@@ -4,7 +4,14 @@ require "rake/testtask"
4
4
  Rake::TestTask.new(:test) do |t|
5
5
  t.libs << "test" << "test/lib"
6
6
  t.libs << "lib"
7
- t.test_files = FileList["test/**/test_*.rb"]
7
+ t.test_files = FileList["test/irb/test_*.rb"]
8
+ end
9
+
10
+ Rake::TestTask.new(:test_yamatanooroti) do |t|
11
+ t.libs << 'test'
12
+ t.libs << 'lib'
13
+ #t.loader = :direct
14
+ t.pattern = 'test/irb/yamatanooroti/test_*.rb'
8
15
  end
9
16
 
10
17
  task :default => :test
data/irb.gemspec CHANGED
@@ -28,60 +28,13 @@ Gem::Specification.new do |spec|
28
28
  "doc/irb/irb.rd.ja",
29
29
  "exe/irb",
30
30
  "irb.gemspec",
31
- "lib/irb.rb",
32
- "lib/irb/cmd/chws.rb",
33
- "lib/irb/cmd/fork.rb",
34
- "lib/irb/cmd/help.rb",
35
- "lib/irb/cmd/info.rb",
36
- "lib/irb/cmd/load.rb",
37
- "lib/irb/cmd/measure.rb",
38
- "lib/irb/cmd/nop.rb",
39
- "lib/irb/cmd/pushws.rb",
40
- "lib/irb/cmd/subirb.rb",
41
- "lib/irb/color.rb",
42
- "lib/irb/color_printer.rb",
43
- "lib/irb/completion.rb",
44
- "lib/irb/context.rb",
45
- "lib/irb/easter-egg.rb",
46
- "lib/irb/ext/change-ws.rb",
47
- "lib/irb/ext/history.rb",
48
- "lib/irb/ext/loader.rb",
49
- "lib/irb/ext/multi-irb.rb",
50
- "lib/irb/ext/save-history.rb",
51
- "lib/irb/ext/tracer.rb",
52
- "lib/irb/ext/use-loader.rb",
53
- "lib/irb/ext/workspaces.rb",
54
- "lib/irb/extend-command.rb",
55
- "lib/irb/frame.rb",
56
- "lib/irb/help.rb",
57
- "lib/irb/init.rb",
58
- "lib/irb/input-method.rb",
59
- "lib/irb/inspector.rb",
60
- "lib/irb/lc/error.rb",
61
- "lib/irb/lc/help-message",
62
- "lib/irb/lc/ja/encoding_aliases.rb",
63
- "lib/irb/lc/ja/error.rb",
64
- "lib/irb/lc/ja/help-message",
65
- "lib/irb/locale.rb",
66
- "lib/irb/magic-file.rb",
67
- "lib/irb/notifier.rb",
68
- "lib/irb/output-method.rb",
69
- "lib/irb/ruby-lex.rb",
70
- "lib/irb/ruby_logo.aa",
71
- "lib/irb/src_encoding.rb",
72
- "lib/irb/version.rb",
73
- "lib/irb/workspace.rb",
74
- "lib/irb/ws-for-case-2.rb",
75
- "lib/irb/xmp.rb",
76
31
  "man/irb.1",
77
- ]
32
+ ] + Dir.glob("lib/**/*")
78
33
  spec.bindir = "exe"
79
34
  spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
80
35
  spec.require_paths = ["lib"]
81
36
 
82
37
  spec.required_ruby_version = Gem::Requirement.new(">= 2.5")
83
38
 
84
- spec.add_dependency "reline", ">= 0.1.5"
85
- spec.add_development_dependency "bundler"
86
- spec.add_development_dependency "rake"
39
+ spec.add_dependency "reline", ">= 0.2.8.pre.1"
87
40
  end
data/lib/irb/cmd/info.rb CHANGED
@@ -14,6 +14,12 @@ module IRB
14
14
  str += "InputMethod: #{IRB.CurrentContext.io.inspect}\n"
15
15
  str += ".irbrc path: #{IRB.rc_file}\n" if File.exist?(IRB.rc_file)
16
16
  str += "RUBY_PLATFORM: #{RUBY_PLATFORM}\n"
17
+ str += "LANG env: #{ENV["LANG"]}\n" if ENV["LANG"] && !ENV["LANG"].empty?
18
+ str += "LC_ALL env: #{ENV["LC_ALL"]}\n" if ENV["LC_ALL"] && !ENV["LC_ALL"].empty?
19
+ if RbConfig::CONFIG['host_os'] =~ /mswin|msys|mingw|cygwin|bccwin|wince|emc/
20
+ codepage = `chcp`.sub(/.*: (\d+)\n/, '\1')
21
+ str += "Code page: #{codepage}\n"
22
+ end
17
23
  str
18
24
  end
19
25
  alias_method :to_s, :inspect
data/lib/irb/cmd/ls.rb ADDED
@@ -0,0 +1,101 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "reline"
4
+ require_relative "nop"
5
+ require_relative "../color"
6
+
7
+ # :stopdoc:
8
+ module IRB
9
+ module ExtendCommand
10
+ class Ls < Nop
11
+ def execute(*arg, grep: nil)
12
+ o = Output.new(grep: grep)
13
+
14
+ obj = arg.empty? ? irb_context.workspace.main : arg.first
15
+ locals = arg.empty? ? irb_context.workspace.binding.local_variables : []
16
+ klass = (obj.class == Class || obj.class == Module ? obj : obj.class)
17
+
18
+ o.dump("constants", obj.constants) if obj.respond_to?(:constants)
19
+ dump_methods(o, klass, obj)
20
+ o.dump("instance variables", obj.instance_variables)
21
+ o.dump("class variables", klass.class_variables)
22
+ o.dump("locals", locals)
23
+ end
24
+
25
+ def dump_methods(o, klass, obj)
26
+ singleton_class = begin obj.singleton_class; rescue TypeError; nil end
27
+ maps = class_method_map((singleton_class || klass).ancestors)
28
+ maps.each do |mod, methods|
29
+ name = mod == singleton_class ? "#{klass}.methods" : "#{mod}#methods"
30
+ o.dump(name, methods)
31
+ end
32
+ end
33
+
34
+ def class_method_map(classes)
35
+ dumped = Array.new
36
+ classes.reject { |mod| mod >= Object }.map do |mod|
37
+ methods = mod.public_instance_methods(false).select do |m|
38
+ dumped.push(m) unless dumped.include?(m)
39
+ end
40
+ [mod, methods]
41
+ end.reverse
42
+ end
43
+
44
+ class Output
45
+ MARGIN = " "
46
+
47
+ def initialize(grep: nil)
48
+ @grep = grep
49
+ @line_width = screen_width - MARGIN.length # right padding
50
+ end
51
+
52
+ def dump(name, strs)
53
+ strs = strs.grep(@grep) if @grep
54
+ strs = strs.sort
55
+ return if strs.empty?
56
+
57
+ # Attempt a single line
58
+ print "#{Color.colorize(name, [:BOLD, :BLUE])}: "
59
+ if fits_on_line?(strs, cols: strs.size, offset: "#{name}: ".length)
60
+ puts strs.join(MARGIN)
61
+ return
62
+ end
63
+ puts
64
+
65
+ # Dump with the largest # of columns that fits on a line
66
+ cols = strs.size
67
+ until fits_on_line?(strs, cols: cols, offset: MARGIN.length) || cols == 1
68
+ cols -= 1
69
+ end
70
+ widths = col_widths(strs, cols: cols)
71
+ strs.each_slice(cols) do |ss|
72
+ puts ss.map.with_index { |s, i| "#{MARGIN}%-#{widths[i]}s" % s }.join
73
+ end
74
+ end
75
+
76
+ private
77
+
78
+ def fits_on_line?(strs, cols:, offset: 0)
79
+ width = col_widths(strs, cols: cols).sum + MARGIN.length * (cols - 1)
80
+ width <= @line_width - offset
81
+ end
82
+
83
+ def col_widths(strs, cols:)
84
+ cols.times.map do |col|
85
+ (col...strs.size).step(cols).map do |i|
86
+ strs[i].length
87
+ end.max
88
+ end
89
+ end
90
+
91
+ def screen_width
92
+ Reline.get_screen_size.last
93
+ rescue Errno::EINVAL # in `winsize': Invalid argument - <STDIN>
94
+ 80
95
+ end
96
+ end
97
+ private_constant :Output
98
+ end
99
+ end
100
+ end
101
+ # :startdoc:
@@ -9,6 +9,9 @@ module IRB
9
9
  end
10
10
 
11
11
  def execute(type = nil, arg = nil, &block)
12
+ # Please check IRB.init_config in lib/irb/init.rb that sets
13
+ # IRB.conf[:MEASURE_PROC] to register default "measure" methods,
14
+ # "measure :time" (abbreviated as "measure") and "measure :stackprof".
12
15
  case type
13
16
  when :off
14
17
  IRB.conf[:MEASURE] = nil
data/lib/irb/cmd/nop.rb CHANGED
@@ -14,10 +14,16 @@ module IRB
14
14
  module ExtendCommand
15
15
  class Nop
16
16
 
17
-
18
- def self.execute(conf, *opts, &block)
19
- command = new(conf)
20
- command.execute(*opts, &block)
17
+ if RUBY_ENGINE == "ruby" && RUBY_VERSION >= "2.7.0"
18
+ def self.execute(conf, *opts, **kwargs, &block)
19
+ command = new(conf)
20
+ command.execute(*opts, **kwargs, &block)
21
+ end
22
+ else
23
+ def self.execute(conf, *opts, &block)
24
+ command = new(conf)
25
+ command.execute(*opts, &block)
26
+ end
21
27
  end
22
28
 
23
29
  def initialize(conf)
@@ -0,0 +1,96 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "nop"
4
+ require_relative "../color"
5
+ require_relative "../ruby-lex"
6
+
7
+ # :stopdoc:
8
+ module IRB
9
+ module ExtendCommand
10
+ class ShowSource < Nop
11
+ def execute(str = nil)
12
+ unless str.is_a?(String)
13
+ puts "Error: Expected a string but got #{str.inspect}"
14
+ return
15
+ end
16
+ source = find_source(str)
17
+ if source && File.exist?(source.file)
18
+ show_source(source)
19
+ else
20
+ puts "Error: Couldn't locate a definition for #{str}"
21
+ end
22
+ nil
23
+ end
24
+
25
+ private
26
+
27
+ # @param [IRB::ExtendCommand::ShowSource::Source] source
28
+ def show_source(source)
29
+ puts
30
+ puts "#{bold("From")}: #{source.file}:#{source.first_line}"
31
+ puts
32
+ code = IRB::Color.colorize_code(File.read(source.file))
33
+ puts code.lines[(source.first_line - 1)...source.last_line].join
34
+ puts
35
+ end
36
+
37
+ def find_source(str)
38
+ case str
39
+ when /\A[A-Z]\w*(::[A-Z]\w*)*\z/ # Const::Name
40
+ eval(str, irb_context.workspace.binding) # trigger autoload
41
+ base = irb_context.workspace.binding.receiver.yield_self { |r| r.is_a?(Module) ? r : Object }
42
+ file, line = base.const_source_location(str) if base.respond_to?(:const_source_location) # Ruby 2.7+
43
+ when /\A(?<owner>[A-Z]\w*(::[A-Z]\w*)*)#(?<method>[^ :.]+)\z/ # Class#method
44
+ owner = eval(Regexp.last_match[:owner], irb_context.workspace.binding)
45
+ method = Regexp.last_match[:method]
46
+ if owner.respond_to?(:instance_method) && owner.instance_methods.include?(method.to_sym)
47
+ file, line = owner.instance_method(method).source_location
48
+ end
49
+ when /\A((?<receiver>.+)(\.|::))?(?<method>[^ :.]+)\z/ # method, receiver.method, receiver::method
50
+ receiver = eval(Regexp.last_match[:receiver] || 'self', irb_context.workspace.binding)
51
+ method = Regexp.last_match[:method]
52
+ file, line = receiver.method(method).source_location if receiver.respond_to?(method)
53
+ end
54
+ if file && line
55
+ Source.new(file: file, first_line: line, last_line: find_end(file, line))
56
+ end
57
+ end
58
+
59
+ def find_end(file, first_line)
60
+ return first_line unless File.exist?(file)
61
+ lex = RubyLex.new
62
+ lines = File.read(file).lines[(first_line - 1)..-1]
63
+ tokens = RubyLex.ripper_lex_without_warning(lines.join)
64
+
65
+ code = +""
66
+ prev_tokens = []
67
+
68
+ # chunk with line number
69
+ tokens.chunk { |tok| tok[0][0] }.each do |lnum, chunk|
70
+ code << lines[lnum]
71
+ prev_tokens.concat chunk
72
+
73
+ continue = lex.process_continue(prev_tokens)
74
+ code_block_open = lex.check_code_block(code, prev_tokens)
75
+ if !continue && !code_block_open
76
+ return first_line + lnum
77
+ end
78
+ end
79
+ first_line
80
+ end
81
+
82
+ def bold(str)
83
+ Color.colorize(str, [:BOLD])
84
+ end
85
+
86
+ Source = Struct.new(
87
+ :file, # @param [String] - file name
88
+ :first_line, # @param [String] - first line
89
+ :last_line, # @param [String] - last line
90
+ keyword_init: true,
91
+ )
92
+ private_constant :Source
93
+ end
94
+ end
95
+ end
96
+ # :startdoc:
@@ -0,0 +1,20 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "nop"
4
+
5
+ # :stopdoc:
6
+ module IRB
7
+ module ExtendCommand
8
+ class Whereami < Nop
9
+ def execute(*)
10
+ code = irb_context.workspace.code_around_binding
11
+ if code
12
+ puts code
13
+ else
14
+ puts "The current context doesn't have code."
15
+ end
16
+ end
17
+ end
18
+ end
19
+ end
20
+ # :startdoc:
data/lib/irb/color.rb CHANGED
@@ -64,6 +64,7 @@ module IRB # :nodoc:
64
64
  on_alias_error: [[RED, REVERSE], ALL],
65
65
  on_class_name_error:[[RED, REVERSE], ALL],
66
66
  on_param_error: [[RED, REVERSE], ALL],
67
+ on___end__: [[GREEN], ALL],
67
68
  }
68
69
  rescue NameError
69
70
  # Give up highlighting Ripper-incompatible older Ruby
@@ -76,7 +77,7 @@ module IRB # :nodoc:
76
77
 
77
78
  class << self
78
79
  def colorable?
79
- $stdout.tty? && supported? && (/mswin|mingw/ =~ RUBY_PLATFORM || (ENV.key?('TERM') && ENV['TERM'] != 'dumb'))
80
+ $stdout.tty? && (/mswin|mingw/ =~ RUBY_PLATFORM || (ENV.key?('TERM') && ENV['TERM'] != 'dumb'))
80
81
  end
81
82
 
82
83
  def inspect_colorable?(obj, seen: {}.compare_by_identity)
@@ -100,26 +101,27 @@ module IRB # :nodoc:
100
101
  end
101
102
  end
102
103
 
103
- def clear
104
- return '' unless colorable?
104
+ def clear(colorable: colorable?)
105
+ return '' unless colorable
105
106
  "\e[#{CLEAR}m"
106
107
  end
107
108
 
108
- def colorize(text, seq)
109
- return text unless colorable?
109
+ def colorize(text, seq, colorable: colorable?)
110
+ return text unless colorable
110
111
  seq = seq.map { |s| "\e[#{const_get(s)}m" }.join('')
111
- "#{seq}#{text}#{clear}"
112
+ "#{seq}#{text}#{clear(colorable: colorable)}"
112
113
  end
113
114
 
114
115
  # If `complete` is false (code is incomplete), this does not warn compile_error.
115
116
  # This option is needed to avoid warning a user when the compile_error is happening
116
117
  # because the input is not wrong but just incomplete.
117
- def colorize_code(code, complete: true, ignore_error: false)
118
- return code unless colorable?
118
+ def colorize_code(code, complete: true, ignore_error: false, colorable: colorable?)
119
+ return code unless colorable
119
120
 
120
121
  symbol_state = SymbolState.new
121
122
  colored = +''
122
123
  length = 0
124
+ end_seen = false
123
125
 
124
126
  scan(code, allow_last_error: !complete) do |token, str, expr|
125
127
  # IRB::ColorPrinter skips colorizing fragments with any invalid token
@@ -132,16 +134,17 @@ module IRB # :nodoc:
132
134
  line = Reline::Unicode.escape_for_print(line)
133
135
  if seq = dispatch_seq(token, expr, line, in_symbol: in_symbol)
134
136
  colored << seq.map { |s| "\e[#{s}m" }.join('')
135
- colored << line.sub(/\Z/, clear)
137
+ colored << line.sub(/\Z/, clear(colorable: colorable))
136
138
  else
137
139
  colored << line
138
140
  end
139
141
  end
140
142
  length += str.bytesize
143
+ end_seen = true if token == :on___end__
141
144
  end
142
145
 
143
146
  # give up colorizing incomplete Ripper tokens
144
- if length != code.bytesize
147
+ unless end_seen or length == code.bytesize
145
148
  return Reline::Unicode.escape_for_print(code)
146
149
  end
147
150
 
@@ -158,11 +161,6 @@ module IRB # :nodoc:
158
161
  seen.delete(obj)
159
162
  end
160
163
 
161
- def supported?
162
- return @supported if defined?(@supported)
163
- @supported = Ripper::Lexer::Elem.method_defined?(:state)
164
- end
165
-
166
164
  def scan(code, allow_last_error:)
167
165
  pos = [1, 0]
168
166
 
@@ -21,6 +21,15 @@ module IRB
21
21
  end
22
22
  end
23
23
 
24
+ def pp(obj)
25
+ if obj.is_a?(String)
26
+ # Avoid calling Ruby 2.4+ String#pretty_print that splits a string by "\n"
27
+ text(obj.inspect)
28
+ else
29
+ super
30
+ end
31
+ end
32
+
24
33
  def text(str, width = nil)
25
34
  unless str.is_a?(String)
26
35
  str = str.inspect
@@ -7,7 +7,7 @@
7
7
  # From Original Idea of shugo@ruby-lang.org
8
8
  #
9
9
 
10
- autoload :RDoc, "rdoc"
10
+ require_relative 'ruby-lex'
11
11
 
12
12
  module IRB
13
13
  module InputCompletor # :nodoc:
@@ -38,8 +38,69 @@ module IRB
38
38
 
39
39
  BASIC_WORD_BREAK_CHARACTERS = " \t\n`><=;|&{("
40
40
 
41
- CompletionProc = proc { |input|
42
- retrieve_completion_data(input).compact.map{ |i| i.encode(Encoding.default_external) }
41
+ def self.retrieve_files_to_require_from_load_path
42
+ @@files_from_load_path ||= $LOAD_PATH.flat_map { |path|
43
+ begin
44
+ Dir.glob("**/*.{rb,#{RbConfig::CONFIG['DLEXT']}}", base: path)
45
+ rescue Errno::ENOENT
46
+ []
47
+ end
48
+ }.uniq.map { |path|
49
+ path.sub(/\.(rb|#{RbConfig::CONFIG['DLEXT']})\z/, '')
50
+ }
51
+ end
52
+
53
+ def self.retrieve_files_to_require_relative_from_current_dir
54
+ @@files_from_current_dir ||= Dir.glob("**/*.{rb,#{RbConfig::CONFIG['DLEXT']}}", base: '.').map { |path|
55
+ path.sub(/\.(rb|#{RbConfig::CONFIG['DLEXT']})\z/, '')
56
+ }
57
+ end
58
+
59
+ CompletionRequireProc = lambda { |target, preposing = nil, postposing = nil|
60
+ if target =~ /\A(['"])([^'"]+)\Z/
61
+ quote = $1
62
+ actual_target = $2
63
+ else
64
+ return nil # It's not String literal
65
+ end
66
+ tokens = RubyLex.ripper_lex_without_warning(preposing.gsub(/\s*\z/, ''))
67
+ tok = nil
68
+ tokens.reverse_each do |t|
69
+ unless [:on_lparen, :on_sp, :on_ignored_sp, :on_nl, :on_ignored_nl, :on_comment].include?(t.event)
70
+ tok = t
71
+ break
72
+ end
73
+ end
74
+ result = []
75
+ if tok && tok.event == :on_ident && tok.state == Ripper::EXPR_CMDARG
76
+ case tok.tok
77
+ when 'require'
78
+ result = retrieve_files_to_require_from_load_path.select { |path|
79
+ path.start_with?(actual_target)
80
+ }.map { |path|
81
+ quote + path
82
+ }
83
+ when 'require_relative'
84
+ result = retrieve_files_to_require_relative_from_current_dir.select { |path|
85
+ path.start_with?(actual_target)
86
+ }.map { |path|
87
+ quote + path
88
+ }
89
+ end
90
+ end
91
+ result
92
+ }
93
+
94
+ CompletionProc = lambda { |target, preposing = nil, postposing = nil|
95
+ if preposing && postposing
96
+ result = CompletionRequireProc.(target, preposing, postposing)
97
+ unless result
98
+ result = retrieve_completion_data(target).compact.map{ |i| i.encode(Encoding.default_external) }
99
+ end
100
+ result
101
+ else
102
+ retrieve_completion_data(target).compact.map{ |i| i.encode(Encoding.default_external) }
103
+ end
43
104
  }
44
105
 
45
106
  def self.retrieve_completion_data(input, bind: IRB.conf[:MAIN_CONTEXT].workspace.binding, doc_namespace: false)
@@ -266,13 +327,22 @@ module IRB
266
327
  end
267
328
 
268
329
  PerfectMatchedProc = ->(matched, bind: IRB.conf[:MAIN_CONTEXT].workspace.binding) {
330
+ begin
331
+ require 'rdoc'
332
+ rescue LoadError
333
+ return
334
+ end
335
+
269
336
  RDocRIDriver ||= RDoc::RI::Driver.new
337
+
270
338
  if matched =~ /\A(?:::)?RubyVM/ and not ENV['RUBY_YES_I_AM_NOT_A_NORMAL_USER']
271
339
  IRB.__send__(:easter_egg)
272
340
  return
273
341
  end
342
+
274
343
  namespace = retrieve_completion_data(matched, bind: bind, doc_namespace: true)
275
344
  return unless namespace
345
+
276
346
  if namespace.is_a?(Array)
277
347
  out = RDoc::Markup::Document.new
278
348
  namespace.each do |m|
@@ -81,6 +81,8 @@ module IRB
81
81
  end
82
82
  }
83
83
  end
84
+ @loaded_history_lines = history.size
85
+ @loaded_history_mtime = File.mtime(history_file)
84
86
  end
85
87
  end
86
88
 
@@ -105,12 +107,20 @@ module IRB
105
107
  raise
106
108
  end
107
109
 
108
- open(history_file, "w:#{IRB.conf[:LC_MESSAGES].encoding}", 0600) do |f|
110
+ if File.exist?(history_file) && @loaded_history_mtime &&
111
+ File.mtime(history_file) != @loaded_history_mtime
112
+ history = history[@loaded_history_lines..-1]
113
+ append_history = true
114
+ end
115
+
116
+ open(history_file, "#{append_history ? 'a' : 'w'}:#{IRB.conf[:LC_MESSAGES].encoding}", 0600) do |f|
109
117
  hist = history.map{ |l| l.split("\n").join("\\\n") }
110
- begin
111
- hist = hist.last(num) if hist.size > num and num > 0
112
- rescue RangeError # bignum too big to convert into `long'
113
- # Do nothing because the bignum should be treated as inifinity
118
+ unless append_history
119
+ begin
120
+ hist = hist.last(num) if hist.size > num and num > 0
121
+ rescue RangeError # bignum too big to convert into `long'
122
+ # Do nothing because the bignum should be treated as inifinity
123
+ end
114
124
  end
115
125
  f.puts(hist)
116
126
  end
@@ -126,7 +126,23 @@ module IRB # :nodoc:
126
126
  ],
127
127
 
128
128
  [
129
- :measure, :Measure, "irb/cmd/measure"
129
+ :irb_ls, :Ls, "irb/cmd/ls",
130
+ [:ls, NO_OVERRIDE],
131
+ ],
132
+
133
+ [
134
+ :irb_measure, :Measure, "irb/cmd/measure",
135
+ [:measure, NO_OVERRIDE],
136
+ ],
137
+
138
+ [
139
+ :irb_show_source, :ShowSource, "irb/cmd/show_source",
140
+ [:show_source, NO_OVERRIDE],
141
+ ],
142
+
143
+ [
144
+ :irb_whereami, :Whereami, "irb/cmd/whereami",
145
+ [:whereami, NO_OVERRIDE],
130
146
  ],
131
147
 
132
148
  ]
@@ -168,12 +184,13 @@ module IRB # :nodoc:
168
184
  end
169
185
 
170
186
  if load_file
187
+ kwargs = ", **kwargs" if RUBY_ENGINE == "ruby" && RUBY_VERSION >= "2.7.0"
171
188
  line = __LINE__; eval %[
172
- def #{cmd_name}(*opts, &b)
189
+ def #{cmd_name}(*opts#{kwargs}, &b)
173
190
  require "#{load_file}"
174
191
  arity = ExtendCommand::#{cmd_class}.instance_method(:execute).arity
175
192
  args = (1..(arity < 0 ? ~arity : arity)).map {|i| "arg" + i.to_s }
176
- args << "*opts" if arity < 0
193
+ args << "*opts#{kwargs}" if arity < 0
177
194
  args << "&block"
178
195
  args = args.join(", ")
179
196
  line = __LINE__; eval %[
@@ -184,7 +201,7 @@ module IRB # :nodoc:
184
201
  end
185
202
  end
186
203
  ], nil, __FILE__, line
187
- __send__ :#{cmd_name}_, *opts, &b
204
+ __send__ :#{cmd_name}_, *opts#{kwargs}, &b
188
205
  end
189
206
  ], nil, __FILE__, line
190
207
  else
data/lib/irb/init.rb CHANGED
@@ -44,7 +44,7 @@ module IRB # :nodoc:
44
44
  @CONF[:IRB_RC] = nil
45
45
 
46
46
  @CONF[:USE_SINGLELINE] = false unless defined?(ReadlineInputMethod)
47
- @CONF[:USE_COLORIZE] = true
47
+ @CONF[:USE_COLORIZE] = !ENV['NO_COLOR']
48
48
  @CONF[:INSPECT_MODE] = true
49
49
  @CONF[:USE_TRACER] = false
50
50
  @CONF[:USE_LOADER] = false
@@ -120,7 +120,11 @@ module IRB # :nodoc:
120
120
  puts 'processing time: %fs' % (now - time) if IRB.conf[:MEASURE]
121
121
  result
122
122
  }
123
+ # arg can be either a symbol for the mode (:cpu, :wall, ..) or a hash for
124
+ # a more complete configuration.
125
+ # See https://github.com/tmm1/stackprof#all-options.
123
126
  @CONF[:MEASURE_PROC][:STACKPROF] = proc { |context, code, line_no, arg, &block|
127
+ return block.() unless IRB.conf[:MEASURE]
124
128
  success = false
125
129
  begin
126
130
  require 'stackprof'
@@ -130,10 +134,18 @@ module IRB # :nodoc:
130
134
  end
131
135
  if success
132
136
  result = nil
133
- stackprof_result = StackProf.run(mode: arg ? arg : :cpu) do
137
+ arg = { mode: arg || :cpu } unless arg.is_a?(Hash)
138
+ stackprof_result = StackProf.run(**arg) do
134
139
  result = block.()
135
140
  end
136
- StackProf::Report.new(stackprof_result).print_text if IRB.conf[:MEASURE]
141
+ case stackprof_result
142
+ when File
143
+ puts "StackProf report saved to #{stackprof_result.path}"
144
+ when Hash
145
+ StackProf::Report.new(stackprof_result).print_text
146
+ else
147
+ puts "Stackprof ran with #{arg.inspect}"
148
+ end
137
149
  result
138
150
  else
139
151
  block.()
@@ -301,11 +313,11 @@ module IRB # :nodoc:
301
313
  break
302
314
  end
303
315
  end
316
+
304
317
  load_path.collect! do |path|
305
318
  /\A\.\// =~ path ? path : File.expand_path(path)
306
319
  end
307
320
  $LOAD_PATH.unshift(*load_path)
308
-
309
321
  end
310
322
 
311
323
  # running config
@@ -14,6 +14,7 @@ require_relative 'magic-file'
14
14
  require_relative 'completion'
15
15
  require 'io/console'
16
16
  require 'reline'
17
+ require 'rdoc'
17
18
 
18
19
  module IRB
19
20
  STDIN_FILE_NAME = "(line)" # :nodoc:
@@ -280,6 +281,7 @@ module IRB
280
281
  Reline.basic_word_break_characters = IRB::InputCompletor::BASIC_WORD_BREAK_CHARACTERS
281
282
  end
282
283
  Reline.completion_append_character = nil
284
+ Reline.completer_quote_characters = ''
283
285
  Reline.completion_proc = IRB::InputCompletor::CompletionProc
284
286
  Reline.output_modifier_proc =
285
287
  if IRB.conf[:USE_COLORIZE]
@@ -307,6 +309,50 @@ module IRB
307
309
  @auto_indent_proc = block
308
310
  end
309
311
 
312
+ SHOW_DOC_DIALOG = ->() {
313
+ begin
314
+ require 'rdoc'
315
+ rescue LoadError
316
+ return nil
317
+ end
318
+ if just_cursor_moving and completion_journey_data.nil?
319
+ return nil
320
+ end
321
+ cursor_pos_to_render, result, pointer = context.pop(3)
322
+ return nil if result.nil? or pointer.nil?
323
+ name = result[pointer]
324
+
325
+ driver = RDoc::RI::Driver.new
326
+ begin
327
+ name = driver.expand_name(name)
328
+ rescue RDoc::RI::Driver::NotFoundError
329
+ return nil
330
+ end
331
+ doc = nil
332
+ used_for_class = false
333
+ if not name =~ /#|\./
334
+ found, klasses, includes, extends = driver.classes_and_includes_and_extends_for(name)
335
+ if not found.empty?
336
+ doc = driver.class_document(name, found, klasses, includes, extends)
337
+ used_for_class = true
338
+ end
339
+ end
340
+ unless used_for_class
341
+ doc = RDoc::Markup::Document.new
342
+ begin
343
+ driver.add_method(doc, name)
344
+ rescue RDoc::RI::Driver::NotFoundError
345
+ doc = nil
346
+ end
347
+ end
348
+ return nil if doc.nil?
349
+ formatter = RDoc::Markup::ToAnsi.new
350
+ formatter.width = 40
351
+ str = doc.accept(formatter)
352
+
353
+ [Reline::CursorPos.new(cursor_pos_to_render.x + 40, cursor_pos_to_render.y + pointer), str.split("\n"), nil, '49']
354
+ }
355
+
310
356
  # Reads the next line from this input method.
311
357
  #
312
358
  # See IO#gets for more information.
@@ -315,6 +361,7 @@ module IRB
315
361
  Reline.output = @stdout
316
362
  Reline.prompt_proc = @prompt_proc
317
363
  Reline.auto_indent_proc = @auto_indent_proc if @auto_indent_proc
364
+ Reline.add_dialog_proc(:show_doc, SHOW_DOC_DIALOG, Reline::DEFAULT_DIALOG_CONTEXT)
318
365
  if l = readmultiline(@prompt, false, &@check_termination_proc)
319
366
  HISTORY.push(l) if !l.empty?
320
367
  @line[@line_no += 1] = l + "\n"
@@ -10,7 +10,7 @@
10
10
  #
11
11
  #
12
12
  Usage: irb.rb [options] [programfile] [arguments]
13
- -f Suppress read of ~/.irbrc
13
+ -f Suppress read of ~/.irbrc
14
14
  -d Set $DEBUG to true (same as `ruby -d')
15
15
  -r load-module Same as `ruby -r'
16
16
  -I path Specify $LOAD_PATH directory
@@ -18,7 +18,7 @@ Usage: irb.rb [options] [programfile] [arguments]
18
18
  -E enc Same as `ruby -E`
19
19
  -w Same as `ruby -w`
20
20
  -W[level=2] Same as `ruby -W`
21
- --context-mode n Set n[0-3] to method to create Binding Object,
21
+ --context-mode n Set n[0-4] to method to create Binding Object,
22
22
  when new workspace was created
23
23
  --echo Show result(default)
24
24
  --noecho Don't show result
@@ -31,8 +31,8 @@ Usage: irb.rb [options] [programfile] [arguments]
31
31
  --colorize Use colorization
32
32
  --nocolorize Don't use colorization
33
33
  --prompt prompt-mode/--prompt-mode prompt-mode
34
- Switch prompt mode. Pre-defined prompt modes are
35
- `default', `simple', `xmp' and `inf-ruby'
34
+ Switch prompt mode. Pre-defined prompt modes are
35
+ `default', `simple', `xmp' and `inf-ruby'
36
36
  --inf-ruby-mode Use prompt appropriate for inf-ruby-mode on emacs.
37
37
  Suppresses --multiline and --singleline.
38
38
  --sample-book-mode/--simple-prompt
@@ -41,8 +41,8 @@ Usage: irb.rb [options] [programfile] [arguments]
41
41
  --single-irb Share self with sub-irb.
42
42
  --tracer Display trace for each execution of commands.
43
43
  --back-trace-limit n
44
- Display backtrace top n and tail n. The default
45
- value is 16.
44
+ Display backtrace top n and tail n. The default
45
+ value is 16.
46
46
  --verbose Show details
47
47
  --noverbose Don't show details
48
48
  -v, --version Print the version of irb
data/lib/irb/ruby-lex.rb CHANGED
@@ -30,29 +30,48 @@ class RubyLex
30
30
  @prompt = nil
31
31
  end
32
32
 
33
- def self.compile_with_errors_suppressed(code)
34
- line_no = 1
33
+ def self.compile_with_errors_suppressed(code, line_no: 1)
35
34
  begin
36
35
  result = yield code, line_no
37
36
  rescue ArgumentError
37
+ # Ruby can issue an error for the code if there is an
38
+ # incomplete magic comment for encoding in it. Force an
39
+ # expression with a new line before the code in this
40
+ # case to prevent magic comment handling. To make sure
41
+ # line numbers in the lexed code remain the same,
42
+ # decrease the line number by one.
38
43
  code = ";\n#{code}"
39
- line_no = 0
44
+ line_no -= 1
40
45
  result = yield code, line_no
41
46
  end
42
47
  result
43
48
  end
44
49
 
45
50
  # io functions
46
- def set_input(io, p = nil, &block)
51
+ def set_input(io, p = nil, context: nil, &block)
47
52
  @io = io
48
53
  if @io.respond_to?(:check_termination)
49
54
  @io.check_termination do |code|
50
- code.gsub!(/\s*\z/, '').concat("\n")
51
- ltype, indent, continue, code_block_open = check_state(code)
52
- if ltype or indent > 0 or continue or code_block_open
53
- false
55
+ if Reline::IOGate.in_pasting?
56
+ lex = RubyLex.new
57
+ rest = lex.check_termination_in_prev_line(code, context: context)
58
+ if rest
59
+ Reline.delete_text
60
+ rest.bytes.reverse_each do |c|
61
+ Reline.ungetc(c)
62
+ end
63
+ true
64
+ else
65
+ false
66
+ end
54
67
  else
55
- true
68
+ code.gsub!(/\s*\z/, '').concat("\n")
69
+ ltype, indent, continue, code_block_open = check_state(code, context: context)
70
+ if ltype or indent > 0 or continue or code_block_open
71
+ false
72
+ else
73
+ true
74
+ end
56
75
  end
57
76
  end
58
77
  end
@@ -60,7 +79,7 @@ class RubyLex
60
79
  @io.dynamic_prompt do |lines|
61
80
  lines << '' if lines.empty?
62
81
  result = []
63
- tokens = ripper_lex_without_warning(lines.map{ |l| l + "\n" }.join)
82
+ tokens = self.class.ripper_lex_without_warning(lines.map{ |l| l + "\n" }.join, context: context)
64
83
  code = String.new
65
84
  partial_tokens = []
66
85
  unprocessed_tokens = []
@@ -72,7 +91,7 @@ class RubyLex
72
91
  t_str = t[2]
73
92
  t_str.each_line("\n") do |s|
74
93
  code << s << "\n"
75
- ltype, indent, continue, code_block_open = check_state(code, partial_tokens)
94
+ ltype, indent, continue, code_block_open = check_state(code, partial_tokens, context: context)
76
95
  result << @prompt.call(ltype, indent, continue || code_block_open, @line_no + line_num_offset)
77
96
  line_num_offset += 1
78
97
  end
@@ -82,7 +101,7 @@ class RubyLex
82
101
  end
83
102
  end
84
103
  unless unprocessed_tokens.empty?
85
- ltype, indent, continue, code_block_open = check_state(code, unprocessed_tokens)
104
+ ltype, indent, continue, code_block_open = check_state(code, unprocessed_tokens, context: context)
86
105
  result << @prompt.call(ltype, indent, continue || code_block_open, @line_no + line_num_offset)
87
106
  end
88
107
  result
@@ -115,15 +134,25 @@ class RubyLex
115
134
  :on_param_error
116
135
  ]
117
136
 
118
- def ripper_lex_without_warning(code)
137
+ def self.ripper_lex_without_warning(code, context: nil)
119
138
  verbose, $VERBOSE = $VERBOSE, nil
139
+ if context
140
+ lvars = context&.workspace&.binding&.local_variables
141
+ if lvars && !lvars.empty?
142
+ code = "#{lvars.join('=')}=nil\n#{code}"
143
+ line_no = 0
144
+ else
145
+ line_no = 1
146
+ end
147
+ end
120
148
  tokens = nil
121
- self.class.compile_with_errors_suppressed(code) do |inner_code, line_no|
149
+ compile_with_errors_suppressed(code, line_no: line_no) do |inner_code, line_no|
122
150
  lexer = Ripper::Lexer.new(inner_code, '-', line_no)
123
151
  if lexer.respond_to?(:scan) # Ruby 2.7+
124
152
  tokens = []
125
153
  pos_to_index = {}
126
154
  lexer.scan.each do |t|
155
+ next if t.pos.first == 0
127
156
  if pos_to_index.has_key?(t[0])
128
157
  index = pos_to_index[t[0]]
129
158
  found_tk = tokens[index]
@@ -168,7 +197,7 @@ class RubyLex
168
197
  if @io.respond_to?(:auto_indent) and context.auto_indent_mode
169
198
  @io.auto_indent do |lines, line_index, byte_pointer, is_newline|
170
199
  if is_newline
171
- @tokens = ripper_lex_without_warning(lines[0..line_index].join("\n"))
200
+ @tokens = self.class.ripper_lex_without_warning(lines[0..line_index].join("\n"), context: context)
172
201
  prev_spaces = find_prev_spaces(line_index)
173
202
  depth_difference = check_newline_depth_difference
174
203
  depth_difference = 0 if depth_difference < 0
@@ -177,7 +206,7 @@ class RubyLex
177
206
  code = line_index.zero? ? '' : lines[0..(line_index - 1)].map{ |l| l + "\n" }.join
178
207
  last_line = lines[line_index]&.byteslice(0, byte_pointer)
179
208
  code += last_line if last_line
180
- @tokens = ripper_lex_without_warning(code)
209
+ @tokens = self.class.ripper_lex_without_warning(code, context: context)
181
210
  corresponding_token_depth = check_corresponding_token_depth
182
211
  if corresponding_token_depth
183
212
  corresponding_token_depth
@@ -189,8 +218,8 @@ class RubyLex
189
218
  end
190
219
  end
191
220
 
192
- def check_state(code, tokens = nil)
193
- tokens = ripper_lex_without_warning(code) unless tokens
221
+ def check_state(code, tokens = nil, context: nil)
222
+ tokens = self.class.ripper_lex_without_warning(code, context: context) unless tokens
194
223
  ltype = process_literal_type(tokens)
195
224
  indent = process_nesting_level(tokens)
196
225
  continue = process_continue(tokens)
@@ -256,7 +285,7 @@ class RubyLex
256
285
  end
257
286
  code = @line + (line.nil? ? '' : line)
258
287
  code.gsub!(/\s*\z/, '').concat("\n")
259
- @tokens = ripper_lex_without_warning(code)
288
+ @tokens = self.class.ripper_lex_without_warning(code)
260
289
  @continue = process_continue
261
290
  @code_block_open = check_code_block(code)
262
291
  @indent = process_nesting_level
@@ -277,8 +306,9 @@ class RubyLex
277
306
  return true
278
307
  elsif tokens.size >= 1 and tokens[-1][1] == :on_heredoc_end # "EOH\n"
279
308
  return false
280
- elsif tokens.size >= 2 and defined?(Ripper::EXPR_BEG) and tokens[-2][3].anybits?(Ripper::EXPR_BEG | Ripper::EXPR_FNAME)
309
+ elsif tokens.size >= 2 and defined?(Ripper::EXPR_BEG) and tokens[-2][3].anybits?(Ripper::EXPR_BEG | Ripper::EXPR_FNAME) and tokens[-2][2] !~ /\A\.\.\.?\z/
281
310
  # end of literal except for regexp
311
+ # endless range at end of line is not a continue
282
312
  return true
283
313
  end
284
314
  false
@@ -324,7 +354,7 @@ class RubyLex
324
354
  # "syntax error, unexpected end-of-input, expecting keyword_end"
325
355
  #
326
356
  # example:
327
- # if ture
357
+ # if true
328
358
  # hoge
329
359
  # if false
330
360
  # fuga
@@ -685,7 +715,7 @@ class RubyLex
685
715
  start_token << t
686
716
  end_type << :on_regexp_end
687
717
  when :on_symbeg
688
- acceptable_single_tokens = %i{on_ident on_const on_op on_cvar on_ivar on_gvar on_kw}
718
+ acceptable_single_tokens = %i{on_ident on_const on_op on_cvar on_ivar on_gvar on_kw on_int}
689
719
  if (i + 1) < tokens.size and acceptable_single_tokens.all?{ |st| tokens[i + 1][1] != st }
690
720
  start_token << t
691
721
  end_type << :on_tstring_end
@@ -738,5 +768,50 @@ class RubyLex
738
768
  nil
739
769
  end
740
770
  end
771
+
772
+ def check_termination_in_prev_line(code, context: nil)
773
+ tokens = self.class.ripper_lex_without_warning(code, context: context)
774
+ past_first_newline = false
775
+ index = tokens.rindex do |t|
776
+ # traverse first token before last line
777
+ if past_first_newline
778
+ if t.tok.include?("\n")
779
+ true
780
+ end
781
+ elsif t.tok.include?("\n")
782
+ past_first_newline = true
783
+ false
784
+ else
785
+ false
786
+ end
787
+ end
788
+ if index
789
+ first_token = nil
790
+ last_line_tokens = tokens[(index + 1)..(tokens.size - 1)]
791
+ last_line_tokens.each do |t|
792
+ unless [:on_sp, :on_ignored_sp, :on_comment].include?(t.event)
793
+ first_token = t
794
+ break
795
+ end
796
+ end
797
+ if first_token.nil?
798
+ return false
799
+ elsif first_token && first_token.state == Ripper::EXPR_DOT
800
+ return false
801
+ else
802
+ tokens_without_last_line = tokens[0..index]
803
+ ltype = process_literal_type(tokens_without_last_line)
804
+ indent = process_nesting_level(tokens_without_last_line)
805
+ continue = process_continue(tokens_without_last_line)
806
+ code_block_open = check_code_block(tokens_without_last_line.map(&:tok).join(''), tokens_without_last_line)
807
+ if ltype or indent > 0 or continue or code_block_open
808
+ return false
809
+ else
810
+ return last_line_tokens.map(&:tok).join('')
811
+ end
812
+ end
813
+ end
814
+ false
815
+ end
741
816
  end
742
817
  # :startdoc:
data/lib/irb/version.rb CHANGED
@@ -11,7 +11,7 @@
11
11
  #
12
12
 
13
13
  module IRB # :nodoc:
14
- VERSION = "1.3.4"
14
+ VERSION = "1.3.8.pre.1"
15
15
  @RELEASE_VERSION = VERSION
16
- @LAST_UPDATE_DATE = "2021-02-25"
16
+ @LAST_UPDATE_DATE = "2021-08-29"
17
17
  end
data/lib/irb.rb CHANGED
@@ -60,7 +60,11 @@ require_relative "irb/easter-egg"
60
60
  # -E enc Same as `ruby -E`
61
61
  # -w Same as `ruby -w`
62
62
  # -W[level=2] Same as `ruby -W`
63
- # --inspect Use `inspect' for output (default except for bc mode)
63
+ # --context-mode n Set n[0-4] to method to create Binding Object,
64
+ # when new workspace was created
65
+ # --echo Show result(default)
66
+ # --noecho Don't show result
67
+ # --inspect Use `inspect' for output
64
68
  # --noinspect Don't use inspect for output
65
69
  # --multiline Use multiline editor module
66
70
  # --nomultiline Don't use multiline editor module
@@ -68,19 +72,24 @@ require_relative "irb/easter-egg"
68
72
  # --nosingleline Don't use singleline editor module
69
73
  # --colorize Use colorization
70
74
  # --nocolorize Don't use colorization
71
- # --prompt prompt-mode
72
- # --prompt-mode prompt-mode
75
+ # --prompt prompt-mode/--prompt-mode prompt-mode
73
76
  # Switch prompt mode. Pre-defined prompt modes are
74
77
  # `default', `simple', `xmp' and `inf-ruby'
75
78
  # --inf-ruby-mode Use prompt appropriate for inf-ruby-mode on emacs.
76
79
  # Suppresses --multiline and --singleline.
77
- # --simple-prompt Simple prompt mode
80
+ # --sample-book-mode/--simple-prompt
81
+ # Simple prompt mode
78
82
  # --noprompt No prompt mode
83
+ # --single-irb Share self with sub-irb.
79
84
  # --tracer Display trace for each execution of commands.
80
85
  # --back-trace-limit n
81
86
  # Display backtrace top n and tail n. The default
82
87
  # value is 16.
83
- # -v, --version Print the version of irb
88
+ # --verbose Show details
89
+ # --noverbose Don't show details
90
+ # -v, --version Print the version of irb
91
+ # -h, --help Print help
92
+ # -- Separate options of irb from the list of command-line args
84
93
  #
85
94
  # == Configuration
86
95
  #
@@ -463,7 +472,7 @@ module IRB
463
472
  conf[:IRB_RC].call(context) if conf[:IRB_RC]
464
473
  conf[:MAIN_CONTEXT] = context
465
474
 
466
- trap("SIGINT") do
475
+ prev_trap = trap("SIGINT") do
467
476
  signal_handle
468
477
  end
469
478
 
@@ -472,6 +481,7 @@ module IRB
472
481
  eval_input
473
482
  end
474
483
  ensure
484
+ trap("SIGINT", prev_trap)
475
485
  conf[:AT_EXIT].each{|hook| hook.call}
476
486
  end
477
487
  end
@@ -514,7 +524,7 @@ module IRB
514
524
  @context.io.prompt
515
525
  end
516
526
 
517
- @scanner.set_input(@context.io) do
527
+ @scanner.set_input(@context.io, context: @context) do
518
528
  signal_status(:IN_INPUT) do
519
529
  if l = @context.io.gets
520
530
  print l if @context.verbose?
@@ -580,9 +590,15 @@ module IRB
580
590
  end
581
591
  end
582
592
 
583
- def convert_invalid_byte_sequence(str)
584
- str = str.force_encoding(Encoding::ASCII_8BIT)
585
- conv = Encoding::Converter.new(Encoding::ASCII_8BIT, Encoding::UTF_8)
593
+ def convert_invalid_byte_sequence(str, enc)
594
+ str.force_encoding(enc)
595
+ str.scrub { |c|
596
+ c.bytes.map{ |b| "\\x#{b.to_s(16).upcase}" }.join
597
+ }
598
+ end
599
+
600
+ def encode_with_invalid_byte_sequence(str, enc)
601
+ conv = Encoding::Converter.new(str.encoding, enc)
586
602
  dst = String.new
587
603
  begin
588
604
  ret = conv.primitive_convert(str, dst)
@@ -630,7 +646,8 @@ module IRB
630
646
  message = exc.full_message(order: :top)
631
647
  order = :top
632
648
  end
633
- message = convert_invalid_byte_sequence(message)
649
+ message = convert_invalid_byte_sequence(message, exc.message.encoding)
650
+ message = encode_with_invalid_byte_sequence(message, IRB.conf[:LC_MESSAGES].encoding) unless message.encoding.to_s.casecmp?(IRB.conf[:LC_MESSAGES].encoding.to_s)
634
651
  message = message.gsub(/((?:^\t.+$\n)+)/) { |m|
635
652
  case order
636
653
  when :top
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: irb
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.3.4
4
+ version: 1.3.8.pre.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Keiju ISHITSUKA
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2021-02-25 00:00:00.000000000 Z
11
+ date: 2021-08-29 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: reline
@@ -16,42 +16,14 @@ dependencies:
16
16
  requirements:
17
17
  - - ">="
18
18
  - !ruby/object:Gem::Version
19
- version: 0.1.5
19
+ version: 0.2.8.pre.1
20
20
  type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
24
  - - ">="
25
25
  - !ruby/object:Gem::Version
26
- version: 0.1.5
27
- - !ruby/object:Gem::Dependency
28
- name: bundler
29
- requirement: !ruby/object:Gem::Requirement
30
- requirements:
31
- - - ">="
32
- - !ruby/object:Gem::Version
33
- version: '0'
34
- type: :development
35
- prerelease: false
36
- version_requirements: !ruby/object:Gem::Requirement
37
- requirements:
38
- - - ">="
39
- - !ruby/object:Gem::Version
40
- version: '0'
41
- - !ruby/object:Gem::Dependency
42
- name: rake
43
- requirement: !ruby/object:Gem::Requirement
44
- requirements:
45
- - - ">="
46
- - !ruby/object:Gem::Version
47
- version: '0'
48
- type: :development
49
- prerelease: false
50
- version_requirements: !ruby/object:Gem::Requirement
51
- requirements:
52
- - - ">="
53
- - !ruby/object:Gem::Version
54
- version: '0'
26
+ version: 0.2.8.pre.1
55
27
  description: Interactive Ruby command-line tool for REPL (Read Eval Print Loop).
56
28
  email:
57
29
  - keiju@ruby-lang.org
@@ -77,10 +49,13 @@ files:
77
49
  - lib/irb/cmd/help.rb
78
50
  - lib/irb/cmd/info.rb
79
51
  - lib/irb/cmd/load.rb
52
+ - lib/irb/cmd/ls.rb
80
53
  - lib/irb/cmd/measure.rb
81
54
  - lib/irb/cmd/nop.rb
82
55
  - lib/irb/cmd/pushws.rb
56
+ - lib/irb/cmd/show_source.rb
83
57
  - lib/irb/cmd/subirb.rb
58
+ - lib/irb/cmd/whereami.rb
84
59
  - lib/irb/color.rb
85
60
  - lib/irb/color_printer.rb
86
61
  - lib/irb/completion.rb
@@ -133,11 +108,11 @@ required_ruby_version: !ruby/object:Gem::Requirement
133
108
  version: '2.5'
134
109
  required_rubygems_version: !ruby/object:Gem::Requirement
135
110
  requirements:
136
- - - ">="
111
+ - - ">"
137
112
  - !ruby/object:Gem::Version
138
- version: '0'
113
+ version: 1.3.1
139
114
  requirements: []
140
- rubygems_version: 3.0.6
115
+ rubygems_version: 3.2.22
141
116
  signing_key:
142
117
  specification_version: 4
143
118
  summary: Interactive Ruby command-line tool for REPL (Read Eval Print Loop).