I'm using binding.pry in some Ruby code and I can't figure out how to get out of a long method that I don't want to be in.
I know n for next line and c for continue, but I can't get out of a method. I don't want to exit I just want to get out of the current method.
Conveniently, pry has a command called "help". Once issued it lists a number of things pry can do, including:
break Set or edit a breakpoint.
breakpoints List defined breakpoints.
continue Continue program execution and end the pry session.
finish Execute until current stack frame returns.
next Execute the next line within the current stack frame.
step Step execution into the next line or method.
It also supports aliases to other commands, which can be convenient:
!!! Alias for `exit-program`
!!# Alias for `exit-all`
$ Alias for `show-source`
? Alias for `show-doc`
# Alias for `whereami`
breakpoint Alias for `break`
breaks Alias for `breakpoints`
c Alias for `continue`
clipit Alias for `gist --clip`
f Alias for `finish`
file-mode Alias for `shell-mode`
history Alias for `hist`
n Alias for `next`
quit Alias for `exit`
quit-program Alias for `exit-program`
reload-method Alias for `reload-code`
s Alias for `step`
show-method Alias for `show-source`
According to the documentation the command you are looking for is f:
finish: Execute until current stack frame returns.
and shortcuts
if defined?(PryDebugger)
Pry.commands.alias_command 'c', 'continue'
Pry.commands.alias_command 's', 'step'
Pry.commands.alias_command 'n', 'next'
Pry.commands.alias_command 'f', 'finish'
end
Related
I am trying to learn Byebug and am following the (https://github.com/deivid-rodriguez/byebug/blob/master/GUIDE.md) and I am getting stuck with setting a breakpoint and continuing after the breakpoint is set. After I set the breakpoint for line 5 and run continue, Byebug quits the session. Can someone see what I am doing wrong?
$byebug hanoi.rb
[1, 10] in /Users/jackburum/ruby/byebug-testing/hanoi.rb
1: #
2: #
3: #
=> 4: def hanoi(n, a, b, c)
5: hanoi(n - 1, a, c, b) if n - 1 > 0
6:
7: puts "Move disk #{a} to #{b}"
8:
9: hanoi(n - 1, c, b, a) if n - 1 > 0
10: end
(byebug) break 5
Successfully created breakpoint with id 1
(byebug) continue
$byebug hanoi.rb
If I run the next command instead of continue, the same issue occurs...
[1, 10] in /Users/jackburum/ruby/byebug-testing/triangle.rb
=> 1: def triangle(n)
2: tri = 0
3:
4: 0.upto(n) { |i| tri += i }
5:
6: tri
7: end
8:
9: # if __FILE__ == $triangle.rb
10: # t = triangle(3)
(byebug) break 2
Successfully created breakpoint with id 1
(byebug) next
$
are you meaning to use next here? continue is the same control+d, and will continue to run your code until either another breakpoint is reached or the code ends.
I'm figuring that when you type continue, the rest of your script runs and the program exits because there isn't another breakpoint.
By the way, it might be worth trying the pry gem instead of byebug. Unlike byebug, copy-pasting multi-line code works in pry and there are a number of other useful features such as source-code browsing and syntax highlighting. Although it doesn't come with 'next' or 'continue' out the box, you can install the pry-byebug gem to get these.
Edit
From the additional info you've given, this seems to actually be the expected behavior here. Here's what you need to understand about breakpoints:
They will not follow a downward scope change. For example, say I've written a method like this:
def my_method
puts "my method started"
byebug
5.times { "do something in a loop" }
end
my_method()
puts "my method is done"
puts "the program will end now"
When you run the code with ruby myfile.rb, the code gets to line 6 before pausing on the breakpoint. Since the breakpoint is inside the method body, it won't be activated until the method is actually called.
What would happen if you typed next? Would you have to type it 5 times to get through the 5.times {} loop? The answer is no, and this is because there is a downward scope change into the iterator. In Javascript this "scope change" is more clear because you use the function keyword to show an anonymous function (and therefore a scope change). But in Ruby, blocks are actually syntactic sugar for Procs, which are anonymous functions and therefore introduce a scope change. I'm not sure of the exact reason, but moving into a method body also entails a downward scope change.
So when you press next, what actually happens is that it moves to the puts "my method is done" call. Although the byebug keyword is inside the method, to return to the scope of the method caller is an 'upward' scope change and is expected. Typing next again would move to the puts "my program will end now" line. Typing it again would get to the end of the code and exit the program.
If you needed to pause at each iteration in the loop, you could put the breakpoint inside the loop block i.e. 5.times { byebug }
To bring it back to your example - when you call your script with the byebug executable (i.e. byebug myprogram.rb), the initial scope is top-level. Typing next will skip over any functions or loops. I don't see this being practical for anything other than very small programs, so it's better to place the byebug keyword in your code and call the program with the ruby executable instead, i.e. ruby myprogram.rb
It's a small detail, but breakpoints are ignored when they are the last line in a program. To prevent this, put anything after the breakpoint, even something as simple as exit.
By the way, all this scope stuff applies to pry too as far as I'm aware.
I would like to assign output of a bash command to a variable in .lua script. Is it possible?
For instance, something similar to:
var = `ps uax | grep myprocess`
Yes, you need to use io.popen for this.
io.popen (prog [, mode])
Starts program prog in a separated process and returns a file handle that you can use to read data from this program (if mode is "r", the default) or to write data to this program (if mode is "w").
This function is system dependent and is not available on all platforms.
Also see How to execute an external command?.
io.popen calls a command but returns a file object so you can read the output of the command, if the second argument is 'r', but you can also pass input to a command with a second argument of 'w'. Unfortunately, you don't get a io.popen2, and you don't get the return code.
Say i have two files:
One is called mainFile.lua:
function altDoFile(name)
dofile(debug.getinfo(1).source:sub(debug.getinfo(1).source:find(".*\\")):sub(2)..name)
end
altDoFile("libs/caller.lua")
function callBack()
print "called back"
end
doCallback()
The other called caller.lua, located in a libs folder:
function doCallback()
print "performing call back"
_G["callBack"]()
end
The output of running the first file is then:
"performing call back"
Then nothing more, i'm missing a line!
Why is callBack never getting executed? is this intended behavior, and how do i get around it?
The fact that the function is getting called from string is important, so that can't be changed.
UPDATE:
I have tested it further, and the _G["callBack"] does resolve to a function (type()) but it still does not get called
Why not just use dofile?
It seems that the purpose of altDoFile is to replace the running script's filename with the script you want to call thereby creating an absolute path. In this case the path for caller.lua is a relative path so you shouldn't need to change anything for Lua to load the file.
Refactoring your code to this:
dofile("libs/caller.lua")
function callBack()
print "called back"
end
doCallback()
Seems to give the result you are looking for:
$ lua mainFile.lua
performing call back
called back
Just as a side note, altDoFile throws an error if the path does not contain a \ character. Windows uses the backslash for path names, but other operating systems like Linux and MacOS do not.
In my case running your script on Linux throws an error because string.find returns nill instead of an index.
lua: mainFile.lua:2: bad argument #1 to 'sub' (number expected, got nil)
If you need to know the working path of the main script, why not pass it as a command line argument:
C:\LuaFiles> lua mainFile.lua C:/LuaFiles
Then in Lua:
local working_path = arg[1] or '.'
dofile(working_path..'/libs/caller.lua')
If you just want to be able to walk back up one directory, you can also modify the loader
package.path = ";../?.lua" .. package.path;
So then you could run your file by doing:
require("caller")
dofile "../Untitled/SensorLib.lua" --use backpath librarys
Best Regards
K.
I read that you can put a 'debugging' symbol in your RoR code, and then execution will Halt at that point and then you can then spit out anything into console to see the state of variables etc.
Is there a way to step though each line and follow the execution path?
There is documentation in the debugger itself. n and s are the commands that you are looking for.
(rdb:1) help
ruby-debug help v0.10.3
Type 'help <command-name>' for help on a specific command
Available commands:
backtrace delete enable help next quit show trace
break disable eval info p reload source undisplay
catch display exit irb pp restart step up
condition down finish list ps save thread var
continue edit frame method putl set tmate where
(rdb:1) help next
n[ext][+-]?[ nnn] step over once or nnn times,
'+' forces to move to another line.
'-' is the opposite of '+' and disables the force_stepping setting.
(rdb:1) help step
s[tep][+-]?[ nnn] step (into methods) once or nnn times
'+' forces to move to another line.
'-' is the opposite of '+' and disables the force_stepping setting.
(rdb:1)
I'm using Rinari for Rails development in Emacs. M-x shell will open a new buffer that is correctly PATH'd for my environment (zsh). M-x eshell uses all the incorrect PATH's and I haven't been able to get it to play nicely with anything.
There's a function of Rinari that fires up an instance of a web server for the Rails app I'm editing, however, but the buffer it opens with the server instance is eshell.
How can I ultimately get this to open a buffer using shell (or what would open with M-x shell) instead?
Below is the defun for the command I'm trying to execute.
Is there simply a setting I can change or a variable that looks for what shell to open?
(defun rinari-web-server (&optional edit-cmd-args)
"Run script/server. Dump output to a compilation buffer
allowing jumping between errors and source code. With optional
prefix argument allows editing of the server command arguments."
(interactive "P")
(let* ((default-directory (rinari-root))
(script (concat (expand-file-name "server"
(file-name-as-directory
(expand-file-name "script" (rinari-root))))
(if rinari-rails-env (concat " -e " rinari-rails-env))))
(command (if edit-cmd-args
(read-string "Run Ruby: " (concat script " "))
script)))
(ruby-compilation-run command)) (rinari-launch))
If you can't find anything to configure, you can always try something like the following:
(defun fooby ()
""
(interactive)
(eshell))
(defadvice fooby (around fooby-replace-eshell-with-shell-around act)
"Substitute `shell` for `eshell` for the duration of this call"
(flet ((eshell () (shell)))
ad-do-it))
For the duration of the call to fooby it will substitute a call to shell any time eshell is called. You want to focus the advice as tightly as possible, so if you can find the function that actually calls eshell, that would be the one to advise. Of course, if you don't feel like digging, you can always just advise rinari-web-server. If you never, ever want to use eshell, then you can use fset to do the substitution globally:
(fset 'eshell 'shell)
Hope that helps!
I was able to alias 'emacs' to launch Emacs.app and in doing so from my terminal environment, Emacs then carries over the appropriate PATH inside eshell.