irb 1.0.0

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