garu / Data-Printer

colored pretty-print of Perl data structures and objects
100 stars 81 forks source link

[wishlist] Feature request show/hide hash keys. #149

Open dwright opened 4 years ago

dwright commented 4 years ago

It would be nice if there was a way for Data::Printer to omit certain hash keys from output. The idea being that sometimes you only care about certain keys and the rest just get in the way of visualizing what you need.

Use case: When displaying a hash, I'd like to be able to omit all key/value pairs where the value is undef.

Another use case: Omit all key/value pairs where the key begins with underscore.

Another use case: Only show / always omit hash keys from a predefined list.

Perhaps this could be a feature of Data::Dumper::Filter.

Or maybe a callback method that is passed a key/value and returns true/false. Though, I could see an argument for also wanting to include context for deciding what to show.

garu commented 4 years ago

Hi! Thanks for using Data::Printer and for taking the time to post a feature request.

I'm thinking about your suggestion and its implications. I've been reluctant to add pathfinding code to Data::Printer because, by filtering out part of the data, developers might miss important hints as to what went wrong. Even worse, they might leave the match/skip option on their .dataprinter file and think they are looking at the full picture when they're not.

But the more I think about it the more it feels like it could be a good use case. Maybe we can force a message saying clearly that the dump is filtered.

  1. Would this syntax look good?
    p %var, match => qr{^_};   # only shows keys OR values starting with underscore
    p %var, match => 'foo';    # only shows keys OR values that are *exactly* 'foo'
    p %var, skip => qr{^_};    # ignore all keys OR values starting with underscore
    p %var, skip => 'foo';     # ignore all keys OR values that are *exactly* 'foo'
    p %var, match_undef => 1;  # only shows undef data
    p %var, skip_undef => 1;   # skip all undef data

Note that, since DDP takes any kind of data structure, it should look for both keys and values, and print whenever one or the other is a match. Same goes for arrays and objects: I would expect DDP to consistently only show objects with class name, methods or internals matching (or skipping) whatever was set on match | skip.

  1. This also leaves open the match/skip precedence when they are used together:
    p %var, skip_undef => 1, match => qr{_}, skip => '_not_me';

Would the code above: (a) skip first and only then try to match (e.g. { _foo => undef, _not_me => 1 } yield NO MATCHES) (b) match first, effectively ignoring the skip options (e.g. { _foo => undef, _not_me => 1 } matches BOTH) (c) throw a warning or error? (d) something else entirely?

  1. As for the output, I'd expect something like:

(a)

(matching: qr{^_})
{
    ....
    foo => [
        ...
        [19] {
            ...
            obj => HTTP::Response {
                ...
                content => '_lala',
                ...
            },
        },
        ...
    ]
    _bar => undef,
}

I'm not sure this is an easy thing to do, specially properly positioning the tons of "..." suggesting trimmed content. It might be (much) easier to do something like:

(b)

(matching: qr{^_})
{
    foo => [
        [19] {
            obj => HTTP::Response {
                content => '_lala',
            },
        },
    ]
    _bar => undef,
}

And, because of the reference labeling done internally, it might be even easier to do something like:

(c)

(matching: qr{^_})
  {foo}[19]{obj}{content}    '_lala'
  {_bar}    undef

It may not look so good but it's telling you exactly where the content you want is positioned on your data structure.

What do you think? Are any of those ideas what you expected? Which one is your favorite? Am I missing something?

Cheers!

garu commented 4 years ago

@karenetheridge @bessarabov @book @oalders @hakonhagland and anyone else, please feel free to chip in!