IRB: exit a changed binding (`cb`) without exiting entire IRB session? - ruby

In an IRB session, I can use cb (change binding) to enter an object, but how do I get out? If I use exit it exits the entire IRB session.
$ irb
❯ o = Object.new
=> #<Object:0x007fc8a32258a8>
❯ cb(o)
=> #<Object:0x007fc8a32258a8>
❯ self
=> #<Object:0x007fc8a32258a8>
❯ exit
$
For that matter, how do I continue navigating objects once I've started? I've found I can access the cb method from whichever object I'm in by first extending IRB::ExtendCommandBundle, but is there a less tedious way?

Your best bet might be to use pry instead. It's a very powerful debugger that can also be used for most of the things irb is used for. I use it for inspecting my code and objects in rails apps.
https://github.com/pry/pry
Get it with gem install pry
Then you can do this:
$ pry
[1] pry(main)> cd ""
[2] pry(""):1> self
=> ""
[3] pry(""):1> exit
=> ""
[4] pry(main)> exit
$
Along with much, much more.

Related

Why doesn't IRB display output when executing in VS Code Terminal?

Newbie here.. I'm trying out VS Code and am running into an issue. I've connected VS Code to WSL through remote connection and everything is running great expect for IRB.. When I open IRB in the Terminal and execute a command, the output is not displayed. If I open pry and execute a command, output is displayed as normal. Even weirder, when using IRB if I switch to the Output tab and then back to Terminal all the output is displayed. Examples below:
➜ ~ irb
3.0.0 :001 > 1 + 1
3.0.0 :002 > greeting = 'hello'
3.0.0 :003 >
➜ ~ pry
[1] pry(main)> 1 + 1
=> 2
[2] pry(main)> greeting = 'hello'
=> "hello"
[3] pry(main)>
If I copy the lines where IRB output is displayed and paste on newline, the output is exactly as expected. Any help would be awesome!

Why is the --simple-prompt command not working?

I'm just starting with Ruby, so please bear with me. The problem is that when I enter --simple-prompt into irb on OS 10.10.3 terminal, I don't get the simple prompt, I get an error message:
irb(main):001:0> --simple-prompt
NameError: undefined local variable or method `simple' for main:Object
from (irb):1
from /usr/local/bin/irb:11:in `<main>'
I'm assuming that the following problem is related to the above in that -v, -cw, etc. don't seem to work either. Thanks for any help!
You seem to be confused about passing flags to commands vs issuing statements in a REPL.
To start irb with the --simple-prompt option enabled, pass it in like so:
$ irb --simple-prompt
>>
Then you should be able to execute Ruby code.
>> puts "hello world!"
hello world!
=> nil
>>
The issue is that the --simple-prompt is a command line option to toggle the prompt.
You can see this by typing exit to get out of IRB and then typing
irb --help
Which gives you something like this:
Usage: irb.rb [options] [programfile] [arguments]
-f Suppress read of ~/.irbrc
-m Bc mode (load mathn, fraction or matrix are available)
-d Set $DEBUG to true (same as `ruby -d')
-r load-module Same as `ruby -r'
-I path Specify $LOAD_PATH directory
-U Same as `ruby -U`
-E enc Same as `ruby -E`
-w Same as `ruby -w`
-W[level=2] Same as `ruby -W`
--context-mode n Set n[0-3] to method to create Binding Object,
when new workspace was created
--echo Show result(default)
--noecho Don't show result
--inspect Use `inspect' for output (default except for bc mode)
--noinspect Don't use inspect for output
--readline Use Readline extension module
--noreadline Don't use Readline extension module
--prompt prompt-mode/--prompt-mode prompt-mode
Switch prompt mode. Pre-defined prompt modes are
`default', `simple', `xmp' and `inf-ruby'
--inf-ruby-mode Use prompt appropriate for inf-ruby-mode on emacs.
Suppresses --readline.
--sample-book-mode/--simple-prompt
Simple prompt mode
--noprompt No prompt mode
--single-irb Share self with sub-irb.
--tracer Display trace for each execution of commands.
--back-trace-limit n
Display backtrace top n and tail n. The default
value is 16.
--irb_debug n Set internal debug level to n (not for popular use)
--verbose Show details
--noverbose Don't show details
-v, --version Print the version of irb
-h, --help Print help
-- Separate options of irb from the list of command-line args
The --sample-book-mode or --simple-prompt is used in a command like this:
irb --simple-prompt
You can also do:
irb --prompt simple
But you can not do these things inside of IRB.
There is a way to change the prompt inside IRB, though, by changing the #prompt variable.

Running several 'exec' in a ruby loop

I'm scanning a folder for audio files and converting them to mp3.
Works great in RUBY.
However, once the first transcoding is done, it stops the whole loop
Here's a breakdown of my code process.
def scanFolder
# lots of code above to get folder list, check for incorrect files etc..
audioFileList.each {
|getFile|
exec_command = "ffmpeg #{getFile} #{newFileName}"
exec exec_command
}
end
What's happening is that it's transcoding the first file it finds, then it stops the whole function. Is there a way to force it to continue?
The ffmpeg does run and finish correctly at the moment, so it's not breaking anything
exec replaces the current process by running the given command. Example:
2.0.0-p598 :001 > exec 'echo "hello"'
hello
shivam#bluegene:$
You can see how exec replaces the irb with system echo which then exits automatically.
Therefore try using system instead. Here the same example using system:
2.0.0-p598 :003 > system 'echo "hello"'
hello
=> true
2.0.0-p598 :004 >
You can see I am still in irb and its not exited after executing the command.
This makes your code as follows:
def scanFolder
# lots of code above to get folder list, check for incorrect files etc..
audioFileList.each {
|getFile|
exec_command = "ffmpeg #{getFile} #{newFileName}"
system exec_command
}
end
Along with shivam's answer about using system, the spawn method may also be useful here:
http://ruby-doc.org//core-2.1.5/Process.html#method-c-spawn

How do I configure ruby to enter the debugger on Ctrl-C (SIGINT)?

I'd like to enter the debugger upon typing ctrl-C (or sending a SIGINT). I have installed the debugger (I'm running Ruby 1.9.3) and verified that it works. I've added this to my setup files (this is for Padrino, but I assume it would be similar for Rails):
# file: config/boot.rb
Padrino.before_load do
trap("SIGINT") { debugger } if Padrino.env == :development
end
... but typing Ctrl-C does not invoke the debugger. In fact, if I replace debugger with puts "saw an interrupt!", typing Ctrl-C doesn't cause a print to happen either.
update
Following this suggestion from Mike Dunlavey, I tried explicitly calling catch Interrupt from within the debugger:
$ rdebug `which padrino` console
^Z^Z$HOME/usr/bin/padrino:9
require 'rubygems'
(rdb:1) catch Interrupt
Catch exception Interrupt.
(rdb:1) c
=> Loading development console (Padrino v.0.10.7)
=> Loading Application BlueDotAe
=> Loading Application Admin
irb(main):001:0> C-c C-c^C
irb(main):001:0>
No joy -- interrupt did not enter the debugger.
What am I missing?
If you want to trap SIGINT while running in the console, the short answer is: you cannot unless you monkey-patch IRB. Every Ruby app (whether padrino, or rails or whatnot) that uses the console will end up calling usr/lib/ruby/1.9.1/irb.rb, and in IRB.start, it does:
trap("SIGINT") do
irb.signal_handle
end
... just before entering the main loop. This will override any trap("SIGINT") you might have put in your startup code.
But if you want to trap SIGINT in a script file (for example, if you want to profile your code as described by Mike Dunlavey here), you can create a script file such as:
# File: profile_complex_operation.rb
trap("SIGINT") { debugger }
MyApp.complex_operation
and then invoke it as in:
$ ruby profile_complex_operation.rb
Now, when you hit ^C (or send SIGINT from another process), it will enter the debugger.
You may try to use GDB wrapper for Ruby (GitHub).
Install on Linux via:
sudo apt-get install gdb python-dev ncurses-dev ruby-rvm
gem install gdb.rb
Basic usage:
require 'gdb'
# create a new GDB::Ruby instance and attach it to
# pid 12345
gdb = GDB::Ruby.new(12345)
# print the (ruby) backtrace of the remote process
gdb.backtrace.each { |line| puts line }
# show the current local variables, and their values
p gdb.local_variables
# evaluate arbitrary ruby code in the remote process
p gdb.eval('%(pid #{$$})')
# show how many instances of each class exist in the
# remote process
p gdb.object_space
# raise an exception in the remote process
gdb.raise Exception, "go boom!"
# close the connection to the remote process
gdb.quit
Or to debug the hung process, attach it via:
rvmsudo gdb.rb PID
then:
# in gdb get a ruby stacktrace with file names and line numbers
# here I'm filtering by files that are actually in my app dir
(gdb) ruby eval caller.select{|l| l =~ /app\//}
Source: Using gdb to inspect a hung ruby process
Some alternatives:
rbtrace - like strace, but for ruby code (usage: rbtrace -p <PID> --firehose).
debug.rb script by tmm1 (author of gdb.rb) which can help to debug a process using strace/gdb.
See also:
Debugging Ruby Tools
Check why ruby script hangs

Using IRB (i.e. calling 'debugger') with Thor?

I'm trying to get Thor to trigger an IRB prompt when 'debugger' is reached in the code (like Rails, etc). Although I can trigger debugger, how do I get IRB to start automatically when debugger is triggered?
Currently, I do the following in the .thor file:
require 'ruby-debug'
desc 'irb', 'Load IRB console for this app.'
def irb
puts 'Starting IRB...'
debugger
end
This results in the debugger being triggered, but IRB must be explicitly started by typing 'irb' at the prompt:
$ thor app
Starting IRB...
(rdb:1) irb
ruby-1.9.2-p180 :001 > puts 'hello'
hello
=> nil
ruby-1.9.2-p180 :002 > exit
(rdb:1) exit
Really quit? (y/n) y
How do I get IRB to trigger instantly so I don't need to type 'irb' and an extra 'exit'?
Thanks!
For those of you who might have the same question, I did locate two solutions (see http://bashdb.sourceforge.net/ruby-debug.html#Autoirb):
OPTION 1: Set 'autoirb' to on. (my preference)
This is nice because it appears to automatically include your local .irbrc. Downside is you still have to type 'exit' twice if you want to quit the execution of the app (once to exit irb, second to exit debugger).
require 'ruby-debug'
::Debugger.settings[:autoirb] = 1
OPTION 2: Set 'autoeval' to on.
This is nice because it auto-evalutes unknown commands in the debugger and only requires entering 'exit' once to quit, since you are technically still in the debugger console (and not in a nested irb session), and your statements are simply being auto-evaluated. The downside is that your .irbrc settings are ignored. Rails uses this method (more info at: http://www.catapult-creative.com/2009/08/12/make-ruby-debug-work-better/).
require 'ruby-debug'
::Debugger.settings[:autoeval] = 1

Resources