irb 1.1.0.pre.3

Sign up to get free protection for your applications and to get access to all the features.
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,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 71eba1b800fb1d93376272f2f222979ae70d21f19a129b9c06a148784a2e178b
4
+ data.tar.gz: 02e1cb9a9d88a5e582467975edf596e848e7076066ada250798c43ccbafdfe0b
5
+ SHA512:
6
+ metadata.gz: a4acfeb73e0b972fb9ca65b89e1e74f8c9523c26b3d9021af148214f7991d4eb9d633b58a6dbd7b7da7b1c800efc7dd814ddee9bd31c0680ee6e59c0c7b4e5b4
7
+ data.tar.gz: c0cf5a8bf14b9d1fc037021cff5cd6ad94834595b4c21f933367111114a241279c7643db6e1e0ac408746c448ff9f9b37acf65923600e1437a4a77aca07d5f49
@@ -0,0 +1,22 @@
1
+ Copyright (C) 1993-2013 Yukihiro Matsumoto. All rights reserved.
2
+
3
+ Redistribution and use in source and binary forms, with or without
4
+ modification, are permitted provided that the following conditions
5
+ are met:
6
+ 1. Redistributions of source code must retain the above copyright
7
+ notice, this list of conditions and the following disclaimer.
8
+ 2. Redistributions in binary form must reproduce the above copyright
9
+ notice, this list of conditions and the following disclaimer in the
10
+ documentation and/or other materials provided with the distribution.
11
+
12
+ THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
13
+ ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
14
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
15
+ ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
16
+ FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
17
+ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
18
+ OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
19
+ HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
20
+ LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
21
+ OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
22
+ SUCH DAMAGE.
@@ -0,0 +1,55 @@
1
+ # IRB
2
+
3
+ IRB stands for "interactive Ruby" and is a tool to interactively execute Ruby expressions read from the standard input.
4
+
5
+ The `irb` command from your shell will start the interpreter.
6
+
7
+ ## Installation
8
+
9
+ Add this line to your application's Gemfile:
10
+
11
+ ```ruby
12
+ gem 'irb'
13
+ ```
14
+
15
+ And then execute:
16
+
17
+ $ bundle
18
+
19
+ Or install it yourself as:
20
+
21
+ $ gem install irb
22
+
23
+ ## Usage
24
+
25
+ Use of irb is easy if you know Ruby.
26
+
27
+ When executing irb, prompts are displayed as follows. Then, enter the Ruby expression. An input is executed when it is syntactically complete.
28
+
29
+ ```
30
+ $ irb
31
+ irb(main):001:0> 1+2
32
+ #=> 3
33
+ irb(main):002:0> class Foo
34
+ irb(main):003:1> def foo
35
+ irb(main):004:2> print 1
36
+ irb(main):005:2> end
37
+ irb(main):006:1> end
38
+ #=> nil
39
+ ```
40
+
41
+ The Readline extension module can be used with irb. Use of Readline is default if it's installed.
42
+
43
+ ## Development
44
+
45
+ After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake test` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
46
+
47
+ To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
48
+
49
+ ## Contributing
50
+
51
+ Bug reports and pull requests are welcome on GitHub at https://github.com/ruby/irb.
52
+
53
+ ## License
54
+
55
+ The gem is available as open source under the terms of the [2-Clause BSD License](https://opensource.org/licenses/BSD-2-Clause).
data/exe/irb ADDED
@@ -0,0 +1,11 @@
1
+ #!/usr/bin/env ruby
2
+ #
3
+ # irb.rb - interactive ruby
4
+ # $Release Version: 0.9.6 $
5
+ # $Revision$
6
+ # by Keiju ISHITSUKA(keiju@ruby-lang.org)
7
+ #
8
+
9
+ require "irb"
10
+
11
+ IRB.start(__FILE__)
@@ -0,0 +1,29 @@
1
+ begin
2
+ require_relative "lib/irb/version"
3
+ rescue LoadError
4
+ # for Ruby core repository
5
+ require_relative "version"
6
+ end
7
+
8
+ Gem::Specification.new do |spec|
9
+ spec.name = "irb"
10
+ spec.version = IRB::VERSION
11
+ spec.authors = ["Keiju ISHITSUKA"]
12
+ spec.email = ["keiju@ruby-lang.org"]
13
+
14
+ spec.summary = %q{Interactive Ruby command-line tool for REPL (Read Eval Print Loop).}
15
+ spec.description = %q{Interactive Ruby command-line tool for REPL (Read Eval Print Loop).}
16
+ spec.homepage = "https://github.com/ruby/irb"
17
+ spec.license = "BSD-2-Clause"
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/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
+ spec.bindir = "exe"
21
+ spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
22
+ spec.require_paths = ["lib"]
23
+
24
+ spec.required_ruby_version = Gem::Requirement.new(">= 2.4")
25
+
26
+ spec.add_dependency "reline", ">= 0.0.1"
27
+ spec.add_development_dependency "bundler"
28
+ spec.add_development_dependency "rake"
29
+ end
@@ -0,0 +1,855 @@
1
+ # frozen_string_literal: false
2
+ #
3
+ # irb.rb - irb main module
4
+ # $Release Version: 0.9.6 $
5
+ # $Revision$
6
+ # by Keiju ISHITSUKA(keiju@ruby-lang.org)
7
+ #
8
+ # --
9
+ #
10
+ #
11
+ #
12
+ require "e2mmap"
13
+ require "ripper"
14
+
15
+ require "irb/init"
16
+ require "irb/context"
17
+ require "irb/extend-command"
18
+
19
+ require "irb/ruby-lex"
20
+ require "irb/input-method"
21
+ require "irb/locale"
22
+ require "irb/color"
23
+
24
+ require "irb/version"
25
+
26
+ # IRB stands for "interactive Ruby" and is a tool to interactively execute Ruby
27
+ # expressions read from the standard input.
28
+ #
29
+ # The +irb+ command from your shell will start the interpreter.
30
+ #
31
+ # == Usage
32
+ #
33
+ # Use of irb is easy if you know Ruby.
34
+ #
35
+ # When executing irb, prompts are displayed as follows. Then, enter the Ruby
36
+ # expression. An input is executed when it is syntactically complete.
37
+ #
38
+ # $ irb
39
+ # irb(main):001:0> 1+2
40
+ # #=> 3
41
+ # irb(main):002:0> class Foo
42
+ # irb(main):003:1> def foo
43
+ # irb(main):004:2> print 1
44
+ # irb(main):005:2> end
45
+ # irb(main):006:1> end
46
+ # #=> nil
47
+ #
48
+ # The Readline extension module can be used with irb. Use of Readline is
49
+ # default if it's installed.
50
+ #
51
+ # == Command line options
52
+ #
53
+ # Usage: irb.rb [options] [programfile] [arguments]
54
+ # -f Suppress read of ~/.irbrc
55
+ # -d Set $DEBUG to true (same as `ruby -d')
56
+ # -r load-module Same as `ruby -r'
57
+ # -I path Specify $LOAD_PATH directory
58
+ # -U Same as `ruby -U`
59
+ # -E enc Same as `ruby -E`
60
+ # -w Same as `ruby -w`
61
+ # -W[level=2] Same as `ruby -W`
62
+ # --inspect Use `inspect' for output (default except for bc mode)
63
+ # --noinspect Don't use inspect for output
64
+ # --reidline Use Reidline extension module
65
+ # --noreidline Don't use Reidline extension module
66
+ # --readline Use Readline extension module
67
+ # --noreadline Don't use Readline extension module
68
+ # --colorize Use colorization
69
+ # --nocolorize Don't use colorization
70
+ # --prompt prompt-mode
71
+ # --prompt-mode prompt-mode
72
+ # Switch prompt mode. Pre-defined prompt modes are
73
+ # `default', `simple', `xmp' and `inf-ruby'
74
+ # --inf-ruby-mode Use prompt appropriate for inf-ruby-mode on emacs.
75
+ # Suppresses --reidline and --readline.
76
+ # --simple-prompt Simple prompt mode
77
+ # --noprompt No prompt mode
78
+ # --tracer Display trace for each execution of commands.
79
+ # --back-trace-limit n
80
+ # Display backtrace top n and tail n. The default
81
+ # value is 16.
82
+ # -v, --version Print the version of irb
83
+ #
84
+ # == Configuration
85
+ #
86
+ # IRB reads from <code>~/.irbrc</code> when it's invoked.
87
+ #
88
+ # If <code>~/.irbrc</code> doesn't exist, +irb+ will try to read in the following order:
89
+ #
90
+ # * +.irbrc+
91
+ # * +irb.rc+
92
+ # * +_irbrc+
93
+ # * <code>$irbrc</code>
94
+ #
95
+ # The following are alternatives to the command line options. To use them type
96
+ # as follows in an +irb+ session:
97
+ #
98
+ # IRB.conf[:IRB_NAME]="irb"
99
+ # IRB.conf[:INSPECT_MODE]=nil
100
+ # IRB.conf[:IRB_RC] = nil
101
+ # IRB.conf[:BACK_TRACE_LIMIT]=16
102
+ # IRB.conf[:USE_LOADER] = false
103
+ # IRB.conf[:USE_REIDLINE] = nil
104
+ # IRB.conf[:USE_READLINE] = nil
105
+ # IRB.conf[:USE_COLORIZE] = true
106
+ # IRB.conf[:USE_TRACER] = false
107
+ # IRB.conf[:IGNORE_SIGINT] = true
108
+ # IRB.conf[:IGNORE_EOF] = false
109
+ # IRB.conf[:PROMPT_MODE] = :DEFAULT
110
+ # IRB.conf[:PROMPT] = {...}
111
+ #
112
+ # === Auto indentation
113
+ #
114
+ # To disable auto-indent mode in irb, add the following to your +.irbrc+:
115
+ #
116
+ # IRB.conf[:AUTO_INDENT] = false
117
+ #
118
+ # === Autocompletion
119
+ #
120
+ # To enable autocompletion for irb, add the following to your +.irbrc+:
121
+ #
122
+ # require 'irb/completion'
123
+ #
124
+ # === History
125
+ #
126
+ # By default, irb will store the last 1000 commands you used in
127
+ # <code>~/.irb_history</code>.
128
+ #
129
+ # If you want to disable history, add the following to your +.irbrc+:
130
+ #
131
+ # IRB.conf[:SAVE_HISTORY] = nil
132
+ #
133
+ # See IRB::Context#save_history= for more information.
134
+ #
135
+ # == Customizing the IRB Prompt
136
+ #
137
+ # In order to customize the prompt, you can change the following Hash:
138
+ #
139
+ # IRB.conf[:PROMPT]
140
+ #
141
+ # This example can be used in your +.irbrc+
142
+ #
143
+ # IRB.conf[:PROMPT][:MY_PROMPT] = { # name of prompt mode
144
+ # :AUTO_INDENT => false, # disables auto-indent mode
145
+ # :PROMPT_I => ">> ", # simple prompt
146
+ # :PROMPT_S => nil, # prompt for continuated strings
147
+ # :PROMPT_C => nil, # prompt for continuated statement
148
+ # :RETURN => " ==>%s\n" # format to return value
149
+ # }
150
+ #
151
+ # IRB.conf[:PROMPT_MODE] = :MY_PROMPT
152
+ #
153
+ # Or, invoke irb with the above prompt mode by:
154
+ #
155
+ # irb --prompt my-prompt
156
+ #
157
+ # Constants +PROMPT_I+, +PROMPT_S+ and +PROMPT_C+ specify the format. In the
158
+ # prompt specification, some special strings are available:
159
+ #
160
+ # %N # command name which is running
161
+ # %m # to_s of main object (self)
162
+ # %M # inspect of main object (self)
163
+ # %l # type of string(", ', /, ]), `]' is inner %w[...]
164
+ # %NNi # indent level. NN is digits and means as same as printf("%NNd").
165
+ # # It can be omitted
166
+ # %NNn # line number.
167
+ # %% # %
168
+ #
169
+ # For instance, the default prompt mode is defined as follows:
170
+ #
171
+ # IRB.conf[:PROMPT_MODE][:DEFAULT] = {
172
+ # :PROMPT_I => "%N(%m):%03n:%i> ",
173
+ # :PROMPT_N => "%N(%m):%03n:%i> ",
174
+ # :PROMPT_S => "%N(%m):%03n:%i%l ",
175
+ # :PROMPT_C => "%N(%m):%03n:%i* ",
176
+ # :RETURN => "%s\n" # used to printf
177
+ # }
178
+ #
179
+ # irb comes with a number of available modes:
180
+ #
181
+ # # :NULL:
182
+ # # :PROMPT_I:
183
+ # # :PROMPT_N:
184
+ # # :PROMPT_S:
185
+ # # :PROMPT_C:
186
+ # # :RETURN: |
187
+ # # %s
188
+ # # :DEFAULT:
189
+ # # :PROMPT_I: ! '%N(%m):%03n:%i> '
190
+ # # :PROMPT_N: ! '%N(%m):%03n:%i> '
191
+ # # :PROMPT_S: ! '%N(%m):%03n:%i%l '
192
+ # # :PROMPT_C: ! '%N(%m):%03n:%i* '
193
+ # # :RETURN: |
194
+ # # => %s
195
+ # # :CLASSIC:
196
+ # # :PROMPT_I: ! '%N(%m):%03n:%i> '
197
+ # # :PROMPT_N: ! '%N(%m):%03n:%i> '
198
+ # # :PROMPT_S: ! '%N(%m):%03n:%i%l '
199
+ # # :PROMPT_C: ! '%N(%m):%03n:%i* '
200
+ # # :RETURN: |
201
+ # # %s
202
+ # # :SIMPLE:
203
+ # # :PROMPT_I: ! '>> '
204
+ # # :PROMPT_N: ! '>> '
205
+ # # :PROMPT_S:
206
+ # # :PROMPT_C: ! '?> '
207
+ # # :RETURN: |
208
+ # # => %s
209
+ # # :INF_RUBY:
210
+ # # :PROMPT_I: ! '%N(%m):%03n:%i> '
211
+ # # :PROMPT_N:
212
+ # # :PROMPT_S:
213
+ # # :PROMPT_C:
214
+ # # :RETURN: |
215
+ # # %s
216
+ # # :AUTO_INDENT: true
217
+ # # :XMP:
218
+ # # :PROMPT_I:
219
+ # # :PROMPT_N:
220
+ # # :PROMPT_S:
221
+ # # :PROMPT_C:
222
+ # # :RETURN: |2
223
+ # # ==>%s
224
+ #
225
+ # == Restrictions
226
+ #
227
+ # Because irb evaluates input immediately after it is syntactically complete,
228
+ # the results may be slightly different than directly using Ruby.
229
+ #
230
+ # == IRB Sessions
231
+ #
232
+ # IRB has a special feature, that allows you to manage many sessions at once.
233
+ #
234
+ # You can create new sessions with Irb.irb, and get a list of current sessions
235
+ # with the +jobs+ command in the prompt.
236
+ #
237
+ # === Commands
238
+ #
239
+ # JobManager provides commands to handle the current sessions:
240
+ #
241
+ # jobs # List of current sessions
242
+ # fg # Switches to the session of the given number
243
+ # kill # Kills the session with the given number
244
+ #
245
+ # The +exit+ command, or ::irb_exit, will quit the current session and call any
246
+ # exit hooks with IRB.irb_at_exit.
247
+ #
248
+ # A few commands for loading files within the session are also available:
249
+ #
250
+ # +source+::
251
+ # Loads a given file in the current session and displays the source lines,
252
+ # see IrbLoader#source_file
253
+ # +irb_load+::
254
+ # Loads the given file similarly to Kernel#load, see IrbLoader#irb_load
255
+ # +irb_require+::
256
+ # Loads the given file similarly to Kernel#require
257
+ #
258
+ # === Configuration
259
+ #
260
+ # The command line options, or IRB.conf, specify the default behavior of
261
+ # Irb.irb.
262
+ #
263
+ # On the other hand, each conf in IRB@Command+line+options is used to
264
+ # individually configure IRB.irb.
265
+ #
266
+ # If a proc is set for IRB.conf[:IRB_RC], its will be invoked after execution
267
+ # of that proc with the context of the current session as its argument. Each
268
+ # session can be configured using this mechanism.
269
+ #
270
+ # === Session variables
271
+ #
272
+ # There are a few variables in every Irb session that can come in handy:
273
+ #
274
+ # <code>_</code>::
275
+ # The value command executed, as a local variable
276
+ # <code>__</code>::
277
+ # The history of evaluated commands
278
+ # <code>__[line_no]</code>::
279
+ # Returns the evaluation value at the given line number, +line_no+.
280
+ # If +line_no+ is a negative, the return value +line_no+ many lines before
281
+ # the most recent return value.
282
+ #
283
+ # === Example using IRB Sessions
284
+ #
285
+ # # invoke a new session
286
+ # irb(main):001:0> irb
287
+ # # list open sessions
288
+ # irb.1(main):001:0> jobs
289
+ # #0->irb on main (#<Thread:0x400fb7e4> : stop)
290
+ # #1->irb#1 on main (#<Thread:0x40125d64> : running)
291
+ #
292
+ # # change the active session
293
+ # irb.1(main):002:0> fg 0
294
+ # # define class Foo in top-level session
295
+ # irb(main):002:0> class Foo;end
296
+ # # invoke a new session with the context of Foo
297
+ # irb(main):003:0> irb Foo
298
+ # # define Foo#foo
299
+ # irb.2(Foo):001:0> def foo
300
+ # irb.2(Foo):002:1> print 1
301
+ # irb.2(Foo):003:1> end
302
+ #
303
+ # # change the active session
304
+ # irb.2(Foo):004:0> fg 0
305
+ # # list open sessions
306
+ # irb(main):004:0> jobs
307
+ # #0->irb on main (#<Thread:0x400fb7e4> : running)
308
+ # #1->irb#1 on main (#<Thread:0x40125d64> : stop)
309
+ # #2->irb#2 on Foo (#<Thread:0x4011d54c> : stop)
310
+ # # check if Foo#foo is available
311
+ # irb(main):005:0> Foo.instance_methods #=> [:foo, ...]
312
+ #
313
+ # # change the active sesssion
314
+ # irb(main):006:0> fg 2
315
+ # # define Foo#bar in the context of Foo
316
+ # irb.2(Foo):005:0> def bar
317
+ # irb.2(Foo):006:1> print "bar"
318
+ # irb.2(Foo):007:1> end
319
+ # irb.2(Foo):010:0> Foo.instance_methods #=> [:bar, :foo, ...]
320
+ #
321
+ # # change the active session
322
+ # irb.2(Foo):011:0> fg 0
323
+ # irb(main):007:0> f = Foo.new #=> #<Foo:0x4010af3c>
324
+ # # invoke a new session with the context of f (instance of Foo)
325
+ # irb(main):008:0> irb f
326
+ # # list open sessions
327
+ # irb.3(<Foo:0x4010af3c>):001:0> jobs
328
+ # #0->irb on main (#<Thread:0x400fb7e4> : stop)
329
+ # #1->irb#1 on main (#<Thread:0x40125d64> : stop)
330
+ # #2->irb#2 on Foo (#<Thread:0x4011d54c> : stop)
331
+ # #3->irb#3 on #<Foo:0x4010af3c> (#<Thread:0x4010a1e0> : running)
332
+ # # evaluate f.foo
333
+ # irb.3(<Foo:0x4010af3c>):002:0> foo #=> 1 => nil
334
+ # # evaluate f.bar
335
+ # irb.3(<Foo:0x4010af3c>):003:0> bar #=> bar => nil
336
+ # # kill jobs 1, 2, and 3
337
+ # irb.3(<Foo:0x4010af3c>):004:0> kill 1, 2, 3
338
+ # # list open sessions, should only include main session
339
+ # irb(main):009:0> jobs
340
+ # #0->irb on main (#<Thread:0x400fb7e4> : running)
341
+ # # quit irb
342
+ # irb(main):010:0> exit
343
+ module IRB
344
+
345
+ # An exception raised by IRB.irb_abort
346
+ class Abort < Exception;end
347
+
348
+ @CONF = {}
349
+
350
+
351
+ # Displays current configuration.
352
+ #
353
+ # Modifying the configuration is achieved by sending a message to IRB.conf.
354
+ #
355
+ # See IRB@Configuration for more information.
356
+ def IRB.conf
357
+ @CONF
358
+ end
359
+
360
+ # Returns the current version of IRB, including release version and last
361
+ # updated date.
362
+ def IRB.version
363
+ if v = @CONF[:VERSION] then return v end
364
+
365
+ @CONF[:VERSION] = format("irb %s (%s)", @RELEASE_VERSION, @LAST_UPDATE_DATE)
366
+ end
367
+
368
+ # The current IRB::Context of the session, see IRB.conf
369
+ #
370
+ # irb
371
+ # irb(main):001:0> IRB.CurrentContext.irb_name = "foo"
372
+ # foo(main):002:0> IRB.conf[:MAIN_CONTEXT].irb_name #=> "foo"
373
+ def IRB.CurrentContext
374
+ IRB.conf[:MAIN_CONTEXT]
375
+ end
376
+
377
+ # Initializes IRB and creates a new Irb.irb object at the +TOPLEVEL_BINDING+
378
+ def IRB.start(ap_path = nil)
379
+ STDOUT.sync = true
380
+ $0 = File::basename(ap_path, ".rb") if ap_path
381
+
382
+ IRB.setup(ap_path)
383
+
384
+ if @CONF[:SCRIPT]
385
+ irb = Irb.new(nil, @CONF[:SCRIPT])
386
+ else
387
+ irb = Irb.new
388
+ end
389
+ irb.run(@CONF)
390
+ end
391
+
392
+ # Calls each event hook of IRB.conf[:AT_EXIT] when the current session quits.
393
+ def IRB.irb_at_exit
394
+ @CONF[:AT_EXIT].each{|hook| hook.call}
395
+ end
396
+
397
+ # Quits irb
398
+ def IRB.irb_exit(irb, ret)
399
+ throw :IRB_EXIT, ret
400
+ end
401
+
402
+ # Aborts then interrupts irb.
403
+ #
404
+ # Will raise an Abort exception, or the given +exception+.
405
+ def IRB.irb_abort(irb, exception = Abort)
406
+ if defined? Thread
407
+ irb.context.thread.raise exception, "abort then interrupt!"
408
+ else
409
+ raise exception, "abort then interrupt!"
410
+ end
411
+ end
412
+
413
+ class Irb
414
+ ASSIGNMENT_NODE_TYPES = [
415
+ # Local, instance, global, class, constant, instance, and index assignment:
416
+ # "foo = bar",
417
+ # "@foo = bar",
418
+ # "$foo = bar",
419
+ # "@@foo = bar",
420
+ # "::Foo = bar",
421
+ # "a::Foo = bar",
422
+ # "Foo = bar"
423
+ # "foo.bar = 1"
424
+ # "foo[1] = bar"
425
+ :assign,
426
+
427
+ # Operation assignment:
428
+ # "foo += bar"
429
+ # "foo -= bar"
430
+ # "foo ||= bar"
431
+ # "foo &&= bar"
432
+ :opassign,
433
+
434
+ # Multiple assignment:
435
+ # "foo, bar = 1, 2
436
+ :massign,
437
+ ]
438
+ # Note: instance and index assignment expressions could also be written like:
439
+ # "foo.bar=(1)" and "foo.[]=(1, bar)", when expressed that way, the former
440
+ # be parsed as :assign and echo will be suppressed, but the latter is
441
+ # parsed as a :method_add_arg and the output won't be suppressed
442
+
443
+ # Creates a new irb session
444
+ def initialize(workspace = nil, input_method = nil, output_method = nil)
445
+ @context = Context.new(self, workspace, input_method, output_method)
446
+ @context.main.extend ExtendCommandBundle
447
+ @signal_status = :IN_IRB
448
+ @scanner = RubyLex.new
449
+ end
450
+
451
+ def run(conf = IRB.conf)
452
+ conf[:IRB_RC].call(context) if conf[:IRB_RC]
453
+ conf[:MAIN_CONTEXT] = context
454
+
455
+ trap("SIGINT") do
456
+ signal_handle
457
+ end
458
+
459
+ begin
460
+ catch(:IRB_EXIT) do
461
+ eval_input
462
+ end
463
+ ensure
464
+ conf[:AT_EXIT].each{|hook| hook.call}
465
+ end
466
+ end
467
+
468
+ # Returns the current context of this irb session
469
+ attr_reader :context
470
+ # The lexer used by this irb session
471
+ attr_accessor :scanner
472
+
473
+ # Evaluates input for this session.
474
+ def eval_input
475
+ exc = nil
476
+
477
+ @scanner.set_prompt do
478
+ |ltype, indent, continue, line_no|
479
+ if ltype
480
+ f = @context.prompt_s
481
+ elsif continue
482
+ f = @context.prompt_c
483
+ elsif indent > 0
484
+ f = @context.prompt_n
485
+ else
486
+ f = @context.prompt_i
487
+ end
488
+ f = "" unless f
489
+ if @context.prompting?
490
+ @context.io.prompt = p = prompt(f, ltype, indent, line_no)
491
+ else
492
+ @context.io.prompt = p = ""
493
+ end
494
+ if @context.auto_indent_mode and !@context.io.respond_to?(:auto_indent)
495
+ unless ltype
496
+ prompt_i = @context.prompt_i.nil? ? "" : @context.prompt_i
497
+ ind = prompt(prompt_i, ltype, indent, line_no)[/.*\z/].size +
498
+ indent * 2 - p.size
499
+ ind += 2 if continue
500
+ @context.io.prompt = p + " " * ind if ind > 0
501
+ end
502
+ end
503
+ @context.io.prompt
504
+ end
505
+
506
+ @scanner.set_input(@context.io) do
507
+ signal_status(:IN_INPUT) do
508
+ if l = @context.io.gets
509
+ print l if @context.verbose?
510
+ else
511
+ if @context.ignore_eof? and @context.io.readable_after_eof?
512
+ l = "\n"
513
+ if @context.verbose?
514
+ printf "Use \"exit\" to leave %s\n", @context.ap_name
515
+ end
516
+ else
517
+ print "\n"
518
+ end
519
+ end
520
+ l
521
+ end
522
+ end
523
+
524
+ @scanner.set_auto_indent(@context) if @context.auto_indent_mode
525
+
526
+ @scanner.each_top_level_statement do |line, line_no|
527
+ signal_status(:IN_EVAL) do
528
+ begin
529
+ line.untaint
530
+ @context.evaluate(line, line_no, exception: exc)
531
+ output_value if @context.echo? && (@context.echo_on_assignment? || !assignment_expression?(line))
532
+ rescue Interrupt => exc
533
+ rescue SystemExit, SignalException
534
+ raise
535
+ rescue Exception => exc
536
+ else
537
+ exc = nil
538
+ next
539
+ end
540
+ handle_exception(exc)
541
+ end
542
+ end
543
+ end
544
+
545
+ def handle_exception(exc)
546
+ if exc.backtrace && exc.backtrace[0] =~ /irb(2)?(\/.*|-.*|\.rb)?:/ && exc.class.to_s !~ /^IRB/ &&
547
+ !(SyntaxError === exc)
548
+ irb_bug = true
549
+ else
550
+ irb_bug = false
551
+ end
552
+
553
+ if STDOUT.tty?
554
+ attr = ATTR_TTY
555
+ print "#{attr[1]}Traceback#{attr[]} (most recent call last):\n"
556
+ else
557
+ attr = ATTR_PLAIN
558
+ end
559
+ messages = []
560
+ lasts = []
561
+ levels = 0
562
+ if exc.backtrace
563
+ count = 0
564
+ exc.backtrace.each do |m|
565
+ m = @context.workspace.filter_backtrace(m) or next unless irb_bug
566
+ count += 1
567
+ if attr == ATTR_TTY
568
+ m = sprintf("%9d: from %s", count, m)
569
+ else
570
+ m = "\tfrom #{m}"
571
+ end
572
+ if messages.size < @context.back_trace_limit
573
+ messages.push(m)
574
+ elsif lasts.size < @context.back_trace_limit
575
+ lasts.push(m).shift
576
+ levels += 1
577
+ end
578
+ end
579
+ end
580
+ if attr == ATTR_TTY
581
+ unless lasts.empty?
582
+ puts lasts.reverse
583
+ printf "... %d levels...\n", levels if levels > 0
584
+ end
585
+ puts messages.reverse
586
+ end
587
+ m = exc.to_s.split(/\n/)
588
+ print "#{attr[1]}#{exc.class} (#{attr[4]}#{m.shift}#{attr[0, 1]})#{attr[]}\n"
589
+ puts m.map {|s| "#{attr[1]}#{s}#{attr[]}\n"}
590
+ if attr == ATTR_PLAIN
591
+ puts messages
592
+ unless lasts.empty?
593
+ puts lasts
594
+ printf "... %d levels...\n", levels if levels > 0
595
+ end
596
+ end
597
+ print "Maybe IRB bug!\n" if irb_bug
598
+ end
599
+
600
+ # Evaluates the given block using the given +path+ as the Context#irb_path
601
+ # and +name+ as the Context#irb_name.
602
+ #
603
+ # Used by the irb command +source+, see IRB@IRB+Sessions for more
604
+ # information.
605
+ def suspend_name(path = nil, name = nil)
606
+ @context.irb_path, back_path = path, @context.irb_path if path
607
+ @context.irb_name, back_name = name, @context.irb_name if name
608
+ begin
609
+ yield back_path, back_name
610
+ ensure
611
+ @context.irb_path = back_path if path
612
+ @context.irb_name = back_name if name
613
+ end
614
+ end
615
+
616
+ # Evaluates the given block using the given +workspace+ as the
617
+ # Context#workspace.
618
+ #
619
+ # Used by the irb command +irb_load+, see IRB@IRB+Sessions for more
620
+ # information.
621
+ def suspend_workspace(workspace)
622
+ @context.workspace, back_workspace = workspace, @context.workspace
623
+ begin
624
+ yield back_workspace
625
+ ensure
626
+ @context.workspace = back_workspace
627
+ end
628
+ end
629
+
630
+ # Evaluates the given block using the given +input_method+ as the
631
+ # Context#io.
632
+ #
633
+ # Used by the irb commands +source+ and +irb_load+, see IRB@IRB+Sessions
634
+ # for more information.
635
+ def suspend_input_method(input_method)
636
+ back_io = @context.io
637
+ @context.instance_eval{@io = input_method}
638
+ begin
639
+ yield back_io
640
+ ensure
641
+ @context.instance_eval{@io = back_io}
642
+ end
643
+ end
644
+
645
+ # Evaluates the given block using the given +context+ as the Context.
646
+ def suspend_context(context)
647
+ @context, back_context = context, @context
648
+ begin
649
+ yield back_context
650
+ ensure
651
+ @context = back_context
652
+ end
653
+ end
654
+
655
+ # Handler for the signal SIGINT, see Kernel#trap for more information.
656
+ def signal_handle
657
+ unless @context.ignore_sigint?
658
+ print "\nabort!\n" if @context.verbose?
659
+ exit
660
+ end
661
+
662
+ case @signal_status
663
+ when :IN_INPUT
664
+ print "^C\n"
665
+ raise RubyLex::TerminateLineInput
666
+ when :IN_EVAL
667
+ IRB.irb_abort(self)
668
+ when :IN_LOAD
669
+ IRB.irb_abort(self, LoadAbort)
670
+ when :IN_IRB
671
+ # ignore
672
+ else
673
+ # ignore other cases as well
674
+ end
675
+ end
676
+
677
+ # Evaluates the given block using the given +status+.
678
+ def signal_status(status)
679
+ return yield if @signal_status == :IN_LOAD
680
+
681
+ signal_status_back = @signal_status
682
+ @signal_status = status
683
+ begin
684
+ yield
685
+ ensure
686
+ @signal_status = signal_status_back
687
+ end
688
+ end
689
+
690
+ def prompt(prompt, ltype, indent, line_no) # :nodoc:
691
+ p = prompt.dup
692
+ p.gsub!(/%([0-9]+)?([a-zA-Z])/) do
693
+ case $2
694
+ when "N"
695
+ @context.irb_name
696
+ when "m"
697
+ @context.main.to_s
698
+ when "M"
699
+ @context.main.inspect
700
+ when "l"
701
+ ltype
702
+ when "i"
703
+ if indent < 0
704
+ if $1
705
+ "-".rjust($1.to_i)
706
+ else
707
+ "-"
708
+ end
709
+ else
710
+ if $1
711
+ format("%" + $1 + "d", indent)
712
+ else
713
+ indent.to_s
714
+ end
715
+ end
716
+ when "n"
717
+ if $1
718
+ format("%" + $1 + "d", line_no)
719
+ else
720
+ line_no.to_s
721
+ end
722
+ when "%"
723
+ "%"
724
+ end
725
+ end
726
+ p
727
+ end
728
+
729
+ def output_value # :nodoc:
730
+ printf @context.return_format, @context.inspect_last_value
731
+ end
732
+
733
+ # Outputs the local variables to this current session, including
734
+ # #signal_status and #context, using IRB::Locale.
735
+ def inspect
736
+ ary = []
737
+ for iv in instance_variables
738
+ case (iv = iv.to_s)
739
+ when "@signal_status"
740
+ ary.push format("%s=:%s", iv, @signal_status.id2name)
741
+ when "@context"
742
+ ary.push format("%s=%s", iv, eval(iv).__to_s__)
743
+ else
744
+ ary.push format("%s=%s", iv, eval(iv))
745
+ end
746
+ end
747
+ format("#<%s: %s>", self.class, ary.join(", "))
748
+ end
749
+
750
+ def assignment_expression?(line)
751
+ # Try to parse the line and check if the last of possibly multiple
752
+ # expressions is an assignment type.
753
+
754
+ # If the expression is invalid, Ripper.sexp should return nil which will
755
+ # result in false being returned. Any valid expression should return an
756
+ # s-expression where the second selement of the top level array is an
757
+ # array of parsed expressions. The first element of each expression is the
758
+ # expression's type.
759
+ ASSIGNMENT_NODE_TYPES.include?(Ripper.sexp(line)&.dig(1,-1,0))
760
+ end
761
+
762
+ ATTR_TTY = "\e[%sm"
763
+ def ATTR_TTY.[](*a) self % a.join(";"); end
764
+ ATTR_PLAIN = ""
765
+ def ATTR_PLAIN.[](*) self; end
766
+ end
767
+
768
+ def @CONF.inspect
769
+ IRB.version unless self[:VERSION]
770
+
771
+ array = []
772
+ for k, v in sort{|a1, a2| a1[0].id2name <=> a2[0].id2name}
773
+ case k
774
+ when :MAIN_CONTEXT, :__TMP__EHV__
775
+ array.push format("CONF[:%s]=...myself...", k.id2name)
776
+ when :PROMPT
777
+ s = v.collect{
778
+ |kk, vv|
779
+ ss = vv.collect{|kkk, vvv| ":#{kkk.id2name}=>#{vvv.inspect}"}
780
+ format(":%s=>{%s}", kk.id2name, ss.join(", "))
781
+ }
782
+ array.push format("CONF[:%s]={%s}", k.id2name, s.join(", "))
783
+ else
784
+ array.push format("CONF[:%s]=%s", k.id2name, v.inspect)
785
+ end
786
+ end
787
+ array.join("\n")
788
+ end
789
+ end
790
+
791
+ class Binding
792
+ # Opens an IRB session where +binding.irb+ is called which allows for
793
+ # interactive debugging. You can call any methods or variables available in
794
+ # the current scope, and mutate state if you need to.
795
+ #
796
+ #
797
+ # Given a Ruby file called +potato.rb+ containing the following code:
798
+ #
799
+ # class Potato
800
+ # def initialize
801
+ # @cooked = false
802
+ # binding.irb
803
+ # puts "Cooked potato: #{@cooked}"
804
+ # end
805
+ # end
806
+ #
807
+ # Potato.new
808
+ #
809
+ # Running <code>ruby potato.rb</code> will open an IRB session where
810
+ # +binding.irb+ is called, and you will see the following:
811
+ #
812
+ # $ ruby potato.rb
813
+ #
814
+ # From: potato.rb @ line 4 :
815
+ #
816
+ # 1: class Potato
817
+ # 2: def initialize
818
+ # 3: @cooked = false
819
+ # => 4: binding.irb
820
+ # 5: puts "Cooked potato: #{@cooked}"
821
+ # 6: end
822
+ # 7: end
823
+ # 8:
824
+ # 9: Potato.new
825
+ #
826
+ # irb(#<Potato:0x00007feea1916670>):001:0>
827
+ #
828
+ # You can type any valid Ruby code and it will be evaluated in the current
829
+ # context. This allows you to debug without having to run your code repeatedly:
830
+ #
831
+ # irb(#<Potato:0x00007feea1916670>):001:0> @cooked
832
+ # => false
833
+ # irb(#<Potato:0x00007feea1916670>):002:0> self.class
834
+ # => Potato
835
+ # irb(#<Potato:0x00007feea1916670>):003:0> caller.first
836
+ # => ".../2.5.1/lib/ruby/2.5.0/irb/workspace.rb:85:in `eval'"
837
+ # irb(#<Potato:0x00007feea1916670>):004:0> @cooked = true
838
+ # => true
839
+ #
840
+ # You can exit the IRB session with the +exit+ command. Note that exiting will
841
+ # resume execution where +binding.irb+ had paused it, as you can see from the
842
+ # output printed to standard output in this example:
843
+ #
844
+ # irb(#<Potato:0x00007feea1916670>):005:0> exit
845
+ # Cooked potato: true
846
+ #
847
+ #
848
+ # See IRB@IRB+Usage for more information.
849
+ def irb
850
+ IRB.setup(source_location[0], argv: [])
851
+ workspace = IRB::WorkSpace.new(self)
852
+ STDOUT.print(workspace.code_around_binding)
853
+ IRB::Irb.new(workspace).run(IRB.conf)
854
+ end
855
+ end