Feature #20987
openAdd dbg - minimal debugging helper
Description
Hi. It's my first time contributing here, so I'm sorry in advance if I've mixed something up.
I’m author of https://github.com/pawurb/dbg-rb gem. dbg
method is inspired by Rust where it's built-in into std-lib (https://doc.rust-lang.org/std/macro.dbg.html). AFAIK in Ruby there's no simple mechanism to puts debug values together with caller info without using external dependencies. What’s more frustrating is that while p nil
outputs nil
to the std, puts nil
prints a blank line, sometimes making debugging sessions confusing.
I would like to propose adding a minimal dbg
helper method to stdlib:
dbg("Hello world", [1, 2, 3])
# => [dir/file.rb:12] "Hello world"
# => [dir/file.rb:12] [1, 2, 3]
dbg
will produce verbose output together with informative file name and LOC info. I think that such built-in feature would be useful for many Ruby devs.
My gem uses external dependencies, but I've came up with this barebones implementation:
def dbg(*msgs)
loc = caller_locations.first.to_s
matching_loc = loc.match(/.+(rb)\:\d+\:(in)\s/)
src = if matching_loc.nil?
loc
else
matching_loc[0][0..-5]
end
file, line = src.split(":")
file = file.split("/").last(2).join("/")
src = "[#{file}:#{line}]"
msgs.each do |msg|
puts "#{src} #{msg.inspect}"
end
nil
end
Files
Updated by pawurb (Pawel Urbanek) 11 days ago
Hi. It's my first time contributing here, so I'm sorry in advance if I've mixed something up.
I’m author of dbg-rb gem. dbg
method is inspired by Rust where it's built-in into std-lib. AFAIK in Ruby there's no simple mechanism to puts debug values together with caller info without using external dependencies. What’s more frustrating is that while p nil
outputs nil
to the std, puts nil
prints a blank line, sometimes making debugging sessions confusing.
I would like to propose adding a minimal dbg helper method to stdlib:
dbg("Hello world", [1, 2, 3])
# => [dir/file.rb:12] "Hello world"
# => [dir/file.rb:12] [1, 2, 3]
dbg
will produce verbose output together with informative file name and LOC info. I think that such built-in feature would be useful for many Ruby devs.
My gem uses external dependencies, but I've came up with this barebones implementation:
def dbg(*msgs)
loc = caller_locations.first
file = if (path = loc.absolute_path)
path.split("/").last(2).join("/")
else
loc.label
end
line = loc.lineno
src = "[#{file}:#{line}]"
msgs.each do |msg|
puts "#{src} #{msg.inspect}"
end
nil
end
Updated by mame (Yusuke Endoh) 10 days ago
Basically, I like this proposal.
I use Kernel#p
and pp
a lot when debugging.
I often include an identifier such as p [:foo, obj]
, p [:bar, obj]
to distinguish which p
the output is from. If the debug output method itself prints the caller filename, this identifier might be unnecessary. (But TBH, I am not sure. The filename and line number could be insufficient for easy recognition.)
Also, I delete all calls to p
after debugging is done, but it is sometimes difficult to find all p
calls. If p
would output the filename, the deletion process would be definitely easy.
I think it would be better to extend p
instead of introducing dbg
. Three letters are too long for every debug method call.
As for a concern, it may be troublesome for p
to always print the filename. Just an idea, how about opt-in by an environment variable?
$ ruby foo.rb
"Hello world".
$ P=1 ruby foo.rb
[foo.rb:1] "Hello world"
Updated by pawurb (Pawel Urbanek) 10 days ago
Thanks for feedback!
One thing I'm worried about with P=1
approach, are Ruby programs that rely on the current p
output, making it impossible to opt-in this new feature. Maybe we could go for d
instead of dbg
?
As for identifiers, dbg-rb gem currently supports passing local variables via symbols like this:
a = 1
b = 2
dbg(:a, :b)
# [models/user.rb:22] a = 1
# [models/user.rb:22] b = 2
This feature requires binding_of_caller gem, but if it was found useful enough, maybe it could be possible to reimplement it without external deps? Optional identifiers together with file name and LOC info would make Ruby debugging much simpler.