douglasg14b/BetterConsoleTables

Version 2 (Colors, New API, and More)

douglasg14b opened this issue · 7 comments

Goals/Scope:

  • Individual Cell Formatting
    • Color
    • Alignment
    • [ ] Wrapping
  • Per Column Formatting
    • Color
    • Alignment
  • Maintain performant, non-formatted Table class
  • DI Friendliness (interface usage)
  • Interoperability between a normal and a formatted table
  • Table/Tables centering and Full-Width
    • To support non-console users, this should accept a outputWidth argument

Out of Scope:

  • Table divider/format coloring
    • The ability to color the table syntax itself
  • Value-based formatting
    • Configurable formatting based on the cells value and/or type

This will mostly require a rewrite of much of the Table's working so I can bake in interoperability and compatibility while minimizing code reuse.

Misc Thoughts:

Extracting table through reflection:

  • Use a more fluent-like API for creation from a Type.
    • Table.From<TModel>(TModel tableModel)
      • .From<> returns a config builder for the type
    • .AddColumn(TModel x => x.MyProp, ...config ... )
    • Alternatively: .AddColumn(TModel x => x.MyProp).SetColor(...).AlignContent(...).AddColumn(...) ...

Bugs

  • Adding rows after headers doesn't ensure rows are sized to match column count
  • Adding columns as an array during table creation doesn't setup format matrix

Making the actual configuration of each cell, row, or column user friendly is quite the pain... It would be unreasonable to expect the caller to pass in a complex configuration with each value.

  • Use a "fluent-like" API?
    • Caller uses a typical action to configure the input?
    • ie. (x => x.HeaderAlignment = Alignment.Right) or (x => { x.HeaderAlignment = Alignment.Right; x.color = Color.Blue; })
  • Store the configurations separate from the values themselves in a matching matrix?
    • This would enable table re-generation from just data, and avoid reconfiguration for every change.
    • This could avoid the need for a 2nd Table type to handle complex formatting, and this could be managed as the default as index lookups are not expensive.
    • Column-base or row-based configurations would just be generated for the entire row/column and stored in the matrix

image

Progress!

More Progress, working through making the configuration easier as it's a bit of a chore right now, while keeping performance in mind.

Right now cell formatting is controlled via the headers. Meaning the formatting granularity is per column, header vs rows. Individual cells cannot be controlled yet, however, it sets the formatting for each individual cell right now.

image

The format setting needs to determine when it should and should not use the CellFormat object, and avoid creating duplicate objects, for the sake of high performance.

To Do (Performance):

  • Override GetHashCode on CellFormat and Format types
  • Implement IEquatable for CellFormat and Format types
  • Cache unique variations of CellFormat for the lifetime of the application (Staticly?), and refer to this cache whenever cell formats are added to the matrix. Just copy the references instead of creating new formats whenever possible.

Version 2 is stable and should be ready for a beta release. A nice fluent API has been developed as well.

This also comes with a console colors/formatting library that performs the same functions as other libraries like crayon but MUCH more efficiently (ie. it isn't a cluster of regex). I created this from scratch because I didn't want unnecessary dependencies, and needed control over the performance characteristics.

Currently v2 will NOT have the performance of v1 when it comes to table creation, though it should still be close. Tables can now have their data replaced, instead of creating a brand new Table object every time you need to print. This reduces the CPU overhead of creating a new table, and a new formatting matrix. Though this comes at the cost of memory utilization (marginally).

Performance actually appears to be better: 0.015 ms.

Though this could be due to having a more controlled performance testing environment, and different hardware.

2.0.0-beta1 Nuget Package

2.0 is now in beta as a nuget package. Along with the Core library and the Colors library.

Relicencing to LGPL-3

2.0 relicences from MIT to LGPL-3, this will not affect anyone using this as a library and puts an extra restriction on unfettered copy/pasting of my code to other projects. I put a lot of effort into this, and it would be a shame for it to be for naught if it was just copy/pasted into a more popular project.