irb 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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