irb 1.1.0.pre.3

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.
Files changed (49) hide show
  1. checksums.yaml +7 -0
  2. data/LICENSE.txt +22 -0
  3. data/README.md +55 -0
  4. data/exe/irb +11 -0
  5. data/irb.gemspec +29 -0
  6. data/lib/irb.rb +855 -0
  7. data/lib/irb/cmd/chws.rb +34 -0
  8. data/lib/irb/cmd/fork.rb +39 -0
  9. data/lib/irb/cmd/help.rb +46 -0
  10. data/lib/irb/cmd/load.rb +67 -0
  11. data/lib/irb/cmd/nop.rb +39 -0
  12. data/lib/irb/cmd/pushws.rb +41 -0
  13. data/lib/irb/cmd/subirb.rb +43 -0
  14. data/lib/irb/color.rb +218 -0
  15. data/lib/irb/completion.rb +339 -0
  16. data/lib/irb/context.rb +459 -0
  17. data/lib/irb/ext/change-ws.rb +46 -0
  18. data/lib/irb/ext/history.rb +120 -0
  19. data/lib/irb/ext/loader.rb +129 -0
  20. data/lib/irb/ext/multi-irb.rb +265 -0
  21. data/lib/irb/ext/save-history.rb +117 -0
  22. data/lib/irb/ext/tracer.rb +72 -0
  23. data/lib/irb/ext/use-loader.rb +77 -0
  24. data/lib/irb/ext/workspaces.rb +67 -0
  25. data/lib/irb/extend-command.rb +328 -0
  26. data/lib/irb/frame.rb +81 -0
  27. data/lib/irb/help.rb +37 -0
  28. data/lib/irb/init.rb +312 -0
  29. data/lib/irb/input-method.rb +298 -0
  30. data/lib/irb/inspector.rb +142 -0
  31. data/lib/irb/lc/.document +4 -0
  32. data/lib/irb/lc/error.rb +32 -0
  33. data/lib/irb/lc/help-message +50 -0
  34. data/lib/irb/lc/ja/encoding_aliases.rb +11 -0
  35. data/lib/irb/lc/ja/error.rb +31 -0
  36. data/lib/irb/lc/ja/help-message +52 -0
  37. data/lib/irb/locale.rb +182 -0
  38. data/lib/irb/magic-file.rb +38 -0
  39. data/lib/irb/notifier.rb +232 -0
  40. data/lib/irb/output-method.rb +92 -0
  41. data/lib/irb/ruby-lex.rb +492 -0
  42. data/lib/irb/ruby-token.rb +267 -0
  43. data/lib/irb/slex.rb +282 -0
  44. data/lib/irb/src_encoding.rb +7 -0
  45. data/lib/irb/version.rb +17 -0
  46. data/lib/irb/workspace.rb +190 -0
  47. data/lib/irb/ws-for-case-2.rb +15 -0
  48. data/lib/irb/xmp.rb +170 -0
  49. metadata +133 -0
@@ -0,0 +1,34 @@
1
+ # frozen_string_literal: false
2
+ #
3
+ # change-ws.rb -
4
+ # $Release Version: 0.9.6$
5
+ # $Revision$
6
+ # by Keiju ISHITSUKA(keiju@ruby-lang.org)
7
+ #
8
+ # --
9
+ #
10
+ #
11
+ #
12
+
13
+ require_relative "nop"
14
+ require_relative "../ext/change-ws"
15
+
16
+ # :stopdoc:
17
+ module IRB
18
+ module ExtendCommand
19
+
20
+ class CurrentWorkingWorkspace < Nop
21
+ def execute(*obj)
22
+ irb_context.main
23
+ end
24
+ end
25
+
26
+ class ChangeWorkspace < Nop
27
+ def execute(*obj)
28
+ irb_context.change_workspace(*obj)
29
+ irb_context.main
30
+ end
31
+ end
32
+ end
33
+ end
34
+ # :startdoc:
@@ -0,0 +1,39 @@
1
+ # frozen_string_literal: false
2
+ #
3
+ # fork.rb -
4
+ # $Release Version: 0.9.6 $
5
+ # $Revision$
6
+ # by Keiju ISHITSUKA(keiju@ruby-lang.org)
7
+ #
8
+ # --
9
+ #
10
+ #
11
+ #
12
+
13
+
14
+ # :stopdoc:
15
+ module IRB
16
+ module ExtendCommand
17
+ class Fork < Nop
18
+ def execute
19
+ pid = send ExtendCommand.irb_original_method_name("fork")
20
+ unless pid
21
+ class << self
22
+ alias_method :exit, ExtendCommand.irb_original_method_name('exit')
23
+ end
24
+ if block_given?
25
+ begin
26
+ yield
27
+ ensure
28
+ exit
29
+ end
30
+ end
31
+ end
32
+ pid
33
+ end
34
+ end
35
+ end
36
+ end
37
+ # :startdoc:
38
+
39
+
@@ -0,0 +1,46 @@
1
+ # frozen_string_literal: false
2
+ #
3
+ # help.rb - helper using ri
4
+ # $Release Version: 0.9.6$
5
+ # $Revision$
6
+ #
7
+ # --
8
+ #
9
+ #
10
+ #
11
+
12
+ require_relative "nop"
13
+
14
+ # :stopdoc:
15
+ module IRB
16
+ module ExtendCommand
17
+ class Help < Nop
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
24
+ else
25
+ def execute(*names)
26
+ if names.empty?
27
+ Ri.interactive
28
+ return
29
+ end
30
+ names.each do |name|
31
+ begin
32
+ Ri.display_name(name.to_s)
33
+ rescue RDoc::RI::Error
34
+ puts $!.message
35
+ end
36
+ end
37
+ nil
38
+ end
39
+ nil
40
+ ensure
41
+ execute(*names)
42
+ end
43
+ end
44
+ end
45
+ end
46
+ # :startdoc:
@@ -0,0 +1,67 @@
1
+ # frozen_string_literal: false
2
+ #
3
+ # load.rb -
4
+ # $Release Version: 0.9.6$
5
+ # $Revision$
6
+ # by Keiju ISHITSUKA(keiju@ruby-lang.org)
7
+ #
8
+ # --
9
+ #
10
+ #
11
+ #
12
+
13
+ require_relative "nop"
14
+ require_relative "../ext/loader"
15
+
16
+ # :stopdoc:
17
+ module IRB
18
+ module ExtendCommand
19
+ class Load < Nop
20
+ include IrbLoader
21
+
22
+ def execute(file_name, priv = nil)
23
+ return irb_load(file_name, priv)
24
+ end
25
+ end
26
+
27
+ class Require < Nop
28
+ include IrbLoader
29
+
30
+ def execute(file_name)
31
+
32
+ rex = Regexp.new("#{Regexp.quote(file_name)}(\.o|\.rb)?")
33
+ return false if $".find{|f| f =~ rex}
34
+
35
+ case file_name
36
+ when /\.rb$/
37
+ begin
38
+ if irb_load(file_name)
39
+ $".push file_name
40
+ return true
41
+ end
42
+ rescue LoadError
43
+ end
44
+ when /\.(so|o|sl)$/
45
+ return ruby_require(file_name)
46
+ end
47
+
48
+ begin
49
+ irb_load(f = file_name + ".rb")
50
+ $".push f
51
+ return true
52
+ rescue LoadError
53
+ return ruby_require(file_name)
54
+ end
55
+ end
56
+ end
57
+
58
+ class Source < Nop
59
+ include IrbLoader
60
+ def execute(file_name)
61
+ source_file(file_name)
62
+ end
63
+ end
64
+ end
65
+
66
+ end
67
+ # :startdoc:
@@ -0,0 +1,39 @@
1
+ # frozen_string_literal: false
2
+ #
3
+ # nop.rb -
4
+ # $Release Version: 0.9.6$
5
+ # $Revision$
6
+ # by Keiju ISHITSUKA(keiju@ruby-lang.org)
7
+ #
8
+ # --
9
+ #
10
+ #
11
+ #
12
+ # :stopdoc:
13
+ module IRB
14
+ module ExtendCommand
15
+ class Nop
16
+
17
+
18
+ def self.execute(conf, *opts)
19
+ command = new(conf)
20
+ command.execute(*opts)
21
+ end
22
+
23
+ def initialize(conf)
24
+ @irb_context = conf
25
+ end
26
+
27
+ attr_reader :irb_context
28
+
29
+ def irb
30
+ @irb_context.irb
31
+ end
32
+
33
+ def execute(*opts)
34
+ #nop
35
+ end
36
+ end
37
+ end
38
+ end
39
+ # :startdoc:
@@ -0,0 +1,41 @@
1
+ # frozen_string_literal: false
2
+ #
3
+ # change-ws.rb -
4
+ # $Release Version: 0.9.6$
5
+ # $Revision$
6
+ # by Keiju ISHITSUKA(keiju@ruby-lang.org)
7
+ #
8
+ # --
9
+ #
10
+ #
11
+ #
12
+
13
+ require_relative "nop"
14
+ require_relative "../ext/workspaces"
15
+
16
+ # :stopdoc:
17
+ module IRB
18
+ module ExtendCommand
19
+ class Workspaces < Nop
20
+ def execute(*obj)
21
+ irb_context.workspaces.collect{|ws| ws.main}
22
+ end
23
+ end
24
+
25
+ class PushWorkspace < Workspaces
26
+ def execute(*obj)
27
+ irb_context.push_workspace(*obj)
28
+ super
29
+ end
30
+ end
31
+
32
+ class PopWorkspace < Workspaces
33
+ def execute(*obj)
34
+ irb_context.pop_workspace(*obj)
35
+ super
36
+ end
37
+ end
38
+ end
39
+ end
40
+ # :startdoc:
41
+
@@ -0,0 +1,43 @@
1
+ # frozen_string_literal: false
2
+ # multi.rb -
3
+ # $Release Version: 0.9.6$
4
+ # $Revision$
5
+ # by Keiju ISHITSUKA(keiju@ruby-lang.org)
6
+ #
7
+ # --
8
+ #
9
+ #
10
+ #
11
+
12
+ require_relative "nop"
13
+ require_relative "../ext/multi-irb"
14
+
15
+ # :stopdoc:
16
+ module IRB
17
+ module ExtendCommand
18
+ class IrbCommand < Nop
19
+ def execute(*obj)
20
+ IRB.irb(nil, *obj)
21
+ end
22
+ end
23
+
24
+ class Jobs < Nop
25
+ def execute
26
+ IRB.JobManager
27
+ end
28
+ end
29
+
30
+ class Foreground < Nop
31
+ def execute(key)
32
+ IRB.JobManager.switch(key)
33
+ end
34
+ end
35
+
36
+ class Kill < Nop
37
+ def execute(*keys)
38
+ IRB.JobManager.kill(*keys)
39
+ end
40
+ end
41
+ end
42
+ end
43
+ # :startdoc:
@@ -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