Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

std/prettyprints: pretty print any expression (including with cycles), customizable #385

Open
timotheecour opened this issue Jun 11, 2021 · 7 comments

Comments

@timotheecour
Copy link
Member

timotheecour commented Jun 11, 2021

proposal

add a std/prettyprints module to allow pretty printing arbitrary expressions

design goal

As with std/jsonutils this should have:

  • sane defaults
  • provide enough options so you don't need to roll your own (eg custom depth etc)
  • customizable via hooks for the cases where existing options aren't enough
  • allows pretty-printing cyclic data structures
  • accepts any expression (including ptr|pointer|etc)
  • builtin $ stays simple (I'd still argue $ works for ref|ptr|pointer for all targets (c,cpp,js,vm) + other bugfixes Nim#14043 should be merged in some form or another but that's orhtogonal to this RFC)

unlike dollars.nim, this is not a low-level module, and can have (at least optionally) heaver dependencies (eg tables.nim) for needed functionality and to simplify implementation

eg:

type Option = ref object
  depth: int # how far to recurse
  showDistinct: bool # when true, if no `$` overload exists for a distinct type, print via undistinct
  fpFormat: string # customizes FP printing eg `"%.02f"`
  # etc... that customizes prettyprinting

pretty[T](result: var string, a: T, options: Options = nil) = ...
template pretty[T](a: T, options: Options = nil): string = pretty(result, a, options)
  # for convenience since so common

all overloads are outplace form and there's a single inplace form, just like in #191

  • distinct can be shown via undistinct depending on showDistinct
  • we use a Hash[ByteAddress] to mark already visited addresses and in case input is cyclic

I've already implemented that in a private project with extensive options, so I know it's quite doable.

sample output

  • as html, with dynamically expandable nodes:
    image

  • as a string, printed in terminal via echo
    image

links

@konsumlamm
Copy link

konsumlamm commented Jun 11, 2021

This looks like a cool idea, but I don't see why it should be in the standard library. I think it would fit better as a nimble package (or at least in dist/stdx).

@Clyybber
Copy link

It exists as a package already; https://github.com/treeform/print, I don't think absorbing/obsoleting packages into the stdlib is healthy for the ecosystem at whole. We should simply ship a bunch of packages with the installation to give them exposure and use.

@zetashift
Copy link

It exists as a package already; https://github.com/treeform/print, I don't think absorbing/obsoleting packages into the stdlib is healthy for the ecosystem at whole. We should simply ship a bunch of packages with the installation to give them exposure and use.

treeform/print could be a great addition to fusion?

@haxscramper
Copy link

I don't think it is a good idea to select any single implementation and add it to the fusion or stdlib, because there are so many elements that can be done differently, it would be quite hard to implement them all and have a reasonably simple solution. I also have a pretty-printer library that supports gitignore-style globs to ignore part of the objects, and global layout optimization - depending on the size of the object it might print it differently. I also plan to add support for int/string print style configuration (using gitignore globs as selectors as well), so I could select to print **/bitFlags in binary representation.

Do these features sound like something one might need? Yes, absolutely. I don't want to stare at the screen-worth of sequences, and for different reasons I do print a lot of them, so I put extra effort to layout things as compact as possible, but make it easier to view. In order to provide good layout, I implemented ad-hoc layouter for the first version and now writing v2 that would use https://research.google/pubs/pub44667/. Others might have different use cases, personal preferences, and in their case it might be completely pointless to put so much effort into this.

For example, to me, it is kind of important that would be able to print things like let val = mapIt(0 .. 20, mapIt(1 .. sample({0 .. 5}), (it, $it))) nicely (this is a synthetic example, but close enough to some things I'm working with). But it seems like this is not the case for treeform/print:

image

@zetashift
Copy link

@haxscramper I see, your prettyprint library does look great!

I don't think it is a good idea to select any single implementation and add it to the fusion or stdlib, because there are so many elements that can be done differently

This is true, but there seems to be a need for easy pretty printing out there, so it might be worth discussing adding one of them to fusion, I don't see them necessarily being needed in a stdlib. I think this is one of those cases, adding one of them to fusion can be useful.

@lypanov
Copy link

lypanov commented Aug 15, 2021

As a nim-newbie leveling up it's extremely unexpected that httpclient's Response isn't echo'able. treeform/print works well enough. But I agree with the sentiments from the OP. I really would expect such functionality to be in the standard library. I do OTOH agree completely that it should be kept as minimal as possible and avoid external large dependencies. Alas at my experience level I can't help with solving that issue.

@haxscramper
Copy link

haxscramper commented Aug 15, 2021

We can add something like treeform/pprint to the fusion. Full-featured pretty print implementation is very complicated, so I don't think like haxscramper/hmisc/pprint would be accepted anyway, and for simple use cases it is usually enough. Add some heuristics here and there to make sure long sequences/tables look good etc, and control whether output is colored or not

This partially contradicts what I said earlier, but in the end treeform/print would be enough for the most, so I think it would be better to settle on an existing simple implementation rather than trying to discuss all potential requirements. But this would mean some things like HTML output should be left out.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

6 participants