Project

General

Profile

Actions

Feature #20987

open

Add dbg - minimal debugging helper

Added by pawurb (Pawel Urbanek) 11 days ago. Updated 10 days ago.

Status:
Open
Assignee:
-
Target version:
-
[ruby-core:120428]

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

Screenshot 2024-12-27 at 00.00.23.png (81.5 KB) Screenshot 2024-12-27 at 00.00.23.png pawurb (Pawel Urbanek), 12/26/2024 11:28 PM

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.

Actions

Also available in: Atom PDF

Like0
Like0Like0Like0