Follow up of this post: Debugging via IEx
In Ruby it's super easy to place a breakpoint via binding.pry or byebug. In Elixir it's a bit more cumbersome:
require IEx
IEx.pry()
Especially the lower and uppercase letters trip me up now and then. It would be nice if we could just call something like pry/0 and have it pause the code there.
But unfortunately that doesn't seem possible because pry/0 would need to be a macro for the breakpoint to be executed in the caller context. (which means it would need to be required and/or imported first).
use DebuggerWith the following snippet (in .iex.exs for example) you can place a breakpoint with just use Debugger.
defmodule Debugger do
defmacro __using__(_opts \\ []) do
quote do
require IEx
IEx.pry()
end
end
end
If we could have iex<tab> or pry<tab> expand to require IEx\n IEx.pry() that would also solve the problem. Maybe worth adding to elixir-editors/elixir-tmbundle
use IEx.Pry to ElixirThis would be a small improvement in my opinion but is worth considering adding this as a built-in feature.
@thomasbrus you can send a PR for pry<tab> to your favorite editors any time. For Elixir itself, the one that makes sense is the use IEx.Pry one. Let's wait for some feedback and see what people think. Thanks!
use IEx.Pry sounds good to me 馃憤
The difference with require IEx; IEx.pry() is minimal, but I think it will be easier to remember and faster to type!
use IEx.pry still has the strange upper/lower casing.
@iwarshak good point. I think the error messages can lead people to the correct solution thought?
iex(1)> use IEx.pry
** (CompileError) iex:1: you must require IEx before invoking the macro IEx.pry/0
(elixir) lib/macro.ex:1276: Macro.do_expand_once/2
(elixir) lib/macro.ex:1337: Macro.expand_until/2
(elixir) lib/kernel.ex:4945: Kernel.expand_aliases/2
(elixir) lib/kernel.ex:4913: Kernel."MACRO-use"/3
(elixir) expanding macro: Kernel.use/1
iex:1: (file)
iex(1)> require IEx; use IEx.pry
** (ArgumentError) invalid arguments for use, expected a compile time atom or alias, got: IEx.pry()
(elixir) lib/kernel.ex:4921: anonymous fn/3 in Kernel."MACRO-use"/3
(elixir) lib/enum.ex:1323: Enum."-map/2-lists^map/1-0-"/2
(elixir) lib/kernel.ex:4913: Kernel."MACRO-use"/3
(elixir) expanding macro: Kernel.use/1
iex:1: (file)
Thoughts?
Why not autoimport the module, and just call pry like with the other iex helpers
@eksperimental I think that wouldn鈥檛 work because you call IEx.pry() inside the module you want to debug, and not during the IEx session :)
I think you would need to auto-require IEx in all the modules for that to work when opening the IEx session. Not sure if that鈥檚 even possible though.
@josevalim I think an error message would be sufficient, but personally, I think debug, debugger, or breakpoint makes even more sense.
@iwarshak IEx is a separate application to Elixir. I wouldn't want Elixir to have keywords or macros that are about a separate application. This sends the message that IEx can cheat, by being part of the language repository, and the same privilege wouldn't be available to other applications from 3rd party developers. If we all play by the same rules, then we dogfood our APIs and aim to find solutions that are better for everyone.
@josevalim I agree, and this is probably a separate issue, but IEx.pry does not clearly indicate it's functionality, which is: dropping you into a debugging session.
@iwarshak I would say it does, (at least if you're familiar with pry in Ruby). But use IEx.Pry on the other hand I find a bit too magical. And it differs from how we'd normally use use (at the module level, and usually just to include some DSL). Although it is cool it works.
We could also use this as an opportunity to step away from the pry naming and solidify on IEx.Debugger. So we would have use IEx.Debugger. Thoughts?
Folks, I have decided to hold-off on this. The issue with calling it a debugger is because it is not a debugger in what people expect in the most sense (with steps and so on). The best IEx can do here is to "pry" the current environment. So even though the name was retrieved from Ruby, it was intentionally done as so, as it is not a debugger per se. I don't want to use IEx.Debugger in case we do get an actual debug in the future. Thank you!
Hello there,
I'm also coming from Ruby and love to use pry in my day to day work too in both Ruby and Elixir, either for debugging or just fiddling around.
The only drawback is the time it needs to actually set a breakpoint in Elixir because of that mentioned boilerplate involved.
For my taste binding.pry is already way too long to type in Ruby, but I guess there is no other solution because of the way the binding in Ruby has to be accessed.
But Elixir doesn't have this restriction, because of the macro system as far as I can tell.
So I thought, why not simply define a pry macro on Kernel which is then available everywhere and makes debugging a breeze?
I'm quite new to Elixir (but already loving it) so I'm not sure if that pry macro is a good idea, but I would love to hear your thoughts about it.
@christophweegen see https://github.com/elixir-lang/elixir/issues/8125#issuecomment-415570322 馃檪
Thanks for the comment!
Most helpful comment
We could also use this as an opportunity to step away from the
prynaming and solidify onIEx.Debugger. So we would haveuse IEx.Debugger. Thoughts?