irb 1.1.0.pre.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/LICENSE.txt +22 -0
- data/README.md +55 -0
- data/exe/irb +11 -0
- data/irb.gemspec +29 -0
- data/lib/irb.rb +855 -0
- data/lib/irb/cmd/chws.rb +34 -0
- data/lib/irb/cmd/fork.rb +39 -0
- data/lib/irb/cmd/help.rb +46 -0
- data/lib/irb/cmd/load.rb +67 -0
- data/lib/irb/cmd/nop.rb +39 -0
- data/lib/irb/cmd/pushws.rb +41 -0
- data/lib/irb/cmd/subirb.rb +43 -0
- data/lib/irb/color.rb +218 -0
- data/lib/irb/completion.rb +339 -0
- data/lib/irb/context.rb +459 -0
- data/lib/irb/ext/change-ws.rb +46 -0
- data/lib/irb/ext/history.rb +120 -0
- data/lib/irb/ext/loader.rb +129 -0
- data/lib/irb/ext/multi-irb.rb +265 -0
- data/lib/irb/ext/save-history.rb +117 -0
- data/lib/irb/ext/tracer.rb +72 -0
- data/lib/irb/ext/use-loader.rb +77 -0
- data/lib/irb/ext/workspaces.rb +67 -0
- data/lib/irb/extend-command.rb +328 -0
- data/lib/irb/frame.rb +81 -0
- data/lib/irb/help.rb +37 -0
- data/lib/irb/init.rb +312 -0
- data/lib/irb/input-method.rb +298 -0
- data/lib/irb/inspector.rb +142 -0
- data/lib/irb/lc/.document +4 -0
- data/lib/irb/lc/error.rb +32 -0
- data/lib/irb/lc/help-message +50 -0
- data/lib/irb/lc/ja/encoding_aliases.rb +11 -0
- data/lib/irb/lc/ja/error.rb +31 -0
- data/lib/irb/lc/ja/help-message +52 -0
- data/lib/irb/locale.rb +182 -0
- data/lib/irb/magic-file.rb +38 -0
- data/lib/irb/notifier.rb +232 -0
- data/lib/irb/output-method.rb +92 -0
- data/lib/irb/ruby-lex.rb +492 -0
- data/lib/irb/ruby-token.rb +267 -0
- data/lib/irb/slex.rb +282 -0
- data/lib/irb/src_encoding.rb +7 -0
- data/lib/irb/version.rb +17 -0
- data/lib/irb/workspace.rb +190 -0
- data/lib/irb/ws-for-case-2.rb +15 -0
- data/lib/irb/xmp.rb +170 -0
- metadata +133 -0
checksums.yaml
ADDED
@@ -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
|
data/LICENSE.txt
ADDED
@@ -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.
|
data/README.md
ADDED
@@ -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
data/irb.gemspec
ADDED
@@ -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
|
data/lib/irb.rb
ADDED
@@ -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
|